automake-patches
[Top][All Lists]
Advanced

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

FYI: honor #serial lines with aclocal --install


From: Alexandre Duret-Lutz
Subject: FYI: honor #serial lines with aclocal --install
Date: Tue, 01 Feb 2005 00:40:48 +0100
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3.50 (gnu/linux)

I'm installing this on HEAD.

Contrary to what I explained in
http://lists.gnu.org/archive/html/bug-gnulib/2005-01/msg00014.html
I've opted not to introduce a newer syntax for #serial line.  

There are several reasons for this, the first of which is
laziness: handling #serial line in aclocal turned out to be
complicated enough so I didn't want to go through m4.  (It's not
just a matter of changing one grep for one --trace, because the
--traces are done much later, and the logic in aclocal is
already very complicated for such a small-looking program.)

Another reason is that the #serial syntax is already used by
some people, and I don't feel right asking people to switch to a
new syntax while the time where aclocal can be reimplemented
using Akim's trick [*] seems very very distant (it would be
after M4 2.0, which in turn would be after libtool 2.0, which
was already expected "soon" more than one year ago -- although
it was called 1.6 at this time).

A final one is that I'm no longer sure reimplementing aclocal
using this trick is worth it.

[*] http://sources.redhat.com/ml/bug-automake/2003/msg00321.html

2005-02-01  Alexandre Duret-Lutz  <address@hidden>

        * 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.

Index: NEWS
===================================================================
RCS file: /cvs/automake/automake/NEWS,v
retrieving revision 1.296
diff -u -r1.296 NEWS
--- NEWS        30 Jan 2005 17:47:36 -0000      1.296
+++ NEWS        31 Jan 2005 23:16:39 -0000
@@ -21,7 +21,8 @@
 
   - 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.
 
Index: aclocal.in
===================================================================
RCS file: /cvs/automake/automake/aclocal.in,v
retrieving revision 1.123
diff -u -r1.123 aclocal.in
--- aclocal.in  30 Jan 2005 17:47:36 -0000      1.123
+++ aclocal.in  31 Jan 2005 23:16:39 -0000
@@ -89,6 +89,9 @@
 # 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 @@
 # 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 @@
 # 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 @@
   %file_includes = ();
   %file_added = ();
   %scanned_configure_dep = ();
+  %invmap = ();
+  %serial = ();
   undef &search;
 }
 
@@ -173,6 +186,34 @@
     }
 }
 
+# Compare two lists of numbers.
+sub list_compare (address@hidden@)
+{
+  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 @@
 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 @@
   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 @@
       $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} = address@hidden;
+               }
+             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 @@
                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 @@
          # 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
Index: doc/automake.texi
===================================================================
RCS file: /cvs/automake/automake/doc/automake.texi,v
retrieving revision 1.89
diff -u -r1.89 automake.texi
--- doc/automake.texi   30 Jan 2005 17:47:38 -0000      1.89
+++ doc/automake.texi   31 Jan 2005 23:16:42 -0000
@@ -1663,6 +1663,11 @@
 specified with @code{-I @var{dir}} instead of copying them in the
 output files.
 
+When this option is used, @command{aclocal} will also honor
address@hidden @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 @@
 system-wide third-party macros in your local macro directory, solving
 the above problem.  Simply use:
 
address@hidden
address@hidden
  ACLOCAL_AMFLAGS = -I m4 --install
address@hidden example
address@hidden 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
address@hidden/} 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
+
address@hidden
+#serial @var{NNN}
address@hidden smallexample
+
address@hidden
+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
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/tests/Makefile.am,v
retrieving revision 1.580
diff -u -r1.580 Makefile.am
--- tests/Makefile.am   16 Jan 2005 00:36:53 -0000      1.580
+++ tests/Makefile.am   31 Jan 2005 23:16:42 -0000
@@ -20,6 +20,7 @@
 acloca15.test \
 acloca16.test \
 acloca17.test \
+acloca18.test \
 acoutnoq.test \
 acoutpt.test \
 acoutpt2.test \
Index: tests/acloca18.test
===================================================================
RCS file: tests/acloca18.test
diff -N tests/acloca18.test
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/acloca18.test 31 Jan 2005 23:16:42 -0000
@@ -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 <<EOF
+#serial 1.8.1230.9
+AC_DEFUN([AM_MACRO1], [echo macro11 >> foo])
+AC_DEFUN([AM_MACRO2], [echo macro21 >> foo])
+EOF
+
+cat >2/m1.m4 <<EOF
+#serial 1.8.1231.9
+AC_DEFUN([AM_MACRO1], [echo macro12 >> foo])
+EOF
+
+cat >3/m2.m4 <<EOF
+#serial 13
+AC_DEFUN([AM_MACRO2], [echo macro23 >> foo])
+EOF
+
+cat >3/m1.m4 <<EOF
+#serial 1.8.1230.1
+AC_DEFUN([AM_MACRO1], [echo macro13 >> foo])
+EOF
+
+cat >4/mumble.m4 <<EOF
+#serial 0
+AC_DEFUN([AM_MACRO1], [echo macro14 >> 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

-- 
Alexandre Duret-Lutz





reply via email to

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