Makefile 让gmake尽早完成食谱

Makefile 让gmake尽早完成食谱,makefile,build,gnu-make,exit,recipe,Makefile,Build,Gnu Make,Exit,Recipe,我知道以前有人问过这个问题,但我发现没有一种解决方案适合我,因为它们是防干的 我有许多目标依赖于不能立即加时间戳的东西,比如从另一个系统复制的文件。我希望能够在变量中列出依赖项,比如nobuild=this,that,并假设这些目标是最新的。因为我有很多这样的东西,我不想在每一个周围都乱丢东西;伪密码更可取的是 ignorable-target: dependencies $(call ifnobuild,$@) .. rest of normal build s

我知道以前有人问过这个问题,但我发现没有一种解决方案适合我,因为它们是防干的

我有许多目标依赖于不能立即加时间戳的东西,比如从另一个系统复制的文件。我希望能够在变量中列出依赖项,比如nobuild=this,that,并假设这些目标是最新的。因为我有很多这样的东西,我不想在每一个周围都乱丢东西;伪密码更可取的是

ignorable-target: dependencies
        $(call ifnobuild,$@)
        .. rest of normal build steps ..
如果nobuild变量中提到了可忽略的目标,则ifnobuild宏将扩展为此配方的某种出口,并使用success gmake指令

我也不想进入多行连续shell命令,以便将条件延迟到配方本身;我希望能够告诉make假设这些目标是最新的,而不是试图构建它们,这样我就可以用已经从有问题的配方中获得的本地副本测试其他方面

gmake中没有任何成功机制的退出秘方,是吗

[经过编辑,希望能使情况更加清楚。]

这里有一个例子。目标remote1和remote2都涉及使用ssh在远程系统上执行耗时的操作,然后在本地复制结果。目标local1是在本地构建的,不是时间接收器。工作目标取决于上述三个方面

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
现在,当我在work下运行make target时,它将运行remote1和remote2的配方。但是,这些文件的本地副本对于我的测试来说“足够好”,所以我不希望每次都运行它们。一旦产品投入生产,它们将每次运行,但是当我正在开发工作中的目标时,我只想使用已经构建的副本,并且我可以每天或以任何方式重新构建它们,以获得必要的测试粒度

上述内容过于简化;有多个步骤和目标依赖于remote1和/或remote2。我知道如何通过让他们只订购先决条件来达到我想要的效果,但这意味着要更改每个将它们作为先决条件的目标的依赖项列表,而不是对remote1和remote2进行单个更改,这样我就可以使用命令行中的某个变量来告诉他们的食谱“假装已经构建了”,如果已经有副本,就不要实际构建它。”


我希望这能让我的问题更清楚。

不,这个提前退出功能不存在

请注意,您的问题可能没有得到充分的说明,因为您没有解释当慢目标还不存在时您想要的行为

让我们假设nobuild中列出的慢目标在不存在的情况下应该重建。您可以使用make函数隐藏其先决条件列表,而不是使用make函数提前退出其配方。这样,即使它们已经存在,也不会重建,即使它们已经过时。唯一的微妙之处是,您需要第二次扩展才能在先决条件列表中使用$@自动变量。在下面的示例中,您的remoteX取决于fast1和local1。fast2您的工作目标取决于fast1和slow:


如果一个目标永远不会被重建,为什么要为它制定规则?这些目标中有没有其他的先决条件?你知道吗?我可能错了,但我怀疑它们可能就是你要找的东西;它们确实得到重建。但是它们需要很长的时间,当我在做依赖于它们的事情时,我想使用上一次构建的东西,而不是再次构建它。没有办法给它们加时间戳,因为如果不做所有远程工作就无法判断是否有任何变化。我想有选择地说‘这不需要重建’;这是有道理的,尽管它比我希望的要复杂得多,而且它需要修改所有目标的prereq,而不仅仅是prereq本身的配方。我要玩一下这个。谢谢@罗丝,一定有什么我不明白的:我以为你想要的是修改可忽略目标的配方。我的建议是修改他们的先决条件列表,而不是配方。而且,在上一个版本中,在某种程度上似乎并不比您的$call ifnobuild、$@初始提案更复杂。但在您的评论中,您提到了prereq本身的配方。我错过了什么?如果五个不同的目标依赖于长时间运行的prereq,那么它们的每个配方都需要更新。如果以您的示例为例,我想在nobuild中列出的是depend1和depend2,因为这些依赖关系是时间密集型的,很难加时间戳。还有更好的吗?@RoUS:那么,如果depend1和depend2列在nobuild中,你想避免重建目标吗?很简单,但不够明确:如果只有depend1是list呢 ed而不是depend2?不,如果depend1在nobuild中,我希望它被视为已生成,并且目标继续,就像depend1已生成一样。这令人困惑;让我重做原来的问题文本。
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