让gmake尽早完成食谱

时间:2018-06-06 20:56:31

标签: makefile build gnu-make exit recipe

我知道以前曾经问过这个问题,但我找不到任何解决方案,因为他们反抗DRY。

我有许多目标依赖于无法随时加盖时间的内容 - 例如从其他系统复制的文件。我喜欢能够做的是在变量中列出依赖关系,例如nobuild=this,that,并且假定的目标是 - 至今。由于我有很多这些,我希望每个人ifdef周围;什么是伪可能的首选将是像

ignorable-target: dependencies
        $(call ifnobuild,$@)
        .. rest of normal build steps ..

如果在ifnobuild中提到gmakeignorable-target宏扩展到某种退出此配方与成功 nobuild指令的位置gmake变量。

我也没有想要进入多行继续shell命令,以便将条件推迟到配方本身;我希望能够告诉make"假设这些目标是最新的,并且不会尝试构建它们,"所以我可以用已经从有问题的食谱中获得的本地副本测试其他方面。

remote1中有不是任何退出配方成功机制吗?

[编辑希望能让情况更清楚。]

这是一个例子。目标remote2ssh均涉及使用local1在远程系统上执行耗时的操作,然后在本地复制结果。目标target-under-work是在本地构建的,并不是时间汇。 local1: local1.c Makefile remote1: local1 scp local1 remote-host:/tmp/ ssh remote-host /tmp/local1 some-args # takes a long time scp remote-host:/tmp/local1.out remote1 remote2: local1 scp local1 other-host:/tmp/ ssh other-host /tmp/local1 other-args # takes a long time scp other-host:/tmp/local1.out remote2 target-under-work: local1 remote1 remote2 do-something-with remote1,remote2 取决于上述所有三个。

make target-under-work

现在,当我运行remote1时,它会运行remote2target-under-work的食谱。但是,这些文件的本地副本足够好'对于我的测试,所以我不要希望它们每次都运行。一旦投入生产,他们将每次都运行,但在我开发remote1时,我只想使用已经构建的副本,我可以每天重建它们(或其他)用于必要的测试粒度。

上述内容过于简化;有多个步骤和目标取决于remote2和/或remote1。我看到如何通过使它们成为仅限订单的先决条件来获得我想要的效果 - 但这将意味着更改将其作为先决条件的每个目标的依赖关系列表,而不是将单个更改为remote2EventTimestamp EventDescription 所以我可以使用命令行中的一些变量来告诉他们的食谱并假装已经构建了这些变量,如果已经构建它,请不要实际构建它副本。'

我希望这会使我的问题更清楚。

1 个答案:

答案 0 :(得分:1)

不,这个早期退出制作功能不存在。

请注意,您的问题可能未明确指定,因为您尚未解释当目标尚不存在时您想要的行为。

假设nobuild中列出的慢速目标只有当它们不存在时才会被重建。您可以使用make函数“隐藏”其先决条件列表,而不是使用make函数提前退出其配方。这样,如果它们已经存在,即使它们已经过时,它们也不会被重建。唯一的细微之处在于,您需要第二次扩展才能在先决条件列表中使用$@自动变量。在以下示例中,slow(您的remoteX)取决于fast1(您的local1)。 fast2(您的target-under-work)取决于fast1slow

host> cat Makefile
# Expands as empty string if $(1) exists and
# listed in $(nobuild). Else expands as $(2).
# $(1): target
# $(2): prerequisites
define HIDE_IF_NOBUILD
$(if $(wildcard $(1)),$(if $(filter $(1),$(nobuild)),,$(2)),$(2))
endef

nobuild :=

fast1:
    @echo 'build $@'
    @touch $@

fast2: fast1 slow
    @echo 'build $@'
    @touch $@

.SECONDEXPANSION:

slow: $$(call HIDE_IF_NOBUILD,$$@,fast1)
    @echo 'build $@'
    @touch $@

# Case 1: slow target not listed in nobuild and not existing
host> rm -f slow; touch fast1; make fast2
build slow
build fast2

# Case 2: slow target not listed in nobuild and existing and outdated
host> touch slow; sleep 2; touch fast1; make fast2
build slow
build fast2

# Case 3: slow target listed in nobuild and not existing
host> rm -f slow; touch fast1; make nobuild="slow" fast2
build slow
build fast2

# Case 4: slow target listed in nobuild and existing and outdated
host> touch slow; sleep 2; touch fast1; make nobuild="slow" fast2
build fast2