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