非递归 make:在循环中包含 makefile 段
Non-recursive make: include makefile segment in a loop
我有一个非递归 makefile,它定义了可用于构建库等的辅助函数
define make-library
# build lib from *.cpp in current dir...
endef
每个 library/binary 都在一个名为 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))
但是,这会更新 global CPPFLAGS
,因此每个模块都会获得更新的标志。
解决方案:
我的想法是迭代 $(modules)
,并在包含每个之前,将 CPPFLAGS
重置为默认集。当前模块中的任何更改都将在下一个模块中重置。
大致如下:
$(foreach module,$(modules),$(eval \
CPPFLAGS := DEFAULT_CPPFLAGS \
include $module))
问题:
以上语法不正确,但应该能说明我正在努力实现的目标 - 关于如何最好地完成我所描述的事情的任何想法?
选择:
或者,也许每个 module.mk
可以定义一个可以传递给 make-library
调用的 LOCAL_FLAGS
变量?
LOCAL_FLAGS := -Wno-unused-but-set-variable
$(eval $(call make-library, my_lib, $(LOCAL_FLAGS)))
如果在配方时使用它们,则不能有每个 makefile 变量。食谱最终执行 assignments/etc。已完成。
如果您使用文件局部变量或在解析时强制扩展全局变量,您可以这样做。
您可以保存、设置、使用和重置每个 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)
但这里重要的是变量在解析时是 expanded/used。它们不能在配方时使用,除非它们保存在其他变量中(如上面示例中的特定于目标的变量)。
在我的 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))
我有一个非递归 makefile,它定义了可用于构建库等的辅助函数
define make-library
# build lib from *.cpp in current dir...
endef
每个 library/binary 都在一个名为 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))
但是,这会更新 global CPPFLAGS
,因此每个模块都会获得更新的标志。
解决方案:
我的想法是迭代 $(modules)
,并在包含每个之前,将 CPPFLAGS
重置为默认集。当前模块中的任何更改都将在下一个模块中重置。
大致如下:
$(foreach module,$(modules),$(eval \
CPPFLAGS := DEFAULT_CPPFLAGS \
include $module))
问题:
以上语法不正确,但应该能说明我正在努力实现的目标 - 关于如何最好地完成我所描述的事情的任何想法?
选择:
或者,也许每个 module.mk
可以定义一个可以传递给 make-library
调用的 LOCAL_FLAGS
变量?
LOCAL_FLAGS := -Wno-unused-but-set-variable
$(eval $(call make-library, my_lib, $(LOCAL_FLAGS)))
如果在配方时使用它们,则不能有每个 makefile 变量。食谱最终执行 assignments/etc。已完成。
如果您使用文件局部变量或在解析时强制扩展全局变量,您可以这样做。
您可以保存、设置、使用和重置每个 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)
但这里重要的是变量在解析时是 expanded/used。它们不能在配方时使用,除非它们保存在其他变量中(如上面示例中的特定于目标的变量)。
在我的 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))