--always-make 可以不影响子品牌吗?

Can --always-make not affect a sub-make?

使用 GNU Make 4.1

总结

我正在从 makefile a.mk 调用子 make b.mk。 调用 b.mk 以确保构建子系统。 有时我想强制重新制作 a.mk 的目标:

make -f a.mk <target> --always-make

当我这样做时,b.mk 也认为所有目标都已过时,但我不希望这样。

补救失败

我已经按照手册中的建议尝试使用 make -f b.mk MAKEFLAGS= 5.7.3 Communicating Options to a Sub-make,但没有运气。

这里是 a.mk 的要点:

.PHONY: all
$(info ===> a.mk MAKEFLAGS: $(MAKEFLAGS))
all:
    $(MAKE) -f b.mk y MAKEFLAGS=

b.mk:

$(info ===> b.mk MAKEFLAGS: $(MAKEFLAGS))
y: x
    cp $< $@

现在,即使 b.mk 通常认为 y 是最新的:

$ make -f b.mk y
===> b.mk MAKEFLAGS: 
make: 'y' is up to date.

... ya.mk 被调用 --always-make (-B):

时被重制
$ make -f a.mk --always-make
===> a.mk MAKEFLAGS: B
make -f b.mk y MAKEFLAGS=
make[1]: Entering directory '/home/matt/junk/make-b'
===> b.mk MAKEFLAGS: 
cp x y
make[1]: Leaving directory '/home/matt/junk/make-b'

如您所见,B 标志出现在 a.mk 的 MAKEFLAGS 中,但未出现在 b.mk 的 MAKEFLAGS 中。 然而,yb.mk 重制了。

问题

更新时间:2020-08-05

我(到底)为什么要这样做?

在回答 中,有人请求查看想要强制重制特定目标但又不想强制子制作的示例。

这里不是发明一些东西,而是引出我的问题的实际 makefile 的摘录:

WWW_SVG := score.svg

%Score.app/$(WWW_SVG): %Score.svg | %Score.app/
    cd $(MUSIC_SCORE_PLAYER) && $(MAKE) -f $(MUSIC_SCORE_PLAYER_MAKEFILE) $(MUSIC_SCORE_PLAYER_TGT) MAKEFLAGS=
    cp $< $(MUSIC_SCORE_PLAYER_DIR)$(WWW_SVG)
    node $(MUSIC_SCORE_PLAYER_SVG_CONVERTER) > $@

该规则的目的是从另一个创建一个 SVG。 在 Web 应用程序加载和修改原始 SVG 之后,新的镜像 DOM 的 SVG 部分的状态。

在测试时,我希望能够强制重新制作具有匹配 %FooScore/score.svg 先决条件的目标,但不重建 Web 应用程序,除非 它已经过时了。

当然,我可以移动调用 sub-make 的行,这样它只会被调用一次,而不是为每个匹配规则的目标调用一次。但这是一种优化,而不是解决方案。

“始终构建”的要点是调用构建的所有部分。 而不是 传递给 sub-makes 是没有意义的。事实上,许多 makefile 在顶层 makefile 几乎没有发生任何事情:它们只是调用一组 sub-makes。如果“始终构建”不被传承下去,它就没有什么用了。

不幸的是,您的示例都基于以这种方式工作的事物,而事实并非如此。为了提出解决方案,我们需要看一个更现实的例子。特别是,你说你想强制重新制作一个特定的目标,但在上面的例子中你没有表现出来。重制的目标是什么?它如何与 b.mk 的 sub-make 调用交互?

请注意,您应该永远不要 使用make 来调用sub-makes。你应该总是使用$(MAKE)(或者,等价地,${MAKE})。

这是基于 及其评论。

从原题看a.mk,需要改一行:

.PHONY: all
$(info ===> a.mk MAKEFLAGS: $(MAKEFLAGS))
all:
    MAKEFLAGS=  $(MAKE) -f b.mk y    # This line has changed

它现在使用 MAKEFLAGS 作为环境变量而不是命令行参数。请参阅 中的评论,了解为什么这会产生影响。

我们现在看到 -B (--always-make) 没有传递给 sub-make 那,不像 MAKEFLAGS 作为命令行变量传递,sub-make 不 "always-make":

$ make -B -f a.mk 
===> a.mk MAKEFLAGS: B
MAKEFLAGS= make -f b.mk y
make[1]: Entering directory '/home/matt/junk/make-b'
===> b.mk MAKEFLAGS: w
make[1]: 'y' is up to date.
make[1]: Leaving directory '/home/matt/junk/make-b'

与原始问题中显示的输出相比,这里的另一个区别是 -w (--print-directory) 标志被传递给 sub-make,这很好。