Make:当二进制为中间目标时,隐式规则链已断开



考虑以下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

如果有一个以上的目标被传给制造,这一点就会分崩离析。

最新更新