jww*_*jww 3 c x86 autoconf autotools
<x86intrin.h>我正在对 Clang 和 GCC 提供的非标准标头执行标头检查。其他编译器遵循英特尔并使用<immintrin.h>:
AC_CHECK_HEADER([x86intrin.h])\nRun Code Online (Sandbox Code Playgroud)\n\nAutotools 在 Linux 测试系统上找到它:
\n\nchecking x86intrin.h usability... yes\nchecking x86intrin.h presence... yes\nchecking for x86intrin.h... yes\nRun Code Online (Sandbox Code Playgroud)\n\n然后我在测试中使用它:
\n\nCXXFLAGS="-mrdseed"\nXXX_PROGRAM="#include <immintrin.h>\n #ifdef HAVE_X86INTRIN_H\n # include <x86intrin.h>\n #endif\n int main(int argc, char** argv) {\n unsigned int x;\n return _rdseed32_step(&x);\n }"\n\nAC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS])\nAC_COMPILE_IFELSE(\n [AC_LANG_SOURCE([$XXX_PROGRAM])],\n [AC_MSG_RESULT([yes])],\n [AC_MSG_RESULT([no])]\n)\nRun Code Online (Sandbox Code Playgroud)\n\n测试失败:
\n\nchecking if g++ supports -mrdseed... no\nRun Code Online (Sandbox Code Playgroud)\n\n机器有该功能并且编译器支持它。condefs.h从config.log节目中看HAVE_X86INTRIN_H并没有按预期设置。
该手册展示了如何使用5.6.3 通用标头检查中检查产生的标头中检查产生的标头。我想我正在做大致相同的事情:
\n\nAC_CHECK_HEADERS([foo.h])\nAC_CHECK_HEADERS([bar.h], [], [],\n[#ifdef HAVE_FOO_H\n # include <foo.h>\n # endif\n])\nRun Code Online (Sandbox Code Playgroud)\n\n如何AC_CHECK_HEADER在AC_COMPILE_IFELSE?
这是我的测试驱动程序:
\n\n$ cat test.cxx\n#include <immintrin.h>\n#ifdef HAVE_X86INTRIN_H\n# include <x86intrin.h>\n#endif\nint main(int argc, char** argv) {\n unsigned int x;\n return _rdseed32_step(&x);\n}\n\n$ g++ -mrdseed test.cxx -o test.exe\ntest.cxx: In function \xe2\x80\x98int main(int, char**)\xe2\x80\x99:\ntest.cxx:7:12: error: \xe2\x80\x98_rdseed32_step\xe2\x80\x99 was not declared in this scope\n return _rdseed32_step(&x);\n ^~~~~~~~~~~~~~\ntest.cxx:7:12: note: suggested alternative: \xe2\x80\x98_rdrand32_step\xe2\x80\x99\n return _rdseed32_step(&x);\n ^~~~~~~~~~~~~~\n _rdrand32_step\n\n$ g++ -DHAVE_X86INTRIN_H -mrdseed test.cxx -o test.exe\n$ ./test.exe\n$\nRun Code Online (Sandbox Code Playgroud)\n\n这是发行版和编译器:
\n\n$ lsb_release -a\nLSB Version: :core-4.1-amd64:core-4.1-noarch\nDistributor ID: Fedora\nDescription: Fedora release 28 (Twenty Eight)\nRelease: 28\n\n$ g++ --version\ng++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5)\nRun Code Online (Sandbox Code Playgroud)\n\n以下是相关部分config.log:
configure:17624: checking if g++ supports -mrdseed\nconfigure:17631: g++ -o conftest -mrdseed conftest.cpp >&5\nconftest.cpp: In function \'int main(int, char**)\':\nconftest.cpp:38:17: error: \'_rdseed32_step\' was not declared in this scope\n return _rdseed32_step(&x);\n ^~~~~~~~~~~~~~\nconftest.cpp:38:17: note: suggested alternative: \'_rdrand32_step\'\n return _rdseed32_step(&x);\n ^~~~~~~~~~~~~~\n _rdrand32_step\nconfigure:17631: $? = 1\nconfigure: failed program was:\n| /* confdefs.h */\n| #define PACKAGE_NAME "Crypto++"\n| ...\n| #define STDC_HEADERS 1\n| #define HAVE_SYS_TYPES_H 1\n| #define HAVE_SYS_STAT_H 1\n| #define HAVE_STDLIB_H 1\n| #define HAVE_STRING_H 1\n| #define HAVE_MEMORY_H 1\n| #define HAVE_STRINGS_H 1\n| #define HAVE_INTTYPES_H 1\n| #define HAVE_STDINT_H 1\n| #define HAVE_UNISTD_H 1\n| #define HAVE_DLFCN_H 1\n| #define LT_OBJDIR ".libs/"\n| ...\n| /* end confdefs.h. */\n| #include <immintrin.h>\n| #ifdef HAVE_X86INTRIN_H\n| # include <x86intrin.h>\n| #endif\n| int main(int argc, char** argv) {\n| unsigned int x;\n| return _rdseed32_step(&x);\n| }\nconfigure:17645: result: no\nRun Code Online (Sandbox Code Playgroud)\n
您被 Autoconf 的陷阱绊倒了。 文档AC_CHECK_HEADER说:
如果系统头文件 header-file 可编译,则执行 shell 命令
action-if-found,否则执行action-if-not-found. 如果您只想在头文件可用的情况下定义一个符号,请考虑使用AC_CHECK_HEADERS。
(强调已添加)
将其与以下文档进行对比AC_CHECK_HEADERS:
对于存在的空白分隔参数列表中的每个给定系统头文件 header-file,定义
HAVE_*header-file*(全部大写)。如果给出了 action-if-found,[...]
请注意,与 的文档不同AC_CHECK_HEADERS, 的 文档AC_CHECK_HEADER并不声明如果找到标头就会定义任何符号。在这种情况下,除了报告检查结果之外,唯一要做的就是运行action-if-found. 您当然可以AC_DEFINE在其中放置一个来定义符号,但您不能像从 中那样免费获得它AC_CHECK_HEADERS。如果您愿意,您AC_CHECK_HEADERS甚至可以使用单个标头。
我确信差异的最初原因与检查可能的许多标头这一事实有关AC_CHECK_HEADERS。此外,有时您并不关心定义符号,或者您可能明确希望避免这样做;对于这些情况,您可以使用AC_CHECK_HEADER.
这是一个完整的 Autoconf 输入文件,演示了支票的工作变体:
AC_PREREQ([2.69])
AC_INIT([test], [0.0.0])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
# Ensure that tests are run with the C++ compiler
AC_LANG([C++])
# Checks for header files.
AC_CHECK_HEADERS([x86intrin.h])
# Check support for -mrdseed
AS_IF([test "$ac_cv_header_x86intrin_h" = "yes"], [
CXXFLAGS_save=$CXXFLAGS
CXXFLAGS="$CXXFLAGS -mrdseed"
XXX_PROGRAM="
#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
#include <x86intrin.h>
#endif
int main(void) {
unsigned int x;
return _rdseed32_step(&x);
}
"
AC_MSG_CHECKING([whether $CXX supports -mrdseed])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([$XXX_PROGRAM])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
CXXFLAGS=$CXXFLAGS_save
])
AC_OUTPUT
Run Code Online (Sandbox Code Playgroud)