为什么GNU Make中无配方的规则会尝试编译不存在的对象文件?
原因拆解
- 你定义的
test.%模式规则会匹配所有前缀为test.的目标,所以test的显式依赖test.dummyextension首先命中该规则,执行echo $*输出dummyextension,这部分符合你的预期。 - 核心问题出在你写的
test规则没有显式指定配方:当一个目标没有显式配方时,make会自动检索内置隐式规则,尝试推导该目标的生成方式。 - make默认内置了生成可执行文件的隐式规则
%: %.o,支持将同名.o目标文件链接为可执行文件。test作为无后缀的目标名命中了这条规则,make会自动为test追加test.o作为隐式依赖。 - 追加的
test.o同样匹配你定义的test.%模式规则,因此执行echo $*输出了o。 - 你的模式规则仅执行echo,不会真实生成
test.dummyextension和test.o文件,接下来make执行隐式规则的链接命令时,找不到这两个输入文件,就抛出了你看到的clang错误。
为什么加;或者配方就能正常工作?
只要你给test规则显式指定了配方(哪怕是;代表的空配方),make就会认为该目标的生成逻辑已经被明确定义,不会再去检索匹配任何隐式规则,也就不会额外生成test.o依赖、执行链接逻辑,仅会处理test的显式依赖test.dummyextension,执行完echo就结束,符合你的预期。
补充说明
你之前查make -p时找错了规则,你要找的不是%: %,而是内置的%: %.o链接规则,这条是默认开启的。如果不想关闭所有隐式规则,也可以在Makefile开头加.PHONY: test test.dummyextension test.o标记这些为伪目标,避免make认为它们是需要生成的真实文件。
内容的提问来源于stack exchange,提问作者Monty Evans
相关产品推荐
相关产品推荐

