1
votes

I have a large project that uses GNU Make for building. Some rules depend on symlinks and other rules have targets that are the the files referenced by the symlinks.

Here is a simple example of what I am talking about:

# assume the following symlink exists s-b2 -> f-b2

f-b1 :
    touch f-b1

f-b2 : f-b1
    touch f-b2

f-b3 : s-b2
    touch f-b3

The behavior I see is that the final rule that depends on the symlink is not fully linked to the earlier rules. E.g. updates to earlier files do not cause the later rule to be re-evaluated. You can see detailed failures of this and try it yourself with this github project.

Is there any way to tell make to follow symlinks when calculating rule dependencies?

1
I guess you already tried -L, --check-symlink-times Use the latest mtime between symlinks and target.. It unfortunately only solves half your problem :-(Stefan Becker
There is no simple way to do this because make uses simple text comparison to match up targets and prerequisites. It doesn't have some underlying representation of a file on a disk that can have multiple names that are understood to all mean the same thing. You can use something like $(realpath s-b2) as the prerequisite which will expand the name before make internalizes it.MadScientist
Thanks for the comments. As you said -L doesn't fully work. $(realpath s-b2) is very interesting, but it might take too long with a huge number of dependencies. I might try it but the makefile is generated so I might just make the generator follow symlinks. In any case, thanks for letting me know that make does not appear to be able to do this naturally.Robert Kleemann
It turns out the correct way to replace dependencies with realpath is $(shell realpath --relative-to=. s-b2)Robert Kleemann
If you control the generator, updating it is the way to go. May I also, cough, cough, suggest ninja.Victor Sergienko

1 Answers

0
votes

If you're not doing anything fancy with symbolic link, maybe try just touching the link?

all : f-b3

init : clean
        ln -s -f f-b2 s-b2

clean :
        -rm f-* s-*

f-b1 :
    touch f-b1 # not necessarily just touch in real makefile

f-b2 : f-b1
    touch f-b2

s-b2 : f-b2
    touch s-b2 # would be just this in real makefile

f-b3 : s-b2
    touch f-b3

Example make result:

$ make init
rm f-* s-*
ln -s -f f-b2 s-b2
$ make
touch f-b1
touch f-b2
touch s-b2
touch f-b3
$ touch f-b1
$ make
touch f-b2
touch s-b2
touch f-b3
$ touch f-b2
$ make
touch f-b3