Makefile伪目标配置疑问:能否用.PHONY: %替代逐个声明所有伪目标?
1. 如何使用通配符将Makefile中的所有目标指定为.PHONY伪目标?
GNU Make(最常用的Make实现)提供了几种实用方式来批量标记目标为伪目标,不过直接用%通配符在.PHONY里并不能直接实现“所有目标”的效果,这里分享两个靠谱的方法:
方法一:用内置变量
$(.TARGETS)自动覆盖所有定义目标
这个变量会自动抓取Makefile里定义的所有目标(包括显式规则和隐式规则的目标),只需要加一行:.PHONY: $(.TARGETS)这是最简洁精准的方式,不过要注意这是GNU Make的特有特性,非POSIX标准Make不支持。
方法二:针对当前执行的目标(
$(MAKECMDGOALS))
如果你只想把用户当前运行命令指定的目标标记为伪目标,可以用:.PHONY: $(MAKECMDGOALS)比如用户输入
make clean test,clean和test都会被强制标记为伪目标,适合临时处理当前命令的场景。
2. 若Makefile中所有目标均非真实文件,仅声明.PHONY: %是否有效,还是需要逐个列出所有目标?
直接说结论:.PHONY: %在GNU Make里能生效但不是最优解,更稳妥的是逐个列出或用$(.TARGETS)。
为什么
.PHONY: %能生效?
GNU Make允许.PHONY使用模式规则(也就是%),任何匹配该模式的目标(简单说就是所有目标)都会被视为伪目标——不管对应的文件是否存在。所以如果你的所有目标都不是真实文件,这个声明确实会让Make跳过文件存在性检查,直接执行目标规则。为什么不推荐用它?
这个模式太宽泛了:如果后续你在工作目录里不小心创建了和某个目标同名的文件(比如误建了clean文件),或者新增了需要依赖真实文件的目标,.PHONY: %会不分青红皂白把它们都标记为伪目标,可能导致不必要的重复构建或逻辑混乱。另外,这是GNU Make的扩展写法,不兼容BSD Make等其他实现。更稳妥的选择:
要么逐个列出所有伪目标(适合目标数量不多的场景,清晰易懂),比如:.PHONY: clean test build install要么用前面提到的
$(.TARGETS),自动把所有定义的目标标记为伪目标,兼顾简洁性和精准性。
内容的提问来源于stack exchange,提问作者chingis

