[PATCH 3/4] compile: don't place built object files in $(srcdir), ever ...

Stefano Lattarini <[email protected]>
Newsgroups gmane.comp.sysutils.automake.patches
Message-ID <860d21b8854eb61dd79f37f1be564af7efa916c6.1420414665.git.stefano.lattarini@gmail.com>
... even when a source file is specified as '$(srdir)/foo.c' or
'$(top_srcdir)/bar.c'. And ditto for dependency-tracking makefile
fragments (those under '.deps' directories).

Such issues used to occur when the 'subdir-objects' option was given.

This change should fix the second and last part of automake bug#13928.
See also bug#16375 and bug#15293.

* NEWS: Update.
* bin/automake.in (handle_single_transform): Make sure object files
and dependency-tracking makefile fragments coming from source like
'$(srcdir)/foo.c' and '$(top_srcdir)/bar.c' are placed respectively
under $(builddir) and $(top_builddir).
* t/subobj-vpath-pr13928.sh: Enhance to expose even more aspects
of the bug we've just fixed.
* t/subobj-pr13928-more-langs.sh: New test, similar to the one above,
but with non-C languages as well.
* t/list-of-tests.mk (XFAIL_TESTS): Remove 'subobj-vpath-pr13928.sh',
it's now supposed to pass.
(handwritten_TESTS): Add 'subobj-pr13928-more-langs.sh'.

Signed-off-by: Stefano Lattarini <[email protected]>
---
 NEWS                           |  21 ++++++-
 bin/automake.in                |  50 ++++++++++-----
 t/list-of-tests.mk             |   2 +-
 t/subobj-pr13928-more-langs.sh | 138 +++++++++++++++++++++++++++++++++++++++++
 t/subobj-vpath-pr13928.sh      |  89 ++++++++++++++++++++++----
 5 files changed, 269 insertions(+), 31 deletions(-)
 create mode 100644 t/subobj-pr13928-more-langs.sh

diff --git a/NEWS b/NEWS
index a930049..eb3bc6f 100644
--- a/NEWS
+++ b/NEWS
@@ -67,8 +67,8 @@ New in 1.16:
 * Bugs fixed:
 
   - Automatic dependency tracking has been fixed to work also when the
-    subdir-object option is used and some 'foo_SOURCES' definition contains
-    unexpanded references to make variables, as in, e.g.:
+    'subdir-object' option is used and some 'foo_SOURCES' definition
+    contains unexpanded references to make variables, as in, e.g.:
 
         a_src = sources/libs/aaa
         b_src = sources/bbb
@@ -78,7 +78,7 @@ New in 1.16:
     tracking information will be correctly placed under the directories
     named 'sources/libs/aaa/.deps' and 'sources/bbb/.deps', rather than
     mistakenly under directories named (literally!) '$(src_a)/.deps' and
