automake-ng
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Automake-NG] [PATCH] [ng] dirstamp: remove, use inlined parent director


From: Stefano Lattarini
Subject: [Automake-NG] [PATCH] [ng] dirstamp: remove, use inlined parent directory creation instead
Date: Mon, 21 May 2012 16:19:07 +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 <address@hidden>
---

 I intend to push this in a couple of days if there is no objection.

 automake.in            |  120 ++++--------------------------------------------
 lib/am/depend2.am      |   14 ++++--
 lib/am/header-vars.am  |   17 +++++++
 lib/am/library.am      |   10 ++--
 lib/am/ltlibrary.am    |    4 +-
 lib/am/program.am      |    6 ++-
 lib/am/texi-vers.am    |    6 +--
 lib/am/texibuild.am    |   22 ++++-----
 t/ensure-dir-exists.sh |   70 ++++++++++++++++++++++++++++
 t/spy-wildcard.sh      |   36 +++++++++++++++
 t/subobj-libtool.sh    |   95 ++++++++++++++++++++++++++++++++++++++
 t/subobj.sh            |   84 ++++++++++++++++++++++++++++++---
 t/subobj6.sh           |   85 ----------------------------------
 13 files changed, 339 insertions(+), 230 deletions(-)
 create mode 100755 t/ensure-dir-exists.sh
 create mode 100755 t/spy-wildcard.sh
 create mode 100755 t/subobj-libtool.sh
 delete mode 100755 t/subobj6.sh

diff --git a/automake.in b/automake.in
index 11d1f0b..e61bfbd 100644
--- a/automake.in
+++ b/automake.in
@@ -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"
-                   . "address@hidden(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
diff --git a/lib/am/depend2.am b/lib/am/depend2.am
index 81660c1..e68bba7 100644
--- a/lib/am/depend2.am
+++ b/lib/am/depend2.am
@@ -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@
diff --git a/lib/am/header-vars.am b/lib/am/header-vars.am
index d620c89..522dfc0 100644
--- a/lib/am/header-vars.am
+++ b/lib/am/header-vars.am
@@ -16,6 +16,23 @@
 
 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
diff --git a/lib/am/library.am b/lib/am/library.am
index 686b648..0d5ac9e 100644
--- a/lib/am/library.am
+++ b/lib/am/library.am
@@ -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) $@
diff --git a/lib/am/ltlibrary.am b/lib/am/ltlibrary.am
index b758880..371e31c 100644
--- a/lib/am/ltlibrary.am
+++ b/lib/am/ltlibrary.am
@@ -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)
diff --git a/lib/am/program.am b/lib/am/program.am
index 699afb5..b444bd9 100644
--- a/lib/am/program.am
+++ b/lib/am/program.am
@@ -13,11 +13,13 @@
 
 ## 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)
diff --git a/lib/am/texi-vers.am b/lib/am/texi-vers.am
index 4f2495c..bdaf900 100644
--- a/lib/am/texi-vers.am
+++ b/lib/am/texi-vers.am
@@ -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"; \
diff --git a/lib/am/texibuild.am b/lib/am/texibuild.am
index 73abd1f..01a737f 100644
--- a/lib/am/texibuild.am
+++ b/lib/am/texibuild.am
@@ -14,14 +14,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/>.
 
-
 ?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
index 0000000..d47d22f
--- /dev/null
+++ b/t/ensure-dir-exists.sh
@@ -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 '(^##|address@hidden@)' 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
index 0000000..83ebde7
--- /dev/null
+++ b/t/spy-wildcard.sh
@@ -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
index 0000000..366e999
--- /dev/null
+++ b/t/subobj-libtool.sh
@@ -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
+
+:
diff --git a/t/subobj.sh b/t/subobj.sh
index b7f6597..1265a43 100755
--- a/t/subobj.sh
+++ b/t/subobj.sh
@@ -16,30 +16,102 @@
 
 # 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
index 2f902f2..0000000
--- a/t/subobj6.sh
+++ /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
-
-:
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]