Makefile结合terminal pattern rule与static pattern rule实现按需安装卸载
实现方案
现有install规则说明
你当前编写的install静态模式规则已经满足第一个要求:只有源文件比目标文件新时才会执行安装逻辑,无需修改。
符合要求的uninstall实现
方案1:优先推荐(匹配你要的静态模式规则需求)
通过wildcard函数预先过滤存在的文件,仅为真实存在的系统文件生成卸载目标,完全避免不存在文件的卸载逻辑执行:
SRC_FILES = ... sys_files = ... # 原有install规则保留 $(sys_files): $(DESTDIR)$(systemdir)/%: $(SRCDIR)/% @echo ' INSTALL $@' $(INSTALL_DATA) -T '$(SRCDIR)/$*' '$@' # ---------- 修正后的uninstall逻辑 ---------- # 过滤出当前实际存在的系统文件 existing_sys_files := $(wildcard $(sys_files)) # 仅为存在的文件生成卸载目标 uninstall_existing_sys_files = $(addprefix uninstall-,$(existing_sys_files)) # 静态模式规则,仅匹配存在的文件的卸载目标 $(uninstall_existing_sys_files): uninstall-%: % @echo ' RM $*' $(RM) '$*' # 总伪目标定义 .PHONY: install uninstall install: $(sys_files) uninstall: $(uninstall_existing_sys_files)
原理说明
wildcard函数在Make解析阶段就会扫描磁盘,筛选出sys_files列表中真实存在的文件,不存在的文件不会被加入卸载依赖链,自然不会触发对应的日志打印和删除操作,也不会出现规则找不到的报错,不会中断构建流程。
方案2:Shell条件判断(兼容性最优)
如果不需要严格使用静态模式规则实现,在规则内加shell存在性判断是最通用的写法:
uninstall_sys_files = $(addprefix uninstall-,$(sys_files)) $(uninstall_sys_files): uninstall-%: @if [ -f '$*' ]; then \ echo ' RM $*'; \ $(RM) '$*'; \ fi .PHONY: uninstall uninstall: $(uninstall_sys_files)
原尝试方案问题说明
你之前写的双冒号静态模式规则没有达到预期,是因为双冒号规则的作用是允许同一目标匹配多条独立规则,和依赖存在性判断无关。添加%作为依赖后,如果对应文件不存在,Make会尝试查找规则生成该文件,找不到就直接报错,反而会中断构建流程。
内容的提问来源于stack exchange,提问作者alx - recommends codidact
相关产品推荐
相关产品推荐

