Adriano Carvalho
Adriano Carvalho

Reputation: 153

makefile: implicit rules: same target different prerequisites

I have the following makefile:

all: DIR/0/a.txt DIR/1/b.txt DIR/2/c.txt DIR/3/abc.txt

DIR/%/abc.txt: DIR/%/def.xtx # rule #1
    mkdir -p $(@D)
    touch $@

DIR/%.txt: # rule #2
    mkdir -p $(@D)
    touch $@

DIR/%.xtx:
    touch $@

I want to generate DIR/%/def.xtx whenever DIR/%/abc.txt is generated; otherwise generate only DIR/%.txt.

Using the makefile above with GNU Make 3.81 however, only DIR/3/abc.txt gets generated and DIR/%/def.xtx is not generated.

Following the "Implicit rule search algorithm" in the GNU make user manual we get:

(1) Split t into a directory part, called d, and the rest, called n. For example, if t is ‘src/foo.o’, then d is ‘src/’ and n is ‘foo.o’.

For DIR/3/abc.txt, d = DIR/3 and n = abc.txt.

(2) Make a list of all the pattern rules one of whose targets matches t or n. If the target pattern contains a slash, it is matched against t; otherwise, against n.

Rules #1 and #2 match.

(3) If any rule in that list is not a match-anything rule, then remove all nonterminal match-anything rules from the list.

NOT SURE: no rule is removed from the list.

(4) Remove from the list all rules with no recipe.

No rule is removed.

(5) For each pattern rule in the list:

(5.a) Find the stem s, which is the nonempty part of t or n matched by the ‘%’ in the target pattern.

For rule #1, s = 3. For rule #2, s = 3/abc

(5.b) Compute the prerequisite names by substituting s for ‘%’; if the target pattern does not contain a slash, append d to the front of each prerequisite name.

For rule #1, it becomes: DIR/3/abc.txt: DIR/3/def.xtx Rule #2 has no prerequisites.

(5.c) Test whether all the prerequisites exist or ought to exist. (If a file name is mentioned in the makefile as a target or as an explicit prerequisite, then we say it ought to exist.)

NOT SURE: DIR/3/def.xtx is mentioned by the rule DIR/%.xtx:.

After this long long long explanation, my opinion is that I am probably wrong in (5.c).

Upvotes: 2

Views: 5082

Answers (1)

Beta
Beta

Reputation: 99172

From the manual,

A rule whose prerequisites actually exist or are mentioned always takes priority over a rule with prerequisites that must be made by chaining other implicit rules.

Your rule #1 requires chaining, your rule #2 has no prerequisites, so Make will choose #2 over #1 when trying to build DIR/3/abc.txt.

EDIT:

If you can stand having a list of directories:

DIRS := DIR/0 DIR/1 DIR/2 DIR/3

then you can do it with a static pattern rule:

all: DIR/0/a.txt DIR/1/b.txt DIR/2/c.txt DIR/3/abc.txt

ABC_TXT := $(addsuffix /abc.txt, $(DIRS))

$(ABC_TXT): DIR/%/abc.txt : DIR/%/def.xtx

DIR/%.txt:
    mkdir -p $(@D)
    touch $@

DIR/%.xtx:
    touch $@

(And it avoids duplication of the .txt rule too!)

Upvotes: 4

Related Questions