Reputation: 966
Let's say I have an output file that is expensive to make. It also requires an environment setup process that is also expensive to run. The recipe to create the output also creates an intermediate file that is then used to create the output file.
output_file :
expensive_env_setup ; \
generate_file
Where generate_file also creates intermediate_file. Given the intermediate_file and the correct parameters, generate_file can resume generating the file, in the event that the second part of the generation failed.
What I am trying to do is allow resume building from the intermediate_file if the build process failed after generating intermediate_file. I don't want to split the build process into separate recipes since the environment setup is also expensive and this would make the build process longer for successful builds.
For example, I could do the following:
output_file : intermediate_file :
expensive_env_setup ; \
generate_file -resume intermediate_file
intermediate_file :
expensive_env_setup ; \
generate_file -intermediate intermediate_file
Where the intermediate_file recipe only generates that file, but this would mean that the environment setup process would need to be run twice.
Is there a way to signify that the output_file recipe may generate a particular intermediate file, and make will rebuild using intermediate_file recipe if the intermediate_file was generated but the output_file was not (ie the second part failed)?
Upvotes: 0
Views: 66
Reputation: 29250
Very old question but as I just solved a similar issue... Make conditionals are one of the solutions, we can use them to test the presence of the intermediate file:
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
Demonstration (with a modified Makefile to emulate the processing, print progress information and allow interrupting the long processing):
$ 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.
Note: the $(DEPS)
variable guarantees that in case intermediate_file
and output_file
both exist but intermediate_file
is newer, we update output_file
with the -resume
option.
Upvotes: 1