autotoolsautoconfm4

Substitute variable into m4 macro when running autoconf


I have something like this in my configure.ac, where a binary name is set and passed via AC_SUBST, and that same binary name is then hardcoded into various other m4 macros.

UTIL_BIN_NAME=foobar
...
AC_ARG_WITH([utils],
  [AS_HELP_STRING([--with-utils],
  [build foobar binary (default=yes)])],
  [build_utils=$withval],
  [build_utils=yes])
...
AC_SUBST(UTIL_BIN_NAME)

Is there a way in which I can substitute in a variable, such that the binary name is only hardcoded in a single place instead of multiple places. e.g. something like:

UTIL_BIN_NAME=foobar
...
AC_ARG_WITH([utils],
  [AS_HELP_STRING([--with-utils],
  [build $UTIL_BIN_NAME binary (default=yes)])],
  [build_utils=$withval],
  [build_utils=yes])
...
AC_SUBST(UTIL_BIN_NAME)

The above unfortunately doesn't work, so just an example of what I am hoping to achieve.

I've attempted various searches to try and find the correct way to do this but am somehow coming up short and not finding anything. How to achieve this?


Solution

  • You can use shell variables in Autoconf macro arguments, but doing so does not always have the effect you want. Autoconf does not expand them itself (normally; there is a whole other story here), but you can be tripped up by the fact that the order of code in the generated configure script does not strictly follow the order of macros in the Autoconf input. In particular, the code for processing arguments goes near the front, before almost everything else. Additionally, variable references do not serve syntactically or semantically in a shell script in some of the places where Autoconf macros inject their arguments.

    If you need an adjustable parameter that is not sensitive to output reordering or that otherwise can serve in contexts where a shell variable cannot, then you're probably looking for an m4 macro or macro argument. Autoconf input is processed with a custom m4 configuration and a sizable stack of pre-defined macros, but it is still m4 input, and you can use normal m4 facilities. Macro definition and expansion is among the most fundamental of these.

    Autoconf renames substantially all of m4's builtins into the m4_ namespace, so the basic define builtin would be spelled "m4_define":

    m4_define([UTIL_BIN_NAME], [foobar])
    

    An m4 macro definition such as that takes effect when processed, so it is not sensitive to Autoconf's juggling of the output order. Subsequent appearances of UTIL_BIN_NAME will be expanded by Autoconf according to the given definition, subject to quoting considerations. Of course, you do need a shell variable to use with AC_SUBST and for some other purposes, but it's not too hard to produce a shell variable from a macro.

    The quoting is a bit tricky, but this produces the wanted result (as I understand it) for me:

    m4_define([UTIL_BIN_NAME], [foobar])
    # Create a shell variable with the same name and (initial) value as the macro:
    [UTIL_BIN_NAME]=UTIL_BIN_NAME
    
    # Note: one could use the (a) macro to customize the names of shell variables
    # such as 'build_utils', too, if that were desirable.  Details are left as an
    # exercise.
    AC_ARG_WITH([UTIL_BIN_NAME],
      [AS_HELP_STRING([--with-[]UTIL_BIN_NAME],
        [build ]UTIL_BIN_NAME[ binary (default=yes)])],
      [build_utils=$withval],
      [build_utils=yes]
    )
    
    # ...
    
    AC_SUBST([UTIL_BIN_NAME])