[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
tracing m4 calls using... M4 [WAS Re: libtool 2.4: questionable advice]
From: |
Gary V. Vaughan |
Subject: |
tracing m4 calls using... M4 [WAS Re: libtool 2.4: questionable advice] |
Date: |
Tue, 5 Oct 2010 13:59:21 +0700 |
On 5 Oct 2010, at 11:36, Ralf Wildenhues wrote:
> Grepping configure.ac is the real kludge, ACLOCAL_AMFLAGS is the
> "redundant" way to also allow more complicated setups. Let's not
> prevent the complex setup just to make the simple setup a wee bit
> simpler.
It would have made more sense to have aclocal take its macro
directory locations from AC_CONFIG_MACRO_DIRS, and it wouldn't
have been difficult to add support for multiple macro-dir decls
in configure.ac to avoid the redundancy. It doesn't bother me
enough to want to fix it though, especially as aclocal needn't
outlive the adoption of M4-2.0 by Autoconf.
Regarding the kludgey grep/sed macro searching that bootstrap
tools which generate input to aclocal have been doing, I've
found a better way while working on the rewrite of gnulib's
bootstrap script:
# func_extract_trace MACRO_NAME [FILENAME]...
# -------------------------------------------
# set `$func_extract_trace_result' to a colon delimited list of
# arguments to MACRO_NAME in FILENAME. If no FILENAME is not given,
# then `configure.ac' is assumed.
func_extract_trace ()
{
$debug_cmd
$require_configure_ac
$require_gnu_m4
my_macro="$1"; shift
test $# -gt 0 || {
set dummy $configure_ac
shift
}
# Generate an error if the first file is missing
<"$1"
# Sadly, we can't use `autom4te' tracing to extract macro
# arguments, because it complains about things we want to
# ignore at bootstrap time - like missing m4_include files;
# AC_PREREQ being newer than the installed autoconf; and
# returns nothing when tracing `AM_INIT_AUTOMAKE' when
# aclocal hasn't been generated yet.
#
# The following tries to emulate a less persnickety version
# of (and due to not having to wait for Perl startup on
# every invocation, it's probably faster too):
#
# autom4te --language=Autoconf --trace=$my_macro:\$% "$@"
#
# First we give a minimal set of macro declarations to M4
# to prime it for reading Autoconf macros, while still
# providing some of the functionality generally used at
# m4-time to supply dynamic arguments to Autocof functions,
# but without following `m4_s?include' files.
#
# We discard M4's stdout, but the M4 trace output from reading
# our "autoconf.mini" followed by any other files passed to
# this function is then scanned by sed to transform it into
# a colon delimited argument list assigned to a shell variable.
#
# Finally, we `eval' the sed generated assignment to get
# the result back into this script for further use by callers
# of this function.
func_extract_trace_result=
eval `echo '
# Initialisation.
m4_changequote([,])
m4_define([m4_copy], [m4_define([$2], m4_defn([$1]))])
m4_define([m4_rename], [m4_copy([$1], [$2])m4_undefine([$1])])
# Disable these macros.
m4_undefine([m4_dnl])
m4_undefine([m4_include])
m4_undefine([m4_m4exit])
m4_undefine([m4_m4wrap])
m4_undefine([m4_maketemp])
# Copy and rename macros not handled by "m4 --prefix".
m4_copy([m4_defn], [defn])
m4_define([dnl], [m4_builtin([dnl])])
m4_copy([m4_define], [m4_defun])
m4_rename([m4_ifelse], [m4_if])
m4_ifdef([m4_mkstemp], [m4_undefine([m4_mkstemp])])
m4_rename([m4_patsubst], [m4_bpatsubst])
m4_rename([m4_regexp], [m4_bregexp])
# "m4sugar.mini" - useful m4-time macros for dynamic arguments.
# If we discover packages that need more m4 macros defined in
# order to bootstrap correctly, add them here:
m4_define([m4_bmatch],
[m4_if([$#], 0, [], [$#], 1, [], [$#], 2, [$2],
[m4_if(m4_bregexp([$1], [$2]), -1,
[$0([$1], m4_shift3($@))], [$3])])])
m4_define([m4_ifndef], [m4_ifdef([$1], [$3], [$2])])
m4_define([m4_ifset],
[m4_ifdef([$1], [m4_ifval(m4_defn([$1]), [$2], [$3])], [$3])])
m4_define([m4_require], [$1])
m4_define([m4_shift3], [m4_shift(m4shift(m4shift($@)))])
# "autoconf.mini" - things from autoconf macros we care about.
m4_copy([m4_defun], [AC_DEFUN])
# Dummy definition for the macro we want to trace.
# AM_INIT_AUTOMAKE at least produces no trace without this.
AC_DEFUN(['"$my_macro"'])' \
|$M4 -daq --prefix --trace="$my_macro" - "$@" 2>&1 1>/dev/null \
|$SED -n 's|#.*$||
/^m4trace: -1- '"$my_macro"'/ {
s|^m4trace: -1- '"$my_macro"'([[]|func_extract_trace_result='\''|
s|], [[]|:|g
s|])$|'\''|
s|[^'\'']$|\&'\''|
p
}'`
}
In the current incarnation this is uglified by the inline m4 script, and in
due course this should be invoked by `autom4te
--language=Autoconf-pre-bootstrap'
or similiar. None-the-less, I think that having tools use M4 to parse and
trace m4 code is a huge step forward from all the greping and seding that
our other tools wind up with. Even in this embryonic state, bootstrap can
correctly extract version arguments from:
AC_INIT([GNU coreutils],
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
address@hidden)
and even:
m4_define([M4_VERSION],
m4_esyscmd([build-aux/git-version-gen .tarball-version]))
m4_bmatch(m4_defn([M4_VERSION]), [^[0-9]], [],
[m4_define([M4_VERSION], [1.9a])])
AC_INIT([GNU M4], m4_defn([M4_VERSION]), address@hidden)
...which no amount of grep and sed could achieve in anything like a general
way.
Once I've shepherded bootstrap back into gnulib, then while I wait for my
libtool queue to be merged, I'll see whether I'm capable of moving that part
of the function above into autom4te -- with one hand over my eyes lest they
be offended by the Perl code therein ;)
Cheers,
--
Gary V. Vaughan (address@hidden)
PGP.sig
Description: This is a digitally signed message part