]> git.ipfire.org Git - thirdparty/automake.git/commitdiff
[ng] dirstamp: remove, use inlined parent directory creation instead
authorStefano Lattarini <stefano.lattarini@gmail.com>
Thu, 17 May 2012 09:40:49 +0000 (11:40 +0200)
committerStefano Lattarini <stefano.lattarini@gmail.com>
Mon, 21 May 2012 14:16:14 +0000 (16:16 +0200)
Since GNU make offers an efficient and simple way to refer to the directory
component of a target within its recipe (through the use of the automatic
variable "$(@D)"), and ways to avoid launching a "sub-recipe" to create
a directory if that directory already exists (through a careful the use
of the $(wildcard) builtin), we can simplify the automake pre-processing
a little by getting rid of dirstamp files creation, instead inlining the
creation of any required parent directory for a target into the recipe of
the target itself.

As a first step, instead of emitting rules like:

    sub/foo.o: sub/foo.c sub/.dirstamp
        $(CC) $(CFLAGS) sub/foo.c
    sub/.dirstamp:
        mkdir sub && touch sub/.dirstamp

we might simply emit rules like:

    sub/foo.o: sub/foo.c
        $(MKDIR_P) $(@D)
        $(CC) $(CFLAGS) sub/foo.c

But the above would be quite wasteful if we really called $(MKDIR_P) for
every created object file, since the directory $(@D) will likely already
exist (in an in-tree build, it will exist unconditionally and beforehand,
and in a VPATH build will exists after the first object file in it has
been created).

So, as hinted above, we employ few optimizations to try to avoid such
extra forks when they are not really required, thus keeping most of
the performance gains offered by dirstamp files, but without the added
pre-processing complexity.

* automake.in (preprocess_file): Add a transform for '%SILENT%', as
returned by the 'silent_flag()' subroutine.
(output_texinfo_build_rules, handle_languages, handle_programs,
handle_libraries): Drop explicit '%SILENT%' transforms for single
'.am' files as a result.
(%directory_map): Delete this global variable.
(initialize_per_input): Do not reset it.
(handle_single_transform): Don't create dependency of subdir objects
on the corresponding dirstamp file.
(handle_programs, handle_libraries): Likewise, but for subdir programs
and libraries.  And drop the '%DIRSTAMP%' transform when processing the
relevant '.am' fragment.
(output_texinfo_build_rules): Don't handle nor return a dirstamp.
(handle_texinfo_helper): Adjust, and drop the '%DIRSTAMP%' transform
when processing the relevant .am fragment.
(require_build_directory, require_build_directory_maybe): Delete.
* lib/am/header-vars.am (am__ensure_dir_exists, am__mkdir): New private
make function, used to create a directory with "maximal" possible
efficiency, especially trying to avoid extra forks when possible.
* t/ensure-dir-exists.sh: New test, checking the behaviour of the new
$(am__mkdir) function.
* t/spy-wildcard.sh: New "spy" test, verifying that the $(wildcard)
GNU make builtin really has the behaviour the $(am__ensure_dir_exists)
expects.
* t/subobj-libtool.sh: New test (subdir objects with libtool).
* t/subobj.sh: Adjust and enhance.
* t/subobj6.sh: Remove as obsolete.

* lib/am/library.am: Adjust to create required targets parent directories
with the help of $(am__ensure_dir_exists) rather than of dirstamp files,
once provided by the now-removed '%DIRSTAMP%' transforms.
* lib/am/ltlibrary.am: Likewise.
* lib/am/program.am: Likewise.
* lib/am/texi-vers.am: Likewise.
* lib/am/texibuild.am: Likewise.
* lib/am/depend2.am: Likewise.  Also ...
(am__ensure_depdir): Rewrite to using $(am__ensure_dir_exists).

Signed-off-by: Stefano Lattarini <stefano.lattarini@gmail.com>
13 files changed:
automake.in
lib/am/depend2.am
lib/am/header-vars.am
lib/am/library.am
lib/am/ltlibrary.am
lib/am/program.am
lib/am/texi-vers.am
lib/am/texibuild.am
t/ensure-dir-exists.sh [new file with mode: 0755]
t/spy-wildcard.sh [new file with mode: 0755]
t/subobj-libtool.sh [new file with mode: 0755]
t/subobj.sh
t/subobj6.sh [deleted file]

index 11d1f0b1592a5598bb6d9c7b8a014bb018a1ab19..e61bfbd12a70afda2c95224566f5f365547d5ebf 100644 (file)
@@ -542,13 +542,6 @@ my %object_map;
 # libtool compilation (the COMPILE_* constants).
 my %object_compilation_map;
 
-
-# This keeps track of the directories for which we've already
-# created dirstamp code.  Keys are directories, values are stamp files.
-# Several keys can share the same stamp files if they are equivalent
-# (as are './/foo' and 'foo').
-my %directory_map;
-
 # All .P files.
 my %dep_files;
 
