我正在尝试为具有不同优化级别等的不同软件目录进行编译。为此,我创建了以下 makefile:
OWNER = betsy molly fred
DOG = poodle mutt doberman
COLOUR = brown red yellow
ATTR = big small
LEGS = 0 3
#we want every possible combination to be excercised
OUTPUT_STUFF = $(foreach own,$(OWNER),$(foreach dog,$(DOG),$(foreach col,$(COLOUR),$(foreach attr,$(ATTR),$(foreach legs,$(LEGS),new/$(own)/$(dog)/$(col)/$(attr)/$(legs)/dogInfo.txt)))))
.PHONY: all
all: $(OUTPUT_STUFF)
define PROGRAM_template
own = $(1)
dog = $(2)
col = $(3)
attr = $(4)
legs = $(5)
BUILD_DIR = new/$(own)/$(dog)/$(col)/$(attr)/$(legs)
#for each build directory, we are going to put a file in it containing the build dir. string
$$(BUILD_DIR)/dogInfo.txt:
@echo "$$@"
mkdir $$(BUILD_DIR)
@echo "$$(BUILD_DIR)" > $$(BUILD_DIR)/dogInfo.txt
endef
#call the function many times
$(foreach own,$(OWNER),$(foreach dog,$(DOG),$(foreach col,$(COLOUR),$(foreach attr,$(ATTR),$(foreach legs,$(LEGS),$(eval $(call PROGRAM_template,$(own),$(dog),$(col),$(attr),$(legs))))))))
如您所见,这个简单的测试程序循环遍历所有者、狗等的不同组合。最终目标是创建一个新目录,其中包含所有所有者作为 dirs,其中包含所有狗等。底部是只是一个包含路径的文件。
当我运行它时,输出是:
new/betsy/poodle/brown/big/0/dogInfo.txt
mkdir new/fred/doberman/yellow/small/3
mkdir: cannot create directory `new/fred/doberman/yellow/small/3': No such file or directory
make: *** [new/betsy/poodle/brown/big/0/dogInfo.txt] Error 1
所以,出于某种原因,目标是好的,但看似完全相同的变量是我循环中的最后一个。从根本上说,我不明白发生了什么。
Makefiles 中奇怪的 foreach + 用户定义函数行为似乎可以回答,但我并不完全明白。在我看来,当调用该函数时,它会用一个 $ 填充所有实例,而转义的则变为 $(BUILD_DIR)。然后它将代码“粘贴”到临时文件,并在完成所有调用后评估文件,并正常替换变量。
我想到的一个(丑陋的)解决方案是让 BUILD_DIR 变量每次都不同,如下所示:
B_D_$(1)_$(2)_$(3)_$(4)_$(5) = ~~~