问题
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:
CFLAGS
is exported in the environment whenconfigure
is invokedCFLAGS
is set onconfigure
command-line- 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
?
回答1:
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 modifiedCFLAGS
instead of any externally detectedCFLAGS
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 containset
and the modifiedCFLAGS
, respectively
This lead to two issues:
- 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. - when invoking the top-level configure with an existing
config.cache
, a corruption is unavoidable, because theconfig.cache
consistency check is performed so early, it cannot be influenced. Only if we were to passCFLAGS
including theconfigure
-modification on the command-line (or environment), would this check pass, no way around it. The only fix for this was to deleteconfig.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 Makefile
s 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
回答2:
The ultimate solution was to un-precious the affected variables:
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])
AC_DEFUN([AX_UNPRECIOUS], [
m4_define([_AC_PRECIOUS_VARS], m4_bpatsubst(_AC_PRECIOUS_VARS, [$1
], []))
])
AX_UNPRECIOUS([CFLAGS])
export CFLAGS
AC_CONFIG_SUBDIRS([sub])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Behind the curtains, CFLAGS
is never seen as precious and thus never cached or passed to sub-package configure
s—they see it as an environment variable exclusively, and then cache it themselves in the common top-level config.cache
.
This works very reliably, and improves upon my previous solution by allowing cached values even across top-level configure runs (and by being simpler).
来源:https://stackoverflow.com/questions/34124337/changing-flags-in-configure-ac-vs-caching-with-subprojects