@@ -657,8 +650,6 @@ sub initialize_per_input ()
     %object_map = ();
     %object_compilation_map = ();
 
-    %directory_map = ();
-
     %dep_files = ();
 
     @dist_targets = ();
@@ -1338,7 +1329,6 @@ sub handle_languages
        my $verbose = verbose_flag ($lang->ccer || 'GEN');
        my $verbose_nodep = ($AMDEP eq 'FALSE')
          ? $verbose : verbose_nodep_flag ($lang->ccer || 'GEN');
-       my $silent = silent_flag ();
 
        my %transform = ('EXT'     => $ext,
                         'PFX'     => $pfx,
@@ -1353,7 +1343,6 @@ sub handle_languages
                         DIST_SOURCE   => 1,
                         VERBOSE   => $verbose,
                         'VERBOSE-NODEP' => $verbose_nodep,
-                        SILENT    => $silent,
                        );
 
        # Generate the appropriate rules for this extension.
@@ -1455,7 +1444,6 @@ sub handle_languages
 
                             VERBOSE   => $verbose,
                             'VERBOSE-NODEP'  => $verbose_nodep,
-                            SILENT    => $silent,
                             COMPILE   => $obj_compile,
                             LTCOMPILE => $obj_ltcompile,
                             -o        => $output_flag,
@@ -1877,7 +1865,6 @@ sub handle_single_transform ($$$$$%)
 
        if (! defined $object_map{$object})
        {
-           my @dep_list = ();
            $object_map{$object} = $full;
 
            # If resulting object is in subdir, we need to make
@@ -1906,12 +1893,7 @@ sub handle_single_transform ($$$$$%)
                    # Remove any libtool object in this directory.
                    $libtool_clean_directories{$directory} = 1;
                }
-
-               push (@dep_list, require_build_directory ($directory));
            }
-
-           &pretty_print_rule ($object . ':', "\t", @dep_list)
-               if scalar @dep_list > 0;
        }
 
        # Transform .o or $o file into .P file (for automatic
@@ -2458,10 +2440,6 @@ sub handle_programs
       my($xlink, $vlink) = &define_per_target_linker_variable ($linker, $xname);
       $vlink = verbose_flag ($vlink || 'GEN');
 
-      # If the resulting program lies into a subdirectory,
-      # make sure this directory will exist.
-      my $dirstamp = require_build_directory_maybe ($one_file);
-
       $libtool_clean_directories{dirname ($one_file)} = 1;
 
       $output_rules .= &file_contents ('program',
@@ -2470,7 +2448,6 @@ sub handle_programs
                                       XPROGRAM => $xname,
                                       XLINK    => $xlink,
                                       VERBOSE  => $vlink,
-                                      DIRSTAMP => $dirstamp,
                                       EXEEXT   => '$(EXEEXT)');
 
       if ($seen_libobjs || $seen_global_libobjs)
@@ -2569,19 +2546,13 @@ sub handle_libraries
       &handle_source_transform ($xlib, $onelib, $obj, $where,
                                NONLIBTOOL => 1, LIBTOOL => 0);
 
-      # If the resulting library lies into a subdirectory,
-      # make sure this directory will exist.
-      my $dirstamp = require_build_directory_maybe ($onelib);
       my $verbose = verbose_flag ('AR');
-      my $silent = silent_flag ();
 
       $output_rules .= &file_contents ('library',
                                       $where,
                                       VERBOSE  => $verbose,
-                                      SILENT   => $silent,
                                       LIBRARY  => $onelib,
-                                      XLIBRARY => $xlib,
-                                      DIRSTAMP => $dirstamp);
+                                      XLIBRARY => $xlib);
 
       if ($seen_libobjs)
        {
@@ -2813,10 +2784,6 @@ sub handle_ltlibraries
            }
        }
 
-      # If the resulting library lies into a subdirectory,
-      # make sure this directory will exist.
-      my $dirstamp = require_build_directory_maybe ($onelib);
-
       # Remember to cleanup .libs/ in this directory.
       my $dirname = dirname $onelib;
       $libtool_clean_directories{$dirname} = 1;
@@ -2827,8 +2794,7 @@ sub handle_ltlibraries
                                       XLTLIBRARY => $xlib,
                                       RPATH      => $rpath,
                                       XLINK      => $xlink,
-                                      VERBOSE    => $vlink,
-                                      DIRSTAMP   => $dirstamp);
+                                      VERBOSE    => $vlink);
       if ($seen_libobjs)
        {
          if (var ($xlib . '_LIBADD'))
@@ -2979,7 +2945,7 @@ sub scan_texinfo_file ($)
 }
 
 
