【问题标题】:Changing *FLAGS in configure.ac vs. caching with subprojects在 configure.ac 中更改 *FLAGS 与使用子项目进行缓存
【发布时间】:2015-12-06 23:52:18
【问题描述】:

假设我希望在我的configure 脚本中向CFLAGS 添加一个特定标志,该标志应该传播到所有子项目的configure 脚本:

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

这在configure 被简单调用时有效。一旦发生以下情况之一:

  1. CFLAGS 在调用configure 时在环境中导出
  2. CFLAGSconfigure 命令行上设置
  3. 使用缓存 (configure -C)

这种方法不再有效。在前两种情况下,导出的CFLAGS 被简单地忽略;在最后一个中,configure 失败了

configure: error: `CFLAGS' 没有在之前的运行中设置


我已经设法通过以下方式可靠地工作:

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

考虑到有多个子项目,以及可能需要这样设置的多个*FLAGS 变量,这还不错,但仍然不是最理想的。有没有办法通过只破解顶级configure.ac来完成这项工作?

【问题讨论】:

  • 当你在传递给configure的环境中尝试define a variable时会发生什么?
  • @rubicks 这行得通,但没有抓住重点:我希望我的顶级configure 为多个子包configure 调用准备和设置各种*FLAGS。我需要autoconf 工具来检查编译器/链接器选项等,以便准备这些标志。 (虽然你确实让我想到了从顶层手动调用子包 configures,但这听起来很脏......)
  • CFLAGS 是一个用户变量,维护者不应该修改它。您可以调整 AM_CFLAGS,(但 -Dfoo 形式的标志属于 AM_CPPFLAGS)
  • 最初的动机是设置强制标志(比如使用与 gcc4 兼容的 c++ ABI),而 AM_*FLAGS 在项目的大约 50 多个 makefile 中被覆盖。虽然可以修复每个target_*FLAGS 覆盖以包含AM_*FLAGS 而不是覆盖它,但这被认为更简单,因为非AM_ *FLAGS 总是包括在内。当在make-time 修改受影响的FLAGS 变量时会出现问题,因为这会覆盖配置生成的定义。由于这是一个“mantainer=user”类型的项目,所以没什么大不了的。

标签: autotools autoconf automake cflags


【解决方案1】:

我终于让它工作了,除了在多个顶级 configure 运行中进行缓存。这个想法是破解 autoconf 的内部变量以获得所需的功能,这并不难:

  • 修改CFLAGS
  • 破解ac_configure_args 以包含修改后的CFLAGS,而不是任何外部检测到的CFLAGS

这立即解决了问题描述中的问题 1. 和 2.(外部CFLAGS)。为了修复缓存,我必须:

  • 破解ac_cv_env_CFLAGS_{set,value}以分别包含set和修改后的CFLAGS

这会导致两个问题:

  1. 使用缓存,./config.status --recheck 将再次执行对 CFLAGS 的修改,即使此修改已被缓存,从而导致重复标志。仅在未完成修改时才进行修改可解决此问题。
  2. 当使用现有的config.cache 调用顶级配置时,损坏是不可避免的,因为config.cache 一致性检查执行得太早,不会受到影响。只有当我们在命令行(或环境)上通过CFLAGS 包括 configure-modification 时,这个检查才会通过,没有办法绕过它。唯一的解决方法是在配置所有子包后删除config.cache。由于子包配置期间的缓存仍然有效,我发现这是可以接受的。

顶级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

子级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

Makefiles 仅在 all-local 目标中打印 $CFLAGS 的值。

输出如下所示:

$ 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】:

    最终的解决方案是un-precious受影响的变量:

    顶级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
    

    在幕后,CFLAGS 从未被视为珍贵,因此从未缓存或传递给子包configures — 他们将其视为环境变量专有,然后将其缓存自己在共同的顶级config.cache

    这非常可靠,并且通过允许缓存值甚至跨顶级配置运行(并且更简单)来改进我之前的解决方案。

    【讨论】:

      猜你喜欢
      • 2021-01-01
      • 2012-12-31
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 2014-05-27
      • 2021-01-13
      • 2023-03-27
      相关资源
      最近更新 更多