Reputation: 7841
Here is two targets in my Makefile.
.SECONDARY:
exp-%.ans:
echo $* > eval/$@
%.scores: %.ans
cat eval/$< > eval/$@
When I write make -n exp-40.scores
output would be:
echo 40 > eval/exp-40.ans
cat eval/exp-40.ans > eval/exp-40.scores
which is good except one thing. It does not aware of the dependency is already hold. If I create eval/exp-40.scores (first time) then I expect that make will say it is already in there if I run the same command. So I try to change my Makefile like this:
.SECONDARY:
exp-%.ans:
echo $* > eval/$@
%.scores: eval/%.ans
cat eval/$< > $@
When I write make -n exp-40.scores
again and output would be:
echo eval/40 > eval/eval/exp-40.ans
cat eval/eval/exp-40.ans > exp-40.scores
which is completely wrong because my parameter should be 40 not eval/40.
How can I achieve the best of the these two worlds? Namely, I want to create *.scores in eval/ folder. I also want make to check whether file is already exist or not. Then make should proceed according to that file existence.
Thanks.
Upvotes: 0
Views: 1456
Reputation: 100781
One of the core rules of make is that you need to build the target your rule told make that you'd build. A rule like foo : bar
tells make that if it runs that recipe, the recipe will create or update a file named foo
. If the recipe creates or updates a file named biz/foo
instead, then your makefile is wrong and things will not work.
Make always puts the target it expects the recipe to create into the $@
automatic variable. Your recipe should create or update $@
and exactly $@
. Not something else.
So in your case, you need to write:
eval/exp-%.ans:
echo $* > $@
eval/%.scores: eval/%.ans
cat $< > $@
If you want to be able to run make exp-40.scores
and have it actually create eval/exp-40.scores
, then you can add a rule like this:
%.scores: eval/%.scores ; @:
(you have to provide some kind of recipe for pattern rules, they cannot have an empty recipe; the one above does nothing).
Upvotes: 2