-# ($DIRSTAMP, @CLEAN_FILES)
+# @CLEAN_FILES
 # output_texinfo_build_rules ($SOURCE, $DEST, $INSRC, @DEPENDENCIES)
 # ------------------------------------------------------------------
 # SOURCE - the source Texinfo file
@@ -3043,10 +3009,6 @@ sub output_texinfo_build_rules ($$$@)
   # extension).
   my $generic_info = ($generic && $dsfx) ? 1 : 0;
 
-  # If the resulting file lie into a subdirectory,
-  # make sure this directory will exist.
-  my $dirstamp = require_build_directory_maybe ($dest);
-
   my $dipfx = ($insrc ? '$(srcdir)/' : '') . $dpfx;
 
   $output_rules .= file_contents ('texibuild',
@@ -3058,12 +3020,10 @@ sub output_texinfo_build_rules ($$$@)
                                  DEST_PREFIX      => $dpfx,
                                  DEST_INFO_PREFIX => $dipfx,
                                  DEST_SUFFIX      => $dsfx,
-                                 DIRSTAMP         => $dirstamp,
                                  GENERIC          => $generic,
                                  GENERIC_INFO     => $generic_info,
                                  INSRC            => $insrc,
                                  MAKEINFOFLAGS    => $makeinfoflags,
-                                  SILENT           => silent_flag(),
                                  SOURCE           => ($generic
                                                       ? '$<' : $source),
                                  SOURCE_INFO      => ($generic_info
@@ -3073,7 +3033,7 @@ sub output_texinfo_build_rules ($$$@)
                                   TEXIQUIET        => verbose_flag('texinfo'),
                                   TEXIDEVNULL      => verbose_flag('texidevnull'),
                                  );
-  return ($dirstamp, "$dpfx.dvi", "$dpfx.pdf", "$dpfx.ps", "$dpfx.html");
+  return ("$dpfx.dvi", "$dpfx.pdf", "$dpfx.ps", "$dpfx.html");
 }
 
 
@@ -3244,8 +3204,8 @@ sub handle_texinfo_helper ($)
          push_dist_common ('$(' . $canonical . '_TEXINFOS)');
        }
 
-      my ($dirstamp, @cfiles) =
-       output_texinfo_build_rules ($texi, $out_file, $insrc, @texi_deps);
+      my @cfiles = output_texinfo_build_rules ($texi, $out_file,
+                                               $insrc, @texi_deps);
       push (@texi_cleans, @cfiles);
 
       push (@info_deps_list, $out_file);
@@ -3291,8 +3251,7 @@ sub handle_texinfo_helper ($)
                                          VTI      => $vti,
                                          STAMPVTI => "${soutdir}stamp-$vti",
                                          VTEXI    => "$soutdir$vtexi",
-                                         MDDIR    => $conf_dir,
-                                         DIRSTAMP => $dirstamp);
+                                         MDDIR    => $conf_dir);
        }
     }
 
@@ -6753,6 +6712,9 @@ sub preprocess_file ($%)
 
                 'LIBTOOL'      => !! var ('LIBTOOL'),
                 'NONLIBTOOL'   => 1,
+
+                'SILENT'       => silent_flag (),
+
                %transform);
 
   if (! defined ($_ = $am_file_cache{$file}))
@@ -7723,68 +7685,6 @@ sub require_conf_file_with_macro ($$$@)
 
 ################################################################
 
-# &require_build_directory ($DIRECTORY)
-# -------------------------------------
-# Emit rules to create $DIRECTORY if needed, and return
-# the file that any target requiring this directory should be made
-# dependent upon.
-# We don't want to emit the rule twice, and want to reuse it
-# for directories with equivalent names (e.g., 'foo/bar' and './foo//bar').
-sub require_build_directory ($)
-{
-  my $directory = shift;
-
-  return $directory_map{$directory} if exists $directory_map{$directory};
-
-  my $cdir = File::Spec->canonpath ($directory);
-
-  if (exists $directory_map{$cdir})
-    {
-      my $stamp = $directory_map{$cdir};
-      $directory_map{$directory} = $stamp;
-      return $stamp;
-    }
-
-  my $dirstamp = "$cdir/\$(am__dirstamp)";
-
-  $directory_map{$directory} = $dirstamp;
-  $directory_map{$cdir} = $dirstamp;
-
-  # Set a variable for the dirstamp basename.
-  define_pretty_variable ('am__dirstamp', TRUE, INTERNAL,
-                         '$(am__leading_dot)dirstamp');
-
-  # Directory must be removed by 'make distclean'.
-  $clean_files{$dirstamp} = DIST_CLEAN;
-
-  $output_rules .= ("$dirstamp:\n"
-                   . "\t\@\$(MKDIR_P) $directory\n"
-                   . "\t\@: > $dirstamp\n");
-
-  return $dirstamp;
-}
-
-# &require_build_directory_maybe ($FILE)
-# --------------------------------------
-# If $FILE lies in a subdirectory, emit a rule to create this
-# directory and return the file that $FILE should be made
-# dependent upon.  Otherwise, just return the empty string.
-sub require_build_directory_maybe ($)
-{
-    my $file = shift;
-    my $directory = dirname ($file);
-
-    if ($directory ne '.')
-    {
-       return require_build_directory ($directory);
-    }
-    else
-    {
-       return '';
-    }
-}
-
-################################################################
 
 # Push a list of files onto dist_common.
 sub push_dist_common
