在 makefile 中指定组合目标

Specifiy a combined target in a makefile

使用 GNU Make,如何确保在最终任务运行之前建立其他目标依赖项?

(我知道这有点滥用make,但是可以吗?)

假设我有 2 个目标 a 和 b。仅构建 a 或仅构建 b 很容易,但如果同时针对 a 和 b,我想触发一种特殊类型的构建。

例如我的Makefile(由一个真实问题简化而来)

a_prereq:
    @echo "making a"

b_prereq:
    @echo "making b"

a: a_prereq default
b: b_prereq default

default:
    @echo "made!"

调用 make a 打印 making a; made!。这是正确的。

调用 make b 打印 making b; made!。这是正确的。

调用 make a b 打印 making a; made!; making b。不是我想要的!

如果我只能更改 makefile 而不能更改调用 make a b.

,我如何让 make a b 打印 making a; making b; made!;

(我知道我可以引入 c: a_prereq b_prereq default 并调用 make c 但是如果没有新目标可以完成吗?)

这看起来像一个 XY 问题。您显然想要的(不是 100% 确定)是强制 defaulta_prereqb_prereq 之后构建,当且仅当 ab 目标在命令行上传递。这很奇怪,并不是 make 的真正用途,但让我们试一试。

强制 defaulta_prereqb_prereq 之后构建,即使使用并行 make,也很简单:将它们声明为 default 的先决条件(事实上,我这样做不知道另一种方法):

default: a_prereq b_prereq
    @echo "made!"

或者,如果您希望将先决条件声明与配方声明分开:

default: a_prereq b_prereq

default:
    @echo "made!"

但正如您所希望的那样,仅当 ab 目标在命令行上传递时,我们才需要检测这种情况。幸运的是 MAKECMDGOALS GNU make 变量列出了在命令行上指定的目标。所以一点 filter 应用到它应该成功。

当且仅当 ab 目标在命令行上传递时,我们可以将 make 变量 MATCH 设置为字符串 ab。我们可以使用 make 条件语句 (ifeq) 声明 a_prereqb_prereq 作为 default 的先决条件当且仅当 $(MATCH) 等于 ab。只需将以下 4 行添加到您的 Makefile 中:

MATCH := $(filter a,$(MAKECMDGOALS))$(filter b,$(MAKECMDGOALS))
ifeq ($(MATCH),ab)
default: a_prereq b_prereq
endif

注意:如果真正的 default 配方使用作为先决条件扩展的自动变量($<$^、...),您必须记住它们的值make amake a b...

不同

注意:如果目标 ab 必须重建但未作为目标传递到命令行,则此操作将无效。例如,如果 ab 是另一个请求目标的先决条件。这是您要求的内容看起来很奇怪的主要原因之一。

注意:如果您还需要在 a_prereq 之后构建 default 当 运行 宁 make a(与 b 相同)时,一个更简单的解决方案是是:

default: $(patsubst %,%_prereq,$(filter a b,$(MAKECMDGOALS)))

这样,如果您 运行 make aa_prereq 被声明为 default 的先决条件,如果您 运行 make bb_prereq 被声明为 default 的先决条件,你 运行 make a b a_prereqb_prereq 都被声明为 default 的先决条件,如果你 运行 make foodefault 根本没有先决条件。