【发布时间】:2014-06-13 18:09:05
【问题描述】:
我知道我可以使用以下语法在make 规则中使用模式匹配:
%.csv : %.tsv
tsv2csv $< $@
但是,如果应该匹配整个目标,这似乎不起作用:
虽然
%.csv : %.csv.gz
zcat $< > $@
和
%.tsv : %.tsv.gz
zcat $< > $@
工作正常,
% : %.gz
zcat $< > $@
没有。
我知道对于这个特定的例子我可以使用
%sv : %sv.gz
zcat $< > $@
但想象一下,我也想使用相同的规则来获取 *.txt 文件的未压缩副本。
这是否有原因(和/或不应该)可能,如果没有,我如何在 (GNU) make 中实现这一目标?
我想这是一个常见的需求(例如将 foo.c 编译为 foo),但我在 SO 和其他地方(网络搜索)都没有找到任何东西。
附录:
正如评论中指出的那样/answer 我上面的最小示例工作得很好。
但是,在我较大的 Makefile 中,它没有。
我发现这似乎是由第二级模式匹配触发的。
考虑以下 Makefile:
all : testA testB
testA : testA.txt
ln -s $< $@
testB : testB.txt
ln -s $< $@
testA.txt : testA.txt.gz
zcat $< > $@
testB.txt : testB.txt.gz
zcat $< > $@
我使用创建了一些虚拟输入文件
touch testA.txt testB.txt
gzip testA.txt testB.txt
如果我运行 make -n 我会得到
zcat testA.txt.gz > testA.txt
ln -s testA.txt testA
zcat testB.txt.gz > testB.txt
ln -s testB.txt testB
使用模式规则,我可以将上面的 Makefile 缩短为
all : testA testB
testA : testA.txt
ln -s $< $@
testB : testB.txt
ln -s $< $@
%.txt : %.txt.gz
zcat $< > $@
在这个版本上使用make -n,我仍然得到和以前一样的输出。
我现在发现我也可以把它缩短为
all : testA testB
testA : testA.txt
ln -s $< $@
testB : testB.txt
ln -s $< $@
% : %.gz
zcat $< > $@
或
all : testA testB
% : %.txt
ln -s $< $@
testA.txt : testA.txt.gz
zcat $< > $@
testB.txt : testB.txt.gz
zcat $< > $@
所以匹配通配符 (%) 的整个目标不是问题。
但是,我不能将上述简化合并到一个 Makefile 中:
all : testA testB
% : %.txt
ln -s $< $@
% : %.gz
zcat $< > $@
此 Makefile 会产生以下 make -n 的输出:
make: *** No rule to make target `testA', needed by `all'. Stop.
我认为make 可能有两个将通配符作为整个目标的模式规则的问题(尽管我认为这是可能的;至少在这种情况下)。
这就是为什么我也尝试了以下版本:
all : testA testB
% : %.txt
ln -s $< $@
%.txt : %.txt.gz
zcat $< > $@
令我惊讶的是,这被make 接受了。
不幸的是,我需要这样的东西:
all : testA.csv testB.csv
testA.csv : testA.txt testA.tsv
tsv2csv $^ $@
testB.csv : testB.txt testB.tsv
tsv2csv $^ $@
testA.txt : testA.txt.gz
zcat $< > $@
testB.txt : testB.txt.gz
zcat $< > $@
testA.tsv : testA.tsv.gz
zcat $< > $@
testB.tsv : testB.tsv.gz
zcat $< > $@
我使用
创建了测试输入touch testA.txt testB.txt testA.tsv testB.tsv
gzip testA.txt testB.txt testA.tsv testB.tsv
运行make -n 返回
zcat testA.txt.gz > testA.txt
zcat testA.tsv.gz > testA.tsv
tsv2csv testA.txt testA.tsv testA.csv
zcat testB.txt.gz > testB.txt
zcat testB.tsv.gz > testB.tsv
tsv2csv testB.txt testB.tsv testB.csv
综合以上观察,我可以将其缩短为
all : testA.csv testB.csv
%.csv : %.txt %.tsv
tsv2csv $^ $@
%.txt : %.txt.gz
zcat $< > $@
%.tsv : %.tsv.gz
zcat $< > $@
但不是这个:
all : testA.csv testB.csv
%.csv : %.txt %.tsv
tsv2csv $^ $@
% : %.gz
zcat $< > $@
make 出现这种行为的原因是什么?有没有办法改变它?
【问题讨论】:
-
你想做的应该可以。如果不是,您应该提供一个不起作用的实际示例,包括 makefile、您键入的命令以及您得到的结果。
-
@MadScientist:抱歉举了一个不好的例子,希望新信息对您有所帮助。
标签: makefile wildcard gnu-make