递归传递规则

Passing rules to make recursively

这样做可能很简单,但我不知道怎么做。

我希望有一个父 Makefile 来决定根据命令行中传递的变量值递归调用哪个 Makefile。

即,我希望能够调用我的主 Makefile:

make some_rule TARGET=a

make some_rule TARGET=b

并让我的主 Makefile 根据 TARGET 的值决定调用哪个 makefile 来 运行 make some_rule。 (例如决定是调用sub_directory_a/Makefile还是sub_directory_b/Makefile来执行规则some_rule。)

注意:我有很多不同的规则,所以我不希望我的主 Makefile 列出所有可能的规则,并为每个规则递归调用正确的 Makefile。我希望我的主 Makefile 可以只有几行,并且在我创建新规则时不必更新。

你可以按照你描述的去做

default_target:

%:
    $(MAKE) -C some_directory_$(TARGET) $@

%:规则是模式匹配所有规则的模式规则(GNU make手册称为match-anything规则); $@ 是当前目标。请注意 default_target: 规则没有配方,因此在没有目标的情况下调用 make 将使用 match-anything 规则的配方(唯一适用并具有配方的规则)来尝试构建 default_target.

这种方法的警告是不能将目标声明为假的。如果你想要假目标,你必须再次指定这些目标的配方,例如

PHONY_TARGETS = all clean distclean

.PHONY: $(PHONY_TARGETS)

$(PHONY_TARGETS):
    $(MAKE) -C some_directory_$(TARGET) $@

%:
    $(MAKE) -C some_directory_$(TARGET) $@

不幸的是,我不知道有什么技巧可以声明所有虚假目标,而这正是您真正想要做的。

请注意,如果您希望 TARGET 的值比部分目录名称更奇特,例如

%:
ifeq ($(TARGET),gibson)
    echo 'Planet $@ was successfully hacked.'
else
    $(MAKE) -C some_directory_$(TARGET) $@
endif

另请注意,为许多 Makefile 设置公共变量的更常见方法是将它们放入一个文件中,通常 common.mkinclude 来自其他 Makefile 的文件:

include ../common.mk    # to include common.mk from some_directory_a/Makefile

但是您必须自己决定哪种方法更适合您的项目。