[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 ()


    my_macro="$1"; shift
    test $# -gt 0 || {
      set dummy $configure_ac

    # Generate an error if the first file is missing

    # 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.
    eval `echo '
        # Initialisation.
        m4_define([m4_copy],   [m4_define([$2], m4_defn([$1]))])
        m4_define([m4_rename], [m4_copy([$1], [$2])m4_undefine([$1])])

        # Disable these macros.

        # 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_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_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

In the current incarnation this is uglified by the inline m4 script, and in
due course this should be invoked by `autom4te 
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]),

and even:

            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

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 ;)

Gary V. Vaughan (address@hidden)

Attachment: PGP.sig
Description: This is a digitally signed message part

reply via email to

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