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