在嵌入式软件开发的编码中,有时使用的一些指令是和编译器相关的,这时就要判断当前使用的编译器类型。
不同的编译器,会定义不同的宏来进行识别。
比如在ARM开发工具包中,cortex-M系列开发中,CMSIS Cortex-Mx Core Peripheral Access Layer Header File如下:

这些头文件里有用到编译器的预定义宏,比如core_cm3.h (cortex-M3的头文件)中:

那这几个宏都是什么含义呢?分别对应什么平台呢?
这些是针对ARM处理器的不同编译器来进行分别处理,使用这些宏可以屏蔽编译器相关的代码的差异,保证对不同的编译器,使用的代码都是兼容的。
__CC_ARM --> ARM's (RealView) compiler
RealView,是一套包含编译、调试和模拟的开发工具,需结合开发环境如Keil uvision、eclipse或者CodeWarrior,形成集成开发环境来使用。
__GNUC__ --> GNU Compiler Collection
GCC的初衷是为GNU操作系统(GNU系统+Linux内核)专门编写的一款编译器。GNU系统是彻底的自由软件。
使用GCC来编译Linux平台上的ARM程序,实际上用的是Linaro的交叉编译器。之前有篇文章介绍过。
而这里的IAR、Keil的编译器,指的是和普通单片机或微控制器一样的bare-metal程序,直接能运行的。
__ICCARM__ --> IAR
同时IAR平台还有个宏__IAR_SYSTEMS_ICC__,可以在下面编译器平台介绍中查到。Embedded Workbench for ARM 是IARSystems 公司为ARM 微处理器开发的一个集成开发环境(下面简称IAR EWARM)。比较其他的ARM 开发环境,IAR EWARM 具有入门容易、使用方便和代码紧凑等特点。
__TI_ARM__ --> Texas Instruments
这个就是TI的了。
__TASKING__ --> Tasking
对应的平台是Altinum Designer。Altium Designer 是原Protel软件开发商Altium公司推出的一体化的电子产品开发系统,主要运行在Windows操作系统。这套软件通过把原理图设计、电路仿真、PCB绘制编辑、拓扑逻辑自动布线、信号完整性分析和设计输出等技术的完美融合,为设计者提供了全新的设计解决方案,使设计者可以轻松进行设计,熟练使用这一软件使电路设计的质量和效率大大提高。
---------------------------------------------------
下面是各个编译器平台的宏定义:
ARM Compiler
| Type | Macro | Format | Description |
| Identification | __CC_ARM | ||
| Version | __ARMCC_VERSION | VRPBBB | V = Version R = Revision P = Patch BBB = Build |
就是ARM公司自己的编译器,Keil uvision中使用的。
Example
| Realview C | __ARMCC_VERSION |
| 3.0 | 300503 |
Clang
| Type | Macro | Format | Description |
| Identification | __clang__ | ||
| Version | __clang_major__ | V | V = Major version |
| Version | __clang_minor__ | R | R = Minor version |
| Version | __clang_patchlevel__ | P | P = Patch level |
| Version | __clang_version__ | V.R.P (tags/RELEASE_VRP/final) | V = Major version R = Minor version P = Patch level |
GCC C/C++
| Type | Macro | Description |
| Identification | __GNUC__ | |
| Version | __GNUC__ | Version |
| Version | __GNUC_MINOR__ | Revision |
| Version | __GNUC_PATCHLEVEL__ | Patch (introduced in version 3.0) |
Example
| GNU C/C++ | __GNUC__ | __GNUC_MINOR__ | __GNUC_PATCHLEVEL__ |
| 2.7.x | 2 | 7 | N/A |
| 3.0.2 | 3 | 0 | 2 |
可以自己添加代码来定义GNU Version:
#if defined(__GNUC__)
# if defined(__GNUC_PATCHLEVEL__)
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
# else
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100)
# endif
#endif
IAR C/C++
| Type | Macro | Format | Description |
| Identification | __IAR_SYSTEMS_ICC__ | ||
| Version | __VER__ | VRR | V = Version RR = Revision |
Example
| IAR C/C++ | __VER__ |
| 3.34__VER__ | 334 |
Intel C/C++
| Type | Macro | Format | Description |
| Identification | __INTEL_COMPILER | ||
| Identification | __ICC | Obsolete | |
| Identification | __ECC | Obsolete | |
| Identification | __ICL | ||
| Version | __INTEL_COMPILER | VRP | V = Version R = Revision P = Patch |
| Version | __INTEL_COMPILER_BUILD_DATE | YYYYMMDD | YYYY = Year MM = Month DD = Day |
Example
| Intel C/C++ | __INTEL_COMPILER | __INTEL_COMPILER_BUILD_DATE |
| 5.0 | 500 | |
| 6.0 | 600 | |
| 8.0 | 800 | |
| 9.0 | 900 | 20060222 |
KEIL C51
| Type | Macro | Format | Description |
| Identification | __C51__ | ||
| Identification | __CX51__ | ||
| Version | __C51__ | VRR | V = Version RR = Revision |
Example
| Keil C51 | __C51__ |
| 7.01 | 701 |
Microsoft Visual C++
| Type | Macro | Format | Description |
| Identification | _MSC_VER | ||
| Version | _MSC_VER | VVRR | VV = Version RR = Revision |
| Version | _MSC_FULL_VER | VVRRPPPP | VV = Version RR = Revision PPPP = Patch From Visual C++ 6.0 Processor Pack |
| Version | _MSC_FULL_VER | VVRRPPPPP | VV = Version RR = Revision PPPPP = Patch From Visual C++ 8.0 |
| Version | _MSC_BUILD | B | B = Build number From Visual C++ 9.0Example |
Example
| Visual C++ 1 2 | _MSC_VER | _MSC_FULL_VER |
| 1.0 | 800 | |
| 3.0 | 900 | |
| 4.0 | 1000 | |
| 4.2 | 1020 | |
| 5.0 | 1100 | |
| 6.0 | 1200 | |
| 6.0 SP6 | 1200 | 12008804 |
| 7.0 | 1300 | 13009466 |
| 7.1 (2003) | 1310 | 13103077 |
| 8.0 (2005) | 1400 | 140050727 |
| 9.0 (2008) | 1500 | 150021022 |
| 9.0 SP1 | 1500 | 150030729 |
| 10.0 (2010) | 1600 | 160030319 |
| 10.0 (2010) SP1 | 1600 | 160040219 |
| 11.0 (2012) | 1700 | 170050727 |
| 12.0 (2013) | 1800 | 180021005 |
| 14.0 (2015) | 1900 | 190023026 |
| 14.0 (2015 Update 1) | 1900 | 190023506 |
| 14.0 (2015 Update 2) | 1900 | 190023918 |
| 14.0 (2015 Update 3) | 1900 | 190024210 |
| 15.0 (2017) | 1910 | 191025017 |
MinGW and MinGW-w64
| Type | Macro | Description | MinGW32 | MinGW-w64 32 Bit | MinGW-w64 64 Bit |
| Identification | __MINGW32__ | defined | defined | defined | |
| Version | __MINGW32_MAJOR_VERSION | Version | defined | defined | defined |
| Version | __MINGW32_MINOR_VERSION | Revision | defined | defined | defined |
| Identification | __MINGW64__ | - | - | defined | |
| Version | __MINGW64_VERSION_MAJOR | Version | - | defined | defined |
| Version | __MINGW64_VERSION_MINOR | Revision | - | defined | defined |
注意,__MINGW32_MAJOR_VERSION, __MINGW32_MINOR_VERSION, __MINGW64_VERSION_MAJOR, 和__MINGW64_VERSION_MINOR,
这几个宏定义需要包含下面的头文件:
<stdlib.h>, <stdio.h>, <windows.h>, <windef.h>,或者还需要其他。
Examples
| __MINGW32_MAJOR_VERSION | __MINGW32_MINOR_VERSION | __MINGW64_VERSION_MAJOR | __MINGW64_VERSION_MINOR | Description |
| 2 | 4 | MinGW32 2.4 | ||
| 3 | 20 | MinGW32 3.20 | ||
| 3 | 11 | 2 | 0 | MinGW-w64 2.0 |
Turbo C/C++
| Type | Macro | Format | Description |
| Identification | __TURBOC__ | ||
| Version | __TURBOC__ | 0xVVRR | VV = Version RR = Revision This pattern does not apply to the values between 0x295 and 0x400. |
Example
| Turbo C | Turbo C++ | __TURBOC__ |
| 2.01 | 0x201 | |
| 1.00 | 0x295 | |
| 1.01 | 0x296 | |
| 2.00 | 0x297 |
手里有Ubuntu虚拟机,来试一下GNU的版本:
#include <stdio.h>
int main()
{
printf("%d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
return 0;
}
$ gcc -o version test.c
$ ./version
9.3.0
其实还有非常多的编译器和相对应的预定义宏,就不一一列举了,可以参见文后引用。
比如TI的编译器、Borland编译器等。
参考:
Pre-defined Compiler Macros / Wiki / Compilers
https://sourceforge.net/p/predef/wiki/Compilers/
本文详细解析了ARM、GNU、IAR和TI等编译器的预定义宏,如__CC_ARM用于ARM RealView编译器,__GNUC__代表GNU C编译器,展示了不同宏如何识别平台和版本。了解这些宏有助于编写兼容多编译器的嵌入式代码。
2086

被折叠的 条评论
为什么被折叠?



