43

I'd like to know if it's possible to write a Makefile with several rules, each one defining its own prerequisites and executing all of them the same recipe without duplicating the recipe. Example:

TARGETS= file1 file2 file3

all: $(TARGETS)

file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1
    cat $^ > $@

Thanks!

Eldar Abusalimov
  • 24,387
  • 4
  • 67
  • 71
superruzafa
  • 701
  • 1
  • 7
  • 10

1 Answers1

64

Yes, it is written in a rather obvious way:

TARGETS= file1 file2 file3

all: $(TARGETS)

file1: dep1 dep2
file2: dep2 dep3 dep4
file3: dep2 dep1

$(TARGETS):
    cat $^ > $@

UPD.

Just to clarify.

Generic make rule looks like this:

targets... : prerequisites...
    recipe
    ...

Any part of the rule can be omitted. Without the recipe, one can populate the list of prerequisites anywhere in the makefile, a target can occur in the left hand side of multiple rule statements.

For example, the following is equivalent to the example above (well, assuming that the Makefile is properly designed so that the order of prerequisites does not matter):

file1 file3       : dep1
file1 file2 file3 : dep2
file2             : dep3 dep4

Unlike listing prerequisites, there can be at most one explicit recipe for each target. Inside the recipe you can use automatic variables to get the target name, the list of prerequisites, etc.

UPD. 2

As @Calmarius mentions in comments this doesn't apply to pattern rules, like %.txt: %.foo. Multiple patterns within targets mean that the rule produces all these targets at once.

This pattern rule has two targets:

%.tab.c %.tab.h: %.y
    bison -d $<

This tells make that the recipe bison -d x.y will make both x.tab.c and x.tab.h. If the file foo depends on the files parse.tab.o and scan.o and the file scan.o depends on the file parse.tab.h, when parse.y is changed, the recipe bison -d parse.y will be executed only once, and the prerequisites of both parse.tab.o and scan.o will be satisfied.

One may define multiple prerequisites in a pattern rule though (that is, provided that its targets contain a % stem, otherwise it would be a regular rule).

Eldar Abusalimov
  • 24,387
  • 4
  • 67
  • 71
  • @superruzafa, see the updated answer, I tried to explain how rule may look like. – Eldar Abusalimov Jul 11 '12 at 21:54
  • 7
    This won't work if you have pattern rules, eg: %.txt: %.foo. If you add some txt files into the TARGETS variable the $^ will expand to nothing. I guess make thiks that the `$(TARGETS): ` is more specific so it won't apply the generic rule. Apparently you cannot avoid recipe repetition for pattern rules. – Calmarius Jul 21 '14 at 17:44