You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用m4_foreach_w在configure中遍历动态构建的函数列表?

动态构建函数测试列表时m4_foreach_w未正确拆分列表

想要动态构建待测试的函数列表,之后针对列表中的每个函数调用对应宏。尝试使用m4_foreach_w处理空格分隔的列表,但工具并未拆分列表,导致整个列表被当作单个元素处理。

可复现示例(搭配空Makefile.in)

AC_INIT([faketest],[0.0],[],[],[])

AC_DEFUN([AC_CHECK_MY_FUNC], [
        _ac_check_my_func_list="$1 $_ac_check_my_func_list"
        ac_cv_my_func_$1=yes
])

m4_define([MY_CHECK_FUNC_RES],[ 
    m4_foreach_w([checkfunc], [$1], [
        AC_MSG_CHECKING([for checkfunc])
        AS_IF([test "x$ac_cv_my_func_checkfunc" = "xyes"], [
                AC_MSG_RESULT(yes)
                AC_DEFINE(AS_TR_CPP(HAVE_MY_checkfunc), 1, [Define if your system has the checkfunc function])
        ], [
           AC_MSG_RESULT(no)
        ])
    ])
])

AC_CHECK_MY_FUNC([fake1],
                    [#include <fake.h>],                                        
                    [if (fake1(x) == 0) return;])
AC_CHECK_MY_FUNC([fake2],
                    [#include <fake.h>],                                        
                    [fake2("", "", 0);])

MY_CHECK_FUNC_RES([[$_ac_check_my_func_list]])


AC_CONFIG_FILES([
    Makefile
])
AC_OUTPUT

预期输出

checking for fake2 ... no
checking for fake1 ... no
configure: creating ./config.status
config.status: creating Makefile

实际输出

checking for fake2 fake1 ... no
configure: creating ./config.status
config.status: creating Makefile

补充:修改MY_CHECK_FUNC_RES调用的m4引号级别并未改变结果。

问题原因

m4_foreach_w是m4预处理阶段的工具,而_ac_check_my_func_list是shell变量,其值在configure脚本运行阶段才会展开。m4预处理时只能看到字面的$_ac_check_my_func_list,无法获取它的实际值,自然无法拆分列表。

解决方法

方法1:使用shell循环处理(推荐)

将MY_CHECK_FUNC_RES修改为生成shell循环代码,在configure运行时逐个处理列表元素:

m4_define([MY_CHECK_FUNC_RES],[ 
    for checkfunc in $_ac_check_my_func_list; do
        AC_MSG_CHECKING([for $checkfunc])
        AS_IF([test "x$ac_cv_my_func_$checkfunc" = "xyes"], [
                AC_MSG_RESULT(yes)
                AC_DEFINE(AS_TR_CPP(HAVE_MY_$checkfunc), 1, [Define if your system has the $checkfunc function])
        ], [
           AC_MSG_RESULT(no)
        ])
    done
])

调用时直接使用:

MY_CHECK_FUNC_RES

方法2:在m4阶段积累列表

改用m4宏来积累函数列表,让m4在预处理阶段就能获取完整列表:

AC_INIT([faketest],[0.0],[],[],[])

# 初始化m4列表宏
m4_define([_ac_check_my_func_list], [])

AC_DEFUN([AC_CHECK_MY_FUNC], [
        # 用m4宏积累逗号分隔的列表
        m4_define([_ac_check_my_func_list], m4_defn([_ac_check_my_func_list])[$1,])
        ac_cv_my_func_$1=yes
])

m4_define([MY_CHECK_FUNC_RES],[ 
    # 使用m4_foreach处理逗号分隔的列表
    m4_foreach([checkfunc], m4_defn([_ac_check_my_func_list]), [
        AC_MSG_CHECKING([for checkfunc])
        AS_IF([test "x$ac_cv_my_func_checkfunc" = "xyes"], [
                AC_MSG_RESULT(yes)
                AC_DEFINE(AS_TR_CPP(HAVE_MY_checkfunc), 1, [Define if your system has the checkfunc function])
        ], [
           AC_MSG_RESULT(no)
        ])
    ])
])

AC_CHECK_MY_FUNC([fake1],
                    [#include <fake.h>],                                        
                    [if (fake1(x) == 0) return;])
AC_CHECK_MY_FUNC([fake2],
                    [#include <fake.h>],                                        
                    [fake2("", "", 0);])

MY_CHECK_FUNC_RES

AC_CONFIG_FILES([
    Makefile
])
AC_OUTPUT

两种方法都能实现逐个处理函数列表的需求,方法1更贴合shell脚本的运行逻辑,方法2则完全在m4预处理阶段完成列表构建。

内容的提问来源于stack exchange,提问作者Daria Phoebe Brashear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 23:43:14