我有一堆shell脚本和Makefile,它们以各种有趣的方式相互调用。对于整个项目,有一件事要构建,一些(不是全部)脚本和Makefile目标需要构建这件事。脚本或Makefile目标都不会改变正在构建的东西的任何内容,所以我希望每个shell脚本/Makefile调用只构建一次。在调用子shell脚本/Makefiles之前,我通过在构建东西时设置环境变量DO_NOT_BUILD来部分实现这一点。所以,我想在需要构建的时候构建这个东西,而DO_NOT_BUILD没有设置,然后让所有的孩子都知道不要重建,所以在构建之后应该设置DO_NOT_BUILD。这在shell脚本中很容易做到,但我发现用Makefiles很难做到。这是我的玩具Makefile:
PARENT_DO_NOT_BUILD := $(DO_NOT_BUILD)
export DO_NOT_BUILD
.PHONY: build
build: DO_NOT_BUILD := true
build:
if [ -z "$(PARENT_DO_NOT_BUILD)" ]; then echo "Building now"; fi
.PHONY: do_thing_with_build
do_thing_with_build: build
echo "DO_NOT_BUILD=$${DO_NOT_BUILD}"
.PHONY: do_thing_without_build
do_thing_without_build:
echo "DO_NOT_BUILD=$${DO_NOT_BUILD}"
我想要的行为是(省略回显命令):
$ make do_thing_without_build
DO_NOT_BUILD=
$ make do_thing_with_build
Building now
DO_NOT_BUILD=true
$ export DO_NOT_BUILD=true && make do_thing_without_build
DO_NOT_BUILD=true
$ export DO_NOT_BUILD=true && make do_thing_with_build
DO_NOT_BUILD=true
相反,make do_thing_with_build
有一个空的$DO_NOT_BUILD
环境变量,因为设置DO_NOT_BUILD := true
只适用于build
目标,而不是do_thing_with_build
目标。
如果build
目标被调用,我如何在将更新的环境变量呈现给子操作时,根据呈现的环境变量来调节在该目标中执行的操作?或者,当调用build
目标时,如何更新DO_NOT_BUILD?或者说,我如何才能产生我想要的行为?
1条答案
按热度按时间k4emjkb11#
我有一堆shell脚本和Makefile,它们以各种有趣的方式相互调用。[...]
听起来很恐怖。
make
不要被误认为是脚本工具。人们通过尝试以这种方式使用它来为自己制造各种麻烦,而最大的陷阱是,如果你足够努力地破解它,那么你通常可以让它工作。结果通常表现出非平凡的肮脏程度。如果只有一个工件要构建,那么就不需要多个makefile。此外,如果一个工件有适当的先决条件声明,那么
make
自然会处理您的一次构建问题。make
当工件相对于其先决条件已经是最新的时候再次执行工件将不会导致其配方被执行。如果系统中的各种脚本要求它是最新的,那么它们可以每个make the_thing
,并且确信只有在它过时时才会构建它。至于你的具体问题,我不明白为什么你的特定示例代表了你想要做的事情,但是你可以实现你指定的结果的一种方法是简单地移动目标特定变量的定义:
我在此重申我对这个问题的看法:
make
的shell中DO_NOT_BUILD
的值。