118

编译C或C++代码时,找出CPU体系结构的最可靠方法是什么?据我所知,不同的编译器有自己的一组非标准预处理器定义(_M_X86号在MSVS中,__i386型__,__臂__在GCC等中)。

是否有标准检测我正在构建的架构的方法?如果没有,是否有针对各种编译器的此类定义的完整列表的源代码,例如包含所有样板文件的头文件#ifdef(如果定义)是吗?

2

8个答案8

重置为默认值
46

享受吧,我是这篇文章的原作者。

外部“C”{const char*getBuild(){//获取当前架构,检测几乎所有架构。由Freak编码#如果定义了(__x86_64__)||定义了(_M_X64)return“x86_64”;#elif定义的(i386)return“x86_32”;#elif定义(__ARM_ARCH_2___)return“ARM2”;#elif定义(__ARM_ARCH_3__)||定义(__ARM_ARCH_3M__)return“ARM3”;#elif定义(__ARM_ARCH_4T__)||定义(__TARGET_ARM_4T)return“ARM4T”;#elif定义(__ARM_ARCH_5_)||定义(__ARM_ARCH.5E_)返回“ARM5”#elif定义(__ARM_ARCH_6T2_)||定义(__ARM_ARCH-6T2_)return“ARM6T2”;#elif定义(__ARM_ARCH_6__)||定义(__ARM_ARCH.6J__)||defined(__AMR_ARCH-6K__)||1definedreturn“ARM6”;#elif定义(__ARM_ARCH_7__)||定义(__ARM_ARCH_MA__)||defined(__AMR_ARCH.7R__)||1definedreturn“ARM7”;#elif定义(__ARM_ARCH_7A__)||定义(__ARM_ARCH-7R__)||defined(__AMR_ARCH.7M__)||1definedreturn“ARM7A”;#elif定义的(__ARM_ARCH_7R__)||定义的(___ARM_ARCH-7M__)||defined(___ARS_ARCH_7S__)return“ARM7R”;#elif定义(__ARM_ARCH_7M_)return“ARM7M”;#elif定义(__ARM_ARCH_7S__)返回“ARM7S”;#elif定义的(__aarch64__)||定义的(_M_ARM64)return“ARM64”;#elif定义的(mips)||定义的(__mips_|)||定义的(__mips)return“MIPS”;#elif定义(__sh__)return“SUPERH”;#elif定义(__powerpc)||定义(__powerpc__)||已定义(__powerpc64__)||defined(__powerpc__)||1definedreturn“POWERPC”;#elif定义(__PPC64__)||定义(__PPC64__)| |定义(_ARCH_PPC64)return“POWERPC64”;#elif定义(__sparc_)||定义(__sparc)return“SPARC”;#elif定义(__m68k__)返回“M68K”;#其他return“未知”;#结尾}}
8
  • 您的ARM字符串混淆了ARM CPU名称,如ARM7系列ARM ISA修订版,如ARMv7型. 评论 2021年2月17日23:41
  • 1
    用正确的arm7版本更新了帖子。以及powerpc64检测正确 评论 2021年2月21日10:10
  • 7
    我的意思是你回来“ARM7”你应该什么时候回来“ARMv7”,或“ARMv7A”或者别的什么。ARM中的“v”在区分特定ARM核心模型与ISA版本之间的差异方面很重要。请记住,有人在查看打印此字符串的程序时,只会看到机器上的一个字符串,而不是整个表,这表明它可能是“ARM6T2”(更清楚地说,这只是ARMv6T2的损坏,而不是CPU型号。) 评论 2021年2月21日10:24
  • 有更简单的方法检测32位ARM吗? 评论 2022年6月5日19:03
  • @如果只支持有限数量的编译器,AaronFranke会更简单。这可能适用于大多数常见的编译器
    – 普吕克
    评论 2022年6月8日1:13
21

虽然没有编译器间标准,但每个编译器往往是相当一致的。您可以为自己构建一个标题,如下所示:

#如果是MSVC#如果定义_M_X86#定义ARCH_X86#结尾#结尾#如果GCC#如果定义__i386__#定义ARCH_X86#结尾#结尾

没有什么必要列出一个全面的列表,因为有数千种编译器,但只有3-4种广泛使用(Microsoft C++、GCC、Intel CC,也许还有TenDRA?)。只需决定应用程序将支持哪些编译器,列出它们的#定义,并根据需要更新标头。

  • 6
    这在Visual Studio 2010上对我来说不起作用。_M_X86号肯定没有定义(32位版本)。正确的是_M_IX86号(以上是谢尔盖的链接)。
    – 托马斯
    评论 2013年12月15日8:20
  • 这些在32位和64位x86上都有效吗? 评论 2021年12月8日21:05
  • …和clang/LLVM。在嵌入式系统的x86以外的体系结构上,还有一些其他常用的体系结构。 评论 6月16日20:13
18

如果您想在特定平台上转储所有可用功能,可以运行GCC,如下所示:

gcc-marc=native-dM-E-</dev/null

它会像这样转储宏#定义__SSE3__ 1,#定义__AES__1等。

4
  • -march=本地GCC 4.9及以下版本的ARM和MIPS失败。
    – jww公司
    评论 2016年6月3日22:04
  • 1
    问题是编译时--这不能回答这个问题
    – 沃尔特
    评论 2022年1月27日9:45
  • 2
    @Walter如果有人可以访问所讨论的体系结构,它允许他们检查实际定义了哪些宏,然后在代码中使用它们,这样它就可以在编译时工作。 评论 2022年10月4日16:32
  • 您还应该使用-xc公司++切换以指定正在编译的内容(C与C++)。 评论 2022年11月27日18:31
14

如果您想要一个交叉编译器解决方案,那么只需使用促进。Predef公司其中包含

  • 增压器_ARCH_对于系统/CPU体系结构,我们正在编译。
  • BOOST_COMP(引导_操作)_对于编译器,我们正在使用。
  • BOOST_LANG(增压_角度)_对于语言标准,人们正在进行编译。
  • 增压_LIB_C_BOOST_LIB_STD(增压器_LIB_STD)_用于正在使用的C和C++标准库。
  • 助推器_对于我们正在编译的操作系统。
  • BOOST_PLAT(增压_平板)_用于操作系统或编译器之上的平台。
  • BOOST_ENDIAN公司_操作系统的端接性和体系结构的结合。
  • BOOST_HW(增压_HW)_用于特定于硬件的功能。
  • 增压_HW_SIMD用于SIMD(单指令多数据)检测。

注意,尽管Boost通常被认为是一个C++库,促进。Predef公司只是纯粹的头部为C工作

例如

#包括<boost/predef.h>//或者只包含必要的标题//#include<boost/predef/architecture.h>//#include<boost/predef/other.h>#如果BOOST_ARCH_X86#如果BOOST_ARCH_X86_64标准::cout<<“x86-64\n”;#消除BOOST_ARCH_X86_32标准::cout<<“x86-32\n”;#其他std::cout<<“x86-”<<BOOST_ARCH_ORD_BITS<<'\n';//可能是x86-16#结尾#elif BOOST_ARCH_ARM(elif引导_警报_警报)#如果BOOST_ARCH_ARM>=BOOST_VERSION_NUMBER(8,0,0)#如果BOOST_ARCH_WORD_BITS==64标准::cout<<“ARMv8+Aarch64\n”;#elif BOOST_ARCH_WORD_BITS==32标准::cout<<“ARMv8+Aarch32\n”;#其他std::cout<<“意外ARMv8+”<<BOOST_ARCH_WORD_BITS<<“bit\n”;#结尾#elif BOOST_ARCH_ARM>=BOOST_VERSION_NUMBER(7,0,0)标准::cout<<“ARMv7(ARM32)\n”;#elif BOOST_ARCH_ARM>=BOOST_VERSION_NUMBER(6,0,0)标准::cout<<“ARMv6(ARM32)\n”;#其他std::cout<<“ARMv5或更早版本\n”;#结尾#elif BOOST_ARCH_MIPS#如果BOOST_ARCH_WORD_BITS==64标准::cout<<“MIPS64\n”;#其他标准::cout<<“MIPS32\n”;#结尾#elif BOOST_ARCH_PPC_64标准::cout<<“PPC64\n”;#elif BOOST_ARCH_PPC公司标准::cout<<“PPC32\n”;#其他std::cout<<“未知”<<BOOST_ARCH_WORD_BITS<<“-bit ARCH\n”;#结尾

您可以了解更多有关如何使用它的信息在这里

Godbolt演示

2
  • 这是否意味着_M_ARM(_ARM)仅在32位ARM上定义? 评论 2022年6月5日19:04
  • @AaronFranke不,那是我的错误,因为文件不清楚。请查看我的更新。您可以使用轻松检查ARM32启动ARCH_WORD_BITS
    – 普吕克
    评论 2022年6月7日16:35
4

这里有一个列表#定义在这里。之前有一个投票结果很高的答案包含了这个链接,但它被一个mod删除了,大概是因为SO的“答案必须有代码”规则。这是一个随机样本。请访问完整列表的链接。

AMD64型

类型 描述
识别 __amd64型__ __amd64型 __x86_64码__ __x86_64码 由GNU C和Sun Studio定义
识别 _M_X64(_M) _M_AMD64(_AMD64) 由Visual Studio定义
2
  • 32位怎么办?在MSVC、GCC和Clang中检测32位和64位x86的最短方法是什么? 评论 2021年12月8日21:09
  • 您可以使用AMD64型英特尔x86该页上列出的宏。但你几乎肯定不应该使用sizeof(),统计_断言等等。您还应该了解x32 ABI。即使在64位体系结构上,指针也可以是32位的。 评论 2021年12月9日11:59
4

没有标准。布莱恩·胡克(Brian Hook)在他的《便携式开源线束》(Portable Open Source Harness)中记录了一堆,甚至试图将它们变成连贯和可用的东西(ymmv)。看到他回购书上的时髦标题:

  • 2
    天啊,对不起,这个假链接应该是hookatooka.com/poshlib它提供有关用户标识/密码的信息。我的浏览器必须在上次访问该页面时“自动登录”。 评论 2009年4月9日21:20
  • 2
    也值得一提。。。该网站的作者说明了他们为什么添加了密码:“对于给您带来的不便,我深表歉意,但由于我们之前的直接链接受到了无法解释的DDoS攻击,我们不得不创建此页面来“缓冲”DDoS…”我不确定为此惩罚迈克尔是否公平。
    – jww公司
    评论 2016年6月3日22:40
  • 所有链接都无效。你能更新一下吗?谢谢! 评论 2023年6月5日13:46
0

我的旋转

用法

#如果是ARCHITECTURE_ARM...#结尾

文件手臂。小时

#如果架构_ARM_H的索引#定义ARCHITECTURE_ARM_H/*发件人:https://github.com/boostorg/predef/blob/develop/include/boost/predef/architecture/arm.hhttps://github.com/cpredef/predef/blob/master/Architectures.mdhttps://wiki.ubuntu.com/ARM/Thumb2PortingHowto网站__arm__|由GNU C和RealView定义__thumb__|由GNU C和RealView在thumb模式下定义__TARGET_ARCH_ARM|由RealView定义__TARGET_ARCH_THUMB|由RealView定义_ARM |由ImageCraft C定义_M_ARM|由Visual Studio定义_M_ARMT|由Visual Studio在Thumb模式下定义__手臂|由Diab定义ARM 2 | __ARM_ARCH_2_ARM 3|__ARM_ARCH_3__,__ARM-ARCH_3M__ARM 4 | __ARM_ARCH_4__ARM 4T |__ARM_ARCH_4T__,__TARGET_ARM_4TARM 5|__ARM_ARCH_5__,__ARM-ARCH_5AE__ARM 5T | __ARM_ARCH_5T__,__ARM-ARCH_5 TE__,__AARM_ARCH_ 5TEJ__ARM 6|__ARM_ARCH_6__,__ARM-ARCH_5J__,__ARM_ARCH.6K__,__RAM_ARCH-6Z__,__ERM_ARCH_6ZK__ARM 6T2|__ARM_ARCH_6T2__ARM 7 | __ARM_ARCH_7__,__ARM-ARCH_7,__AMR_ARCH-7R__,__ARM_ARCH.7M_,__AARM_ARCH_7S__ARM 2 | __ARM_ARCH_2_ARM 3|__ARM_ARCH_3__,__ARM-ARCH_3M__ARM 4T |__ARM_ARCH_4T__,__TARGET_ARM_4TARM 5|__ARM_ARCH_5__,__ARM-ARCH_5AE__ARM 5T | __ARM_ARCH_5T__,__ARM-ARCH_5 TE__,__AARM_ARCH_ 5TEJ__ARM 6|__ARM_ARCH_6__,__ARM-ARCH_5J__,__ARM_ARCH.6K__,__RAM_ARCH-6Z__,__ERM_ARCH_6ZK__ARM 6T2|__ARM_ARCH_6T2__手臂7 |__ARM_ARCH_7__,__ARM_ARCH_7A_,__ARM_ARCH_7R__,__ARM_ARCH_7M__,__ARM_ARCH_7S__*/#如果已定义(__ARM_ARCH_2_)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_2 1#elif定义(__ARM_ARCH_3__)||定义(__ARM_ARCH_3M__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_3 1#elif定义(__ARM_ARCH_4__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_4 1#elif定义(__ARM_ARCH_4T__)||定义(__TARGET_ARM_4T)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_4T 1#elif定义(__ARM_ARCH_5__)||定义(__ARM_ARCH.5E__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_5 1#elif定义的(__ARM_ARCH_5T__)||定义的(___ARM_ARCH.5TE__)||已定义的(__ ARM_ARC H_5TEJ__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_5T 1#elif定义(__ARM_ARCH_6__)||定义(__ARM_ARCH.6J__)||defined(__AMR_ARCH-6K__)||1defined#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_6 1#elif定义(__ARM_ARCH_6T2__)||定义(__ARM_ARCH.6T2__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_6T2 1#elif定义(__ARM_ARCH_7__)||定义(__ARM_ARCH_MA__)||defined(__AMR_ARCH.7R__)||1defined#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_7 1#elif定义(__ARM_ARCH_7A__)||定义(__ARM_ARCH-7R__)||defined(__AMR_ARCH.7M__)||1defined#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_7A 1#elif定义的(__ARM_ARCH_7R__)||定义的(___ARM_ARCH-7M__)||defined(___ARS_ARCH_7S__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_7R 1#elif定义(__ARM_ARCH_7M_)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_7M 1#elif定义(__ARM_ARCH_7S__)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_7S 1#elif已定义(__aarch64__)||已定义(_M_ARM64)||定义(__AARCH64EL__)||defined(__ARM64)#定义ARCHITECTURE_ARM 1#定义ARCHITECTURE_ARM_64 1#elif定义(__arm__)||定义(__tumb__)||defined(__TARG_ARCH_arm)||已定义(__TAR GET_ARCH_thumb)||自定义(__arm)| |已定义的(_M_arm_T)| |定义的(__arm_ARCH)#定义ARCHITECTURE_ARM 1#结尾#endif/*架构_ARM_H*/

文件x86_64.h

#如果建筑_X86_64_H#定义ARCHITECTURE_X86_64_H/*发件人:https://github.com/cpredef/predef/blob/master/Architectures.mdhttps://github.com/boostorg/predef/blob/develop/include/boost/predef/architecture/x86/64.h__amd64__、__amd64、__x86_64__、___x86_64 |由GNU C和Sun Studio定义_M_X64,_M_AMD64|由Visual C定义++*/#if defined(__x86_64__)|| defined#定义ARCHITECTURE_X86_64#结尾#endif/*架构_X86_64_H*/

文件x86_32.小时

#ifndef建筑_X86_32_H#定义ARCHITECTURE_X86_32_H/*发件人:https://github.com/cpredef/predef/blob/master/Architectures.mdhttps://github.com/boostorg/predef/blob/develop/include/boost/predef/architecture/x86/32.hi386,__i386__i386|由Sun Studio定义__i386,__IA32__|由分层VOS C定义_M_I86 |仅为16位体系结构定义。由Visual C++、Digital Mars和Watcom C/C++定义(请参阅下面的注释)_M_IX86 |仅为32位体系结构定义。由Visual C++、Intel C/C++、Digital Mars和Watcom C/C定义++__X86__|由Watcom C/C定义++_X86_|由MinGW32定义__THW_INTEL__|由XL C/C定义++__I86__|由数字火星定义__INTEL__|由CodeWarrior定义__386|由Diab定义*/#如果定义(i386)||定义的(__i386#定义ARCHITECTURE_X86_32 1#结尾#endif/*架构_X86_32_H*/
-3

如果需要对CPU功能进行细粒度检测,最好的方法是同时提供一个CPUID程序,该程序将输出到stdout或某个“CPU_config.h”文件(CPU支持的功能集)。然后将该程序与构建过程集成。

1
  • 6
    不适用于交叉编译。如果不知道需要在哪台机器上运行,那么如何编译cpuid程序? 评论 2016年1月12日16:40

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.