From: Alexandre Duret-Lutz Date: Mon, 31 Jan 2005 23:41:10 +0000 (+0000) Subject: * aclocal.in (list_compare): New functions. X-Git-Tag: Release-1-9b~202 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfa86f00e9cdb1e7b72c93f0f8ffab7cba09d706;p=thirdparty%2Fautomake.git * aclocal.in (list_compare): New functions. (scan_file): Honor #serial lines. * tests/acloca18.test: New test. * tests/Makefile.am (TESTS): Add it. * doc/automake.texi (aclocal options, Local Macros): Document #serial. --- diff --git a/ChangeLog b/ChangeLog index ec2f1ec7b..787069216 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-02-01 Alexandre Duret-Lutz + + * aclocal.in (list_compare): New functions. + (scan_file): Honor #serial lines. + * tests/acloca18.test: New test. + * tests/Makefile.am (TESTS): Add it. + * doc/automake.texi (aclocal options, Local Macros): Document + #serial. + 2005-01-30 Alexandre Duret-Lutz Preliminary support for `aclocal --install'. diff --git a/NEWS b/NEWS index f369e3225..f82112774 100644 --- a/NEWS +++ b/NEWS @@ -21,7 +21,8 @@ New in 1.9a: - aclocal supports an --install option, that will cause system-wide third-party macros to be installed in the local directory - specified with the first -I flag. + specified with the first -I flag. This option also uses #serial + lines in M4 files to upgrade local macros. - Per-target flags are now correctly handled in link rules. diff --git a/aclocal.in b/aclocal.in index 44b687eb8..a071cfdcd 100644 --- a/aclocal.in +++ b/aclocal.in @@ -89,6 +89,9 @@ my %map = (); # Ditto, but records the last definition of each macro as returned by --trace. my %map_traced_defs = (); +# Map basenames to macro names. +my %invmap = (); + # Map file names to file contents. my %file_contents = (); @@ -107,6 +110,11 @@ my %file_added = (); # Files that have already been scanned. my %scanned_configure_dep = (); +# Serial numbers, for files that have one. +# The key is the basename of the file, +# the value is the serial number represented as a list. +my %serial = (); + # Matches a macro definition. # AC_DEFUN([macroname], ...) # or @@ -123,6 +131,9 @@ my $ac_require_rx = "AC_REQUIRE\\((?:\\[([^]]+)\\]|([^],)\n]+))\\)"; # Matches an m4_include line my $m4_include_rx = "(?:m4_)?s?include\\((?:\\[([^]]+)\\]|([^],)\n]+))\\)"; +# Match a serial number +my $serial_line_rx = '^#\s*serial\s*(.*?)\s*$'; +my $serial_number_rx = '^\d+(?:\.\d+)*$'; ################################################################ @@ -150,6 +161,8 @@ sub reset_maps () %file_includes = (); %file_added = (); %scanned_configure_dep = (); + %invmap = (); + %serial = (); undef &search; } @@ -173,6 +186,34 @@ sub install_file ($$) } } +# Compare two lists of numbers. +sub list_compare (\@\@) +{ + my @l = @{$_[0]}; + my @r = @{$_[1]}; + while (1) + { + if (0 == @l) + { + return (0 == @r) ? 0 : -1; + } + elsif (0 == @r) + { + return 1; + } + elsif ($l[0] < $r[0]) + { + return -1; + } + elsif ($l[0] > $r[0]) + { + return 1; + } + shift @l; + shift @r; + } +} + ################################################################ # scan_m4_dirs($TYPE, @DIRS) @@ -343,7 +384,8 @@ my $underquoted_manual_once = 0; sub scan_file ($$$) { my ($type, $file, $where) = @_; - my $base = dirname $file; + my $dirname = dirname $file; + my $basename = basename $file; # Do not scan the same file twice. return @{$file_includes{$file}} if exists $file_includes{$file}; @@ -360,6 +402,11 @@ sub scan_file ($$$) my $contents = ''; my @inc_files = (); my %inc_lines = (); + + my $defun_seen = 0; + my $serial_seen = 0; + my $serial_older = 0; + while ($_ = $fh->getline) { # Ignore `##' lines. @@ -368,8 +415,57 @@ sub scan_file ($$$) $contents .= $_; my $line = $_; + if ($line =~ /$serial_line_rx/go) + { + my $number = $1; + if ($number !~ /$serial_number_rx/go) + { + msg ('syntax', "$file:$.", + "malformed serial number `$number', " + . "expecting only digits and dots"); + } + elsif ($defun_seen) + { + # aclocal removes all definitions from M4 file with the + # same basename if a greater serial number is found. + # Encountering a serial after some macros will undefine + # these macros... + msg ('syntax', "$file:$.", + 'the serial number must appear before any macro definition'); + } + # We really care about serials only for non-automake macros + # and when --install is used. But the above diagnostics are + # made regardless of this, because not using --install is + # not a reason not the fix macro files. + elsif ($install && $type != FT_AUTOMAKE) + { + $serial_seen = 1; + my @new = split (/\./, $number); + + verb "$file:$.: serial $number"; + + if (!exists $serial{$basename} + || list_compare (@new, @{$serial{$basename}}) > 0) + { + # Delete any definition we knew from the old macro. + foreach my $def (@{$invmap{$basename}}) + { + verb "$file:$.: ignoring previous definition of $def"; + delete $map{$def}; + } + $invmap{$basename} = []; + $serial{$basename} = \@new; + } + else + { + $serial_older = 1; + } + } + } + while ($line =~ /$ac_defun_rx/go) { + $defun_seen = 1; if (! defined $1) { msg ('syntax', "$file:$.", "warning: underquoted definition of $2" @@ -379,11 +475,20 @@ sub scan_file ($$$) unless $underquoted_manual_once; $underquoted_manual_once = 1; } + + # If this macro does not have a serial and we have already + # seen a macro with the same basename earlier, we should + # ignore the macro (don't exit immediately so we can still + # diagnose later #serial numbers and underquoted macros). + $serial_older ||= ($type != FT_AUTOMAKE + && !$serial_seen && exists $serial{$basename}); + my $macro = $1 || $2; - if (! defined $map{$macro}) + if (!$serial_older && !defined $map{$macro}) { verb "found macro $macro in $file: $."; $map{$macro} = $file; + push @{$invmap{$basename}}, $macro; } else { @@ -406,12 +511,19 @@ sub scan_file ($$$) # paths (they might be used later of aclocal outputs an # m4_include for this file, or if the user itself includes # this file). - $ifile = "$base/$ifile" - unless $base eq '.' || File::Spec->file_name_is_absolute ($ifile); + $ifile = "$dirname/$ifile" + unless $dirname eq '.' || File::Spec->file_name_is_absolute ($ifile); push (@inc_files, $ifile); $inc_lines{$ifile} = $.; } } + + # Ignore any file that has an old serial (or no serial if we know + # another one with a serial). + return () + if ($serial_older || + ($type != FT_AUTOMAKE && !$serial_seen && exists $serial{$basename})); + $file_contents{$file} = $contents; # For some reason I don't understand, it does not work diff --git a/doc/automake.texi b/doc/automake.texi index 71a428f81..ed99f1076 100644 --- a/doc/automake.texi +++ b/doc/automake.texi @@ -1663,6 +1663,11 @@ Install system-wide third-party macros into the first directory specified with @code{-I @var{dir}} instead of copying them in the output files. +When this option is used, @command{aclocal} will also honor +@code{#serial @var{NUMBER}} lines that appear in macros: an M4 file is +ignored if there exists another M4 file with the same basename and a +greater serial number in the search path. + @item --force @opindex --force Always overwrite the output file. The default is to overwrite the output @@ -2247,18 +2252,34 @@ Since Automake 1.10, @command{aclocal} offers an option to copy these system-wide third-party macros in your local macro directory, solving the above problem. Simply use: -@example +@smallexample ACLOCAL_AMFLAGS = -I m4 --install -@end example +@end smallexample @noindent With this setup, system-wide macros will be copied to @file{m4/} the first time you run @command{autoreconf}. Then the locally installed macros will have precedence over the system-wide installed -macros each time @command{aclocal} is run again. (So the only reason -to keep @code{--install} in the flags after the first run is that when -you later edit @file{configure.ac} and depend on a new macro, this -macro will be installed in your @file{m4/} automatically.) +macros each time @command{aclocal} is run again. + +One reason why you should keep @code{--install} in the flags even +after the first run is that when you later edit @file{configure.ac} +and depend on a new macro, this macro will be installed in your +@file{m4/} automatically. Another one is that serial numbers can be +used to update the macros in your source tree automatically when new +system-wide versions are installed. A serial number should be a +single line of the form + +@smallexample +#serial @var{NNN} +@end smallexample + +@noindent +where @var{NNN} contains only digits and dots. It should appear in +the M4 file before any macro definition. It is a good practice to +maintain a serial number for each macro you distribute, even if you do +not use the @code{--install} option of @command{aclocal}: this allows +other people to use it. @node Future of aclocal diff --git a/doc/stamp-vti b/doc/stamp-vti index 21e3ad8c7..f8d917edf 100644 --- a/doc/stamp-vti +++ b/doc/stamp-vti @@ -1,4 +1,4 @@ -@set UPDATED 30 January 2005 -@set UPDATED-MONTH January 2005 +@set UPDATED 1 February 2005 +@set UPDATED-MONTH February 2005 @set EDITION 1.9a @set VERSION 1.9a diff --git a/doc/version.texi b/doc/version.texi index 21e3ad8c7..f8d917edf 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -1,4 +1,4 @@ -@set UPDATED 30 January 2005 -@set UPDATED-MONTH January 2005 +@set UPDATED 1 February 2005 +@set UPDATED-MONTH February 2005 @set EDITION 1.9a @set VERSION 1.9a diff --git a/tests/Makefile.am b/tests/Makefile.am index 8e5e60f45..80779b6f0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,6 +20,7 @@ acloca14.test \ acloca15.test \ acloca16.test \ acloca17.test \ +acloca18.test \ acoutnoq.test \ acoutpt.test \ acoutpt2.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 5d0fcfca5..837565d63 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -140,6 +140,7 @@ acloca14.test \ acloca15.test \ acloca16.test \ acloca17.test \ +acloca18.test \ acoutnoq.test \ acoutpt.test \ acoutpt2.test \ diff --git a/tests/acloca18.test b/tests/acloca18.test new file mode 100755 index 000000000..362d8bab1 --- /dev/null +++ b/tests/acloca18.test @@ -0,0 +1,95 @@ +#! /bin/sh +# Copyright (C) 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Automake. +# +# GNU Automake 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. +# +# GNU Automake 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 Automake; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# Test for --install with #serial numbers. + +. ./defs || exit 1 + +set -e + +cat >> configure.in << 'END' +AM_MACRO1 +AM_MACRO2 +END + +mkdir 1 2 3 4 + +cat >1/m1.m4 <> foo]) +AC_DEFUN([AM_MACRO2], [echo macro21 >> foo]) +EOF + +cat >2/m1.m4 <> foo]) +EOF + +cat >3/m2.m4 <> foo]) +EOF + +cat >3/m1.m4 <> foo]) +EOF + +cat >4/mumble.m4 <> foo]) +EOF + + +ACLOCAL_TESTSUITE_FLAGS='-I 1 -I 2 -I 3 -I 4' + +$ACLOCAL +$AUTOCONF +./configure +grep macro11 foo +grep macro21 foo + +rm -f foo +$ACLOCAL --install +$AUTOCONF +./configure +grep macro12 foo +grep macro23 foo + +ACLOCAL_TESTSUITE_FLAGS='-I 4 -I 1 -I 2 -I 3' +rm -f foo +$ACLOCAL --install +$AUTOCONF +./configure +grep macro14 foo +grep macro23 foo + +ACLOCAL_TESTSUITE_FLAGS='-I 4 -I 1 -I 2' +rm -f foo +$ACLOCAL --install 2>stderr && exit 1 +grep AM_MACRO2 stderr + +ACLOCAL_TESTSUITE_FLAGS='-I 4 -I 1' +rm -f foo +$ACLOCAL --install +$AUTOCONF +./configure +grep macro14 foo +grep macro21 foo