考虑以下Makefile:
%.o.gz: %.o
gzip $<
如果hello.c存在于同一目录中,我可以使用目标hello.o.gz:调用make
$ make hello.o.gz
cc -c -o hello.o hello.c
gzip hello.o
$
我相信这会调用一系列隐含的规则:
- 将.c编译为.o的内置隐式规则
- makefile中给出的对.o文件进行gzip的隐含规则
这工作得很好,正如我所期望的。
现在假设我稍微修改了makefile:
%.gz: %
gzip $<
这里的想法是使用"compile.c to binary"内置的隐式规则,然后对生成的二进制文件进行gzip。我希望能够调用这样的make:
$ make hello.gz
make: *** No rule to make target `hello.gz'. Stop.
$
但它不起作用。
有趣的是,如果我调用make两次,一次构建二进制文件,一次对其进行gzip,它确实有效,所以这似乎与规则链接有关:
$ make hello
cc hello.c -o hello
$ make hello.gz
gzip hello
$
为什么我不能将"compile.c to binary"内置隐式规则放入链中,而可以将"compile.c to.o"隐式规则置于链中?
有没有什么方法可以修改我的隐式gzip规则来实现这一点?
我已经阅读了make文档的"隐式规则链"部分,但据我所见,"compile.c to binary"内置隐式规则没有例外。还是我错过了什么?
我相信你达到了这个目的,因为你使用的是匹配任何规则(也就是说,目标是没有限制的%
的规则)。处理这些规则有很多特殊情况,因为如果没有这些特殊情况,在隐式规则搜索过程中需要检查的规则数量将大很多数量级。
请参阅http://www.gnu.org/software/make/manual/html_node/Match_002dAnything-Rules.html获取有关"匹配任何内容"规则的限制的信息。
到目前为止,我能想到的最好的解决方法是:
ifneq (,$(wildcard $(MAKECMDGOALS:%.gz=%.c)))
$(MAKECMDGOALS): %.gz: %
gzip $<
endif
如果有一个以上的目标被传给制造,这一点就会分崩离析。