特定于目标的变量作为 Makefile 中的先决条件

Posted

技术标签:

【中文标题】特定于目标的变量作为 Makefile 中的先决条件【英文标题】:Target-specific Variables as Prerequisites in a Makefile 【发布时间】:2010-11-23 07:51:54 【问题描述】:

我正在尝试编写一个 GNU make Makefile,它有很多类似的目标,其中构建命令在它们之间略有不同。 我正在尝试使用target-specific variables 来表示这些变化。其中一些变量值引用了我想用作先决条件的文件。例如:

target_1:special_filename=target1_prereq
target_2:special_filename=target2_prereq

target_1 target_2: common_filename $(special_filename)
    do_something common_filename --a-weird-option=$(special_filename)

当我调用“make target_1”时,如果它不存在,我希望它生成 target1_prereq。目前,它似乎没有使用 target1_prereq 作为先决条件,即使使用正确的参数调用构建命令 (do_something)。

我正在使用 GNU Make 3.80。


编辑: 来自真实系统的更多复杂情况。一些变量本身是基于其他变量的值。手动指定先决条件不会扩展。 一个稍微复杂一点的例子:

target_1:special_filename_base=target1_prereq
target_2:special_filename_base=target2_prereq

some_filename_a = $(special_filename_base).exta
some_filename_b = $(special_filename_base).extb

target_1 target_2: common_filename $(special_filename_b) $(special_filename_a)
    do_something common_filename --a-weird-option=$(special_filename_a) --second=$(special_filename_b)

【问题讨论】:

【参考方案1】:

特定于目标的变量仅在目标的命令中定义(或在其他特定于目标的分配中);它不能用作目标的先决条件之一。我认为在 Make 中没有一种干净的方式来做你想做的事,但有几种笨拙的方法,例如:

扩展 = .exta .extb target_1: $(添加前缀 target1_prereq,$(EXTENSIONS)) target_2: $(addprefix target2_prereq,$(EXTENSIONS)) target_1 target_2:common_filename do_something common_filename --a-weird-option=$(filter %.extb,$^) --second=$(filter %.extb,$^)

【讨论】:

为了其他偶然发现它的人的利益,复活这个线程。 more elegant solution 使用二次扩展。 @Seth,我同意:target_1 target_2: common_filename $$(special_filename_base).exta $$(special_filename_base).extb ...【参考方案2】:

作为一个简单的解决方法:

target_1:special_filename=target1_prereq target_1:target1_prereq target_2:special_filename=target2_prereq target_2:target2_prereq target_1 target_2: common_filename $(special_filename) do_something common_filename --a-weird-option=$(special_filename)

有一些冗余,但它是本地化的,所以还不错。

【讨论】:

我想这解决了我发布的具体案例,但我希望有一个更通用的解决方案。我将使用更复杂的示例进行编辑。【参考方案3】:

我找到了一种相当干净的方法来避开这个限制。它会是这样的:

target_1:export special_filename_base=target1_prereq
target_2:export special_filename_base=target2_prereq

some_filename_a = $(special_filename_base).exta
some_filename_b = $(special_filename_base).extb

target_1 target_2:
    $(MAKE) -f $(firstword $(MAKEFILE_LIST)) target-proxy

target-proxy: common_filename $(special_filename_b) $(special_filename_a)
    do_something common_filename --a-weird-option=$(special_filename_a) --second=$(special_filename_b)

两个重点:

    export 目标变量,以便我们重新运行 Makefile 时可以访问它们。 创建一个代理目标,它具有target_1 target_2 的所有原始先决条件,并在target_1 target_2 中使用此代理目标再次调用 Makefile。由于到那时目标特定变量将具有值(那时我们在配方中)并且它们是exported,它们将在@987654326中可用@ - 瞧 :)

这种方法的缺点是我们正在创建另一个make 进程 - 如果它只是另一个,那么它可能没问题,但是 YMMV 所以要格外小心。

【讨论】:

确实看起来递归使用 make 是一种选择。通过这样做,可以将先决条件声明为***,并避免构建先决条件列表的斗争。感谢您的回答。

以上是关于特定于目标的变量作为 Makefile 中的先决条件的主要内容,如果未能解决你的问题,请参考以下文章

特定于目标的变量是有条件地设置变量的合适工具吗?

Makefile:获取目标先决条件的先决条件

makefile:隐式规则:相同的目标不同的先决条件

管理两个特定于设备的应用程序

如何确保将 Makefile 变量设置为先决条件?

如何使用特定于应用程序的值覆盖共享库中的 sass 变量