Reputation: 9492
I have a small set of source code files for C. I'm trying to piece together a Makefile for them that builds several different outputs from the same set of source code. Each output is customized using target-specific variables.
(The real-world example is firmware that runs on several different circuit board revisions but is built from the same source code and customized using conditional compilation.)
Here's an example Makefile illustrating the problems I've running into:
CINPUTFILES = Testfile.c
all: v12target v13target
# the same source code is built several different ways depending on a
# list of preset configurations
v12target: lots_of_common_variables = hello
v12target: more_variables = v12_specific
v12target: Rev12Output.mycommontargets
v13target: lots_of_common_variables = hello
v13target: more_variables = v13_specific
v13target: Rev13Output.mycommontargets
# (more vXXtarget targets omitted)
# TODO: why is @echo required?
%.mycommontargets: %.hex %.elf
@echo
# TODO: why are these output files deleted?
%.elf: $(CINPUTFILES)
cp $< $@
%.hex: %.elf
cp $< $@
# TODO: correct way of adding the dummy mycommontargets to PHONY?
.PHONY : all clean
The idea is that the all
target builds several different targets - one for each hardware revision. Because the build process for each is identical except for a list of configuration variables, it calls a number of vXXtarget
targets which set variables and then call a common target: %.mycommontargets
. This target then sets about generating the actual output files.
Notice the TODO marks...
%.mycommontargets
: for some reason, if I remove the @echo
I get an error message:
make: *** No rule to make target `Rev12Output.mycommontargets', needed by `v12target'. Stop.
Why does this happen and what do I need to do to get rid of it?
If I leave the @echo
in place, the build does successfully complete. But then make decides to go ahead and delete the outputs anyway!
$ make
cp Testfile.c Rev12Output.elf
cp Rev12Output.elf Rev12Output.hex
cp Testfile.c Rev13Output.elf
cp Rev13Output.elf Rev13Output.hex
rm Rev12Output.hex Rev12Output.elf Rev13Output.hex Rev13Output.elf
Why does make do this? What decides when it will do this and when it does not? I never previously realized make even had the capability to delete files like this; it runs counter to the whole idea of incremental builds, which I thought make was supposed to help out with. I'd rather have all intermediate and output files retained...
mycommontargets
pattern to .PHONY
?I suppose I could just leave @echo
in place and then add each target to .PRECIOUS
. But even though I don't have a lot of experience with make, I have a strong feeling that I'm doing it wrong if I have to use a hack like @echo
and use a more obscure special target like .PRECIOUS
. Just doesn't feel right.
(Apologies for appearing to ask 3 questions in the space for 1 question, but I have the feeling they are strongly related...)
Upvotes: 3
Views: 305
Reputation: 36059
The output files are intermediate files, i.e. not mentioned explicitly in the Makefile, but required by pattern rules. By default, make deletes all intermediate files. The easiest way to disable auto-deletion here is to mention the .SECONDARY
target without prerequisites, i.e. add a line somewhere just saying:
.SECONDARY :
If you really need the .PHONY here, you have to live w/o pattern rules. Which is quite undesirable in your layout, so better let it be.
Overall, I'd suggest a more orthodox layout here. Normally, you'd leave cross-compiling issues out of the Makefile and give the host board (autotools parlance: the host board is the board the software will run on) as an argument to configure
. Let configure generate one build tree per host board from a central source tree, and build in these build trees.
Upvotes: 1