覆盖父 makefile 中子 make 分配的变量

发布于 2024-09-06 10:38:58 字数 1210 浏览 3 评论 0原文

我正在使用 Make,并且有一个 makefile,它设置了一个变量,该变量的值需要我从父 makefile 覆盖。我尝试在父 makefile 中设置变量并使用 export 将其传递给子 make,但该变量没有使用传递下来的值,而是使用在子 makefile 中显式设置的值生成文件。

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

更新

我应该提到我无法修改 submake 文件,因为它来自我们跟踪的外部存储库,并且我无权修改它,因此我需要处理父 makefile影响子品牌的水平。

示例

这是父 makefile 中调用子 make 的代表性目标:

$.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

I'm using Make and I have a makefile which sets a variable with a value that I need to override from a parent makefile. I've tried setting the variable in the parent makefile and using export to pass it to the submake but the variable is not using the passed down value, instead it is using the value explicitly set in the sub-Makefile.

I know that variables specified on the command line override any ordinary assignments in the makefile (unless override is used) but is there a way to achieve this for submakes without having to specify it on the command line for each invocation of the submake (because there are quite a few and I like to stay DRY)?

UPDATE

I should have mentioned that I can't modify the submake file because it's from an external repository that we track and I don't have the authority to modify it so I need to work at the parent makefile level to influence the submake.

EXAMPLE

Here's a representative target in the parent makefile that's calling the submake:

$.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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我不吻晚风 2024-09-13 10:38:58

(你似乎使用的是 GNUMake 以外的东西,这是我所知道的唯一 Make,所以对此持保留态度。)

首先,你可以通过使组件单独的目标来使你的 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

如果您想为某些目标覆盖几个变量,那就有点棘手了......

(You appear to be using something other than GNUMake, which is the only Make I know, so take this with a grain of salt.)

First you can make your Makefile tidier by making the components separate targets:

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) $@

(If you're worried about name collisions, there are simple ways to deal with that.)

Now if you want to override a variable called, say, VAR, you can do it all in one place:

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) $@

This assumes that you want to override the same variable for all components, which is how I read the question. If you want to override a different variable for some targets, that's easy:

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

If you want to override several variables for some targets, that's a little tricky...

人生戏 2024-09-13 10:38:58

如果您不希望子 makefile 覆盖父 makefile 设置的值,请​​让子 makefile 使用 VARIABLE ?= value 语法分配值。仅当变量尚未定义时才会执行赋值。在您的情况下,该变量将在父 makefile 中定义,因此不会发生赋值。

更新:
如果你不能修改子makefile,那么你就没有很多选择。我可能会建议在调用子 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 中完成。

If you don't want your sub-makefile to override the value set by the parent, have the sub-makefile assign the value using the VARIABLE ?= value syntax. This will only perform the assignment if the variable has yet been defined. In your case, the variable will have been defined in the parent makefile so the assignment will not take place.

Update:
If you can't modify the sub-makefile, then you don't have a lot of options. I would probably recommend setting the variable on the command line when you invoke the sub-make file. Wrap these definitions in a make variable for the sake of clarity. For example,

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

It's not the prettiest solution, but it can be done from the parent makefile.

我家小可爱 2024-09-13 10:38:58

除了并不总是推荐使用 Export 之外,您还可以像这样将变量传递给子 make 文件 --

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

all:

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

因此,如果您的子 make 文件有 2 个文件,每个文件都需要不同的编译工具链,您可以执行上面显示的操作。

Apart from using Export which is not always recommended, you can pass variables to sub-make files like this --

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

all:

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

so if your sub-make file has 2 files each requires different compile toolchain you can do what is shown above.

情魔剑神 2024-09-13 10:38:58

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

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 变量,或者明确导出您想要的变量使用。

Section 5.7.2 of make.info (gnu make that is):

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 ...

So, my recommendation is to either use the MAKEFLAGS variable, or else explicitly export the variable you want to use.

请远离我 2024-09-13 10:38:58

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

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

如果您希望仅在尚未设置变量时将其设置为值,则可以使用简写运算符 ?=' 而不是='。变量“FOO”的这两个设置是相同的(参见起源函数):

 FOO ?= bar

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

You would need to check to see if the variable already has a value before assigning it in the sub-make.

From the GNU Make manual (http://www.gnu.org/software/make/manual/make.html) Section 6.5:

If you'd like a variable to be set to a value only if it's not already set, then you can use the shorthand operator ?=' instead of='. These two settings of the variable `FOO' are identical (see The origin Function):

 FOO ?= bar

and

 ifeq ($(origin FOO), undefined)
 FOO = bar
 endif
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文