编译 C 或 C++ 代码时找出 CPU 架构最可靠的方法是什么?据我所知,不同的编译器有自己的一组非标准预处理器定义(_M_X86
在 MSVS 中__i386__
,__arm__
在 GCC 中等)。
有没有一种标准的方法来检测我正在构建的架构?如果没有,是否有各种编译器的此类定义的完整列表的来源,例如带有所有样板#ifdef
的标头?
编译 C 或 C++ 代码时找出 CPU 架构最可靠的方法是什么?据我所知,不同的编译器有自己的一组非标准预处理器定义(_M_X86
在 MSVS 中__i386__
,__arm__
在 GCC 中等)。
有没有一种标准的方法来检测我正在构建的架构?如果没有,是否有各种编译器的此类定义的完整列表的来源,例如带有所有样板#ifdef
的标头?
没有编译器间标准,但每个编译器都趋于一致。您可以为自己构建一个标题,如下所示:
#if MSVC
#ifdef _M_X86
#define ARCH_X86
#endif
#endif
#if GCC
#ifdef __i386__
#define ARCH_X86
#endif
#endif
一个完整的列表没有多大意义,因为有成千上万的编译器,但只有 3-4 个被广泛使用(Microsoft C++、GCC、Intel CC,也许是 TenDRA?)。只需决定您的应用程序将支持哪些编译器,列出它们的#defines,并根据需要更新您的标头。
如果您想转储特定平台上的所有可用功能,您可以运行 GCC,如下所示:
gcc -march=native -dM -E - </dev/null
它会转储宏,如#define __SSE3__ 1
,#define __AES__ 1
等。
享受,我是这个的原作者。
extern "C" {
const char *getBuild() { //Get current architecture, detectx nearly every architecture. Coded by Freak
#if defined(__x86_64__) || defined(_M_X64)
return "x86_64";
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
return "x86_32";
#elif defined(__ARM_ARCH_2__)
return "ARM2";
#elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__)
return "ARM3";
#elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T)
return "ARM4T";
#elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_)
return "ARM5"
#elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_)
return "ARM6T2";
#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
return "ARM6";
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
return "ARM7";
#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
return "ARM7A";
#elif defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__)
return "ARM7R";
#elif defined(__ARM_ARCH_7M__)
return "ARM7M";
#elif defined(__ARM_ARCH_7S__)
return "ARM7S";
#elif defined(__aarch64__) || defined(_M_ARM64)
return "ARM64";
#elif defined(mips) || defined(__mips__) || defined(__mips)
return "MIPS";
#elif defined(__sh__)
return "SUPERH";
#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC)
return "POWERPC";
#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
return "POWERPC64";
#elif defined(__sparc__) || defined(__sparc)
return "SPARC";
#elif defined(__m68k__)
return "M68K";
#else
return "UNKNOWN";
#endif
}
}
如果您想要一个交叉编译器解决方案,那么只需使用Boost.Predef
包含
BOOST_ARCH_
对于正在编译的系统/CPU架构。BOOST_COMP_
对于正在使用的编译器。BOOST_LANG_
对于一个正在编译的语言标准。BOOST_LIB_C_
和 BOOST_LIB_STD_ 用于使用的 C 和 C++ 标准库。BOOST_OS_
对于我们正在编译的操作系统。BOOST_PLAT_
适用于操作系统或编译器之上的平台。BOOST_ENDIAN_
用于操作系统和架构组合的字节顺序。BOOST_HW_
对于硬件特定的功能。BOOST_HW_SIMD
用于 SIMD(单指令多数据)检测。例如
#if defined(BOOST_ARCH_X86)
#if BOOST_ARCH_X86_64
std::cout << "x86_64 " << BOOST_ARCH_X86_64 << " \n";
#elif BOOST_ARCH_X86_32
std::cout << "x86 " << BOOST_ARCH_X86_32 << " \n";
#endif
#elif defined(BOOST_ARCH_ARM)
#if _M_ARM
std::cout << "ARM " << _M_ARM << " \n";
#elif _M_ARM64
std::cout << "ARM64 " << _M_ARM64 << " \n";
#endif
#endif
您可以在此处了解有关如何使用它的更多信息
没有什么标准。Brian Hook 在他的“Portable Open Source Harness”中记录了其中的一堆,甚至试图将它们变成连贯且可用的东西(ymmv 关于这一点)。请参阅此站点上的 posh.h 标头:
请注意,由于前一段时间的 DOS 攻击,上面的链接可能要求您输入一些虚假的用户名/密码。
这里#define
有一个s的列表。之前有一个高度投票的答案包含此链接,但可能是由于 SO 的“答案必须有代码”规则而被 mod 删除。所以这里是一个随机样本。点击链接查看完整列表。
类型 | 宏 | 描述 |
---|---|---|
鉴别 | __amd64__ __amd64 __x86_64__ __x86_64 |
由 GNU C 和 Sun Studio 定义 |
鉴别 | _M_X64 _M_AMD64 |
由 Visual Studio 定义 |
如果您需要对 CPU 功能进行细粒度检测,最好的方法是同时发布一个 CPUID 程序,该程序将 CPU 支持的一组功能输出到 stdout 或某些“cpu_config.h”文件。然后将该程序与您的构建过程集成。