非递归make:在循环中包含makefile段

时间:2015-01-12 22:37:35

标签: c++ makefile gnu-make

我有一个非递归的makefile,它定义了可用于构建库等的辅助函数

define make-library
    # build lib from *.cpp in current dir...
endef

每个库/二进制文件都在一个名为module.mk的单独makefile段中定义,该段调用这些辅助函数

$(eval $(call make-library, my_lib))

makefile在源树中搜索makefile段,并包含它们

modules := $(shell find . -name module.mk | xargs echo)
include $(modules)

问题:

我在makefile的顶部定义了一个默认的CPPFLAGS

CPPFLAGS += -m64 -std=c++11 -Wall -Wextra -Werror -Wno-system-headers

根据构建变体等有选择地更新它们:

ifeq "$(BUILD)" "debug"
    CPPFLAGS += $(DEBUG_FLAGS)
endif

它们在需要的每个目标中使用:

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    @$(CXX) $(CPPFLAGS) -I$(BASE_DIR) -I. -o $@ -c $(filter %.cpp,$^)

我遇到的问题是有时候我想覆盖模块中的CPPFLAGS

CPPFLAGS += -Wno-unused-but-set-variable
$(eval $(call make-library, my_lib))

但是,这会更新全局 CPPFLAGS,因此每个模块都会获得更新的标记。

解决方案:

我的想法是迭代$(modules),在包含每一个之前,将CPPFLAGS重置为默认设置。当前模块中的任何更改都将在下一个模块中重置。

有些事情:

$(foreach module,$(modules),$(eval \
    CPPFLAGS := DEFAULT_CPPFLAGS \
    include $module))

问题:

上述语法不正确,但应该有希望说明我想要实现的目标 - 关于如何最好地完成我所描述的内容的任何想法?

替代:

或者,也许每个module.mk都可以定义一个LOCAL_FLAGS变量,该变量可以传递给make-library来电?

LOCAL_FLAGS := -Wno-unused-but-set-variable
$(eval $(call make-library, my_lib, $(LOCAL_FLAGS)))

2 个答案:

答案 0 :(得分:1)

如果在配方时使用per-makefile变量,则不能使用它们。食谱在所有作业/等之后执行。已经完成了。

如果您使用文件局部变量或在分析时强制全局变量扩展,您可以这样做。

您可以保存,设置,使用和重置每个module.mk文件中的值。

$ cat foo/module.mk
oCPPFLAGS:=$(CPPFLAGS)
CPPFLAGS+=something local

target: CPPFLAGS:=$(CPPFLAGS)
target:
        some_cmd $(CPPFLAGS)

FOO:=$(oFOO)

或者,更像是您的原始尝试,您可以在循环期间强制将它们评估为某个默认值。

$ cat Makefile
$(foreach module,$(modules),$(eval CPPFLAGS := DEFAULT_CPPFLAGS)$(eval include $(module)))
$(eval CPPFLAGS := DEFAULT_CPPFLAGS)

$ cat foo/module.mk
target: CPPFLAGS:=$(CPPFLAGS)
target:
        some_cmd $(CPPFLAGS)

但重要的是变量在解析时扩展/使用。它们不能在配方时使用,除非它们保存在其他变量中(如上例中的目标特定变量)。

答案 1 :(得分:0)

在我的 prorab构建系统中,我将参数从this_*变量而不是全局CFLAGS传递给编译器,尽管CFLAGS也传递给编译器。 然后,在我定义构建规则后,我可以清除所有this_*变量,如下所示:

$(foreach var,$(filter this_%,$(.VARIABLES)),$(eval $(var) := ))

我为此创建了一个定义

prorab-clear-this-vars = $(foreach var,$(filter this_%,$(.VARIABLES)),$(eval $(var) := ))

它可以像这样使用

$(eval $(prorab-clear-this-vars))