将Makefile附加到先前依赖项的变量

将Makefile附加到先前依赖项的变量,makefile,gnu-make,Makefile,Gnu Make,我有一个接受参数列表的命令foo。我想根据我正在构建的目标更改传递给foo的参数。我已经尝试附加到特定于目标的变量,但这并不完全符合我的要求 因此,以这个Makefile为例(因为foo是由target1构建的,所以它不起作用): 发生了什么: > make all foo abc target1 target2 > make target1 foo abc target1 > make target2 foo def target2 我想要的是: > make a

我有一个接受参数列表的命令
foo
。我想根据我正在构建的目标更改传递给
foo
的参数。我已经尝试附加到特定于目标的变量,但这并不完全符合我的要求

因此,以这个Makefile为例(因为foo是由target1构建的,所以它不起作用):

发生了什么:

> make all
foo abc
target1
target2

> make target1
foo abc
target1

> make target2
foo def
target2
我想要的是:

> make all
foo abc def
target1
target2

> make target1
foo abc
target1

> make target2
foo def
target2

Makefile语法可以特定于GNU make。我还希望保持并行性,以便target1和target2可以并行构建。

您的示例缺少许多细节,可能有更好的处理方法(例如,为什么TARGET
是假的?
foo
如何依赖于
target1
?),一个完整的例子可以准确地显示文件是如何生成的,这将为您提供更好的答案

也就是说,在这种情况下,类似于以下内容的内容应该可以工作

.PHONY: all foo target1 target2

all: foo_args += abc def
all: target1 target2

target1: foo_args += abc
target1: foo
    @echo Target1

target2: foo_args += def
target2: foo
    @echo Target2

foo:
    @echo foo $(sort $(foo_args))

生成特定于目标的变量的问题在于,它们仅在该目标的范围内可用。特别是,如果您正在构建一个具有多个依赖项的目标,那么一次只能下一个依赖项,
foo_args
只会在您恰好从中调用的
foo
树的一侧反映目标

另一种解决方案可能是在makefile的顶部使用类似以下内容的内容:

foo_args_target1 := abc
foo_args_target2 := def
foo_args_all := abc def
foo_args := $(sort $(foreach goal,$(MAKECMDGOALS),$(foo_args_$(goal))))
$(info foo_args is $(foo_args))

这样做的好处是
foo_args
可以在全球范围内使用。但这仍然存在可伸缩性问题——如果要创建一个新的目标
all2:target1 target2
,则必须将
foo\u args\u all2:=…
添加到makefile中(您无法自动检测到
all2
依赖于
target1
target2
,并自动更新
foo_args

John答案的可伸缩变体:

define add_target
foo_args_all += $2
foo_args_$(strip $1) := $2
$1: foo; @echo $$@
foo_targets += $1
endef

all:
$(eval $(call add_target, target1, abc))
$(eval $(call add_target, target2, def))

all: $(foo_targets)
foo:; @echo foo $(sort $(foreach g,$(or $(MAKECMDGOALS), all),$(foo_args_$g)))

.PHONY: all $(foo_targets)
输出:

$ make  -f sample.gmk
foo abc def
target1
target2

$ make  -f sample.gmk all
foo abc def
target1
target2

$ make  -f sample.gmk target1
foo abc
target1

$ make  -f sample.gmk target2
foo def
target2

$ make  -f sample.gmk target2 target1
foo abc def
target2
target1

$ make  -f sample.gmk target1 target2
foo abc def
target1
target2

但是,如果你做了
make target1 target2
,它将输出
foo abc
foo def
中的一个。这是我现在拥有的一个更简单的版本,它几乎满足了我的需要。我希望有一个更优雅、更可扩展的解决方案,但如果没有人给出更好的答案,我会在几天内接受这个答案。
$ make  -f sample.gmk
foo abc def
target1
target2

$ make  -f sample.gmk all
foo abc def
target1
target2

$ make  -f sample.gmk target1
foo abc
target1

$ make  -f sample.gmk target2
foo def
target2

$ make  -f sample.gmk target2 target1
foo abc def
target2
target1

$ make  -f sample.gmk target1 target2
foo abc def
target1
target2