my @automake_includes = ("@datadir@/aclocal-$APIVERSION");
my @system_includes = ('@datadir@/aclocal');
+# Whether we should copy M4 file in $user_includes[0].
+my $install = 0;
+
# configure.ac or configure.in.
my $configure_ac;
# Output file name.
my $output_file = 'aclocal.m4';
-# Modification time of the youngest dependency.
-my $greatest_mtime = 0;
-
# Option --force.
my $force_output = 0;
+# Modification time of the youngest dependency.
+my $greatest_mtime = 0;
+
# Which macros have been seen.
my %macro_seen = ();
# Map file names to included files (transitively closed).
my %file_includes = ();
+# Files which have already been added.
+my %file_added = ();
+
+# Files that have already been scanned.
+my %scanned_configure_dep = ();
+
# Matches a macro definition.
# AC_DEFUN([macroname], ...)
# or
}
}
+sub reset_maps ()
+{
+ $greatest_mtime = 0;
+ %macro_seen = ();
+ @file_order = ();
+ %map = ();
+ %map_traced_defs = ();
+ %file_contents = ();
+ %file_type = ();
+ %file_includes = ();
+ %file_added = ();
+ %scanned_configure_dep = ();
+ undef &search;
+}
+
+# install_file ($SRC, $DEST)
+sub install_file ($$)
+{
+ my ($src, $dest) = @_;
+
+ if ($force_output
+ || !exists $file_contents{$dest}
+ || $file_contents{$src} ne $file_contents{$dest})
+ {
+ if (system ('cp', $src, $dest))
+ {
+ error ("error while copying `$src' to `$dest'");
+ }
+ else
+ {
+ msg 'note', "installing `$dest'";
+ }
+ }
+}
+
################################################################
# scan_m4_dirs($TYPE, @DIRS)
# Scan a configure dependency (configure.ac, or separate m4 files)
# for uses of know macros and AC_REQUIREs of possibly unknown macros.
# Recursively scan m4_included files.
-my %scanned_configure_dep = ();
sub scan_configure_dep ($)
{
my ($file) = @_;
# add_file ($FILE)
# ----------------
# Add $FILE to output.
-my %file_added = (); # files which have already been added.
sub add_file ($)
{
my ($file) = @_;
################################################################
# Write output.
+# Return 0 iff some files were installed locally.
sub write_aclocal ($@)
{
my ($output_file, @macros) = @_;
# Never include configure.ac :)
delete $files{$configure_ac};
+ my $installed = 0;
+
for my $file (grep { exists $files{$_} } @file_order)
{
# Check the time stamp of this file, and of all files it includes.
if ($file_type{$file} != FT_USER
|| $file =~ m,^(?:\w:)?[\\/],)
{
- $output .= $file_contents{$file} . "\n";
+ if (!$install || $file_type{$file} != FT_SYSTEM)
+ {
+ # Copy the file into aclocal.m4.
+ $output .= $file_contents{$file} . "\n";
+ }
+ else
+ {
+ # Install the file (and any file it includes).
+ my $dest;
+ for my $ifile (@{$file_includes{$file}}, $file)
+ {
+ $dest = "$user_includes[0]/" . basename $ifile;
+ verb "installing $ifile to $dest";
+ install_file ($ifile, $dest);
+ }
+ $installed = 1;
+ }
}
else
{
}
}
+ if ($installed)
+ {
+ verb "running aclocal anew, because some files were installed locally";
+ return 0;
+ }
+
# Nothing to output?!
# FIXME: Shouldn't we diagnose this?
- return if ! length ($output);
+ return 1 if ! length ($output);
# We used to print `# $output_file generated automatically etc.' But
# this creates spurious differences when using autoreconf. Autoreconf
&& $output eq contents ($output_file))
{
verb "$output_file unchanged";
- return;
+ return 1;
}
verb "writing $output_file";
my $out = new Automake::XFile "> $output_file";
print $out $output;
- return;
+ return 1;
}
################################################################
--force always update output file
--help print this help, then exit
-I DIR add directory to search list for .m4 files
+ --install copy third-party files to the first -I directory
--output=FILE put output in FILE (default aclocal.m4)
--print-ac-dir print name of directory holding m4 files, then exit
--verbose don't be silent
},
'force' => \$force_output,
'I=s' => \@user_includes,
+ 'install' => \$install,
'output=s' => \$output_file,
'print-ac-dir' => \$print_and_exit,
'verbose' => sub { setup_channel 'verb', silent => 0; },
exit 0;
}
+ if ($install && !@user_includes)
+ {
+ fatal ("--install should copy macros in the directory indicated by the"
+ . "\nfirst -I option, but no -I was supplied.");
+ }
+
if (! -d $system_includes[0])
{
# By default $(datadir)/aclocal doesn't exist. We don't want to
parse_WARNINGS; # Parse the WARNINGS environment variable.
parse_arguments;
$configure_ac = require_configure_ac;
-scan_m4_files;
-scan_configure;
-if (! $exit_code)
+
+# We may have to rerun aclocal if some file have been installed, but
+# it should not happen more than once. The reason we must run again
+# is that once the file has been moved from /usr/share/aclocal/ to the
+# local m4/ directory it appears at a new place in the search path,
+# hence it should be output at a different position in aclocal.m4. If
+# we did not rerun aclocal, the next run of aclocal would produce a
+# different aclocal.m4.
+my $loop = 0;
+while (1)
{
+ ++$loop;
+ prog_error "Too many loops." if $loop > 2;
+
+ reset_maps;
+ scan_m4_files;
+ scan_configure;
+ last if $exit_code;
my %macro_traced = trace_used_macros;
- write_aclocal ($output_file, keys %macro_traced);
+ last if write_aclocal ($output_file, keys %macro_traced);
}
check_acinclude;
Add the directory @var{dir} to the list of directories searched for
@file{.m4} files.
+@item --install
+@opindex --install
+Install system-wide third-party macros into the first directory
+specified with @code{-I @var{dir}} instead of copying them in the
+output files.
+
@item --force
@opindex --force
Always overwrite the output file. The default is to overwrite the output
such third-party macros in your local @file{m4/} directory so they get
distributed.
+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
+ ACLOCAL_AMFLAGS = -I m4 --install
+@end example
+
+@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.)
+
+
@node Future of aclocal
@section The Future of @command{aclocal}
@cindex @command{aclocal}'s scheduled death
The new implementation will probably be done slightly differently.
For instance it could enforce the @file{m4/}-style layout discussed in
-@ref{Local Macros}, and take care of copying (and even updating)
-third-party macros from @file{/usr/share/aclocal/} into the local
-@file{m4/} directory.
+@ref{Local Macros}.
We have no idea when and how this will happen. This has been
discussed several times in the past, but someone still has to commit
#! /bin/sh
-# Copyright (C) 2003 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
#
# This file is part of GNU Automake.
#
# Make sure aclocal define macros in the same order as -I's.
# This is the same as aclocal9.test, with the macro calls reversed.
# (It did make a difference.)
+#
+# Also check for --install.
. ./defs || exit 1
cat >> configure.in << 'END'
MACRO2
MACRO1
+MACRO3
END
-mkdir m4_1 m4_2
+mkdir m4_1 m4_2 dirlist-test
cat >m4_1/somedefs.m4 <<EOF
AC_DEFUN([MACRO1], [echo macro11 >> foo])
AC_DEFUN([MACRO1], [echo macro12 >> foo])
EOF
+cat >dirlist-test/macro.m4 <<EOF
+AC_DEFUN([MACRO3], [echo macro3 >> foo])
+EOF
+
$ACLOCAL -I m4_1 -I m4_2
$AUTOCONF
./configure
grep macro11 foo
grep macro21 foo
+grep macro3 foo
+grep MACRO3 aclocal.m4
+test ! -f m4_1/macro.m4
+test ! -f m4_2/macro.m4
$ACLOCAL -I m4_2 -I m4_1
$AUTOCONF
./configure
grep macro12 foo
grep macro21 foo
+grep macro3 foo
+grep MACRO3 aclocal.m4
+test ! -f m4_1/macro.m4
+test ! -f m4_2/macro.m4
+
+ACLOCAL_TESTSUITE_FLAGS='-I m4_1 -I m4_2'
+$ACLOCAL --install
+$AUTOCONF
+./configure
+grep macro11 foo
+grep macro21 foo
+grep macro3 foo
+grep MACRO3 aclocal.m4 && exit 1
+test -f m4_1/macro.m4
+test ! -f m4_2/macro.m4
+cp aclocal.m4 copy.m4
+
+echo '#GREPME' >>dirlist-test/macro.m4
+$ACLOCAL --install
+$AUTOCONF
+./configure
+grep macro11 foo
+grep macro21 foo
+grep macro3 foo
+grep MACRO3 aclocal.m4 && exit 1
+grep GREPME m4_1/macro.m4 && exit 1
+test -f m4_1/macro.m4
+test ! -f m4_2/macro.m4
+diff aclocal.m4 copy.m4
# -*- shell-script -*-
# @configure_input@
#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
#
# This file is part of GNU Automake.
# Use -Werror because this also turns some Perl warnings into error.
# (Tests for which this is inappropriate should use -Wno-error.)
test -z "$ACLOCAL" && ACLOCAL="aclocal-@APIVERSION@ -Werror"
+# Extra flags to pass to aclocal before all other flags added by this script.
+ACLOCAL_TESTSUITE_FLAGS=
+export ACLOCAL_TESTSUITE_FLAGS
+
# See how Automake should be run. We put --foreign as the default
# strictness to avoid having to create lots and lots of files. A test
# can override this by specifying a different strictness. Use -Wall