Baskaya
Baskaya

Reputation: 7841

Path dependency in Makefile

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

Answers (1)

MadScientist
MadScientist

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

Related Questions