Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing *FLAGS in configure.ac vs. caching with subprojects

Say I wish to add a specific flag to CFLAGS within my configure script, that should propagate to all subprojects' configure scripts:

CFLAGS+=" -Dfoobar"
export CFLAGS
AC_CONFIG_SUBDIRS([sub])

This works when configure is invoked trivially. As soon as one of the following happens:

  1. CFLAGS is exported in the environment when configure is invoked
  2. CFLAGS is set on configure command-line
  3. caching is used (configure -C)

This approach no longer works. In the first two cases, the exported CFLAGS is simply ignored; and in the last one, configure fails with

configure: error: `CFLAGS' was not set in the previous run


I have managed to get this working reliably by:

AM_CFLAGS+=" -Dfoobar"
export AM_CFLAGS
AC_SUBST([AM_CFLAGS]) # repeat this line in every configure.ac for each *FLAGS
AC_CONFIG_SUBDIRS([sub])

Considering there are multiple subprojects, and multiple *FLAGS variables that may need to be set like this, this is half-way okay but still suboptimal. Is there a way to make this work by only hacking the top-level configure.ac?

like image 974
Irfy Avatar asked Oct 30 '22 14:10

Irfy


1 Answers

I have finally gotten this to work, except for caching across multiple top-level configure runs. The idea is to hack autoconf's internal variables to get the desired functionality, and it wasn't too hard:

  • modify CFLAGS
  • hack ac_configure_args to include the modified CFLAGS instead of any externally detected CFLAGS

This immediately solved problems 1. and 2. from the problem description (external CFLAGS). In order to fix caching, I had to:

  • hack ac_cv_env_CFLAGS_{set,value} to contain set and the modified CFLAGS, respectively

This lead to two issues:

  1. with caching, ./config.status --recheck would perform the modification to CFLAGS again, even though this modification has already been cached, resulting in repeated flags. Doing the modification only if it hadn't been done resolved this issue.
  2. when invoking the top-level configure with an existing config.cache, a corruption is unavoidable, because the config.cache consistency check is performed so early, it cannot be influenced. Only if we were to pass CFLAGS including the configure-modification on the command-line (or environment), would this check pass, no way around it. The only fix for this was to delete config.cache after all sub-packages have been configured. As caching during sub-package configuration still works, I found this acceptable.

Top-level configure.ac:

AC_INIT([test], [0.1])
AC_CONFIG_MACRO_DIR([m4]) # for ax_append_flag.m4
AM_INIT_AUTOMAKE([-Wall -Werror foreign])

AC_PROG_CC
AC_PROG_SED

# Modify the CFLAGS. AX_APPEND_FLAG makes sure not to add the flag if it's already there
AX_APPEND_FLAG([-Dtop-configure], [CFLAGS])

# Replace/add CFLAGS in/to ac_configure_args
AS_CASE([$ac_configure_args],
    [*CFLAGS=*], [ac_configure_args=`AS_ECHO "$ac_configure_args" | $SED ["s|CFLAGS=[^']*|CFLAGS=$CFLAGS|"]`],
    [AS_VAR_APPEND([ac_configure_args],[" 'CFLAGS=$CFLAGS'"])]
)

# Fix the cache vars
ac_cv_env_CFLAGS_set=set
ac_cv_env_CFLAGS_value=$CFLAGS

# exporting CFLAGS is not needed for sub-packages: they get CFLAGS from ac_configure_args

AC_CONFIG_SUBDIRS([sub])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

AC_MSG_NOTICE([removing config.cache])
rm -f config.cache

Sub-level configure.ac:

AC_INIT([test-sub], [0.1])
AC_CONFIG_MACRO_DIR([../m4])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AX_APPEND_FLAG([-Dsub-configure], [CFLAGS])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

The Makefiles only print the value of $CFLAGS in an all-local target.

Output looks like this:

$ autoconf && ./configure -C >/dev/null && make | grep CFLAGS # 1st run
sub CFLAGS: -g -O2 -Dtop-configure -Dsub-configure
top CFLAGS: -g -O2 -Dtop-configure
$ ./configure -C >/dev/null && make | grep CFLAGS # 2nd run
sub CFLAGS: -g -O2 -Dtop-configure -Dsub-configure
top CFLAGS: -g -O2 -Dtop-configure
$ touch configure.ac && make | grep CFLAGS # recheck run
running CONFIG_SHELL=/bin/sh /bin/sh ./configure -C CFLAGS=-g -O2 -Dtop-configure --no-create --no-recursion
sub CFLAGS: -g -O2 -Dtop-configure -Dsub-configure
top CFLAGS: -g -O2 -Dtop-configure
$ CFLAGS=-Dexternal ./configure -C >/dev/null && make | grep CFLAGS # 1st run
sub CFLAGS: -Dexternal -Dtop-configure -Dsub-configure
top CFLAGS: -Dexternal -Dtop-configure
$ CFLAGS=-Dexternal ./configure -C >/dev/null && make | grep CFLAGS # 2nd run
sub CFLAGS: -Dexternal -Dtop-configure -Dsub-configure
top CFLAGS: -Dexternal -Dtop-configure
$ touch configure.ac && make | grep CFLAGS # recheck run
running CONFIG_SHELL=/bin/sh /bin/sh ./configure -C CFLAGS=-Dexternal -Dtop-configure --no-create --no-recursion
sub CFLAGS: -Dexternal -Dtop-configure -Dsub-configure
top CFLAGS: -Dexternal -Dtop-configure
like image 71
Irfy Avatar answered Nov 13 '22 04:11

Irfy