# aclocal - create aclocal.m4 by scanning configure.ac
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-# Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009 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)
+# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-# 02111-1307, USA.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Written by Tom Tromey <tromey@redhat.com>, and
# Alexandre Duret-Lutz <adl@gnu.org>.
# Some globals.
+# We do not operate in threaded mode.
+$perl_threads = 0;
+
# Include paths for searching macros. We search macros in this order:
# user-supplied directories first, then the directory containing the
# automake macros, and finally the system-wide directories for
# Whether we should copy M4 file in $user_includes[0].
my $install = 0;
+# --diff
+my @diff_command;
+
+# --dry-run
+my $dry_run = 0;
+
# configure.ac or configure.in.
my $configure_ac;
# Matches an AC_REQUIRE line.
my $ac_require_rx = "AC_REQUIRE\\((?:\\[([^]]+)\\]|([^],)\n]+))\\)";
-# Matches an m4_include line
-my $m4_include_rx = "(?:m4_)?s?include\\((?:\\[([^]]+)\\]|([^],)\n]+))\\)";
+# Matches an m4_include line.
+my $m4_include_rx = "(m4_|m4_s|s)include\\((?:\\[([^]]+)\\]|([^],)\n]+))\\)";
-# Match a serial number
-my $serial_line_rx = '^#\s*serial\s*(.*?)\s*$';
+# Match a serial number.
+my $serial_line_rx = '^#\s*serial\s+(\S*)';
my $serial_number_rx = '^\d+(?:\.\d+)*$';
+
+# Autoconf version
+# Set by trace_used_macros.
+my $ac_version;
+
+# If set, names a temporary file that must be erased on abnormal exit.
+my $erase_me;
\f
################################################################
+# Erase temporary file ERASE_ME. Handle signals.
+sub unlink_tmp
+{
+ my ($sig) = @_;
+
+ if ($sig)
+ {
+ verb "caught SIG$sig, bailing out";
+ }
+ if (defined $erase_me && -e $erase_me && !unlink ($erase_me))
+ {
+ fatal "could not remove `$erase_me': $!";
+ }
+ undef $erase_me;
+
+ # reraise default handler.
+ if ($sig)
+ {
+ $SIG{$sig} = 'DEFAULT';
+ kill $sig => $$;
+ }
+}
+
+$SIG{'INT'} = $SIG{'TERM'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'unlink_tmp';
+END { unlink_tmp }
+
# Check macros in acinclude.m4. If one is not used, warn.
sub check_acinclude ()
{
sub install_file ($$)
{
my ($src, $dest) = @_;
+ my $diff_dest;
if ($force_output
|| !exists $file_contents{$dest}
|| $file_contents{$src} ne $file_contents{$dest})
{
- if (system ('cp', $src, $dest))
+ if (-e $dest)
{
- error ("error while copying `$src' to `$dest'");
+ msg 'note', "overwriting `$dest' with `$src'";
+ $diff_dest = $dest;
}
else
{
- msg 'note', "installing `$dest'";
+ msg 'note', "installing `$dest' from `$src'";
+ }
+
+ if (@diff_command)
+ {
+ if (! defined $diff_dest)
+ {
+ # $dest does not exist. We create an empty one just to
+ # run diff, and we erase it afterward. Using the real
+ # the destination file (rather than a temporary file) is
+ # good when diff is run with options that display the
+ # file name.
+ #
+ # If creating $dest fails, fall back to /dev/null. At
+ # least one diff implementation (Tru64's) cannot deal
+ # with /dev/null. However working around this is not
+ # worth the trouble since nobody run aclocal on a
+ # read-only tree anyway.
+ $erase_me = $dest;
+ my $f = new IO::File "> $dest";
+ if (! defined $f)
+ {
+ undef $erase_me;
+ $diff_dest = '/dev/null';
+ }
+ else
+ {
+ $diff_dest = $dest;
+ $f->close;
+ }
+ }
+ my @cmd = (@diff_command, $diff_dest, $src);
+ $! = 0;
+ verb "running: @cmd";
+ my $res = system (@cmd);
+ Automake::FileUtils::handle_exec_errors "@cmd", 1
+ if $res;
+ unlink_tmp;
+ }
+ elsif (!$dry_run)
+ {
+ xsystem ('cp', $src, $dest);
}
}
}
# scan_configure_dep ($file)
# --------------------------
# Scan a configure dependency (configure.ac, or separate m4 files)
-# for uses of know macros and AC_REQUIREs of possibly unknown macros.
+# for uses of known macros and AC_REQUIREs of possibly unknown macros.
# Recursively scan m4_included files.
sub scan_configure_dep ($)
{
# Remove comments from current line.
s/\bdnl\b.*$//;
s/\#.*$//;
+ # Avoid running all the following regexes on white lines.
+ next if /^\s*$/;
while (/$m4_include_rx/go)
{
- push (@ilist, $1 || $2);
+ my $ifile = $2 || $3;
+ # Skip missing `sinclude'd files.
+ next if $1 ne 'm4_' && ! -f $ifile;
+ push @ilist, $ifile;
}
while (/$ac_require_rx/go)
}
add_macro ($_) foreach (@rlist);
- my $dirname = dirname $file;
- &scan_configure_dep (File::Spec->rel2abs ($_, $dirname)) foreach (@ilist);
+ &scan_configure_dep ($_) foreach @ilist;
}
# add_file ($FILE)
my $underquoted_manual_once = 0;
# scan_file ($TYPE, $FILE, $WHERE)
-# -------------------------
+# --------------------------------
# Scan a single M4 file ($FILE), and all files it includes.
# Return the list of included files.
# $TYPE is one of FT_USER, FT_AUTOMAKE, or FT_SYSTEM, depending
sub scan_file ($$$)
{
my ($type, $file, $where) = @_;
- my $dirname = dirname $file;
my $basename = basename $file;
# Do not scan the same file twice.
if ($number !~ /$serial_number_rx/go)
{
msg ('syntax', "$file:$.",
- "malformed serial number `$number', "
- . "expecting only digits and dots");
+ "warning: ill-formed serial number `$number', "
+ . "expecting a version string with only digits and dots");
}
elsif ($defun_seen)
{
}
}
+ # Remove comments from current line.
+ # Do not do it earlier, because the serial line is a comment.
+ $line =~ s/\bdnl\b.*$//;
+ $line =~ s/\#.*$//;
+
while ($line =~ /$ac_defun_rx/go)
{
$defun_seen = 1;
while ($line =~ /$m4_include_rx/go)
{
- my $ifile = $1 || $2;
- # m4_include is relative to the directory of the file which
- # perform the include, but we want paths relative to the
- # directory where aclocal is run. Do not use
- # File::Spec->rel2abs, because we want to store relative
- # paths (they might be used later of aclocal outputs an
- # m4_include for this file, or if the user itself includes
- # this file).
- $ifile = "$dirname/$ifile"
- unless $dirname eq '.' || File::Spec->file_name_is_absolute ($ifile);
+ my $ifile = $2 || $3;
+ # Skip missing `sinclude'd files.
+ next if $1 ne 'm4_' && ! -f $ifile;
push (@inc_files, $ifile);
$inc_lines{$ifile} = $.;
}
sub strip_redundant_includes (%)
{
my %files = @_;
+
+ # Always include acinclude.m4, even if it does not appear to be used.
+ $files{'acinclude.m4'} = 1 if -f 'acinclude.m4';
+ # File included by $configure_ac are redundant.
+ $files{$configure_ac} = 1;
+
# Files at the end of @file_order should override those at the beginning,
# so it is important to preserve these trailing files. We can remove
# a file A if it is going to be output before a file B that includes
verb "$ifile is already included by $file";
}
}
+
+ # configure.ac is implicitly included.
+ delete $files{$configure_ac};
+
return %files;
}
sub trace_used_macros ()
{
my %files = map { $map{$_} => 1 } keys %macro_seen;
- $files{'acinclude.m4'} = 1 if -f 'acinclude.m4';
%files = strip_redundant_includes %files;
- # configure.ac is implicitly included.
- delete $files{$configure_ac};
my $traces = ($ENV{AUTOM4TE} || 'autom4te');
$traces .= " --language Autoconf-without-aclocal-m4 ";
# All candidate files.
- $traces .= join (' ', grep { exists $files{$_} } @file_order) . " ";
+ $traces .= join (' ',
+ (map { "'$_'" }
+ (grep { exists $files{$_} } @file_order))) . " ";
# All candidate macros.
$traces .= join (' ',
- (map { "--trace='$_:\$f::\$n::\$1'" } ('AC_DEFUN',
- 'AC_DEFUN_ONCE',
- 'AU_DEFUN')),
+ (map { "--trace='$_:\$f::\$n::\$1'" }
+ ('AC_DEFUN',
+ 'AC_DEFUN_ONCE',
+ 'AU_DEFUN',
+ '_AM_AUTOCONF_VERSION')),
# Do not trace $1 for all other macros as we do
# not need it and it might contains harmful
# characters (like newlines).
if ($macro eq 'AC_DEFUN'
|| $macro eq 'AC_DEFUN_ONCE'
|| $macro eq 'AU_DEFUN');
+
+ $ac_version = $arg1 if $macro eq '_AM_AUTOCONF_VERSION';
}
$tracefh->close;
if (exists $map_traced_defs{$m}
&& $map{$m} eq $map_traced_defs{$m});
}
- # Always include acinclude.m4, even if it does not appear to be used.
- $files{'acinclude.m4'} = 1 if -f 'acinclude.m4';
# Do not explicitly include a file that is already indirectly included.
%files = strip_redundant_includes %files;
- # Never include configure.ac :)
- delete $files{$configure_ac};
my $installed = 0;
# FIXME: Shouldn't we diagnose this?
return 1 if ! length ($output);
+ if ($ac_version)
+ {
+ # Do not use "$output_file" here for the same reason we do not
+ # use it in the header below. autom4te will output the name of
+ # the file in the diagnostic anyway.
+ $output = "m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [$ac_version],,
+[m4_warning([this file was generated for autoconf $ac_version.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+$output";
+ }
+
# We used to print `# $output_file generated automatically etc.' But
# this creates spurious differences when using autoreconf. Autoreconf
# creates aclocal.m4t and then rename it to aclocal.m4, but the
$output = "# generated automatically by aclocal $VERSION -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009 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.
verb "writing $output_file";
- my $out = new Automake::XFile "> $output_file";
- print $out $output;
+ if (!$dry_run)
+ {
+ if (-e $output_file && !unlink $output_file)
+ {
+ fatal "could not remove `$output_file': $!";
+ }
+ my $out = new Automake::XFile "> $output_file";
+ print $out $output;
+ }
return 1;
}
Options:
--acdir=DIR directory holding config files (for debugging)
+ --diff[=COMMAND] run COMMAND [diff -u] on M4 files that would be
+ changed (implies --install and --dry-run)
+ --dry-run pretend to, but do not actually update any file
--force always update output file
--help print this help, then exit
-I DIR add directory to search list for .m4 files
{
print <<EOF;
aclocal (GNU $PACKAGE) $VERSION
+Copyright (C) 2009 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
Written by Tom Tromey <tromey\@redhat.com>
and Alexandre Duret-Lutz <adl\@gnu.org>.
-
-Copyright (C) 2005 Free Software Foundation, Inc.
-This is free software; see the source for copying conditions. There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
EOF
exit 0;
}
sub parse_arguments ()
{
my $print_and_exit = 0;
+ my $diff_command;
my %cli_options =
(
@automake_includes = ();
@system_includes = ($_[1])
},
+ 'diff:s' => \$diff_command,
+ 'dry-run' => \$dry_run,
'force' => \$force_output,
'I=s' => \@user_includes,
'install' => \$install,
exit 0;
}
+ if (defined $diff_command)
+ {
+ $diff_command = 'diff -u' if $diff_command eq '';
+ @diff_command = split (' ', $diff_command);
+ $install = 1;
+ $dry_run = 1;
+ }
+
if ($install && !@user_includes)
{
fatal ("--install should copy macros in the directory indicated by the"
# strip off newlines and end-of-line comments
s/\s*\#.*$//;
chomp;
- push (@system_includes, $_) if -d $_;
+ foreach my $dir (glob)
+ {
+ push (@system_includes, $dir) if -d $dir;
+ }
}
close (DIRLIST);
}
last if $exit_code;
my %macro_traced = trace_used_macros;
last if write_aclocal ($output_file, keys %macro_traced);
+ last if $dry_run;
}
check_acinclude;