index 81660c18ecc79f87cfc360b1fef2ec0e5c8fd845..e68bba7abcf5f2f1378aeda1c14f9b159a23b8a3 100644 (file)
@@ -38,7 +38,7 @@ if %?FIRST%
 ## FIXME: more precise in the removal of the suffix?
 am__depbase = $(am__depdir)/$(basename $(notdir $@))
 ## Avoid useless forks when possible.
-am__ensure_depdir = test -d $(am__depdir) || $(MKDIR_P) $(am__depdir)
+am__ensure_depdir = $(call am__ensure_dir_exists,$(am__depdir))
 endif %?FIRST%
 
 if %?NONLIBTOOL%
@@ -51,7 +51,9 @@ if %FASTDEP%
                 %-c% -o $@ %SOURCEFLAG%$<
        %SILENT%$(am__mv) $(am__depbase).Tpo $(am__depbase).Po
 else !%FASTDEP%
-if %AMDEP%
+if !%AMDEP%
+       %SILENT%$(am__ensure_target_dir_exists)
+else %AMDEP%
        %SILENT%$(am__ensure_depdir)
        %VERBOSE%source='%SOURCE%' object='%OBJ%' libtool=no @AMDEPBACKSLASH@
        DEPDIR=$(DEPDIR) $(%FPFX%DEPMODE) $(depcomp) @AMDEPBACKSLASH@
@@ -69,7 +71,9 @@ if %FASTDEP%
                 %-c% -o $@ %SOURCEFLAG%`$(CYGPATH_W) $<`
        %SILENT%$(am__mv) $(am__depbase).Tpo $(am__depbase).Po
 else !%FASTDEP%
-if %AMDEP%
+if !%AMDEP%
+       %SILENT%$(am__ensure_target_dir_exists)
+else %AMDEP%
        %SILENT%$(am__ensure_depdir)
        %VERBOSE%source='%SOURCE%' object='%OBJOBJ%' libtool=no @AMDEPBACKSLASH@
        DEPDIR=$(DEPDIR) $(%FPFX%DEPMODE) $(depcomp) @AMDEPBACKSLASH@
@@ -89,7 +93,9 @@ if %FASTDEP%
                 %-c% -o $@ %SOURCEFLAG%$<
        %SILENT%$(am__mv) $(am__depbase).Tpo $(am__depbase).Plo
 else !%FASTDEP%
-if %AMDEP%
+if !%AMDEP%
+       %SILENT%$(am__ensure_target_dir_exists)
+else %AMDEP%
        %SILENT%$(am__ensure_depdir)
        %VERBOSE%source='%SOURCE%' object='%LTOBJ%' libtool=yes @AMDEPBACKSLASH@
        DEPDIR=$(DEPDIR) $(%FPFX%DEPMODE) $(depcomp) @AMDEPBACKSLASH@
index d620c8948434c4dd085a8a3e6d7ff23393e2c8f7..522dfc08035c84a125522164fd10e83a525b6686 100644 (file)
 
 VPATH = @srcdir@
 
+am__mkdir = test -d $1 || $(MKDIR_P) $1
+
+# In a recipe, ensure the given directory exists, creating it if
+# necessary; but tries to do so avoiding useless forks, stats, and
+# extra recipe text (the latter is useful when doing "make V=1").
+# If the target has no directory component, or if the parent
+# directory of the target already exists, we have nothing to do, so
+# try to optimize for those cases -- especially because, for our
+# usage patterns, one of them should always be true in non-VPATH
+# builds.
+am__ensure_dir_exists = \
+  $(if $(filter .,$1),:,$(if $(wildcard $1/),:,$(call am__mkdir,$1)))
+
+# Ensure the directory containing the target of the current recipe
+# exists, by creating it if necessary.
+am__ensure_target_dir_exists = $(call am__ensure_dir_exists,$(@D))
+
 ## The 'all' target must be the default one, independently from the
 ## position it is declared in the output Makefile.
 .DEFAULT_GOAL := all
index 686b648edebe004ee66000e2eb58e9f6a5c87ebe..0d5ac9e700defcd4d1f7871f47cb216c237d5e36 100644 (file)
@@ -13,7 +13,9 @@
 
 ## You should have received a copy of the GNU General Public License
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%LIBRARY%: $(%XLIBRARY%_OBJECTS) $(%XLIBRARY%_DEPENDENCIES) $(EXTRA_%XLIBRARY%_DEPENDENCIES) %DIRSTAMP%
-       %SILENT%-rm -f %LIBRARY%
-       %VERBOSE%$(%XLIBRARY%_AR) %LIBRARY% $(%XLIBRARY%_OBJECTS) $(%XLIBRARY%_LIBADD)
-       %SILENT%$(RANLIB) %LIBRARY%
+%LIBRARY%: $(%XLIBRARY%_OBJECTS) $(%XLIBRARY%_DEPENDENCIES) \
+           $(EXTRA_%XLIBRARY%_DEPENDENCIES)
+       %SILENT%rm -f $@
+       %SILENT%$(am__ensure_target_dir_exists)
+       %VERBOSE%$(%XLIBRARY%_AR) $@ $(%XLIBRARY%_OBJECTS) $(%XLIBRARY%_LIBADD)
+       %SILENT%$(RANLIB) $@
index b758880a01ba68dd5c96efb5bff990bfab0d5b78..371e31c13f9ae7d934c78ffa83470f04eef2912a 100644 (file)
@@ -13,5 +13,7 @@
 
 ## You should have received a copy of the GNU General Public License
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%LTLIBRARY%: $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_DEPENDENCIES) $(EXTRA_%XLTLIBRARY%_DEPENDENCIES) %DIRSTAMP%
+%LTLIBRARY%: $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_DEPENDENCIES) \
+             $(EXTRA_%XLTLIBRARY%_DEPENDENCIES)
+       %SILENT%$(am__ensure_target_dir_exists)
        %VERBOSE%$(%XLINK%) %RPATH% $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_LIBADD) $(LIBS)
index 699afb54030b72ea2b20e7ae6bcfcb5455346b4c..b444bd933e27017922c34281f8284c2957e0b682 100644 (file)
 
 ## You should have received a copy of the GNU General Public License
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
-%PROGRAM%%EXEEXT%: $(%XPROGRAM%_OBJECTS) $(%XPROGRAM%_DEPENDENCIES) $(EXTRA_%XPROGRAM%_DEPENDENCIES) %DIRSTAMP%
+%PROGRAM%%EXEEXT%: $(%XPROGRAM%_OBJECTS) $(%XPROGRAM%_DEPENDENCIES) \
+                   $(EXTRA_%XPROGRAM%_DEPENDENCIES)
 ## Remove program before linking.  Otherwise the link will fail if the
 ## program is running somewhere.  FIXME: this could be a loss if
 ## you're using an incremental linker.  Maybe we should think twice?
 ## Or maybe not... sadly, incremental linkers are rarer than losing
 ## systems.
-       @rm -f %PROGRAM%%EXEEXT%
+       %SILENT%rm -f $@
+       %SILENT%$(am__ensure_target_dir_exists)
        %VERBOSE%$(%XLINK%) $(%XPROGRAM%_OBJECTS) $(%XPROGRAM%_LDADD) $(LIBS)
index 4f2495c5ac83ad54ef7fac5d47151ca747bc3ed2..bdaf900f43d1835b4d40c654ca56dbd22d8cff90 100644 (file)
@@ -27,11 +27,7 @@ am__dist_common += %VTEXI% %STAMPVTI%
 ## (Not configure.ac, because not all setups define the version number
 ## in this file.)
 %STAMPVTI%: %TEXI% $(top_srcdir)/configure
