重新评估 GNU make makefile 变量
Re-evaluating GNU make makefile variable
我继承了一个大的分支项目?这需要一组可变的 .a 档案 $(LIB_FILES) 包含到 link 目标中,位于某些目录 $(LIB_DIRS) 中。我可以这样写一个表达式:
LIBDEP = $(foreach ldir, $(LIB_DIRS), \
$(filter $(addprefix %/, $(LIB_FILES)), $(wildcard $(ldir)/* )))
问题是它们在调用 make 时可能不存在,并且会通过在另一个目标的规则中调用 $(MAKE) 来构建,这是 link 步骤的先决条件。
问题是应该创建的实际文件列表因构建步骤中确定的外部因素而异,我无法正确地对其进行硬编码,而不会将 makefile 变成一团乱七八糟的东西,并且所说的变量不是 re -在 link 命令调用时评估。
我怀疑 $(eval ) 函数可以以某种方式使用,但手册不是很方便,而且我没有找到以这种方式使用它的示例。
工具链:GCC 和 binutils,make 3.81
有时需要连续多次调用make。一种可能性是使用条件:
ifeq ($(STEP),)
all:
<do-first-step>
$(MAKE) STEP=2 $@
else ifeq ($(STEP),2)
all:
<do-second-step>
$(MAKE) STEP=3 $@
else ifeq ($(STEP),3)
all:
<do-third-step>
endif
在每个步骤中,您都可以生成新文件并在下一步中保留它们。
另一种解决方案是创建 make 脚本对当前创建变量 $(LIB_FILES)
的步骤输出的显式依赖。这就是手册在 How makefiles are remade 章中处理的内容,它针对的是 make 最擅长的技术,即从文件的存在和时间戳(而不是变量)中导出依赖关系。下面希望描述您在推导由两个变量 $(LIBS_THIS_TIME)
和 $(LIB_CONFIG_SET)
模拟的一组新库的过程中的情况。
LIBS_THIS_TIME = foo.a:baz.a:bar.a
LIB_CONFIG_SET = $(subst :,_,$(LIBS_THIS_TIME))
include libdeps.d
linkstep:
@echo I am linking $^ now
touch $@
libdeps.d: $(LIB_CONFIG_SET)
-rm libdeps.d
$(foreach lib,$(subst :, ,$(LIBS_THIS_TIME)),echo linkstep: $(lib) >> libdeps.d;)
$(LIB_CONFIG_SET):
touch $@
如果 make 发现 libdeps.d
不是您当前库配置的最新版本,它会在 make 执行任何其他规则之前重新制作,尽管它不是 makefile 中的第一个目标。这样,如果您的构建过程创建了一组新的或不同的库,libdeps.d
将首先重新制作,然后 make 将继续使用您的顶级 makefile 中的其他目标,现在具有正确的依赖信息。
我继承了一个大的分支项目?这需要一组可变的 .a 档案 $(LIB_FILES) 包含到 link 目标中,位于某些目录 $(LIB_DIRS) 中。我可以这样写一个表达式:
LIBDEP = $(foreach ldir, $(LIB_DIRS), \
$(filter $(addprefix %/, $(LIB_FILES)), $(wildcard $(ldir)/* )))
问题是它们在调用 make 时可能不存在,并且会通过在另一个目标的规则中调用 $(MAKE) 来构建,这是 link 步骤的先决条件。
问题是应该创建的实际文件列表因构建步骤中确定的外部因素而异,我无法正确地对其进行硬编码,而不会将 makefile 变成一团乱七八糟的东西,并且所说的变量不是 re -在 link 命令调用时评估。
我怀疑 $(eval ) 函数可以以某种方式使用,但手册不是很方便,而且我没有找到以这种方式使用它的示例。
工具链:GCC 和 binutils,make 3.81
有时需要连续多次调用make。一种可能性是使用条件:
ifeq ($(STEP),)
all:
<do-first-step>
$(MAKE) STEP=2 $@
else ifeq ($(STEP),2)
all:
<do-second-step>
$(MAKE) STEP=3 $@
else ifeq ($(STEP),3)
all:
<do-third-step>
endif
在每个步骤中,您都可以生成新文件并在下一步中保留它们。
另一种解决方案是创建 make 脚本对当前创建变量 $(LIB_FILES)
的步骤输出的显式依赖。这就是手册在 How makefiles are remade 章中处理的内容,它针对的是 make 最擅长的技术,即从文件的存在和时间戳(而不是变量)中导出依赖关系。下面希望描述您在推导由两个变量 $(LIBS_THIS_TIME)
和 $(LIB_CONFIG_SET)
模拟的一组新库的过程中的情况。
LIBS_THIS_TIME = foo.a:baz.a:bar.a
LIB_CONFIG_SET = $(subst :,_,$(LIBS_THIS_TIME))
include libdeps.d
linkstep:
@echo I am linking $^ now
touch $@
libdeps.d: $(LIB_CONFIG_SET)
-rm libdeps.d
$(foreach lib,$(subst :, ,$(LIBS_THIS_TIME)),echo linkstep: $(lib) >> libdeps.d;)
$(LIB_CONFIG_SET):
touch $@
如果 make 发现 libdeps.d
不是您当前库配置的最新版本,它会在 make 执行任何其他规则之前重新制作,尽管它不是 makefile 中的第一个目标。这样,如果您的构建过程创建了一组新的或不同的库,libdeps.d
将首先重新制作,然后 make 将继续使用您的顶级 makefile 中的其他目标,现在具有正确的依赖信息。