我知道我可以使用以下语法在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
这种行为的原因是什么,有没有办法改变它?
答案 0 :(得分:1)
目标为%
的规则受到GNU make的不同处理,如http://www.gnu.org/software/make/manual/make.html#Match_002dAnything-Rules
您可能可以通过智能放置双冒号来制定规则,或许可以遵守此规则:
% :: %.gz
答案 1 :(得分:0)
我不确定您是如何尝试执行make
命令的,但以下命令序列对我有用。
生成文件:
% : %.gz
zcat $< > $@
命令:
touch foo.txt
gzip foo.txt # Creates foo.txt.gz
make foo.txt # Produces foo.txt again.