-## It is wrong to have %STAMPVTI% dependent on %DIRSTAMP%, because
-## %STAMPVTI% is distributed and %DIRSTAMP% isn't: a distributed file
-## should never be dependent upon a non-distributed built file.
-## Therefore we ensure that %DIRSTAMP% exists in the rule.
-?DIRSTAMP?     test -f %DIRSTAMP% || $(MAKE) %DIRSTAMP%
+       @$(am__ensure_target_dir_exists)
        @(dir=.; test -f ./%TEXI% || dir=$(srcdir); \
        set `$(SHELL) %MDDIR%mdate-sh $$dir/%TEXI%`; \
        echo "@set UPDATED $$1 $$2 $$3"; \
index 73abd1f0fdec060e162b75bdc902656ee89cef9d..01a737f85a9aa34fa6a32ebf5cf9de4a46018c2f 100644 (file)
 ## You should have received a copy of the GNU General Public License
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-
 ?GENERIC_INFO?%%DEST_SUFFIX%: %%SOURCE_SUFFIX%
 ?!GENERIC_INFO?%DEST_INFO_PREFIX%%DEST_SUFFIX%: %SOURCE_INFO% %DEPS%
-## It is wrong to have 'info' files dependent on %DIRSTAMP%, because
-## 'info' files are distributed and %DIRSTAMP% isn't: a distributed file
-## should never be dependent upon a non-distributed built file.
-## Therefore we ensure that %DIRSTAMP% exists in the rule.
-?!INSRC??DIRSTAMP?     @test -f %DIRSTAMP% || $(MAKE) %DIRSTAMP%
+?!INSRC?       @$(am__ensure_target_dir_exists)
 ## Back up the info files before running makeinfo. This is the cheapest
 ## way to ensure that
 ## 1) If the texinfo file shrinks (or if you start using --no-split),
@@ -60,8 +55,9 @@
 INFO_DEPS += %DEST_INFO_PREFIX%%DEST_SUFFIX%
 
 ?GENERIC?%.dvi: %%SOURCE_SUFFIX%
-?!GENERIC?%DEST_PREFIX%.dvi: %SOURCE% %DEPS% %DIRSTAMP%
-       %AM_V_TEXI2DVI%TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+?!GENERIC?%DEST_PREFIX%.dvi: %SOURCE% %DEPS%
+       %AM_V_TEXI2DVI%$(am__ensure_target_dir_exists) && \
+       TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
 ## Must set MAKEINFO like this so that version.texi will be found even
 ## if it is in srcdir (-I $(srcdir) is set in %MAKEINFOFLAGS%).
        MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) %MAKEINFOFLAGS%' \
@@ -75,8 +71,9 @@ INFO_DEPS += %DEST_INFO_PREFIX%%DEST_SUFFIX%
 ?!GENERIC?     $(TEXI2DVI) %TEXIQUIET% --clean -o $@ `test -f '%SOURCE%' || echo '$(srcdir)/'`%SOURCE% %TEXIDEVNULL%
 
 ?GENERIC?%.pdf: %%SOURCE_SUFFIX%
-?!GENERIC?%DEST_PREFIX%.pdf: %SOURCE% %DEPS% %DIRSTAMP%
-       %AM_V_TEXI2PDF%TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
+?!GENERIC?%DEST_PREFIX%.pdf: %SOURCE% %DEPS%
+       %AM_V_TEXI2PDF%$(am__ensure_target_dir_exists) && \
+       TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
 ## Must set MAKEINFO like this so that version.texi will be found even
 ## if it is in srcdir (-I $(srcdir) is set in %MAKEINFOFLAGS%).
        MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) %MAKEINFOFLAGS%' \
@@ -90,7 +87,8 @@ INFO_DEPS += %DEST_INFO_PREFIX%%DEST_SUFFIX%
 ?!GENERIC?     $(TEXI2PDF) %TEXIQUIET% --clean -o $@ `test -f '%SOURCE%' || echo '$(srcdir)/'`%SOURCE% %TEXIDEVNULL%
 
 ?GENERIC?%.html: %%SOURCE_SUFFIX%
-?!GENERIC?%DEST_PREFIX%.html: %SOURCE% %DEPS% %DIRSTAMP%
+?!GENERIC?%DEST_PREFIX%.html: %SOURCE% %DEPS%
+       %SILENT%$(am__ensure_target_dir_exists)
 ## When --split (the default) is used, makeinfo will output a
 ## directory.  However it will not update the time stamp of a
 ## previously existing directory, and when the names of the nodes
@@ -114,8 +112,6 @@ INFO_DEPS += %DEST_INFO_PREFIX%%DEST_SUFFIX%
        fi
 
 ## If we are using the generic rules, we need separate dependencies.
-## (Don't wonder about %DIRSTAMP% here, this is used only by non-generic
-## rules.)
 if %?GENERIC_INFO%
 %DEST_INFO_PREFIX%%DEST_SUFFIX%: %SOURCE_REAL% %DEPS%
 endif %?GENERIC_INFO%
