如何在GNU Make每次运行开始时无条件创建符号链接
实现方法
要让make每次运行初始阶段无条件创建符号链接,不要用模式规则匹配软链接下的文件,直接用make内置的特殊目标实现前置执行即可,完全不会触发中间文件误删问题。
推荐方案:使用.INIT特殊目标
GNU Make内置的.INIT目标下的命令,会在所有其他目标执行前、依赖解析完成后无条件运行,不需要挂载到任何业务规则的依赖列表中,也不参与文件时间戳判断,完全匹配需求。
配置代码如下:
# 初始化阶段无条件创建/修复软链接 .INIT: @ln -snf ../application/src appsrc
ln命令参数说明:
-s:创建符号链接-n:将已存在的同名软链接视为普通文件,避免出现嵌套链接问题-f:强制覆盖已存在的异常链接,不会因链接已存在报错中断- 命令前的
@用于关闭命令回显,不需要可以删除
原有编译规则可以直接简化,不需要额外挂载appsrc依赖:
obj/%.o : appsrc/%.cpp $(CC) $(CFLAGS) -o ./obj/$(@F) -c $<
兼容方案:显式初始化伪目标
如果使用4.0以下的老旧GNU Make版本(.INIT行为不稳定),可以定义伪目标作为强制前置依赖:
# 声明伪目标,避免和同名文件冲突 .PHONY: init-symlink init-symlink: @ln -snf ../application/src appsrc # 所有依赖源码的目标,将init-symlink放在依赖项最前面 obj/%.o : init-symlink appsrc/%.cpp $(CC) $(CFLAGS) -o ./obj/$(@F) -c $<
原有方案失效原因
- 初始版本将
appsrc作为普通文件目标加入.o文件依赖,由于appsrc目录不存在时appsrc/%.cpp的通配符匹配直接失败,make不会将appsrc加入待执行队列,ln命令不会触发。 - 后续新增的无命令模式规则
appsrc/%: ../application/src/% appsrc,会让make将appsrc路径下的所有.cpp文件判定为可自动生成的中间文件,构建完成后自动清理;由于appsrc是指向源码目录的软链接,清理操作会直接作用于原始源码,造成源文件丢失。
避坑提示
- 禁止编写无构建命令的空模式规则,这类规则会让make误判目标属性,触发非预期的文件清理
- 创建目录软链接时必须加
-n -f参数,避免重复执行时出现链接嵌套、权限报错问题 - 不要将软链接本身作为普通文件目标做时间戳判断:软链接的时间戳为链接自身创建时间,不会随源码目录内容变化,只要链接存在make就不会重新执行,无法满足每次运行校验链接的需求
内容的提问来源于stack exchange,提问作者fpeelo
相关产品推荐
相关产品推荐

