在编写跨平台的代码时,我们往往需要用到条件编译的宏,以便让同一套代码兼容编译器不同版本、不同操作系统,下面就介绍下这些宏。
每个编译器都会自带一些预定义宏,以下拿gcc和VC++举例:
在编译器众多的预定义宏中,肯定有一个是用于标识编译器版本的宏定义:
__GNUC__是用来定义gcc编译器的版本,我们可以使用如下代码来进行条件编译:
- /* Test for GCC > 3.2.0 */
- #if __GNUC__ > 3 || \
- (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
- (__GNUC_MINOR__ == 2 && \
- __GNUC_PATCHLEVEL__ > 0))
-
- Another approach is to use the predefined macros to calculate a single number, then compare that against a threshold:
-
- #define GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
-
- /* Test for GCC > 3.2.0 */
- #if GCC_VERSION > 30200
-
_MSC_VER是微软公司推出的C/C++编译器在ANSI/ISO C99标准之外扩展的宏定义,用来定义当前微软公司自己的编译器的主版本。下面是一些编译器版本的_MSC_VER值:
- MSVC++ 14.1 _MSC_VER == 1910 (Visual Studio 2017)
- MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
- MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
- MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
- MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
- MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
- MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
- MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
- MSVC++ 7.0 _MSC_VER == 1300
- MSVC++ 6.0 _MSC_VER == 1200
- MSVC++ 5.0 _MSC_VER == 1100
-
其中MS VC++ 14.0表示Visual C++的版本为14.0,后面括号中的Visual Studio 2015,表明该VC++包含在微软开发工具Visual Studio 2015中。
- /* Test for MSVC++ > Microsoft Visual Studio 2010 */
- #if _MSC_VER > 1600
-
可以参考QtCore/qsystemdetection.h文件:
- #ifndef QSYSTEMDETECTION_H
- #define QSYSTEMDETECTION_H
-
- /*
- The operating system, must be one of: (Q_OS_x)
- DARWIN - Any Darwin system
- MAC - OS X and iOS
- OSX - OS X
- IOS - iOS
- MSDOS - MS-DOS and Windows
- OS2 - OS/2
- OS2EMX - XFree86 on OS/2 (not PM)
- WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
- WINCE - WinCE (Windows CE 5.0)
- WINRT - WinRT (Windows 8 Runtime)
- CYGWIN - Cygwin
- SOLARIS - Sun Solaris
- HPUX - HP-UX
- ULTRIX - DEC Ultrix
- LINUX - Linux [has variants]
- FREEBSD - FreeBSD [has variants]
- NETBSD - NetBSD
- OPENBSD - OpenBSD
- BSDI - BSD/OS
- IRIX - SGI Irix
- OSF - HP Tru64 UNIX
- SCO - SCO OpenServer 5
- UNIXWARE - UnixWare 7, Open UNIX 8
- AIX - AIX
- HURD - GNU Hurd
- DGUX - DG/UX
- RELIANT - Reliant UNIX
- DYNIX - DYNIX/ptx
- QNX - QNX [has variants]
- QNX6 - QNX RTP 6.1
- LYNX - LynxOS
- BSD4 - Any BSD 4.4 system
- UNIX - Any UNIX BSD/SYSV system
- ANDROID - Android platform
- HAIKU - Haiku
- The following operating systems have variants:
- LINUX - both Q_OS_LINUX and Q_OS_ANDROID are defined when building for Android
- - only Q_OS_LINUX is defined if building for other Linux systems
- QNX - both Q_OS_QNX and Q_OS_BLACKBERRY are defined when building for Blackberry 10
- - only Q_OS_QNX is defined if building for other QNX targets
- FREEBSD - Q_OS_FREEBSD is defined only when building for FreeBSD with a BSD userland
- - Q_OS_FREEBSD_KERNEL is always defined on FreeBSD, even if the userland is from GNU
- */
-
- #if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
- # define Q_OS_DARWIN
- # define Q_OS_BSD4
- # ifdef __LP64__
- # define Q_OS_DARWIN64
- # else
- # define Q_OS_DARWIN32
- # endif
- #elif defined(ANDROID)
- # define Q_OS_ANDROID
- # define Q_OS_LINUX
- #elif defined(__CYGWIN__)
- # define Q_OS_CYGWIN
- #elif !defined(SAG_COM) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
- # define Q_OS_WIN32
- # define Q_OS_WIN64
- #elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
- # if defined(WINCE) || defined(_WIN32_WCE)
- # define Q_OS_WINCE
- # elif defined(WINAPI_FAMILY)
- # if defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
- # define Q_OS_WINPHONE
- # define Q_OS_WINRT
- # elif WINAPI_FAMILY==WINAPI_FAMILY_APP
- # define Q_OS_WINRT
- # else
- # define Q_OS_WIN32
- # endif
- # else
- # define Q_OS_WIN32
- # endif
- #elif defined(__sun) || defined(sun)
- # define Q_OS_SOLARIS
- #elif defined(hpux) || defined(__hpux)
- # define Q_OS_HPUX
- #elif defined(__ultrix) || defined(ultrix)
- # define Q_OS_ULTRIX
- #elif defined(sinix)
- # define Q_OS_RELIANT
- #elif defined(__native_client__)
- # define Q_OS_NACL
- #elif defined(__linux__) || defined(__linux)
- # define Q_OS_LINUX
- #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
- # ifndef __FreeBSD_kernel__
- # define Q_OS_FREEBSD
- # endif
- # define Q_OS_FREEBSD_KERNEL
- # define Q_OS_BSD4
- #elif defined(__NetBSD__)
- # define Q_OS_NETBSD
- # define Q_OS_BSD4
- #elif defined(__OpenBSD__)
- # define Q_OS_OPENBSD
- # define Q_OS_BSD4
- #elif defined(__bsdi__)
- # define Q_OS_BSDI
- # define Q_OS_BSD4
- #elif defined(__sgi)
- # define Q_OS_IRIX
- #elif defined(__osf__)
- # define Q_OS_OSF
- #elif defined(_AIX)
- # define Q_OS_AIX
- #elif defined(__Lynx__)
- # define Q_OS_LYNX
- #elif defined(__GNU__)
- # define Q_OS_HURD
- #elif defined(__DGUX__)
- # define Q_OS_DGUX
- #elif defined(__QNXNTO__)
- # define Q_OS_QNX
- #elif defined(_SEQUENT_)
- # define Q_OS_DYNIX
- #elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */
- # define Q_OS_SCO
- #elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */
- # define Q_OS_UNIXWARE
- #elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */
- # define Q_OS_UNIXWARE
- #elif defined(__INTEGRITY)
- # define Q_OS_INTEGRITY
- #elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */
- # define Q_OS_VXWORKS
- #elif defined(__HAIKU__)
- # define Q_OS_HAIKU
- #elif defined(__MAKEDEPEND__)
- #else
- # error "Qt has not been ported to this OS - see http://www.qt-project.org/"
- #endif
-
- #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
- # define Q_OS_WIN
- #endif
-
- #if defined(Q_OS_DARWIN)
- # define Q_OS_MAC
- # if defined(Q_OS_DARWIN64)
- # define Q_OS_MAC64
- # elif defined(Q_OS_DARWIN32)
- # define Q_OS_MAC32
- # endif
- # include <TargetConditionals.h>
- # if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
- # define Q_OS_IOS
- # elif defined(TARGET_OS_MAC) && TARGET_OS_MAC
- # define Q_OS_OSX
- # define Q_OS_MACX // compatibility synonym
- # endif
- #endif
-
- #if defined(Q_OS_WIN)
- # undef Q_OS_UNIX
- #elif !defined(Q_OS_UNIX)
- # define Q_OS_UNIX
- #endif
-
- #ifdef Q_OS_DARWIN
- # include <Availability.h>
- # include <AvailabilityMacros.h>
- #
- # ifdef Q_OS_OSX
- # if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6
- # undef __MAC_OS_X_VERSION_MIN_REQUIRED
- # define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6
- # endif
- # if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- # undef MAC_OS_X_VERSION_MIN_REQUIRED
- # define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
- # endif
- # endif
- #
- # // Numerical checks are preferred to named checks, but to be safe
- # // we define the missing version names in case Qt uses them.
- #
- # if !defined(__MAC_10_7)
- # define __MAC_10_7 1070
- # endif
- # if !defined(__MAC_10_8)
- # define __MAC_10_8 1080
- # endif
- # if !defined(__MAC_10_9)
- # define __MAC_10_9 1090
- # endif
- # if !defined(__MAC_10_10)
- # define __MAC_10_10 101000
- # endif
- # if !defined(__MAC_10_11)
- # define __MAC_10_11 101100
- # endif
- # if !defined(MAC_OS_X_VERSION_10_7)
- # define MAC_OS_X_VERSION_10_7 1070
- # endif
- # if !defined(MAC_OS_X_VERSION_10_8)
- # define MAC_OS_X_VERSION_10_8 1080
- # endif
- # if !defined(MAC_OS_X_VERSION_10_9)
- # define MAC_OS_X_VERSION_10_9 1090
- # endif
- # if !defined(MAC_OS_X_VERSION_10_10)
- # define MAC_OS_X_VERSION_10_10 101000
- # endif
- # if !defined(MAC_OS_X_VERSION_10_11)
- # define MAC_OS_X_VERSION_10_11 101100
- # endif
- #
- # if !defined(__IPHONE_4_3)
- # define __IPHONE_4_3 40300
- # endif
- # if !defined(__IPHONE_5_0)
- # define __IPHONE_5_0 50000
- # endif
- # if !defined(__IPHONE_5_1)
- # define __IPHONE_5_1 50100
- # endif
- # if !defined(__IPHONE_6_0)
- # define __IPHONE_6_0 60000
- # endif
- # if !defined(__IPHONE_6_1)
- # define __IPHONE_6_1 60100
- # endif
- # if !defined(__IPHONE_7_0)
- # define __IPHONE_7_0 70000
- # endif
- # if !defined(__IPHONE_7_1)
- # define __IPHONE_7_1 70100
- # endif
- # if !defined(__IPHONE_8_0)
- # define __IPHONE_8_0 80000
- # endif
- # if !defined(__IPHONE_8_1)
- # define __IPHONE_8_1 80100
- # endif
- # if !defined(__IPHONE_8_2)
- # define __IPHONE_8_2 80200
- # endif
- # if !defined(__IPHONE_8_3)
- # define __IPHONE_8_3 80300
- # endif
- # if !defined(__IPHONE_8_4)
- # define __IPHONE_8_4 80400
- # endif
- # if !defined(__IPHONE_9_0)
- # define __IPHONE_9_0 90000
- # endif
- #endif
-
- #ifdef __LSB_VERSION__
- # if __LSB_VERSION__ < 40
- # error "This version of the Linux Standard Base is unsupported"
- # endif
- #ifndef QT_LINUXBASE
- # define QT_LINUXBASE
- #endif
- #endif
-
- #endif // QSYSTEMDETECTION_H