我有以下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 $@
每当生成DIR/%/def.xtx
时,我想生成DIR/%/abc.txt
;否则只生成DIR/%.txt
。
使用GNU Make 3.81上面的makefile,只生成DIR/3/abc.txt
并且不生成DIR/%/def.xtx
。
遵循GNU make用户手册中的“隐式规则搜索算法”,我们得到:
(1)将t拆分为名为d的目录部分,其余部分称为n。例如,如果t是'src / foo.o',则d是'src /',n是'foo.o'。
适用于DIR/3/abc.txt
,d = DIR/3
和n = abc.txt
。
(2)列出其目标与t或n匹配的所有模式规则。如果目标模式包含斜杠,则与t匹配;否则,反对n。
规则#1和#2匹配。
(3)如果该列表中的任何规则不是匹配任何规则,则从列表中删除所有非终结匹配任何规则。
不确定:列表中没有删除任何规则。
(4)从列表中删除所有没有食谱的规则。
没有删除任何规则。
(5)对于列表中的每个模式规则:
(5.a)找到词干s,它是t或n的非空位部分,与目标模式中的'%'匹配。
对于规则#1,s = 3
。
对于规则#2,s = 3/abc
(5.b)用s代替'%'计算先决条件名称;如果目标模式不包含斜杠,则将d附加到每个先决条件名称的前面。
对于规则#1,它变为:DIR/3/abc.txt: DIR/3/def.xtx
规则#2没有先决条件。
(5.c)测试是否存在所有先决条件或应该存在。 (如果在makefile中提到文件名作为目标或作为显式先决条件,那么我们说它应该存在。)
不确定:规则DIR/3/def.xtx
提到DIR/%.xtx:
。
经过长时间的长篇解释后,我认为(5.c)可能错了。
答案 0 :(得分:4)
来自the manual,
一条规则,其先决条件实际存在或始终被提及 优先于具有必须由之前的先决条件的规则 链接其他隐含规则。
您的规则#1需要链接,您的规则#2没有先决条件,因此在尝试构建DIR/3/abc.txt
时,Make会在#1上选择#2。
修改
如果您能够拥有目录列表:
DIRS := DIR/0 DIR/1 DIR/2 DIR/3
然后你可以使用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 $@
(它也避免了.txt
规则的重复!)