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

耗尽温柔 提交于 2019-12-10 18:08:04

问题


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?


回答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 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



回答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 configures—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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!