diff --git a/t/ensure-dir-exists.sh b/t/ensure-dir-exists.sh
new file mode 100755 (executable)
index 0000000..d47d22f
--- /dev/null
@@ -0,0 +1,70 @@
+#! /bin/sh
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test Automake-provided internal macro 'am__ensure_dir_exists'.
+
+am_create_testdir=empty
+. ./defs || Exit 1
+
+cp "$am_amdir"/header-vars.am . \
+  || fatal_ "fetching makefile fragment headers-vars.am"
+
+# Filter out Automake comments and things that would need configure
+# substitutions.
+LC_ALL=C $EGREP -v '(^##|=.*@[a-zA-Z0-9_]+@)' header-vars.am > defn.mk
+rm -f header-vars.am
+
+cat > Makefile << 'END'
+include ./defn.mk
+
+files = x/1 x/2 x/3
+
+all: $(files)
+.PHONY: all
+
+sanity-check:
+       $(warning $(call am__ensure_dir_exists,x))
+       $(if $(filter $(call am__ensure_dir_exists,x),:MKDIR_P:),, \
+             $(error am__ensure_dir_exists does not contain $$(MKDIR_P)))
+.PHONY: sanity-check
+
+$(files):
+       $(call am__ensure_dir_exists,x)
+       echo dummy > $@
+END
+
+# Sanity check.
+$MAKE sanity-check MKDIR_P=:MKDIR_P:
+
+# Basic usage.
+$MAKE MKDIR_P='mkdir -p'
+test -f x/1
+test -f x/2
+test -f x/3
+
+# Mkdir is not called uselessly.
+rm -rf x
+mkdir x
+$MAKE MKDIR_P=false
+
+# Mkdir is  not called too many times.
+rm -rf x
+$MAKE MKDIR_P=mkdir
+test -f x/1
+test -f x/2
+test -f x/3
+
+:
diff --git a/t/spy-wildcard.sh b/t/spy-wildcard.sh
new file mode 100755 (executable)
index 0000000..83ebde7
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that the behaviour of the $(wildcard) builtin in corner cases
+# matches the assumptions done in our recipes.
+
+. ./defs || Exit 1
+
+mkdir dir
+echo dummy > file
+
+cat > Makefile <<'END'
+.PHONY: test
+test:
+       test x'$(wildcard dir)'    = x'dir'
+       test x'$(wildcard file)'   = x'file'
+       test x'$(wildcard dir/)'   = x'dir/'
+       test x'$(wildcard file/.)' = x''
+END
+
+$MAKE test
+
+:
diff --git a/t/subobj-libtool.sh b/t/subobj-libtool.sh
new file mode 100755 (executable)
index 0000000..366e999
--- /dev/null
@@ -0,0 +1,95 @@
+#! /bin/sh
+# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test of subdir objects with libtool.
+
+required='cc libtoolize'
+. ./defs || Exit 1
+
+cat >> configure.ac << 'END'
+AC_PROG_CC
+AM_PROG_CC_C_O
+AM_PROG_AR
+AC_PROG_LIBTOOL
+AC_OUTPUT
+END
+
+cat > Makefile.am << 'END'
+AUTOMAKE_OPTIONS = subdir-objects
+noinst_LTLIBRARIES = libs/libfoo.la
+libs_libfoo_la_SOURCES = generic/1.c generic/2.c sub/subsub/3.c
+
+.PHONY: remake-single-object
+remake-single-object:
+       rm -rf generic
+       $(MAKE) generic/1.lo
+       test -f generic/1.lo
+       test ! -f generic/2.lo
+       rm -rf generic
+       $(MAKE) generic/2.lo
+       test ! -f generic/1.lo
+       test -f generic/2.lo
+       rm -rf sub generic
+       $(MAKE) sub/subsub/3.lo
+       test -f sub/subsub/3.lo
+       test ! -d generic
+END
+
+mkdir generic sub sub/subsub
+echo 'int one (void) { return 1; }' > generic/1.c
+echo 'int two (void) { return 2; }' > generic/2.c
+echo 'int three (void) { return 3; }' > sub/subsub/3.c
+
+libtoolize
+$ACLOCAL
+
+$AUTOMAKE --add-missing 2>stderr || { cat stderr >&2; Exit 1; }
+cat stderr >&2
+
+# Make sure compile is installed, and that Automake says so.
+grep 'install.*compile' stderr
+test -f compile
+
+grep '[^/][123]\.lo' Makefile.in && Exit 1
+
+$AUTOCONF
+
+mkdir build
+cd build
+../configure
+$MAKE
+
+test -d libs
+test -d generic
+test -d sub/subsub
+
+# The libraries and executables are not uselessly remade.
+: > xstamp
+$sleep
+echo dummy > libs/change-dir-timestamp
+echo dummy > generic/change-dir-timestamp
+echo dummy > sub/change-dir-timestamp
+echo dummy > sub/subsub/change-dir-timestamp
+$MAKE
+is_newest xstamp libs/libfoo.la
+
+$MAKE remake-single-object
+
+# VPATH builds must work also with dependency tracking disabled.
+# Also sanity check the distribution.
+$MAKE distcheck DISTCHECK_CONFIGURE_FLAGS=--disable-dependency-tracking
+
+:
index b7f6597d49dfaa8577cb34fd3d609c5deb9144fe..1265a43d0192ebdbfed343aaece6b027611122ac 100755 (executable)
 
 # Test of subdir objects with C.
 
+required=cc
 . ./defs || Exit 1
 
 cat >> configure.ac << 'END'
 AC_PROG_CC
 AM_PROG_CC_C_O
+AM_PROG_AR
+AC_PROG_RANLIB
+AC_OUTPUT
 END
 
 cat > Makefile.am << 'END'
 AUTOMAKE_OPTIONS = subdir-objects
-bin_PROGRAMS = wish
-wish_SOURCES = generic/a.c generic/b.c
+bin_PROGRAMS = progs/wish
+lib_LIBRARIES = libs/libhope.a
+progs_wish_SOURCES = generic/a.c generic/b.c
+libs_libhope_a_SOURCES = sub/sub2/foo.c
+
+.PHONY: remake-single-object
+remake-single-object:
+       rm -rf generic
+       $(MAKE) generic/a.$(OBJEXT)
+       test -f generic/a.$(OBJEXT)
+       test ! -f generic/b.$(OBJEXT)
+       rm -rf generic
+       $(MAKE) generic/b.$(OBJEXT)
+       test ! -f generic/a.$(OBJEXT)
+       test -f generic/b.$(OBJEXT)
+       rm -rf sub generic
+       $(MAKE) sub/sub2/foo.$(OBJEXT)
+       test -f sub/sub2/foo.$(OBJEXT)
+       test ! -d generic
+END
+
+mkdir generic sub sub/sub2
+cat > generic/a.c <<END
+int main (void)
+{
+  extern int i;
+  return i;
+}
+END
+echo 'int i = 0;' > generic/b.c
+
+cat > sub/sub2/foo.c <<'END'
+int answer (void)
+{
+  return 42;
+}
 END
 
 $ACLOCAL
 $AUTOMAKE --add-missing 2>stderr || { cat stderr >&2; Exit 1; }
 cat stderr >&2
+
 # Make sure compile is installed, and that Automake says so.
 grep 'install.*compile' stderr
 test -f compile
 
-grep '^generic/a\.\$(OBJEXT):' Makefile.in
-grep '[^/]a\.\$(OBJEXT)' Makefile.in && Exit 1
+$EGREP '[^/](a|b|foo)\.\$(OBJEXT)' Makefile.in && Exit 1
+
+$AUTOCONF
+
+mkdir build
+cd build
+../configure
+$MAKE
+
+test -d progs
+test -d libs
+test -d generic
+test -d sub/sub2
+
+if test -f progs/wish; then
+  EXEEXT=
+elif test -f progs/wish.exe; then
+  EXEEXT=.exe
+else
+  fatal_ "couldn't determine extension of executables"
+fi
+
+# The libraries and executables are not uselessly remade.
+: > xstamp
+$sleep
+echo dummy > progs/change-dir-timestamp
+echo dummy > libs/change-dir-timestamp
+echo dummy > generic/change-dir-timestamp
+echo dummy > sub/change-dir-timestamp
+echo dummy > sub/sub2/change-dir-timestamp
+$MAKE
+is_newest xstamp progs/wish$EXEEXT libs/libhope.a
+
+$MAKE remake-single-object
 
-# Opportunistically test for a different bug.
-grep '^generic/b\.\$(OBJEXT):.*dirstamp' Makefile.in
+# Must work also with dependency tracking disabled.
+# Also sanity check the distribution.
+$MAKE distcheck DISTCHECK_CONFIGURE_FLAGS=--disable-dependency-tracking
 
 :
diff --git a/t/subobj6.sh b/t/subobj6.sh
deleted file mode 100755 (executable)
index 2f902f2..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#! /bin/sh
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-# Test of subdir make distclean rules.
-# From Robert Collins.
-
-required=cc
-. ./defs || Exit 1
-
-cat >> configure.ac << 'END'
-AM_PROG_CC_C_O
-AC_OUTPUT
-END
-
-cat > Makefile.am << 'END'
-AUTOMAKE_OPTIONS = subdir-objects
-bin_PROGRAMS = wish
-wish_SOURCES = generic/a.c
-
-test-all: all
-       test -f generic/$(am__dirstamp)
-test-mostlyclean: mostlyclean
-       test ! -f generic/a.o
-test-distclean: distclean
-       test ! -f generic/$(am__dirstamp)
-END
-
-mkdir generic
-cat > generic/a.c << 'END'
-#include <stdio.h>
-int main ()
-{
-   printf ("maude!\n");
-   return 0;
-}
-END
-
-$ACLOCAL
-$AUTOCONF
-$AUTOMAKE --include-deps --copy --add-missing
-
-mkdir build
-cd build
-
-../configure
-$MAKE test-all
-$MAKE test-mostlyclean
-$MAKE test-distclean
-
-cd ..
-
-# Now test without the subdir.
-cat > Makefile.am << 'END'
-AUTOMAKE_OPTIONS = subdir-objects
-bin_PROGRAMS = wish
-wish_SOURCES = a.c
-END
-
-mv generic/a.c a.c
-
-$ACLOCAL
-$AUTOCONF
-$AUTOMAKE --include-deps --copy --add-missing
-
-mkdir build2
-cd build2
-
-../configure
-$MAKE
-$MAKE mostlyclean
-
-: