如果另一个配方在 Makefile 中创建目标,如何跳过目标的配方

Posted

技术标签:

【中文标题】如果另一个配方在 Makefile 中创建目标,如何跳过目标的配方【英文标题】:how to skip target's recipe if another recipe creates the target in Makefile 【发布时间】:2018-08-30 02:14:49 【问题描述】:

我有一个 Makefile,如下所示:

all: build

build:
ifdef USE_CACHE
        @printf ":sigh: failure  :(\nThis should have been skipped by cache's recipe.\n"
endif
        @printf "Building ...\n"
    touch $@

ifdef USE_CACHE
build: cache

cache:
        @printf "Installing cache ...\n"
    touch $@
        @printf "Trying to skip build because cache satisfied it ... \n"
    touch build
endif

默认的“构建”会产生:

$ rm build cache; make
Building ...
touch build

这很简单,也是意料之中的,但如果定义了 USE_CACHE 参数,构建配方仍会执行,如下所示:

$ rm build cache; make USE_CACHE=1
Installing cache ...
touch cache
Trying to skip build because cache satisfied it ...
touch build
:sigh: failure  :(
This should have been skipped by cache's recipe.
Building ...
touch build

我知道这是因为 Make 的构建图是在解析所有文件之后和执行任何配方之前建立的,所以在我的“缓存”配方执行后重新评估所需的构建配方为时已晚。

但是,假设 USE_CACHE 目标已定义,我希望“缓存”目标的配方额外满足“构建”目标,跳过“构建”配方的执行。

有没有办法实现这一点,或者在 GNU Make 中是不可能的?

顺便说一句,我的真实案例比上述玩具要复杂得多。为了这个问题,请假设“构建”目标配方的定义存在于另一个我无法编辑的文件中。我必须按原样“包含”它以获取基本的、不相关的陈述。

【问题讨论】:

gnu.org/software/make/manual/make.html#Overriding-Makefiles 不清楚你可以编辑多少makefile。 【参考方案1】:

我最终使用了类似以下的内容,这会触发重新读取 Make 文件并重新评估依赖项:

    .PHONY: all clean

    all: build
            @true

    clean:
            rm -f build cache sync

    build:
    ifdef USE_CACHE
            @printf ":sigh: failure  :(\nThis should have been skipped by cache's recipe.\n"
    endif
            @printf "Building ...\n"
            touch $@

    ifdef USE_CACHE

    include sync

    cache:
            @printf "Installing cache ...\n"
            touch $@
            @printf "Trying to skip build because cache satisfied it ... \n"
            touch build

    sync: cache
            @printf "Creating cache synchronization file ...\n"
            @printf '$$(info Loading build cache ...  If this works, it should be the last line printed ...)\n' >| $@

    endif

执行重新解析对性能有明显影响(如果创建包含的文件目标,GNU Make 总是重新解析并重新评估所有内容),但我认为不可能避免重新评估。

【讨论】:

以上是关于如果另一个配方在 Makefile 中创建目标,如何跳过目标的配方的主要内容,如果未能解决你的问题,请参考以下文章

C ++如何将两个makefile对象目标规则(位于另一个文件夹中)组合到一个目标/规则中?

无法制作 raylib,收到 makefile 错误 576:目标“rmodels.o”的配方失败

从不同的源文件夹在一个文件夹中创建目标文件

目标“Project1.exe”的配方失败

MAKEFILE:将目标视为已更新而不修改文件

通过 makefile 链接文件