GNU Makefile生成无重复文件对失效问题排查与修复
问题分析与修改方案
你的Makefile核心问题出在两两组合的生成逻辑错误,导致PAIRS变量最终为空,因此Make认为all目标没有需要执行的依赖,输出Nothing to be done for 'all'。此外,原逻辑试图通过循环中引用未完全生成的PAIRS来过滤重复对,但Make的变量立即展开特性导致这个判断完全失效。
具体修改点
1. 修复无重复两两组合的生成
原代码中$(if $(filter-out $(file2)_$(file1),$(PAIRS)),...)的判断无法工作,因为在:=立即展开的变量赋值中,循环执行时PAIRS还未被赋值(始终为空),所有条件都不成立,最终PAIRS为空。
改用字典序比较的方式生成无重复对:只保留文件名字典序更小的文件在前的组合,彻底避免反向重复。修改后的PAIRS赋值如下:
PAIRS := $(foreach file1,$(FILES),$(foreach file2,$(filter-out $(file1),$(FILES)),$(if $(shell [ "$(file1)" \< "$(file2)" ] && echo 1),$(file1)_$(file2))))
2. 将组合目标标记为PHONY
由于你执行的命令(如ls)不会生成file1_file2这样的实际文件,若不将这些目标标记为PHONY,Make会每次都执行命令(因为目标不存在),但标记后能明确告知Make这些是伪目标,逻辑更清晰。修改.PHONY行:
.PHONY: all $(PAIRS)
修改后的完整Makefile
FOLDER := . FILES := $(wildcard $(FOLDER)/*.txt) # 生成无重复的两两组合:仅保留file1字典序小于file2的对 PAIRS := $(foreach file1,$(FILES),$(foreach file2,$(filter-out $(file1),$(FILES)),$(if $(shell [ "$(file1)" \< "$(file2)" ] && echo 1),$(file1)_$(file2)))) .PHONY: all $(PAIRS) all: $(PAIRS) define execute_command $(1)_$(2): ls "$(1)" "$(2)" endef $(foreach pair,$(PAIRS),$(eval $(call execute_command,$(word 1,$(subst _, ,$(pair))),$(word 2,$(subst _, ,$(pair))))))
效果验证
假设目录下有f1.txt、f2.txt、f3.txt,执行make后会依次执行:
ls "f1.txt" "f2.txt" ls "f1.txt" "f3.txt" ls "f2.txt" "f3.txt"
不会出现反向的f2.txt_f1.txt这类重复组合,且Make不会再提示Nothing to be done。
内容的提问来源于stack exchange,提问作者sunxd
相关产品推荐
相关产品推荐