-    '$(src_b)/.deps' (this was automake bug#13928).
+    '$(src_b)/.deps' (this was the first part of automake bug#13928).
 
     Notice that in order to fix this bug we had to slightly change the
     semantics of how config.status bootstraps the makefile fragments
@@ -88,6 +88,21 @@ New in 1.16:
     using a private target that is only meant to bootstrap the required
     makefile fragments.
 
+  - The 'subdir-object' option no longer causes object files corresponding
+    to source files specified with an explicit '$(srcdir)' component to be
+    placed in the source tree rather than in the build tree.
+
+    For example, if Makefile.am contains:
+
+        AUTOMAKE_OPTIONS = subdir-objects
+        foo_SOURCES = $(srcdir)/foo.c $(srcdir)/s/bar.c $(top_srcdir)/baz.c
+
+    then "make all" will create 'foo.o' and 's/bar.o' in $(builddir) rather
+    than in $(srcdir), and will create 'baz.o' in $(top_builddir) rather
+    than in $(top_srcdir).
+
+    This was the second part of automake bug#13928.
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 New in 1.15:
diff --git a/bin/automake.in b/bin/automake.in
index f19be92..d8ecca5 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -1617,9 +1617,9 @@ sub handle_single_transform
 	my $renamed = 0;
 	my ($linker, $object);
 
-	# This records whether we've seen a derived source file (e.g.
-	# yacc output).
-	my $derived_source = 0;
+        # This records whether we've seen a derived source file (e.g., yacc
+        # or lex output).
+        my $derived_source;
 
 	# This holds the 'aggregate context' of the file we are
 	# currently examining.  If the file is compiled with
@@ -1667,17 +1667,36 @@ sub handle_single_transform
 	    # Now extract linker and other info.
 	    $linker = $lang->linker;
 
-	    my $this_obj_ext;
-	    if (defined $source_extension)
-	    {
-		$this_obj_ext = $source_extension;
-		$derived_source = 1;
-	    }
-	    else
-	    {
-		$this_obj_ext = $obj;
-	    }
-	    $object = $base . $this_obj_ext;
+            my $this_obj_ext;
+            if (defined $source_extension)
+              {
+                $this_obj_ext = $source_extension;
+                $derived_source = 1;
+              }
+            else
+              {
+                $this_obj_ext = $obj;
+                $derived_source = 0;
+                # Don't ever place built object files in $(srcdir),
+                # even when sources are specified explicitly as (say)
+                # '$(srcdir)/foo.c' or '$(top_srcdir)/foo.c'.
+                # See automake bug#13928.
+                my @d = split '/', $directory;
+                if (@d > 0 && option 'subdir-objects')
+                  {
+                    my $d = $d[0];
+                    if ($d eq '$(srcdir)' or $d eq '${srcdir}')
+                      {
+                        shift @d;
+                      }
+                    elsif ($d eq '$(top_srcdir)' or $d eq '${top_srcdir}')
+                      {
+                        $d[0] = '$(top_builddir)';
+                      }
+                    $directory = join '/', @d;
+                  }
+              }
+            $object = $base . $this_obj_ext;
 
 	    if ($have_per_exec_flags)
 	    {
@@ -1710,8 +1729,7 @@ sub handle_single_transform
 		$renamed = 1;
 	    }
 
-	    # If rewrite said it was ok, put the object into a
-	    # subdir.
+	    # If rewrite said it was ok, put the object into a subdir.
 	    if ($directory ne '')
 	    {
               if ($r == LANG_SUBDIR)
diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk
index 5085780..ddf5fdf 100644
--- a/t/list-of-tests.mk
+++ b/t/list-of-tests.mk
@@ -41,7 +41,6 @@ t/java-nobase.sh \
 t/objext-pr10128.sh \
 t/remake-timing-bug-pr8365.sh \
 t/lex-subobj-nodep.sh \
-t/subobj-vpath-pr13928.sh \
 t/remake-am-pr10111.sh \
 t/remake-m4-pr10111.sh \
 $(perl_fake_XFAIL_TESTS)
@@ -1063,6 +1062,7 @@ t/subobj-clean-pr10697.sh \
 t/subobj-clean-lt-pr10697.sh \
 t/subobj-indir-pr13928.sh \
 t/subobj-vpath-pr13928.sh \
+t/subobj-pr13928-more-langs.sh \
 t/subpkg.sh \
 t/subpkg2.sh \
 t/subpkg3.sh \
diff --git a/t/subobj-pr13928-more-langs.sh b/t/subobj-pr13928-more-langs.sh
new file mode 100644
index 0000000..323e248
--- /dev/null
+++ b/t/subobj-pr13928-more-langs.sh
@@ -0,0 +1,138 @@
+#! /bin/sh
+# Copyright (C) 2015 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/>.
+
+# Expose part of automake bug#13928, also for non-C languages: if the
+# subdir-objects option is in use and a source file is listed in a
+# _SOURCES variable with a leading $(srcdir) component, Automake will
+# generate a Makefile that tries to create the corresponding object
+# file in $(srcdir) as well.
+
+required='cc c++ fortran77 fortran'
+. test-init.sh
+
+cat >> configure.ac <<'END'
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_F77
+AC_PROG_FC
+AM_CONDITIONAL([OBVIOUS], [:])
+AC_CONFIG_FILES([sub/Makefile])
+AC_OUTPUT
+END
+
+cat > Makefile.am <<'END'
+AUTOMAKE_OPTIONS = subdir-objects
+SUBDIRS = sub
+
+LESS = m/o/r/e
+
+noinst_PROGRAMS = test test2
+test_SOURCES = $(srcdir)/test.f90
+
+test2_SOURCES = $(indir)
+
+indir = ${indir2} $(empty)
+indir2 =
+if OBVIOUS
+indir2 += ${srcdir}/$(LESS)///test.f
+else
+endif
+
+test-objs:
+	ls -la @srcdir@ .
+        :
+	test ! -f @srcdir@/test.$(OBJEXT)
+	test -f test.$(OBJEXT)
+	test ! -f @srcdir@/m/o/r/e/test.$(OBJEXT)
+	test -f m/o/r/e/test.$(OBJEXT)
+        :
+	test ! -f @srcdir@/bar.$(OBJEXT)
+	test -f bar.$(OBJEXT)
+	test ! -f @srcdir@/baz.$(OBJEXT)
+	test -f baz.$(OBJEXT)
+        :
+	test ! -d @srcdir@/$(DEPDIR)
+	test ! -d @srcdir@/m/o/r/e/$(DEPDIR)
+	test -d $(DEPDIR)
+	test -d m/o/r/e/$(DEPDIR)
+
+check-local: test-objs
+END
+
+mkdir sub
+cat > sub/Makefile.am <<'END'
+AUTOMAKE_OPTIONS = subdir-objects
+bin_PROGRAMS = foo
+foo = baz
+foo_SOURCES = foo.h \
+	      $(top_srcdir)/bar.cc \
+              ${top_srcdir}/$(foo).c
+END
+
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+
+mkfiles='Makefile.in sub/Makefile.in'
+$EGREP '(test|ba[rz])\.|DEPDIR|dirstamp|srcdir' $mkfiles # For debugging.
+$EGREP '\$.(top_)?srcdir./(test|ba[rz]|\$.foo.)\.[o$]' $mkfiles && exit 1
+$FGREP '\$.(top_)?srcdir./.*$(am__dirstamp)' $mkfiles && exit 1
+$FGREP '\$.(top_)?srcdir./.*$(DEPDIR)' $mkfiles && exit 1
+
+cat > test.f90 <<'EOF'
+      program foo
+      stop
+      end
+EOF
+
+mkdir -p m/o/r/e
+cp test.f90 m/o/r/e/test.f
+
+cat > sub/foo.h <<'END'
+#ifdef __cplusplus
+extern "C"
+#endif
+int foo (void);
+END
+
+cat > bar.cc <<'END'
+#include "foo.h"
+#include <iostream>
+int main (void)
+{
+  std::cout << "OK!" << "\n";
+  return foo ();
+}
+END
+
+cat > baz.c <<'END'
+#include "foo.h"
+int foo (void)
+{
+  return 0;
+}
+END
+
+mkdir build
+cd build
+../configure
+
+$MAKE
+$MAKE test-objs
+$MAKE distcheck
+
+:
diff --git a/t/subobj-vpath-pr13928.sh b/t/subobj-vpath-pr13928.sh
index 8c3a6c5..24eff1d 100644
--- a/t/subobj-vpath-pr13928.sh
+++ b/t/subobj-vpath-pr13928.sh
@@ -22,39 +22,106 @@
 required=cc
 . test-init.sh
 
-cat >> configure.ac << 'END'
+cat >> configure.ac <<'END'
 AC_PROG_CC
 AM_PROG_CC_C_O
+AM_CONDITIONAL([OBVIOUS], [:])
+AC_CONFIG_FILES([sub/Makefile])
 AC_OUTPUT
 END
 
 cat > Makefile.am <<'END'
 AUTOMAKE_OPTIONS = subdir-objects
-noinst_PROGRAMS = test
+SUBDIRS = sub
+
+LESS = more
+
+noinst_PROGRAMS = test test2
 test_SOURCES = $(srcdir)/test.c
+
+test2_SOURCES = $(indir)
+
+indir =
+if OBVIOUS
+indir += ${srcdir}/$(LESS)/test.c
+else
+endif
+
 test-objs:
-	test ! -f '@srcdir@/test.$(OBJEXT)'
+	ls -la @srcdir@ .
+        :
+	test ! -f @srcdir@/test.$(OBJEXT)
 	test -f test.$(OBJEXT)
+	test ! -f @srcdir@/more/test.$(OBJEXT)
+	test -f more/test.$(OBJEXT)
+        :
+	test ! -f @srcdir@/bar.$(OBJEXT)
+	test -f bar.$(OBJEXT)
+	test ! -f @srcdir@/baz.$(OBJEXT)
+	test -f baz.$(OBJEXT)
+        :
+	test ! -d @srcdir@/$(DEPDIR)
+	test ! -d @srcdir@/more/$(DEPDIR)
+	test -d $(DEPDIR)
+	test -d more/$(DEPDIR)
+
+check-local: test-objs
+END
+
+mkdir sub
+cat > sub/Makefile.am <<'END'
+AUTOMAKE_OPTIONS = subdir-objects
+bin_PROGRAMS = foo
+foo_SOURCES = foo.h \
+	      $(top_srcdir)/bar.c \
+              ${top_srcdir}/baz.c
+END
+
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+
+mkfiles='Makefile.in sub/Makefile.in'
+$EGREP '(test|ba[rz])\.|DEPDIR|dirstamp|srcdir' $mkfiles # For debugging.
+$EGREP '\$.(top_)?srcdir./(test|ba[rz])\.[o$]' $mkfiles && exit 1
+$FGREP '\$.(top_)?srcdir./.*$(am__dirstamp)' $mkfiles && exit 1
+$FGREP '\$.(top_)?srcdir./.*$(DEPDIR)' $mkfiles && exit 1
+
+cat > test.c <<'END'
+int main (void)
+{
+  return 0;
+}
 END
 
-$ACLOCAL && $AUTOCONF && $AUTOMAKE -a || fatal_ "autotools failed"
+mkdir more
+cp test.c more/test.c
 
-$EGREP 'test\.|DEPDIR|dirstamp|srcdir' Makefile.in || : # For debugging.
-$EGREP '\$.srcdir./test\.[o$]' Makefile.in && exit 1
-$FGREP '$(srcdir)/$(am__dirstamp)' Makefile.in && exit 1
-$FGREP '$(srcdir)/$(DEPDIR)' Makefile.in && exit 1
+echo 'int foo (void);' > sub/foo.h
 
-cat > test.c << 'END'
+cat > bar.c <<'END'
+#include "foo.h"
 int main (void)
 {
+  return foo ();
+}
+END
+
+cat > baz.c <<'END'
+#include "foo.h"
+int foo (void)
+{
   return 0;
 }
 END
 
-mkdir build && cd build || fatal "preparation of build directory failed"
-../configure || fatal_ "./configure failed"
+mkdir build
+cd build
+../configure
 
 $MAKE
 $MAKE test-objs
+$MAKE distcheck
 
 :
-- 
2.1.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.