【问题标题】:searchpath for prereqisites, like vpath, but only for some pattern rules先决条件的搜索路径,如 vpath,但仅适用于某些模式规则
【发布时间】: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.cy/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 以避免内置规则)。

标签: makefile gnu-make


【解决方案1】:

首先,使用 VPATH 或 vpath 查找派生文件(由 make 构建的文件)是不正确的......其中包括“生成的源文件”(如果它们是由 make 生成的,而不是在 make 之前生成的)以某种方式调用)。 VPATH/vpath 只能用于查找源文件(不是 make 构建的文件)。请参阅How not to use VPATH 了解更多信息。

其次,vpath 是一个全局设置,而不是针对每个目标的设置。每当 make 想要找到一个先决条件并且该先决条件“正常”不存在时,make 将使用 vpath 设置来找到它。 vpath 中没有工具可以说“为此目标使用这些 vpath 设置,为该目标使用这些设置”。在理想情况下,您可以将 VPATH 设置为特定于目标的变量,但这不起作用。

有多种方法可以根据目标生成先决条件:您可能会发现 metaprogramming in make 上的一些建议很有帮助。

最后,您给出的关于$^ 的makefile 示例不正确:

# the following rule is ignored:
build/%.o: y/%.c
# because there is a matching pattern rule with a recipe:
build/%.o:
        @echo \"$@\" from \"$^\"
        @touch $@

您不能在没有任何配方的情况下指定模式规则,并让它“添加”先决条件模式到一些其他现有模式规则。它适用于显式规则,为目标添加更多先决条件,但指定没有配方的模式规则只需 deletes the pattern rule

因此,$^ 对于 build/y.o 是空的,因为模式规则中没有定义任何先决条件,并且您没有像为 build/x.o 所做的那样为 build/y.o 定义任何明确的先决条件。

ETA:对元编程的引用是为了建议您可以使用它来创建您的第二个选项,这是我将使用的选项,更少输入和更易于维护。选择您喜欢的方法并自动生成各种模式规则。这可以称为“第五种选择”。

除了你建议的四个中的任何一个都可以,而且我知道你没有其他选择。

【讨论】:

  • 生成的文件:这就是我不想要递归制作的原因。这些我不需要 VPATH。
  • 你不能指定一个没有任何配方的模式规则,并让它“添加”先决条件模式到其他一些现有的模式规则:是的,我也意识到这一点,在我尝试之后,我试图解释为什么因此,来自 cmets 的一个想法对我不起作用。感谢您的背景说明。
  • 元编程:有趣的页面,谢谢。但是还没有找到我的问题的答案。
猜你喜欢
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多