From 3da1457d426f1be7b9f792fce1461a7b8227d7e7 Mon Sep 17 00:00:00 2001 From: Stefano Lattarini Date: Tue, 12 Jun 2012 14:48:12 +0200 Subject: [PATCH] recursion: support user-defined recursive targets The user can now define his own recursive targets that recurse in the directories specified in $(SUBDIRS). That can be done by specifying the name of such targets in invocations of the new 'AM_EXTRA_RECURSIVE_TARGETS' m4 macro. The API goes like this: $ cat configure.ac AC_INIT([pkg-name], [1.0] AM_INIT_AUTOMAKE AM_EXTRA_RECURSIVE_TARGETS([foo]) AC_CONFIG_FILES([Makefile sub/Makefile]) AC_OUTPUT $ cat Makefile.am SUBDIRS = sub foo-local: @echo This will be run by "make foo". $ cat sub/Makefile.am foo-local: @echo This too will be run by a "make foo" issued either in @echo the 'sub/' directory or in the top-level directory. Like for the "default" recursive targets (e.g., 'all' and 'check'), the user-defined recursive targets descend in the $(SUBDIRS) in a depth-first fashion, and process '.' last (unless that is explicitly specified in $(SUBDIRS)). * NEWS, doc/automake.texi: Document the new feature. * automake.in (@extra_recursive_targets): New global variable. (scan_autoconf_traces): Trace macro '_AM_EXTRA_RECURSIVE_TARGETS'. (handle_user_recursion): New subroutine; among other things, it defines the new internal '$(am__extra_recursive_targets)' make variable, and the '*-am', '*-local' and '*-recursive' targets associated with the user-specified user recursive targets. (generate_makefile): Call the new subroutine. * lib/am/subdirs.am (am__recursive_targets): New internal make variable, listing all of '$(RECURSIVE_TARGETS)', '$(RECURSIVE_CLEAN_TARGETS)' and '$(am__extra_recursive_targets)' together. (AM_RECURSIVE_TARGETS): Adjust the definition of this variable ... (.PHONY, .MAKE): ... and the list of dependencies of these special targets to take advantage of the new '$(am__recursive_targets)' variable. ($(am__recursive_targets)): New targets, superseding ... ($(RECURSIVE_TARGETS), $(RECURSIVE_CLEAN_TARGETS)): ... these, and inheriting their rules. This way, the rules to handle recursion for built-in recursive targets (e.g., 'all', 'dvi', 'clean') and for user defined recursive targets are the same. * m4/extra-recurs.m4: New file, contain definition of new macro 'AM_EXTRA_RECURSIVE_TARGETS' and '_AM_EXTRA_RECURSIVE_TARGETS'. These macros are basically dummy, only used for tracing by automake. * m4/Makefile.am (dist_automake_ac_DATA): Update. * t/recurs-user.sh: New test. * t/recurs-user2.sh: Likewise. * t/recurs-user-deeply-nested.sh: Likewise. * t/recurs-user-indir.sh: Likewise. * t/recurs-user-keep-going.sh: Likewise. * t/recurs-user-many.sh: Likewise. * t/recurs-user-no-subdirs.sh: Likewise. * t/recurs-user-no-top-level.sh: Likewise. * t/recurs-user-override.sh: Likewise. * t/recurs-user-phony.sh: Likewise. * t/recurs-user-wrap.sh: Likewise. * t/remake-recurs-user.sh: Likewise. * t/list-of-tests.mk: Update. Signed-off-by: Stefano Lattarini --- Makefile.am | 1 + NEWS | 7 +++ automake.in | 35 ++++++++++++++ doc/automake.texi | 28 +++++++++++ lib/am/subdirs.am | 17 ++++--- m4/extra-recurs.m4 | 17 +++++++ t/list-of-tests.mk | 12 +++++ t/recurs-user-deeply-nested.sh | 97 ++++++++++++++++++++++++++++++++++++++ t/recurs-user-indir.sh | 99 +++++++++++++++++++++++++++++++++++++++ t/recurs-user-keep-going.sh | 95 +++++++++++++++++++++++++++++++++++++ t/recurs-user-many.sh | 73 +++++++++++++++++++++++++++++ t/recurs-user-no-subdirs.sh | 52 +++++++++++++++++++++ t/recurs-user-no-top-level.sh | 50 ++++++++++++++++++++ t/recurs-user-override.sh | 68 +++++++++++++++++++++++++++ t/recurs-user-phony.sh | 64 +++++++++++++++++++++++++ t/recurs-user-wrap.sh | 59 +++++++++++++++++++++++ t/recurs-user.sh | 81 ++++++++++++++++++++++++++++++++ t/recurs-user2.sh | 103 +++++++++++++++++++++++++++++++++++++++++ t/remake-recurs-user.sh | 89 +++++++++++++++++++++++++++++++++++ 19 files changed, 1040 insertions(+), 7 deletions(-) create mode 100644 m4/extra-recurs.m4 create mode 100755 t/recurs-user-deeply-nested.sh create mode 100755 t/recurs-user-indir.sh create mode 100755 t/recurs-user-keep-going.sh create mode 100755 t/recurs-user-many.sh create mode 100755 t/recurs-user-no-subdirs.sh create mode 100755 t/recurs-user-no-top-level.sh create mode 100755 t/recurs-user-override.sh create mode 100755 t/recurs-user-phony.sh create mode 100755 t/recurs-user-wrap.sh create mode 100755 t/recurs-user.sh create mode 100755 t/recurs-user2.sh create mode 100755 t/remake-recurs-user.sh diff --git a/Makefile.am b/Makefile.am index 9e5512e..829c31f 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 54acc7a..08ca231 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 11e750d..b7b03f3 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 87776b3..38f9159 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 3fc2888..005483a 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 0000000..7b7ecc7 --- /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 4b16822..919b6f0 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 0000000..c9e5c1f --- /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 . + +# 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 0000000..01d98a7 --- /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 . + +# 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 0000000..6c2d432 --- /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 . + +# 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 < 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 0000000..c1e4757 --- /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 . + +# 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 0000000..ed56d07 --- /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 . + +# 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 0000000..f80010a --- /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 . + +# 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 0000000..64ef2ee --- /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 . + +# 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 0000000..29e50a8 --- /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 . + +# 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 0000000..9c4e375 --- /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 . + +# 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 0000000..34a3fd2 --- /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 . + +# 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 <> \$(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 0000000..0e4cba5 --- /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 . + +# 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 0000000..27e8bad --- /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 . + +# 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 + +: -- 2.7.4