覆盖父makefile中的子映射分配变量

时间:2010-06-23 16:16:53

标签: makefile

我正在使用Make,我有一个makefile,它设置一个变量,其值需要从父makefile覆盖。我已尝试在父makefile中设置变量并使用export将其传递给子制表但变量未使用传递的值,而是使用在子Makefile中显式设置的值。 / p>

我知道命令行中指定的变量会覆盖makefile中的任何普通赋值(除非使用override)但是有一种方法可以实现这一点,而不必在命令行中为每个子目录指定它调用submake(因为有很多,我喜欢保持DRY)?

更新

我应该提到我不能修改submake文件,因为它来自我们跟踪的外部存储库,我没有权限修改它所以我需要在父makefile级别工作来影响submake

示例

这是调用子制作的父makefile中的代表目标:

$.PHONY (external_lib)
$(external_lib): 
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_a
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_b
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_c
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_d
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_e
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_f
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_g
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_h
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) make_i
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) library

5 个答案:

答案 0 :(得分:5)

(你似乎正在使用GNUMake以外的东西,这是我所知道的唯一的东西,所以请带上一粒盐。)

首先,您可以通过使组件分离目标来使Makefile更整洁:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) $@

(如果您担心名称冲突,可以采用简单的方法来处理。)

现在,如果你想覆盖一个名为VAR的变量,你可以在一个地方完成所有这些:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) VAR=$(VAR) $@

这假设您要为所有组件覆盖相同的变量,这就是我阅读问题的方式。如果您想为某些目标覆盖不同的变量,那很容易:

COMPONENTS =  make_a make_b make_c make_d make_e make_f make_g make_h make_i \
        library

.PHONY: external_lib $(COMPONENTS)
$(external_lib): $(COMPONENTS)

VARNAME = VAR
$(COMPONENTS):
    @$(MAKE) -s -C $(source_dir)/project/component $(PROJECTVARS) \
$(VARNAME)=$($(VARNAME)) $@

make_c: VARNAME=OtherVar
make_h: VARNAME=YetAnotherVar

如果你想覆盖某些目标的几个变量,这有点棘手......

答案 1 :(得分:1)

如果您不希望子makefile覆盖父级设置的值,请​​让sub-makefile使用VARIABLE ?= value语法分配值。这只会在尚未定义变量的情况下执行赋值。在您的情况下,变量将在父makefile中定义,因此不会进行赋值。

<强>更新 如果你不能修改子makefile,那么你没有很多选项。我建议您在调用sub-make文件时在命令行上设置变量。为清楚起见,将这些定义包装在make变量中。例如,

CUSTOM_DEFINITIONS := VAR1=value1 VAR2=value2 VAR3=value3
$(external_lib): 
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_a
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_b
    $(MAKE) -C $(source_dir)/project/component $(PROJECTVARS) $(CUSTOM_DEFINITIONS) make_c

这不是最漂亮的解决方案,但可以从父makefile完成。

答案 2 :(得分:1)

除了使用并不总是推荐的导出之外,你可以将变量传递给像这样的子制作文件 -

**HOSTCC = gcc**
CC= MIPS-GCC
FLAGS = -O2 -Wall -DSELECT_PROBLEM
M="CC=$(CC) $(FLAGS)"

所有

cd ../rng ; $(MAKE) $(M) **HOSTCC=$(HOSTCC)** ;

所以如果你的sub-make文件有2个文件,每个文件需要不同的编译工具链,你可以做上面显示的。

答案 3 :(得分:0)

make.info的第5.7.2节(gnu make that):

The special variable `MAKEFLAGS` is always exported. ...

Variables are _not_ normally passed down if they were created by
default by `make` (Implicit Rules)

if you want to export specific variables to sub-`make`, use the
`export` directive.

    export VARIABLE ...

因此,我的建议是使用MAKEFLAGS变量,或者明确export您想要使用的变量。

答案 4 :(得分:0)

在将子变量分配给子变量之前,您需要检查变量是否已经有值。

从GNU Make手册(http://www.gnu.org/software/make/manual/make.html)第6.5节:

如果您希望变量仅在尚未设置的情况下设置为值,则可以使用简写运算符?=' instead of ='。变量“FOO”的这两个设置是相同的(参见原点功能):

 FOO ?= bar

 ifeq ($(origin FOO), undefined)
 FOO = bar
 endif