Autoconf 循环但在第一次成功后停止?
Autoconf loop but stop after first success?
我有这个片段来检测并要求最高可用的 C++ 标准。它完全按照我想要的方式工作——首先检查最高值,并在第一次成功后停止搜索。它也非常丑陋且难以维护。
# Require highest supported C++ standard
AC_LANG(C++)
AX_CHECK_COMPILE_FLAG([-std=c++20], [CXXFLAGS="$CXXFLAGS -std=c++20"], [
AX_CHECK_COMPILE_FLAG([-std=c++2a], [CXXFLAGS="$CXXFLAGS -std=c++2a"], [
AX_CHECK_COMPILE_FLAG([-std=c++17], [CXXFLAGS="$CXXFLAGS -std=c++17"], [
AX_CHECK_COMPILE_FLAG([-std=c++1z], [CXXFLAGS="$CXXFLAGS -std=c++1z"], [
AX_CHECK_COMPILE_FLAG([-std=c++14], [CXXFLAGS="$CXXFLAGS -std=c++14"], [
AX_CHECK_COMPILE_FLAG([-std=c++1y], [CXXFLAGS="$CXXFLAGS -std=c++1y"], [
AC_MSG_ERROR([Could not enable at least C++1y (C++14) - upgrade your compiler])
])
])
])
])
])
])
有没有办法把它变成一个列表?我理想中想要的是类似于以下伪代码的东西,以便 add/remove 特定的 C++ 变体只是更改列表而不是整个树:
foreach([-std=c++20, -std=c++2a, -std=c++17, etc],
[if(AX_CHECK_COMPILE_FLAG(, [CXXFLAGS+=]), break)])
据我所知,m4 根本无法循环。它可以递归,但是打破递归是我显然无法工作的那种m4黑魔法。
不,更改为另一个构建系统不是一个选项。这在 CMake 中是微不足道的,但这个项目是 autotools。
From what I can find, m4 simply cannot loop. It can recurse, but breaking out of a recursion is the kind of m4 black magic that I apparently can't get to work.
M4 absolutely can loop,但您不需要它来实现您的目的,而且您可能不想要它。事实上,通常 不想在自己的 Autoconf 代码中直接利用 M4 功能。
请始终记住,M4 在您构建构建系统时运行,而不是在您配置项目时运行。它生成 configure
、shell 脚本和 用于 configure-time 控制流,您需要 configure
来利用 shell 特征。 Autoconf 围绕某些 shell 特性提供了宏,但您没有义务使用它们,您当然也没有义务避免使用 shell 特性只是因为没有 Autoconf 宏包装它们。主要警告是您应该小心编写 portable shell 代码。事实上,Autoconf 为 shell flow-control.
提供任何宏都是为了 objective
考虑到这一点,这里有一种使用 shell 循环来更干净地执行检查的方法:
# language versions to test, in priority order:
for version in 20 2a 17 1z 14 1y; do
version_flag="-std=c++${version}"
AX_CHECK_COMPILE_FLAG([${version_flag}], [
break
], [
version_flag=none
])
done
AS_IF([test "$version_flag" == none], [
AC_MSG_ERROR([Could not enable at least C++1y (C++14) - upgrade your compiler])
])
CXXFLAGS="$CXXFLAGS ${version_flag}"
如果您想更改已测试的版本或更改您喜欢的版本的优先级,那么您只需更改 for
语句中的列表即可。
但是,我提出一个框架挑战:有什么意义?如果 -std=c++1y
足以满足您程序的目的,那么通过有条件地 select 使用更新的版本可以获得什么?
也许确实有一点 - 例如,源代码可能包含预处理器条件,以便在按照更新的标准构建时启用其他功能。然而,在那种特殊情况下,更好的 Autoconf 习惯用法是为条件特征添加一个或多个 --enable
标志,并向 select 添加所需的 C++ 版本标志,如果有的话,被选中。然后就没有必要测试任何其他选项,而且对于想要影响实际启用的功能的构建者来说,它就不那么神奇了。
我有这个片段来检测并要求最高可用的 C++ 标准。它完全按照我想要的方式工作——首先检查最高值,并在第一次成功后停止搜索。它也非常丑陋且难以维护。
# Require highest supported C++ standard
AC_LANG(C++)
AX_CHECK_COMPILE_FLAG([-std=c++20], [CXXFLAGS="$CXXFLAGS -std=c++20"], [
AX_CHECK_COMPILE_FLAG([-std=c++2a], [CXXFLAGS="$CXXFLAGS -std=c++2a"], [
AX_CHECK_COMPILE_FLAG([-std=c++17], [CXXFLAGS="$CXXFLAGS -std=c++17"], [
AX_CHECK_COMPILE_FLAG([-std=c++1z], [CXXFLAGS="$CXXFLAGS -std=c++1z"], [
AX_CHECK_COMPILE_FLAG([-std=c++14], [CXXFLAGS="$CXXFLAGS -std=c++14"], [
AX_CHECK_COMPILE_FLAG([-std=c++1y], [CXXFLAGS="$CXXFLAGS -std=c++1y"], [
AC_MSG_ERROR([Could not enable at least C++1y (C++14) - upgrade your compiler])
])
])
])
])
])
])
有没有办法把它变成一个列表?我理想中想要的是类似于以下伪代码的东西,以便 add/remove 特定的 C++ 变体只是更改列表而不是整个树:
foreach([-std=c++20, -std=c++2a, -std=c++17, etc],
[if(AX_CHECK_COMPILE_FLAG(, [CXXFLAGS+=]), break)])
据我所知,m4 根本无法循环。它可以递归,但是打破递归是我显然无法工作的那种m4黑魔法。
不,更改为另一个构建系统不是一个选项。这在 CMake 中是微不足道的,但这个项目是 autotools。
From what I can find, m4 simply cannot loop. It can recurse, but breaking out of a recursion is the kind of m4 black magic that I apparently can't get to work.
M4 absolutely can loop,但您不需要它来实现您的目的,而且您可能不想要它。事实上,通常 不想在自己的 Autoconf 代码中直接利用 M4 功能。
请始终记住,M4 在您构建构建系统时运行,而不是在您配置项目时运行。它生成 configure
、shell 脚本和 用于 configure-time 控制流,您需要 configure
来利用 shell 特征。 Autoconf 围绕某些 shell 特性提供了宏,但您没有义务使用它们,您当然也没有义务避免使用 shell 特性只是因为没有 Autoconf 宏包装它们。主要警告是您应该小心编写 portable shell 代码。事实上,Autoconf 为 shell flow-control.
考虑到这一点,这里有一种使用 shell 循环来更干净地执行检查的方法:
# language versions to test, in priority order:
for version in 20 2a 17 1z 14 1y; do
version_flag="-std=c++${version}"
AX_CHECK_COMPILE_FLAG([${version_flag}], [
break
], [
version_flag=none
])
done
AS_IF([test "$version_flag" == none], [
AC_MSG_ERROR([Could not enable at least C++1y (C++14) - upgrade your compiler])
])
CXXFLAGS="$CXXFLAGS ${version_flag}"
如果您想更改已测试的版本或更改您喜欢的版本的优先级,那么您只需更改 for
语句中的列表即可。
但是,我提出一个框架挑战:有什么意义?如果 -std=c++1y
足以满足您程序的目的,那么通过有条件地 select 使用更新的版本可以获得什么?
也许确实有一点 - 例如,源代码可能包含预处理器条件,以便在按照更新的标准构建时启用其他功能。然而,在那种特殊情况下,更好的 Autoconf 习惯用法是为条件特征添加一个或多个 --enable
标志,并向 select 添加所需的 C++ 版本标志,如果有的话,被选中。然后就没有必要测试任何其他选项,而且对于想要影响实际启用的功能的构建者来说,它就不那么神奇了。