autoconf: Make Target Lookup
1
1 12.18.6 Make Target Lookup
1 --------------------------
1
1 GNU `make' uses a complex algorithm to decide when it should use files
11 found via a `VPATH' search. ⇒How Directory Searches are
Performed (make)Search Algorithm.
1
1 If a target needs to be rebuilt, GNU `make' discards the file name
1 found during the `VPATH' search for this target, and builds the file
1 locally using the file name given in the makefile. If a target does
1 not need to be rebuilt, GNU `make' uses the file name found during the
1 `VPATH' search.
1
1 Other `make' implementations, like NetBSD `make', are easier to
1 describe: the file name found during the `VPATH' search is used whether
1 the target needs to be rebuilt or not. Therefore new files are created
1 locally, but existing files are updated at their `VPATH' location.
1
1 OpenBSD and FreeBSD `make', however, never perform a `VPATH' search
1 for a dependency that has an explicit rule. This is extremely annoying.
1
1 When attempting a `VPATH' build for an autoconfiscated package
1 (e.g., `mkdir build && cd build && ../configure'), this means GNU
1 `make' builds everything locally in the `build' directory, while BSD
1 `make' builds new files locally and updates existing files in the
1 source directory.
1
1 $ cat Makefile
1 VPATH = ..
1 all: foo.x bar.x
1 foo.x bar.x: newer.x
1 @echo Building $@
1 $ touch ../bar.x
1 $ touch ../newer.x
1 $ make # GNU make
1 Building foo.x
1 Building bar.x
1 $ pmake # NetBSD make
1 Building foo.x
1 Building ../bar.x
1 $ fmake # FreeBSD make, OpenBSD make
1 Building foo.x
1 Building bar.x
1 $ tmake # Tru64 make
1 Building foo.x
1 Building bar.x
1 $ touch ../bar.x
1 $ make # GNU make
1 Building foo.x
1 $ pmake # NetBSD make
1 Building foo.x
1 $ fmake # FreeBSD make, OpenBSD make
1 Building foo.x
1 Building bar.x
1 $ tmake # Tru64 make
1 Building foo.x
1 Building bar.x
1
1 Note how NetBSD `make' updates `../bar.x' in its VPATH location, and
1 how FreeBSD, OpenBSD, and Tru64 `make' always update `bar.x', even when
1 `../bar.x' is up to date.
1
1 Another point worth mentioning is that once GNU `make' has decided
1 to ignore a `VPATH' file name (e.g., it ignored `../bar.x' in the above
1 example) it continues to ignore it when the target occurs as a
1 prerequisite of another rule.
1
1 The following example shows that GNU `make' does not look up `bar.x'
1 in `VPATH' before performing the `.x.y' rule, because it ignored the
1 `VPATH' result of `bar.x' while running the `bar.x: newer.x' rule.
1
1 $ cat Makefile
1 VPATH = ..
1 all: bar.y
1 bar.x: newer.x
1 @echo Building $@
1 .SUFFIXES: .x .y
1 .x.y:
1 cp $< $@
1 $ touch ../bar.x
1 $ touch ../newer.x
1 $ make # GNU make
1 Building bar.x
1 cp bar.x bar.y
1 cp: cannot stat `bar.x': No such file or directory
1 make: *** [bar.y] Error 1
1 $ pmake # NetBSD make
1 Building ../bar.x
1 cp ../bar.x bar.y
1 $ rm bar.y
1 $ fmake # FreeBSD make, OpenBSD make
1 echo Building bar.x
1 cp bar.x bar.y
1 cp: cannot stat `bar.x': No such file or directory
1 *** Error code 1
1 $ tmake # Tru64 make
1 Building bar.x
1 cp: bar.x: No such file or directory
1 *** Exit 1
1
1 Note that if you drop away the command from the `bar.x: newer.x'
1 rule, GNU `make' magically starts to work: it knows that `bar.x' hasn't
1 been updated, therefore it doesn't discard the result from `VPATH'
1 (`../bar.x') in succeeding uses. Tru64 also works, but FreeBSD and
1 OpenBSD still don't.
1
1 $ cat Makefile
1 VPATH = ..
1 all: bar.y
1 bar.x: newer.x
1 .SUFFIXES: .x .y
1 .x.y:
1 cp $< $@
1 $ touch ../bar.x
1 $ touch ../newer.x
1 $ make # GNU make
1 cp ../bar.x bar.y
1 $ rm bar.y
1 $ pmake # NetBSD make
1 cp ../bar.x bar.y
1 $ rm bar.y
1 $ fmake # FreeBSD make, OpenBSD make
1 cp bar.x bar.y
1 cp: cannot stat `bar.x': No such file or directory
1 *** Error code 1
1 $ tmake # Tru64 make
1 cp ../bar.x bar.y
1
1 It seems the sole solution that would please every `make'
1 implementation is to never rely on `VPATH' searches for targets. In
1 other words, `VPATH' should be reserved to unbuilt sources.
1