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

发布于 2024-08-02 14:36:16 字数 1093 浏览 4 评论 0原文

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

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(如果它不存在)。目前,即使使用正确的参数调用构建命令(do_something),它似乎也没有使用 target1_prereq 作为先决条件。

我正在使用 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)

I'm trying to write a GNU make Makefile which has a load of similar targets, where the build commands vary slightly between them.
I'm trying to use target-specific variables to represent these variations. Some of these variable values refer to files I want to use as prerequisites. For example:

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)

When I call 'make target_1', I want it to make target1_prereq if it doesn't exist. At the moment, it doesn't seem to use target1_prereq as a prerequisite, even though the build command (do_something) is called with the right parameter.

I'm using GNU Make 3.80.


Edit:
A few more complications from the real system. Some of the variables are themselves based on the values of other variables. Manually specifying the prerequisites wouldn't scale.
A slightly more complicated example:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寄意 2024-08-09 14:36:16

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

EXTENSIONS = .exta .extb
target_1: $(addprefix target1_prereq,$(EXTENSIONS))
target_2: $(addprefix target2_prereq,$(EXTENSIONS))

target_1 target_2: common_filename
    do_something common_filename --a-weird-option=$(filter %.exta,$^) --second=$(filter %.extb,$^)

A target-specific variable is defined only in the target's commands (or in other target-specific assignments); it can't be used as one of the target's prereqs. I don't think there's a clean way to do what you want in Make, but there are several kludgey approaches, such as the following:

EXTENSIONS = .exta .extb
target_1: $(addprefix target1_prereq,$(EXTENSIONS))
target_2: $(addprefix target2_prereq,$(EXTENSIONS))

target_1 target_2: common_filename
    do_something common_filename --a-weird-option=$(filter %.exta,$^) --second=$(filter %.extb,$^)
断肠人 2024-08-09 14:36:16

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

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)

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

As a simple workaround:

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)

There is some redundancy, but it is localized, so it's not too bad.

睫毛溺水了 2024-08-09 14:36:16

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

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)

有两个要点:

  1. 导出目标变量,以便我们重新运行 Makefile 时可以访问它们。
  2. 创建一个具有 target_1 target_2 的所有原始先决条件的代理目标,并在 target_1 target_2 中使用此代理目标再次调用 Makefile。由于目标特定变量届时将具有值(那时我们已在配方中)并且它们已被导出,因此它们将在 target-proxy 中可用 - 瞧:)

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

I've found a rather clean way of side-stepping this limitation. It'd go something like this:

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)

Two important points:

  1. export the target variables, so that they'll be accessible when we re-run the Makefile.
  2. Create a proxy target that has all the original prerequisites of target_1 target_2 and in target_1 target_2 invoke the Makefile again with this proxy target. Since the target specific variables will have values by then (we are in the recipe by that time) and they were exported, they'll be available in target-proxy - voila :)

The downside of this approach is that we are creating another make process - if it's just another one then it's probably ok, but YMMV so be extra careful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文