在Makefile中,是否可以通过特定目标的变量来覆盖全局变量?

3

考虑下面的makefile:

# various settings, lots of them
# (supposed to be in defaults.mk)
option1="glob_val1"
option2="glob_val2"
#option3="glob_val3" # uncomment and it will override target-specific in sub-make
option4="glob_val4"

# goal is to make many items with various options
# which share common setup, but change in details.
all: item1 item2

# Item 1 is common + changed option3
item1: export option3="i1_val3"
item1:
    @echo "start item1:option3=$(option3)"
    $(MAKE) generic_item
    @echo "done item1"

# Item 2 is common + another option3
item2: export option3="i2_val3"
item2:
    @echo "start item2: option3=$(option3)"
    $(MAKE) generic_item
    @echo "done item2"

# This is generic item that does everything
# basing on options settings
generic_item:
    @echo "do generic option3=$(option3) [expecting i<X>_val3 here]"

我希望的是覆盖目标中的任何选项,然后调用“generic_item”中的通用例程。
问题在于,如果在Makefile顶部定义了option3,则它将不会被改变地传递到子级make。如果在顶部注释掉option3,则一切都按预期工作:
start item1:option3=i1_val3
make generic_item
make[1]: Entering directory `/tmp/make_items'
do generic option3=i1_val3 [expecting i<X>_val3 here]
make[1]: Leaving directory `/tmp/make_items'
done item1
start item2: option3=i2_val3
make generic_item
make[1]: Entering directory `/tmp/make_items'
do generic option3=i2_val3 [expecting i<X>_val3 here]
make[1]: Leaving directory `/tmp/make_items'
done item2

我不想使用 $(MAKE) option1=... option2=... generic_item 语法,因为它看起来不太好,而且可能会有很多选项和长值,所有这些都会进入日志,看起来不太好。
目标是拥有一个通用的目标,根据选项(有很多)的值执行操作,并能够通过其他目标扩展它,这些目标只需要覆盖特定的值/添加新的操作即可,其余部分留给通用目标。
如果我的方法不正确,请提供另一种方法。
1个回答

2

主要修复是在子Makefile中添加-e

我建议进行一些增强。GNU Make手册对这种高级脚本编写非常有用。

请注意,使用下面展示的方法几乎不需要子Makefile。我只在以下情况下使用子Makefile:

  • 由于更改了包含文件而需要重新加载主Makefile(我认为这是设计上的问题,尽量避免)
  • 我想将工作分配到子Makefile中

为了方便起见,我坚持使用您的子Makefile方法来向您展示它是可行的:

export option="glob_val"

.SECONDEXPANSION: # http://www.gnu.org/s/hello/manual/make/Secondary-Expansion.html

TARGETS=item1 item2 item3 item4 item5

all: $(TARGETS)

$(TARGETS): option="$(@)_val"
$(TARGETS):
    @echo "start $@:option=$(option)"
    $(MAKE) -e generic_item
    @echo "done $@"

generic_item:
    @echo "do generic option=$(option)"

make -s 的输出结果

start item1:option=item1_val
start item2:option=item2_val
start item3:option=item3_val
start item4:option=item4_val
start item5:option=item5_val
do generic option=item1_val
do generic option=item2_val
done item1
do generic option=item4_val
done item2
do generic option=item3_val
done item4
do generic option=item5_val
done item5
done item3

谢谢!-e 是缺失的部分。 - VLH
@VLH:感谢您的接受并欢迎来到StackOverflow!非常感谢您的反馈。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接