Make:是否可以使用“快捷方式”目标来恢复构建

时间:2012-02-21 10:07:29

标签: makefile

假设我的输出文件很昂贵。它还需要一个环境设置过程,运行起来也很昂贵。创建输出的配方还会创建一个中间文件,然后用于创建输出文件。

output_file :
    expensive_env_setup ; \
    generate_file

其中generate_file也创建了intermediate_file。给定intermediate_file和正确的参数,如果生成的第二部分失败,generate_file可以继续生成文件。

我想要做的是,如果在生成intermediate_file之后构建过程失败,则允许从intermediate_file进行简历构建。我不想将构建过程拆分为单独的配方,因为环境设置也很昂贵,这会使构建过程更长,以便成功构建。

例如,我可以执行以下操作:

output_file : intermediate_file :
    expensive_env_setup ; \
    generate_file -resume intermediate_file

intermediate_file :
    expensive_env_setup ; \
    generate_file -intermediate intermediate_file

如果intermediate_file配方生成该文件,但这意味着环境设置过程需要运行两次。

有没有办法表示output_file配方可能会生成一个特定的中间文件,如果生成了intermediate_file但是output_file没有(即第二部分失败),make会使用intermediate_file配方重建吗?

1 个答案:

答案 0 :(得分:1)

一个非常老的问题,但是正如我刚刚解决了一个类似的问题...使条件语句成为解决方案之一,我们可以使用它们来测试中间文件的存在:

ifeq ($(wildcard intermediate_file),intermediate_file)
GENERATEFLAGS := -resume
DEPS          := intermediate_file
else
GENERATEFLAGS := -intermediate
DEPS          :=
endif

output_file: $(DEPS)
    expensive_env_setup; \
    generate_file $(GENERATEFLAGS) intermediate_file

clean:
    rm -f output_file intermediate_file

演示(带有经过修改的Makefile以模拟处理,打印进度信息并允许中断长时间的处理):

$ cat Makefile
ifeq ($(wildcard intermediate_file),intermediate_file)
GENERATEFLAGS := -resume
DEPS          := intermediate_file
else
GENERATEFLAGS := -intermediate
DEPS          :=
endif

output_file: $(DEPS)
    @printf 'expensive_env_setup\n'; \
    printf 'generate_file $(GENERATEFLAGS) intermediate_file\n'; \
    touch intermediate_file; \
    if [ -n "$(STOP)" ]; then printf 'Interrupted\n'; exit 0; fi; \
    touch intermediate_file; \
    touch output_file

clean:
    rm -f output_file intermediate_file
$ make
expensive_env_setup
generate_file -intermediate intermediate_file
$ ls
Makefile  intermediate_file  output_file
$ touch intermediate_file
$ make
expensive_env_setup
generate_file -resume intermediate_file
$ ls
Makefile  intermediate_file  output_file
$ make
make: 'output_file' is up to date.
$ make clean
rm -f output_file intermediate_file
$ make STOP=1
expensive_env_setup
generate_file -intermediate intermediate_file
Interrupted
$ ls
Makefile  intermediate_file
$ make
expensive_env_setup
generate_file -resume intermediate_file
$ ls
Makefile  intermediate_file  output_file
$ make
make: 'output_file' is up to date.

注意:$(DEPS)变量保证在intermediate_fileoutput_file都存在但intermediate_file较新的情况下,我们用{{1 }}选项。