【发布时间】:2015-01-09 09:20:55
【问题描述】:
我正在尝试在一个 make 实例中构建多个可执行文件,正如建议的那样
Recursive Make Considered Harmful。
那篇论文的论点适用于我的项目,因为我的一些源文件已生成,并进入多个可执行文件。
每个可执行文件的目标文件都放在不同的目录中,因为它们是使用不同的预处理器标志编译的。
如何为这些可执行文件中的每一个指定单独的 vpath 设置,以便在不同目录中具有重复文件名的源文件进入我希望它们进入的可执行文件?
在规则之前设置vpath 为一个可执行文件构建目标文件,然后将其删除(不提供任何目录)不会产生预期的效果。显然,最后一个设置用于所有规则。
我目前看到的解决方案:
- 重命名源文件名以使用唯一名称,以便我可以使用全局
vpath设置 - 不要使用
vpath,而是为每个源目录使用单独的规则,源目录采用先决条件模式 (*) - 递归 make,在每个
make实例中使用单独的vpath设置,并以某种方式处理由此产生的问题。 - 使用不同于
make的内容。
有没有更好的解决方案,或者您更喜欢以上哪一种?
(*) 单独规则的解决方案如下:
build/$(PROGRAM)/%.o: %.c
$(COMPILE_RECIPE)
build/$(PROGRAM)/%.o: $($(PROGRAM)_SOURCE_DIR)/%.c
$(COMPILE_RECIPE)
对我当前的项目来说还可以,但如果可执行文件的源路径中有多个不同的目录,它会很快变得丑陋
编辑: 测试 @Etan 的建议,这表明 $^ 为空,前提条件仅出现在模式规则 (y/y.c) 中 - 这仅在给出每个依赖项时才有效直接,至于x/x.c。
.PHONY: all
all: build/x.o build/y.o
build/x.o: x/x.c
# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
@echo \"$@\" from \"$^\"
@touch $@
文件x/x.c、y/y.c和目录build存在。
输出:
"build/x.o" from "x/x.c"
"build/y.o" from ""
用GNU Make 3.82.90测试
【问题讨论】:
-
我认为这里最好的解决方案可能是显式构造先决条件对,将输入映射到输出。但是你不需要每对的配方只是先决条件添加。您只需要一次输出模式的配方。有关此模型的示例(第二个
eval解决方案),请参阅我的答案here。 -
@Etan:使用您的解决方案,其中配方的规则没有先决条件模式,您不能在配方中使用
$^(我试过并得到一个空字符串)。那么如何告诉编译器在哪个目录下找到源文件呢? -
您确定您的规则生成正确吗?因为那应该工作得很好。输出文件的静态模式规则可能更安全一些,但可能不是必需的。见gist.github.com/deryni/10d25d020b2232867bd7
-
@Etan:这仅在直接给出每个依赖项时才有效,请参阅我附加到问题的测试。在这里,使用静态模式规则并没有改善任何东西。
-
很公平。所以每个人都需要
$(COMPILE_RECIPE),哦,好吧。也就是说,假设您将模式规则用于除我没有建议的最终目标之外的任何内容。我建议我的要点中的所有文字对(需要静态模式版本或-r以避免内置规则)。