summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--NEWS7
-rw-r--r--automake.in35
-rw-r--r--doc/automake.texi28
-rw-r--r--lib/am/subdirs.am17
-rw-r--r--m4/extra-recurs.m417
-rw-r--r--t/list-of-tests.mk12
-rwxr-xr-xt/recurs-user-deeply-nested.sh97
-rwxr-xr-xt/recurs-user-indir.sh99
-rwxr-xr-xt/recurs-user-keep-going.sh95
-rwxr-xr-xt/recurs-user-many.sh73
-rwxr-xr-xt/recurs-user-no-subdirs.sh52
-rwxr-xr-xt/recurs-user-no-top-level.sh50
-rwxr-xr-xt/recurs-user-override.sh68
-rwxr-xr-xt/recurs-user-phony.sh64
-rwxr-xr-xt/recurs-user-wrap.sh59
-rwxr-xr-xt/recurs-user.sh81
-rwxr-xr-xt/recurs-user2.sh103
-rwxr-xr-xt/remake-recurs-user.sh89
19 files changed, 1040 insertions, 7 deletions
diff --git a/Makefile.am b/Makefile.am
index 9e5512e41..829c31f26 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -266,6 +266,7 @@ dist_automake_ac_DATA = \
m4/depend.m4 \
m4/depout.m4 \
m4/dmalloc.m4 \
+ m4/extra-recurs.m4 \
m4/gcj.m4 \
m4/init.m4 \
m4/install-sh.m4 \
diff --git a/NEWS b/NEWS
index 54acc7a5c..08ca231c1 100644
--- a/NEWS
+++ b/NEWS
@@ -81,6 +81,13 @@ New in 1.13:
script to avoid such issues; a simple example is provided in the
"CVS and generated files" chapter of the automake manual.
+* Recursive targets:
+
+ The user can now define his own recursive targets that recurse
+ in the directories specified in $(SUBDIRS). This can be done by
+ specifying the name of such targets in invocations of the new
+ 'AM_EXTRA_RECURSIVE_TARGETS' m4 macro.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
New in 1.12.2:
diff --git a/automake.in b/automake.in
index 11e750d5a..b7b03f34b 100644
--- a/automake.in
+++ b/automake.in
@@ -362,6 +362,9 @@ my $ac_gettext_location;
# Whether AM_GNU_GETTEXT_INTL_SUBDIR has been seen.
my $seen_gettext_intl = 0;
+# The arguments of the AM_EXTRA_RECURSIVE_TARGETS call (if any).
+my @extra_recursive_targets = ();
+
# Lists of tags supported by Libtool.
my %libtool_tags = ();
# 1 if Libtool uses LT_SUPPORTED_TAG. If it does, then it also
@@ -4546,6 +4549,32 @@ sub handle_all ($)
}
}
+# Generate helper targets for user recursion, where needed.
+sub handle_user_recursion ()
+{
+ return unless @extra_recursive_targets;
+
+ define_pretty_variable ('am__extra_recursive_targets', TRUE, INTERNAL,
+ map { "$_-recursive" } @extra_recursive_targets);
+ my $aux = var ('SUBDIRS') ? 'recursive' : 'am';
+ foreach my $target (@extra_recursive_targets)
+ {
+ # This allows the default target's rules to be overridden in
+ # Makefile.am.
+ user_phony_rule ($target);
+ depend ("$target", "$target-$aux");
+ depend ("$target-am", "$target-local");
+ # Every user-defined recursive target 'foo' *must* have a valid
+ # associated 'foo-local' rule; we define it as an empty rule by
+ # default, so that the user can transparently extend it in his
+ # own Makefile.am.
+ pretty_print_rule ("$target-local:");
+ # $target-recursive might as well be undefined, so do not add
+ # it here; it's taken care of in subdirs.am anyway.
+ depend (".PHONY", "$target-am", "$target-local");
+ }
+}
+
# &do_check_merge_target ()
# -------------------------
@@ -5163,6 +5192,7 @@ sub scan_autoconf_traces ($)
AC_SUBST_TRACE => 1,
AM_AUTOMAKE_VERSION => 1,
AM_CONDITIONAL => 2,
+ _AM_EXTRA_RECURSIVE_TARGETS => 1,
AM_GNU_GETTEXT => 0,
AM_GNU_GETTEXT_INTL_SUBDIR => 0,
AM_INIT_AUTOMAKE => 0,
@@ -5323,6 +5353,10 @@ sub scan_autoconf_traces ($)
{
$configure_cond{$args[1]} = $where;
}
+ elsif ($macro eq '_AM_EXTRA_RECURSIVE_TARGETS')
+ {
+ push @extra_recursive_targets, split (' ', $args[1]);
+ }
elsif ($macro eq 'AM_GNU_GETTEXT')
{
$seen_gettext = $where;
@@ -7998,6 +8032,7 @@ sub generate_makefile ($$)
handle_data;
handle_headers;
handle_subdirs;
+ handle_user_recursion;
handle_tags;
handle_minor_options;
# Must come after handle_programs so that %known_programs is up-to-date.
diff --git a/doc/automake.texi b/doc/automake.texi
index 87776b354..38f91593f 100644
--- a/doc/automake.texi
+++ b/doc/automake.texi
@@ -4204,6 +4204,34 @@ will be built. It is customary to arrange test directories to be
built after everything else since they are meant to test what has
been constructed.
+In addition to the built-in recursive targets defined by Automake
+(@code{all}, @code{check}, etc.), the developer can also define his
+own recursive targets. That is done by passing the names of such
+targets as arguments to the m4 macro @code{AM_EXTRA_RECURSIVE_TARGETS}
+in @file{configure.ac}. Automake generates rules to handle the
+recursion for such targets; and the developer can define real actions
+for them by defining corresponding @code{-local} targets.
+
+@example
+% @kbd{cat configure.ac}
+AC_INIT([pkg-name], [1.0]
+AM_INIT_AUTOMAKE
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_CONFIG_FILES([Makefile sub/Makefile sub/src/Makefile])
+AC_OUTPUT
+% @kbd{cat Makefile.am}
+SUBDIRS = sub
+foo-local:
+ @@echo This will be run by "make foo".
+% @kbd{cat sub/Makefile.am}
+SUBDIRS = src
+% @kbd{cat sub/src/Makefile.am}
+foo-local:
+ @@echo This too will be run by a "make foo" issued either in
+ @@echo the 'sub/src/' directory, the 'sub/' directory, or the
+ @@echo top-level directory.
+@end example
+
@node Conditional Subdirectories
@section Conditional Subdirectories
@cindex Subdirectories, building conditionally
diff --git a/lib/am/subdirs.am b/lib/am/subdirs.am
index 3fc28884b..005483a9a 100644
--- a/lib/am/subdirs.am
+++ b/lib/am/subdirs.am
@@ -17,13 +17,17 @@
RECURSIVE_TARGETS += all-recursive check-recursive installcheck-recursive
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
+
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+
## All documented targets which invoke 'make' recursively, or depend
-## on targets that do so.
-AM_RECURSIVE_TARGETS += $(RECURSIVE_TARGETS:-recursive=) \
- $(RECURSIVE_CLEAN_TARGETS:-recursive=)
+## on targets that do so. GNUmakefile from gnulib depends on this.
+AM_RECURSIVE_TARGETS += $(am__recursive_targets:-recursive=)
-.PHONY: $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS)
-.MAKE: $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS)
+.PHONY .MAKE: $(am__recursive_targets)
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
@@ -32,7 +36,7 @@ AM_RECURSIVE_TARGETS += $(RECURSIVE_TARGETS:-recursive=) \
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
-$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
+$(am__recursive_targets):
## Using $failcom allows "-k" to keep its natural meaning when running a
## recursive rule.
@fail= failcom='exit 1'; \
@@ -66,7 +70,6 @@ $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
-
mostlyclean: mostlyclean-recursive
clean: clean-recursive
distclean: distclean-recursive
diff --git a/m4/extra-recurs.m4 b/m4/extra-recurs.m4
new file mode 100644
index 000000000..7b7ecc71b
--- /dev/null
+++ b/m4/extra-recurs.m4
@@ -0,0 +1,17 @@
+# AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*-
+
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_EXTRA_RECURSIVE_TARGETS
+# --------------------------
+# Define the list of user recursive targets. This macro exists only to
+# be traced by Automake, which will ensure that a proper definition of
+# user-defined recursive targets (and associated rules) is propagated
+# into all the generated Makefiles.
+AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], [_$0(m4_flatten([$1]))])
+# TODO: We should really reject non-literal arguments here...
+m4_define([_AM_EXTRA_RECURSIVE_TARGETS], [])
diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk
index 4b1682264..919b6f0ce 100644
--- a/t/list-of-tests.mk
+++ b/t/list-of-tests.mk
@@ -884,6 +884,17 @@ t/python-dist.sh \
t/python-vars.sh \
t/python-virtualenv.sh \
t/python-pr10995.sh \
+t/recurs-user.sh \
+t/recurs-user2.sh \
+t/recurs-user-deeply-nested.sh \
+t/recurs-user-indir.sh \
+t/recurs-user-keep-going.sh \
+t/recurs-user-many.sh \
+t/recurs-user-no-subdirs.sh \
+t/recurs-user-no-top-level.sh \
+t/recurs-user-override.sh \
+t/recurs-user-phony.sh \
+t/recurs-user-wrap.sh \
t/relativize.tap \
t/remake.sh \
t/remake1a.sh \
@@ -907,6 +918,7 @@ t/remake11.sh \
t/remake12.sh \
t/remake-all-1.sh \
t/remake-all-2.sh \
+t/remake-recurs-user.sh \
t/remake-subdir-from-subdir.sh \
t/remake-subdir-gnu.sh \
t/remake-subdir.sh \
diff --git a/t/recurs-user-deeply-nested.sh b/t/recurs-user-deeply-nested.sh
new file mode 100755
index 000000000..c9e5c1f5c
--- /dev/null
+++ b/t/recurs-user-deeply-nested.sh
@@ -0,0 +1,97 @@
+#! /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 recursion on user-defined targets can be made to work
+# with "deeply" nested uses of $(SUBDIRS).
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([
+ sub1/Makefile
+ sub1/sub2/Makefile
+ sub1/sub2/sub3/Makefile
+ sub1/sub2/sub3/sub4/Makefile
+])
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_OUTPUT
+END
+
+dirs='sub1 sub1/sub2 sub1/sub2/sub3 sub1/sub2/sub3/sub4'
+
+mkdir $dirs
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub1
+
+foo-local:
+ cp sub1/foo foo
+MOSTLYCLEANFILES = foo
+
+.PHONY: test
+test:
+ echo 'It works!' > exp
+ diff exp foo
+ diff exp sub1/foo
+ test ! -f sub1/sub2/foo
+ test ! -f sub1/sub2/sub3/foo
+ diff exp sub1/sub2/sub3/sub4/foo
+ rm -f exp
+
+all-local: foo
+check-local: test
+END
+
+cat > sub1/Makefile.am <<'END'
+SUBDIRS = sub2
+foo-local:
+ test ! -f sub2/sub3/foo
+ cp sub2/sub3/sub4/foo foo
+MOSTLYCLEANFILES = foo
+END
+
+# Here we deliberately lack an explicit definition the 'foo-local'
+# target; that shouldn't stop 'foo' recursion into subdirectory
+# 'sub3/sub4'.
+echo SUBDIRS = sub3 > sub1/sub2/Makefile.am
+echo SUBDIRS = sub4 > sub1/sub2/sub3/Makefile.am
+
+cat > sub1/sub2/sub3/sub4/Makefile.am <<'END'
+foo-local:
+ echo 'It works!' > foo
+MOSTLYCLEANFILES = foo
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+for d in $dirs; do
+ $FGREP foo-am $d/Makefile.in || exit 1
+ case $d in
+ */sub4);;
+ *) $FGREP foo-recursive $d/Makefile.in || exit 1;;
+ esac
+done
+
+./configure
+
+$MAKE foo
+$MAKE test
+
+$MAKE distcheck
+
+:
diff --git a/t/recurs-user-indir.sh b/t/recurs-user-indir.sh
new file mode 100755
index 000000000..01d98a722
--- /dev/null
+++ b/t/recurs-user-indir.sh
@@ -0,0 +1,99 @@
+#! /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 user recursion works with various types of indirections
+# *involved in the definition of the '*-local' targets*: make macros,
+# AC_SUBST'd strings, automake-time file inclusions, automake
+# conditionals...
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([
+ sub1/Makefile
+ sub1/subsub/Makefile
+ sub2/Makefile
+ sub2/subsub/Makefile
+])
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_SUBST([FOO_LOCAL], [foo-local])
+AM_CONDITIONAL([COND], [:])
+AC_OUTPUT
+END
+
+mkdir sub1 sub1/subsub sub2 sub2/subsub
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub1 sub2
+AM_FOO_LOCAL = foo-local
+
+$(AM_FOO_LOCAL):
+ pwd && : > foo
+CLEANFILES = foo
+
+all-local: foo
+check-local:
+ test -f foo
+ test -f sub1/foo
+ test -f sub1/subsub/foo
+ test -f sub2/foo
+ test -f sub2/subsub/foo
+ test ! -r sub2/subsub/bar
+END
+
+cat > sub1/Makefile.am <<'END'
+SUBDIRS = subsub
+@FOO_LOCAL@:
+ pwd && : > foo
+CLEANFILES = foo
+END
+
+cat > sub1/subsub/Makefile.am <<'END'
+$(FOO_LOCAL):
+ pwd && : > foo
+CLEANFILES = foo
+END
+
+cat > sub2/Makefile.am <<'END'
+include $(srcdir)/bar.am
+include $(srcdir)/baz.am
+CLEANFILES = foo
+END
+
+echo 'SUBDIRS = subsub' > sub2/bar.am
+echo 'foo-local: ; pwd && : > foo' > sub2/baz.am
+
+cat > sub2/subsub/Makefile.am <<'END'
+if COND
+foo-local:
+ pwd && : > foo
+CLEANFILES = foo
+else !COND
+foo-local:
+ pwd && : > bar
+endif !COND
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE check
+$MAKE distcheck
+
+:
diff --git a/t/recurs-user-keep-going.sh b/t/recurs-user-keep-going.sh
new file mode 100755
index 000000000..6c2d4328e
--- /dev/null
+++ b/t/recurs-user-keep-going.sh
@@ -0,0 +1,95 @@
+#! /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 user recursion works with "make -k".
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_CONFIG_FILES([
+ sub1/Makefile
+ sub1/subsub1/Makefile
+ sub2/Makefile
+ sub2/subsub2/Makefile
+ sub3/Makefile
+])
+FAIL='@echo "FAIL $@ in `pwd`"; exit 1'
+PASS='@echo "PASS $@ in `pwd`"; : > foo'
+AC_SUBST([FAIL])
+AC_SUBST([PASS])
+AC_OUTPUT
+END
+
+mkdir sub1 sub1/subsub1 sub2 sub2/subsub2 sub3
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub1 . sub2 sub3
+foo-local:; @FAIL@
+END
+
+cat > sub1/Makefile.am <<'END'
+SUBDIRS = subsub1
+foo-local:; @PASS@
+END
+
+cat > sub2/Makefile.am <<'END'
+SUBDIRS = subsub2
+foo-local:; @FAIL@
+END
+
+echo 'foo-local:; @FAIL@' > sub1/subsub1/Makefile.am
+echo 'foo-local:; @PASS@' > sub2/subsub2/Makefile.am
+echo 'foo-local:; @PASS@' > sub3/Makefile.am
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+cat > exp <<END
+./sub1/foo
+./sub2/subsub2/foo
+./sub3/foo
+END
+
+as_expected ()
+{
+ find . -name foo > t || { cat t; exit 1; }
+ LC_ALL=C sort t > got
+ cat exp
+ cat got
+ diff exp got
+}
+
+# Without "-k", we fail in 'sub1/subsub1', and do nothing else.
+# So, no 'foo' file gets created.
+$MAKE foo && exit 1
+find . -name foo | grep . && exit 1
+
+if using_gmake; then
+ $MAKE -k foo && exit 1
+ as_expected
+ $MAKE --keep-going foo && exit 1
+ as_expected
+else
+ # Don't trust the exit status of 'make -k' for non-GNU makes.
+ $MAKE -k foo || :
+ as_expected
+fi
+
+:
diff --git a/t/recurs-user-many.sh b/t/recurs-user-many.sh
new file mode 100755
index 000000000..c1e475722
--- /dev/null
+++ b/t/recurs-user-many.sh
@@ -0,0 +1,73 @@
+#! /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 many user-defined recursive targets can be supported
+# at once, and that calls to 'AM_EXTRA_RECURSIVE_TARGETS' are
+# cumulative.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([sub/Makefile])
+## NOTE: extra white spaces, tabs, newlines and backslashes in the
+## lines below: on purpose.
+AM_EXTRA_RECURSIVE_TARGETS([ foo \
+ bar ])
+AC_SUBST([CLEANFILES], ['foo bar baz'])
+AC_OUTPUT
+# Yes, this appears after AC_OUTPUT. So what?
+AM_EXTRA_RECURSIVE_TARGETS([baz])
+END
+
+mkdir sub
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub
+foo-local:
+ : > foo
+bar-local:
+ echo x > bar
+baz-local: ; touch baz
+check-local: foo bar baz
+ ls -l . sub ;: For debugging.
+ test -f foo
+ test -f bar
+ test -f baz
+ test -f sub/foo
+ test -f sub/bar
+ test -f sub/baz
+END
+
+cat > sub/Makefile.am <<'END'
+foo-local bar-local baz-local:
+ touch `echo $@ | sed 's/-local$$//'`
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+for t in foo bar baz; do
+ $FGREP "$t-am" Makefile.in
+ $FGREP "$t-am" sub/Makefile.in
+done
+
+./configure
+
+$MAKE check
+$MAKE distcheck
+
+:
diff --git a/t/recurs-user-no-subdirs.sh b/t/recurs-user-no-subdirs.sh
new file mode 100755
index 000000000..ed56d07f7
--- /dev/null
+++ b/t/recurs-user-no-subdirs.sh
@@ -0,0 +1,52 @@
+#! /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 user recursion can be made to work even when $(SUBDIRS)
+# is empty or undefined.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_OUTPUT
+END
+
+$ACLOCAL
+$AUTOCONF
+
+# First try with undefined $(SUBDIRS).
+cat > Makefile.am <<'END'
+all-local: foo
+foo-local:
+ : > bar
+MOSTLYCLEANFILES = bar
+END
+$AUTOMAKE
+./configure
+$MAKE foo
+test -f bar
+
+$MAKE distclean
+test ! -r bar # Sanity check.
+
+# Now try with empty but defined $(SUBDIRS).
+echo SUBDIRS = >> Makefile.am
+$AUTOMAKE
+./configure
+$MAKE foo
+test -f bar
+
+:
diff --git a/t/recurs-user-no-top-level.sh b/t/recurs-user-no-top-level.sh
new file mode 100755
index 000000000..f80010aa1
--- /dev/null
+++ b/t/recurs-user-no-top-level.sh
@@ -0,0 +1,50 @@
+#! /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 user recursion works even for targets that don't exist
+# in the top-level Makefile.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([sub/Makefile])
+AM_EXTRA_RECURSIVE_TARGETS([foo-bar])
+AC_OUTPUT
+END
+
+mkdir sub
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub
+all-local: foo-bar
+END
+
+cat > sub/Makefile.am <<'END'
+foo-bar-local:
+ : > foo-bar
+MOSTLYCLEANFILES = foo-bar
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE foo-bar
+test -f sub/foo-bar
+
+:
diff --git a/t/recurs-user-override.sh b/t/recurs-user-override.sh
new file mode 100755
index 000000000..64ef2eec2
--- /dev/null
+++ b/t/recurs-user-override.sh
@@ -0,0 +1,68 @@
+#! /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 override of user-defined recursive targets work as
+# expected.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([sub/Makefile])
+AM_EXTRA_RECURSIVE_TARGETS([foobar zardoz])
+AC_OUTPUT
+END
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub
+all-local: foobar zardoz
+foobar:
+ : > foobar.out
+MOSTLYCLEANFILES = foobar.out
+check-local:
+ test -f foobar.out
+ test ! -r sub/foobar.out
+ test -f sub/zardoz.out
+ test ! -r sub/baz.out
+END
+
+mkdir sub
+cat > sub/Makefile.am <<'END'
+foobar foobar-local:
+ : > foobar.out
+zardoz-local:
+ : > baz.out
+zardoz:
+ : > zardoz.out
+MOSTLYCLEANFILES = zardoz.out
+END
+
+$ACLOCAL
+$AUTOCONF
+
+AUTOMAKE_fails
+grep '^Makefile\.am:3:.*user target.*foobar' stderr
+grep '^Makefile\.am:.*foobar-local.*instead of foobar$' stderr
+grep '^sub/Makefile\.am:5:.*user target.*zardoz' stderr
+grep '^sub/Makefile\.am:.*zardoz-local.*instead of zardoz$' stderr
+
+$AUTOMAKE -Wno-override
+
+./configure
+
+$MAKE check
+$MAKE distcheck
+
+:
diff --git a/t/recurs-user-phony.sh b/t/recurs-user-phony.sh
new file mode 100755
index 000000000..29e50a89b
--- /dev/null
+++ b/t/recurs-user-phony.sh
@@ -0,0 +1,64 @@
+#! /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 user-defined recursive targets and their associate
+# '-local', '-am' and '-recursive' targets are declared as phony.
+
+# Require GNU make, because some vendo makes (e.g., Solaris) doesn't
+# truly respect .PHONY.
+required=GNUmake
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES([sub/Makefile])
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_OUTPUT
+END
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub
+foo-local:
+ echo 'GOOD!' > foo
+END
+
+mkdir sub
+cat > sub/Makefile.am <<'END'
+foo-local:
+ echo 'GOOD!' > foo
+END
+
+dummy_files='
+ foo
+ foo-local
+ foo-am
+ foo-recursive
+ sub/foo
+ sub/foo-local
+ sub/foo-am
+'
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+./configure
+
+touch $dummy_files
+
+$MAKE foo
+grep 'GOOD!' foo
+grep 'GOOD!' sub/foo
+
+:
diff --git a/t/recurs-user-wrap.sh b/t/recurs-user-wrap.sh
new file mode 100755
index 000000000..9c4e3758e
--- /dev/null
+++ b/t/recurs-user-wrap.sh
@@ -0,0 +1,59 @@
+#! /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 rules generated by user recursion are apt to be wrapped
+# by other makefiles.
+
+required=GNUmake
+. ./defs || exit 1
+
+cat >> configure.ac << 'END'
+AM_EXTRA_RECURSIVE_TARGETS([extra])
+AC_CONFIG_FILES([src/Makefile])
+AC_OUTPUT
+END
+
+mkdir src
+echo SUBDIRS = src > Makefile.am
+echo 'bar: ; : > $@ ' > src/Makefile.am
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE extra
+test ! -f extra-local
+test ! -f src/bar
+
+cat > GNUmakefile << 'END'
+.DEFAULT_GOAL = all
+extra-local:
+ : > $@
+include ./Makefile
+END
+
+cat > src/GNUmakefile << 'END'
+include ./Makefile
+extra-local: bar
+END
+
+$MAKE extra
+test -f extra-local
+test -f src/bar
+
+:
diff --git a/t/recurs-user.sh b/t/recurs-user.sh
new file mode 100755
index 000000000..34a3fd25e
--- /dev/null
+++ b/t/recurs-user.sh
@@ -0,0 +1,81 @@
+#! /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/>.
+
+# Basic checks on user-defined recursive rules.
+# Check that user recursion respect $(SUBDIRS) order,
+# and proceeds in a depth-first fashion.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_CONFIG_FILES([
+ sub1/Makefile
+ sub2/Makefile
+ sub3/Makefile
+ sub3/deeper/Makefile
+])
+AC_OUTPUT
+END
+
+mkdir sub1 sub2 sub3 sub3/deeper
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub1 . sub3 sub2
+foo-local:
+ echo '.' >> $(top_builddir)/got
+.PHONY: test
+test: foo
+ cat $(srcdir)/exp
+ cat ./got
+ diff $(srcdir)/exp ./got
+check-local: test
+MOSTLYCLEANFILES = got
+EXTRA_DIST = exp
+END
+
+for i in 1 2 3; do
+ cat > sub$i/Makefile.am <<END
+foo-local:
+ echo 'sub$i' >> \$(top_builddir)/got
+END
+done
+
+echo SUBDIRS = deeper >> sub3/Makefile.am
+
+cat >> sub3/deeper/Makefile.am <<'END'
+foo-local:
+ echo sub3/deeper >> $(top_builddir)/got
+END
+
+cat >> exp <<'END'
+sub1
+.
+sub3/deeper
+sub3
+sub2
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE test
+$MAKE distcheck
+
+:
diff --git a/t/recurs-user2.sh b/t/recurs-user2.sh
new file mode 100755
index 000000000..0e4cba5ab
--- /dev/null
+++ b/t/recurs-user2.sh
@@ -0,0 +1,103 @@
+#! /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 user recursion can be made to work when $(SUBDIRS) are
+# not "strictly" nested, as in e.g.:
+# SUBDIRS = src external/lib external/tests
+# with no Makefile in 'external'.
+
+. ./defs || exit 1
+
+cat >> configure.ac <<'END'
+AC_CONFIG_FILES(
+ sub1/Makefile
+ sub2/Makefile
+dnl There's deliberately no 'sub3/Makefile'.
+ sub3/subsub/Makefile
+ sub4/Makefile
+ sub4/subsub/Makefile
+)
+AM_EXTRA_RECURSIVE_TARGETS([foo])
+AC_OUTPUT
+END
+
+mkdir sub1 sub2 sub3 sub4 sub3/subsub sub4/subsub
+
+cat > Makefile.am <<'END'
+SUBDIRS = sub1 sub2 sub3/subsub sub4 sub4/subsub
+
+foo-local:
+ echo _rootdir_ >foo
+MOSTLYCLEANFILES = foo
+
+.PHONY: test
+test: foo
+ grep _rootdir_ foo
+ grep ':sub1:' sub1/foo
+ grep ',sub1,' sub1/bar
+ test ! -r sub2/foo
+ test ! -r sub3/foo
+ grep '%sub3/subsub%' sub3/subsub/quux
+ test ! -r sub3/subsub/foo
+ test ! -r sub4/foo
+ grep '=sub4/subsub=' sub4/subsub/foo
+
+check-local: test
+END
+
+# A 'foo-local' target with dependencies shouldn't cause problems.
+cat > sub1/Makefile.am <<'END'
+foo-local: bar
+ sed 's/,/:/g' bar >foo
+bar:
+ echo ',sub1,' >$@
+MOSTLYCLEANFILES = foo bar
+END
+
+# The lack of a 'foo' target here shouldn't cause any error in
+# automake nor in make.
+: > sub2/Makefile.am
+
+# The lack of file 'sub3/Makefile.am' shouldn't cause any problem either.
+rm -f sub3/Makefile.am
+
+# A 'foo-local' creating a file != 'foo' shouldn't cause any problem.
+cat > sub3/subsub/Makefile.am <<'END'
+foo-local:
+ echo '%sub3/subsub%' >quux
+MOSTLYCLEANFILES = quux
+END
+
+# No 'foo-local' nor 'foo' target here ...
+: > sub4/Makefile.am
+# ... should not cause errors, nor cause the 'foo-local' target
+# here not to be executed.
+cat > sub4/subsub/Makefile.am <<'END'
+foo-local:
+ echo '=sub4/subsub=' >foo
+MOSTLYCLEANFILES = foo
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE test
+$MAKE distcheck
+
+:
diff --git a/t/remake-recurs-user.sh b/t/remake-recurs-user.sh
new file mode 100755
index 000000000..27e8bad64
--- /dev/null
+++ b/t/remake-recurs-user.sh
@@ -0,0 +1,89 @@
+#! /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/>.
+
+# Remake rules and user-defined recursive rules.
+
+. ./defs || exit 1
+
+cat >> configure.ac << 'END'
+m4_include([extra-targets.m4])
+AC_CONFIG_FILES([sub/Makefile])
+AC_OUTPUT
+END
+
+echo 'AM_EXTRA_RECURSIVE_TARGETS([foo])' > extra-targets.m4
+
+cat > Makefile.am << 'END'
+SUBDIRS = sub
+all-local: foo
+foo-local:
+ : > foo
+bar-local:
+ : > bar
+MOSTLYCLEANFILES = foo
+END
+
+mkdir sub
+cat > sub/Makefile.am << 'END'
+foo-local:
+ : > foo2
+MOSTLYCLEANFILES = foo2
+bar-local: later-target
+END
+
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE
+
+./configure
+
+$MAKE
+test -f foo
+test -f sub/foo2
+test ! -f bar
+test ! -f sub/zardoz
+$MAKE distcheck
+
+$sleep
+
+echo 'AM_EXTRA_RECURSIVE_TARGETS([bar])' >> extra-targets.m4
+
+cat >> Makefile.am <<'END'
+MOSTLYCLEANFILES += bar oof
+all-local: bar
+foo-local: oof
+oof:
+ : > $@
+END
+
+echo 'include $(srcdir)/more.am' >> sub/Makefile.am
+
+cat > sub/more.am << 'END'
+later-target:
+ : > zardoz
+DISTCLEANFILES = zardoz
+END
+
+using_gmake || $MAKE Makefile
+$MAKE
+test -f foo
+test -f oof
+test -f sub/foo2
+test -f bar
+test -f sub/zardoz
+$MAKE distcheck
+
+: