如何在 AC_COMPILE_IFELSE 程序中使用 AC_CHECK_HEADER header
How to use an AC_CHECK_HEADER header in an AC_COMPILE_IFELSE program
我正在对 Clang 和 GCC 提供的 non-standard <x86intrin.h>
header 进行 header 检查。其他编译器遵循 Intel 并使用 <immintrin.h>
:
AC_CHECK_HEADER([x86intrin.h])
Autotools 在 Linux 测试系统上找到它:
checking x86intrin.h usability... yes
checking x86intrin.h presence... yes
checking for x86intrin.h... yes
然后我在测试中使用它:
CXXFLAGS="-mrdseed"
XXX_PROGRAM="#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([$XXX_PROGRAM])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
测试失败:
checking if g++ supports -mrdseed... no
机器有这个特性,编译器支持。从 config.log
查看 condefs.h
显示 HAVE_X86INTRIN_H
未按预期设置。
手册说明了如何使用 5.6.3 Generic Header Checks 处检查得到的 header。我想我在做大致相同的事情:
AC_CHECK_HEADERS([foo.h])
AC_CHECK_HEADERS([bar.h], [], [],
[#ifdef HAVE_FOO_H
# include <foo.h>
# endif
])
如何在 AC_COMPILE_IFELSE
程序中使用 AC_CHECK_HEADER
header?
这是我的测试driver:
$ cat test.cxx
#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}
$ g++ -mrdseed test.cxx -o test.exe
test.cxx: In function ‘int main(int, char**)’:
test.cxx:7:12: error: ‘_rdseed32_step’ was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
test.cxx:7:12: note: suggested alternative: ‘_rdrand32_step’
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
$ g++ -DHAVE_X86INTRIN_H -mrdseed test.cxx -o test.exe
$ ./test.exe
$
这是发行版和编译器:
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: Fedora
Description: Fedora release 28 (Twenty Eight)
Release: 28
$ g++ --version
g++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5)
以下是 config.log
的相关部分:
configure:17624: checking if g++ supports -mrdseed
configure:17631: g++ -o conftest -mrdseed conftest.cpp >&5
conftest.cpp: In function 'int main(int, char**)':
conftest.cpp:38:17: error: '_rdseed32_step' was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
conftest.cpp:38:17: note: suggested alternative: '_rdrand32_step'
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
configure:17631: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "Crypto++"
| ...
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_DLFCN_H 1
| #define LT_OBJDIR ".libs/"
| ...
| /* end confdefs.h. */
| #include <immintrin.h>
| #ifdef HAVE_X86INTRIN_H
| # include <x86intrin.h>
| #endif
| int main(int argc, char** argv) {
| unsigned int x;
| return _rdseed32_step(&x);
| }
configure:17645: result: no
您被 Autoconf 陷阱绊倒了。 The docs for AC_CHECK_HEADER
说:
If the system header file header-file is compilable, execute shell
commands action-if-found
, otherwise execute action-if-not-found
.
If you just want to define a symbol if the header file is available,
consider using AC_CHECK_HEADERS
instead.
(强调)
将其与 AC_CHECK_HEADERS
的文档进行对比:
For each given system header file header-file in the blank-separated
argument list that exists, define HAVE_*header-file*
(in all capitals).
If action-if-found is given, [...]
请注意,与 AC_CHECK_HEADERS
的文档不同,AC_CHECK_HEADER
的文档并未声明如果找到 header 将定义任何符号。在这种情况下,除了报告检查结果之外,唯一要做的就是 运行 action-if-found
中的命令。您当然可以在其中放置一个 AC_DEFINE
来定义一个符号,但是您不会像从 AC_CHECK_HEADERS
那样免费获得它。如果需要,即使是单个 header.
也可以使用 AC_CHECK_HEADERS
我确信最初造成差异的原因围绕着 AC_CHECK_HEADERS
检查可能很多 header 这一事实。此外,有时您并不关心定义一个符号,或者您可能明确希望避免这样做;对于这些情况,您可以使用 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
我正在对 Clang 和 GCC 提供的 non-standard <x86intrin.h>
header 进行 header 检查。其他编译器遵循 Intel 并使用 <immintrin.h>
:
AC_CHECK_HEADER([x86intrin.h])
Autotools 在 Linux 测试系统上找到它:
checking x86intrin.h usability... yes
checking x86intrin.h presence... yes
checking for x86intrin.h... yes
然后我在测试中使用它:
CXXFLAGS="-mrdseed"
XXX_PROGRAM="#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}"
AC_MSG_CHECKING([if $CXXNAME supports $CXXFLAGS])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([$XXX_PROGRAM])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]
)
测试失败:
checking if g++ supports -mrdseed... no
机器有这个特性,编译器支持。从 config.log
查看 condefs.h
显示 HAVE_X86INTRIN_H
未按预期设置。
手册说明了如何使用 5.6.3 Generic Header Checks 处检查得到的 header。我想我在做大致相同的事情:
AC_CHECK_HEADERS([foo.h])
AC_CHECK_HEADERS([bar.h], [], [],
[#ifdef HAVE_FOO_H
# include <foo.h>
# endif
])
如何在 AC_COMPILE_IFELSE
程序中使用 AC_CHECK_HEADER
header?
这是我的测试driver:
$ cat test.cxx
#include <immintrin.h>
#ifdef HAVE_X86INTRIN_H
# include <x86intrin.h>
#endif
int main(int argc, char** argv) {
unsigned int x;
return _rdseed32_step(&x);
}
$ g++ -mrdseed test.cxx -o test.exe
test.cxx: In function ‘int main(int, char**)’:
test.cxx:7:12: error: ‘_rdseed32_step’ was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
test.cxx:7:12: note: suggested alternative: ‘_rdrand32_step’
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
$ g++ -DHAVE_X86INTRIN_H -mrdseed test.cxx -o test.exe
$ ./test.exe
$
这是发行版和编译器:
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: Fedora
Description: Fedora release 28 (Twenty Eight)
Release: 28
$ g++ --version
g++ (GCC) 8.1.1 20180712 (Red Hat 8.1.1-5)
以下是 config.log
的相关部分:
configure:17624: checking if g++ supports -mrdseed
configure:17631: g++ -o conftest -mrdseed conftest.cpp >&5
conftest.cpp: In function 'int main(int, char**)':
conftest.cpp:38:17: error: '_rdseed32_step' was not declared in this scope
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
conftest.cpp:38:17: note: suggested alternative: '_rdrand32_step'
return _rdseed32_step(&x);
^~~~~~~~~~~~~~
_rdrand32_step
configure:17631: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME "Crypto++"
| ...
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_DLFCN_H 1
| #define LT_OBJDIR ".libs/"
| ...
| /* end confdefs.h. */
| #include <immintrin.h>
| #ifdef HAVE_X86INTRIN_H
| # include <x86intrin.h>
| #endif
| int main(int argc, char** argv) {
| unsigned int x;
| return _rdseed32_step(&x);
| }
configure:17645: result: no
您被 Autoconf 陷阱绊倒了。 The docs for AC_CHECK_HEADER
说:
If the system header file header-file is compilable, execute shell commands
action-if-found
, otherwise executeaction-if-not-found
. If you just want to define a symbol if the header file is available, consider usingAC_CHECK_HEADERS
instead.
(强调)
将其与 AC_CHECK_HEADERS
的文档进行对比:
For each given system header file header-file in the blank-separated argument list that exists, define
HAVE_*header-file*
(in all capitals). If action-if-found is given, [...]
请注意,与 AC_CHECK_HEADERS
的文档不同,AC_CHECK_HEADER
的文档并未声明如果找到 header 将定义任何符号。在这种情况下,除了报告检查结果之外,唯一要做的就是 运行 action-if-found
中的命令。您当然可以在其中放置一个 AC_DEFINE
来定义一个符号,但是您不会像从 AC_CHECK_HEADERS
那样免费获得它。如果需要,即使是单个 header.
AC_CHECK_HEADERS
我确信最初造成差异的原因围绕着 AC_CHECK_HEADERS
检查可能很多 header 这一事实。此外,有时您并不关心定义一个符号,或者您可能明确希望避免这样做;对于这些情况,您可以使用 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