如果我想在用户运行时创建foo.txt
make foo
,这很简单:
foo: foo.txt
foo.txt:
touch foo.txt
但是,如果我提前不知道名称foo
,并且我想支持创建任何其他任意命名的文本文件,该怎么办?
这是我尝试过的:
%: %.txt
%.txt:
touch %.txt
但是如果我尝试make clojure
,而不是运行touch clojure.txt
,它会失败并No rule to make target clojure
。
这是怎么做到的?
这里有很多问题。 首先,你的食谱是错误的; 食谱中的%
不是特别的,不会被替换。 您的命令touch %.txt
创建字面上名为%.txt
的文件,而不管模式匹配什么。 您想在此处使用touch $@
;请参阅自动变量的讨论。
第二,你的规则:
%: %.txt
不做你想的那样。 与显式规则不同,创建没有配方的隐式或模式规则不会简单地为与模式匹配的目标创建先决条件关系:而是删除预先存在的模式规则。
由于您没有预先存在的模式规则,因此您的生成文件与简单地编写相同:
%.txt:
touch %.txt
并且无法使用此生成文件构建目标clojure
。
一种解决方案是创建一个这样的虚拟配方:
% : %.txt
@:
%.txt:
touch $@
如果您没有要添加到 makefile 中的其他目标,另一种解决方案是使用静态模式规则来告诉 make 每个目标都应被视为此类型:
$(MAKECMDGOALS): % : %.txt
%.txt:
touch $@
MAKECMDGOALS
变量包含您在命令行上提供的任何目标。