Reputation: 52739
Consider the following makefile:
foo :
mkdir foo
foo/a.out : foo a.in
cp a.in foo/a.out
foo/b.out : foo b.in
cp b.in foo/b.out
and the following interaction with it, starting from a directory that contains files a.in
and b.in
and nothing else:
$ make foo/a.out
mkdir foo
cp a.in foo/a.out
So far, so good.
$ make foo/b.out
cp b.in foo/b.out
Still good, but now:
$ make foo/a.out # a.out should be up to date now!
cp a.in foo/a.out
It rebuilds the a.out
target, even though none of its prerequisites have changed.
It seems like what's happening is that when foo/b.out
is created, the last modification time of the directory foo
is updated, so it picks that up as having "changed".
Is there a way to avoid this? For example, is there a way to declare that foo/a.out
depends on foo
only in that foo
has to exist, and the creating of files inside foo
doesn't cause foo
to be considered out of date?
Upvotes: 1
Views: 702
Reputation: 189387
I like @Beta's answer, but it is not portable. For a simple portable workaround, create a sentinel file when you create the directory, and depend on the sentinel file instead.
foo/.dir:
mkdir -p foo
touch $@
foo/a.out: a.in foo/.dir
cp $< $@
foo/b.out: b.in foo/.dir
cp $< $@
This can be further simplified with a pattern rule:
foo/%.out: %.in foo/.dir
cp $< $@
Upvotes: 2
Reputation: 280
Instead of making the targets dependent on the directory, you can simply create the directory unconditionally in their build rules:
foo/a.out: a.in
mkdir -p foo
cp a.in foo/a.out
foo/b.out: b.in
mkdir -p foo
cp b.in foo/b.out
This avoids problems with using a directory as a prerequisite.
Upvotes: 1
Reputation: 99094
As an authority on Make recently pointed out:
"The one thing you must NEVER do is use a directory as a simple prerequisite. The rules the filesystem uses to update the modified time on directories do not work well with make."
But I think this will do what you want:
foo :
mkdir foo
foo/a.out : a.in | foo
cp a.in foo/a.out
foo/b.out : b.in | foo
cp b.in foo/b.out
Upvotes: 4