Reputation: 9475
This could or not be a duplicate of Makefile Variable Assignment Executes Early
Is it possible to define a condition and reuse it later?
MAIN_FILE_PATH := main
define copy_resulting_pdf=
if [[ -f "${MAIN_FILE_PATH}" ]] \
then \
cp "${MAIN_FILE_PATH}" "${MAIN_FILE_PATH}.pdf"; \
else \
$(error Error: The PDF ${MAIN_FILE_PATH} was not generated!); \
fi
endef
all:
echo doing other things.
$(copy_resulting_pdf)
other:
echo doing more other things.
$(copy_resulting_pdf)
When run this, make does not even start to build the all
rule. It just throws out:
Makefile:14: *** Error: The PDF main was not generated!. Stop.
Upvotes: 1
Views: 1133
Reputation: 15513
Just one note to add: writing bash control structures in a recipe is a bit of a code smell IMHO. Things invariably look better is you replace them with make idioms.
Another smell here is when you lie to make: Your makefile does not say that the recipe for all
creates main.pdf
for instance.
MAIN_FILE_PATH := main
.PHONY: other_things
other_things:
blah-dy-blah…
${MAIN_FILE_PATH}.pdf: | other_things
${MAIN_FILE_PATH}.pdf: ${MAIN_FILE_PATH}
cp $< $@
.PHONY: all
all: ${MAIN_FILE_PATH}.pdf
echo $@ Success
So what happens when you ask make to make all
?
all
:
main.pdf
other_things
blah-dy-blah…
runsmain
is copied to main.pdf
all Success
is printedThe existence of main
is checked by make rather than bash.
One good characteristic of this is that you can easily add another recipe if you have a programmatic way of creating main
.
Another is that the copy does not happen if main.pdf
is already up-to-date.
Since you are no longer lying to make,
this makefile is parallel safe,
allowing you to use the -j
n flag.
Hello performance.
Upvotes: 1
Reputation: 15196
The problem with your code is that $(error ...)
is a text substitution too. So any expansion of $(copy_resulting_pdf)
also leads to the recursive expansion of all embedded variables and functions, including $(error ...)
. Normally, $(error ...)
is guarded by make conditionals (such as ifeq
), or another substitutions (such as $(if ...)
). But in your case it was "guarded" by shell conditional, which means nothing to make.
But the following works just as expected:
MAIN_FILE_PATH := main
define copy_resulting_pdf
echo Printing results...
if [[ -f "${MAIN_FILE_PATH}" ]]; then \
printf 'Copying PDF...\n'; \
cp "${MAIN_FILE_PATH}" "${MAIN_FILE_PATH}.pdf"; \
else \
printf "Error: The PDF \"${MAIN_FILE_PATH}\" was not generated!\n"; \
exit 1; \
fi
endef
.PHONY: all other
all:
@echo doing other things.
@$(copy_resulting_pdf)
other:
@echo doing more other things.
@$(copy_resulting_pdf)
Note: you don't need eval and some fancy escapes here.
Upvotes: 2
Reputation: 9475
I managed to do it with this:
SHELL := /bin/bash
MAIN_FILE_PATH := main
define copy_resulting_pdf=
echo Printing results...
eval "if [[ -f "${MAIN_FILE_PATH}" ]]; then \
printf 'Coping PDF...\\n'; \
cp "${MAIN_FILE_PATH}" "${MAIN_FILE_PATH}.pdf"; \
else \
printf \"Error: The PDF "${MAIN_FILE_PATH}" was not generated!\\n\"; \
exit 1; \
fi"
endef
all:
echo doing other things.
$(copy_resulting_pdf)
Running it:
echo doing other things.
doing other things.
echo Printing results...
Printing results...
eval "if [[ -f "main" ]]; then printf 'Coping PDF...\\n'; cp "main" "main.pdf"; else printf \"Error: The PDF "main" was not generated!\\n\"; exit 1; fi"
Error: The PDF main was not generated!
make: *** [setup/makefile.mk:17: all] Error 1
References:
Upvotes: -1