GNU Make伪目标被include时的异常行为及合规实现问询
GNU Make
-include generator 伪目标的行为差异与规范解法 问题背景
假设Makefile内容如下:
generator: some_files some_files: whatever recipe .PHONY: generator
当执行-include generator语句时,当前目录不存在generator文件。根据GNU Make文档:
make will not attempt to remake makefiles which are marked phony.
理论上不应有任何操作,但实际表现存在版本差异:GNU Make 4.3会触发some_files的生成,而部分版本符合文档预期无生成。
行为差异的原因
这是GNU Make版本间的规则匹配逻辑差异导致的:
- 在GNU Make 4.3及部分新版本中,处理
-include generator时,虽然generator是伪目标,但make会先检查是否存在能生成该目标的规则。由于generator依赖some_files,make会尝试执行some_files的规则来满足依赖,哪怕最终不会生成generator文件。 - 旧版本或部分实现中,会严格遵循文档描述,直接跳过伪目标的重建逻辑,不会触发其依赖的规则执行。
文档依据
GNU Make官方文档对这一细节的描述存在边界模糊:
当make尝试重建缺失的包含文件时,会查找对应的生成规则。如果目标被标记为
.PHONY,make不会尝试生成它,但在部分版本中,仍会处理该伪目标的依赖链。
这种版本实现差异并未在文档中完全明确,属于规则执行逻辑的细节区别。
构建初期生成指定文件的规范方法
推荐两种可靠方案:
1. 使用FORCE目标触发前置生成
定义一个特殊的FORCE目标,确保每次构建都执行生成规则:
generator: some_files some_files: FORCE whatever recipe FORCE: # 无依赖无命令,总是被视为过期 -include generator
FORCE目标没有依赖和命令,make会判定它始终过期,从而触发some_files的规则执行,且行为在各版本中一致。
2. 直接在Makefile开头添加前置生成逻辑
如果不需要通过包含文件触发,直接在Makefile最开头加入条件判断和生成命令:
# 检查目标文件是否存在,不存在则执行生成 ifeq ($(wildcard some_files),) $(shell whatever recipe) endif # 后续构建规则 ...
这种方式更直接,完全避免了包含伪目标带来的行为歧义。
内容的提问来源于stack exchange,提问作者fffred
相关产品推荐
相关产品推荐

