Reputation: 909
Consider the following (MCVE of a) Makefile
:
my_target: prepare test.bin
prepare:
echo >test.dat
%.bin: %.dat
cp $? $@
If you run make
in a clean directory, it fails:
echo >test.dat
make: *** No rule to make target 'test.bin', needed by 'my_target'. Stop.
Run it again and it succeeds:
echo >test.dat
cp test.dat test.bin
What seems to happen is that the rule to make *.bin
from *.dat
only recognises that it knows how to make test.bin
if test.dat
exists before anything is executed, even though according to the output it has already created test.dat
before it tries to create test.bin
.
This is inconvenient for me as I have to prepare a few files first (import them from a different, earlier part of the build).
Is there a solution? Perhaps some way to allow the rules to be (re)evaluated in the light of the files which are now present?
Upvotes: 3
Views: 2264
Reputation: 6994
you have to write
test.dat: prepare
or (when when you want to stay with wildcards)
%.dat: prepare
@:
Usually, you might want to create and use .stamp
files instead of a prepare
target.
Upvotes: 0
Reputation: 101111
There are a number of issues with your makefile. However based on your comments I'm inclined to assume that the MCVE here is just a little too "M" and it's been reduced so much that it has a number of basic problems. So I won't discuss them, unless you want me to.
The issue here is that you're creating important files without indicating to make that that's what you're doing. Make keeps internally a cache of the contents of directories that it's worked with, for performance reasons, and that cache is only updated when make invokes a rule that it understands will modify it.
Here your target is prepare
but the recipe actually creates a completely different file, test.dat
. So, make doesn't modify its internal cache of the directory contents and when it checks the cache to see if the file test.dat
exists, it doesn't.
You need to be sure that your makefile is written such that it doesn't trick make: if a recipe creates a file foo
then the target name should be foo
, not bar
.
Upvotes: 3
Reputation: 57203
This happens for wildcard targets, like %.bin
. They get evaluated at the first pass. You could add an explicit target of test.bin. Or, follow the advice of tkausl and have test.dat depend on prepare (a phony target). In this case, you don't need the double dependency anymore:
my_target: test.bin
Upvotes: 0