Win Unix Mac 等多种系统平台的宏定义

本文介绍了C++程序从Windows平台向Unix平台移植的方法,并详细解释了qt宏定义文件qglobal.h中的各种宏定义,这些定义有助于识别不同的操作系统平台。

最近正在学习C++程序从 Windows 平台向 Unix 平台移植,参考了 qt 的宏定义文件

Win Unix Mac 等多种系统平台的宏定义,平台移植时可做参考

#ifndef QGLOBAL_H #define QGLOBAL_H #define QT_VERSION_STR "3.1.2" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ #define QT_VERSION 0x030102 /* The operating system, must be one of: (Q_OS_x) MACX - Mac OS X MAC9 - Mac OS 9 MSDOS - MS-DOS and Windows OS2 - OS/2 OS2EMX - XFree86 on OS/2 (not PM) WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) CYGWIN - Cygwin SOLARIS - Sun Solaris HPUX - HP-UX ULTRIX - DEC Ultrix LINUX - Linux FREEBSD - FreeBSD 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 QNX6 - QNX RTP 6.1 LYNX - LynxOS BSD4 - Any BSD 4.4 system UNIX - Any UNIX BSD/SYSV system */ #if defined(__APPLE__) && defined(__GNUC__) # define Q_OS_MACX #elif defined(__MACOSX__) # define Q_OS_MACX #elif defined(macintosh) # define Q_OS_MAC9 #elif defined(__CYGWIN__) # define Q_OS_CYGWIN #elif defined(MSDOS) || defined(_MSDOS) # define Q_OS_MSDOS #elif defined(__OS2__) # if defined(__EMX__) # define Q_OS_OS2EMX # else # define Q_OS_OS2 # endif #elif !defined(SAG_COM) && (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__)) # define Q_OS_WIN32 #elif defined(__MWERKS__) && defined(__INTEL__) # define Q_OS_WIN32 #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(__linux__) || defined(__linux) # define Q_OS_LINUX #elif defined(__FreeBSD__) # define Q_OS_FREEBSD # 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_HURD__) # define Q_OS_HURD #elif defined(__DGUX__) # define Q_OS_DGUX #elif defined(__QNXNTO__) # define Q_OS_QNX6 #elif defined(__QNX__) # 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 # define Q_OS_UNIXWARE7 #elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */ # define Q_OS_UNIXWARE # define Q_OS_UNIXWARE7 #else # error "Qt has not been ported to this OS - talk to qt-bugs@trolltech.com" #endif #if defined(Q_OS_MAC9) || defined(Q_OS_MACX) # define Q_OS_MAC #endif #if defined(Q_OS_MAC9) || defined(Q_OS_MSDOS) || defined(Q_OS_OS2) || defined(Q_OS_WIN32) || defined(Q_OS_WIN64) # undef Q_OS_UNIX #elif !defined(Q_OS_UNIX) # define Q_OS_UNIX #endif

===================================================================

拓展参考:

qglobal.h中可以得到的信息

<think>在C++中,判断操作系统环境通常依赖于预定义的宏。然而,在交叉编译环境下,这些宏可能由编译器根据目标平台定义,而不是根据编译环境定义。因此,使用预定义宏是一种可靠的方法,因为它反映了代码将要运行的目标平台。 常用的预定义宏包括:- `_WIN32`:在Windows32位和64位系统上都会被定义。- `_WIN64`:仅在64位Windows上定义。- `__linux__`:通常在Linux系统上定义。 -`__APPLE__`:在苹果系统macOS、iOS等)上定义。要区分macOS和iOS,可以进一步检查`TARGET_OS_MAC`和`TARGET_OS_IPHONE`等宏(这些通常在苹果提供的头文件中定义)。- `__unix__`:在Unix系统上定义(包括LinuxmacOS)。 -`__ANDROID__`:在Android上定义,通常也会定义`__linux__`,所以需要先检测Android再检测Linux。但是,这些宏并不是由C++标准定义的,而是由编译器或系统头文件定义的。因此,不同的编译器可能定义不同的宏。为了在交叉编译环境下正确判断目标操作系统,我们只能依赖这些预定义宏。因为交叉编译时,编译器会为目标平台定义相应的宏。下面是一个示例,展示如何根据这些宏来判断操作系统: ```cpp#include <iostream>intmain(){#ifdefined(_WIN32)|| defined(_WIN64)std::cout<< "Windows"<< std::endl;#elifdefined(__APPLE__)#include <TargetConditionals.h>#ifTARGET_OS_IPHONEstd::cout <<"iOS" <<std::endl;#elif TARGET_OS_MACstd::cout<< "macOS" <<std::endl;#elsestd::cout<< "Other Appleplatform"<< std::endl;#endif#elifdefined(__ANDROID__)std::cout <<"Android" <<std::endl;#elif defined(__linux__)std::cout<< "Linux"<< std::endl;#elifdefined(__unix__)std::cout<< "OtherUnix"<< std::endl;#elsestd::cout <<"UnknownOS"<< std::endl;#endifreturn0;} ```注意:1.对于苹果平台,我们需要包含`TargetConditionals.h`头文件,然后使用`TARGET_OS_IPHONE`和`TARGET_OS_MAC`来进一步区分。 2.检测顺序很重要。例如,Android也是基于Linux内核,所以先检测`__ANDROID__`再检测`__linux__`。同样,苹果平台也可能会定义`__unix__`,所以要先检测苹果。这种方法在交叉编译时也能工作,因为编译器会为当前编译的目标平台定义相应的宏。但是,请注意,有些宏可能同时被定义(比如在Windows上,`_WIN32`和`_WIN64`可能同时被定义,但`_WIN64`仅在64位Windows上定义,而`_WIN32`在32位和64位都会定义)。因此,我们通常先检测特定平台(如Windows64位)再检测通用平台(如Windows32位),但上面代码中我们使用`defined(_WIN32)|| defined(_WIN64)`来覆盖所有Windows平台。 另外,有些平台可能有多个宏,比如Windows上还有`__WIN32__`等,但最常用的是`_WIN32`和`_WIN64`。对于不同的编译器(如GCC、Clang、MSVC),它们定义的宏可能略有不同,但上述宏是相对标准的。 如果使用CMake等构建工具,也可以在构建时通过检测系统来定义宏,然后将这些宏传递给编译器。但这种方法需要在构建系统层面处理,而不是在代码层面。总结:在C++代码中,使用预定义宏是判断目标操作系统的最常用且可靠的方法,即使在交叉编译环境下也是如此。 §§相关问题§§: 1.在C++中,如何判断当前编译器是MSVC、GCC还是Clang?2.如何检测当前操作系统的位数(32位或64位)?3.在跨平台开发中,如何处理不同操作系统的路径分隔符(如Windows的'\'和Unix的'/')?4.如何编写跨平台的动态库加载代码(如Windows上的LoadLibrary和Linux上的dlopen)?</think>### 判断操作系统环境的方法 在 C++ 中,除了使用 `_WIN32` 等平台宏外,还可以通过以下方法判断操作系统环境(包括交叉编译场景): #### 1. **编译器内置宏检测** 编译器会在编译时自动定义目标平台的宏,这些宏在交叉编译时同样有效: ```cpp #include <iostream> int main() { #if defined(__linux__) std::cout << "Linux" << std::endl; #elif defined(_WIN32) || defined(_WIN64) std::cout << "Windows" << std::endl; #elif defined(__APPLE__) && defined(__MACH__) #include <TargetConditionals.h> #if TARGET_OS_MAC std::cout << "macOS" << std::endl; #elif TARGET_OS_IPHONE std::cout << "iOS" << std::endl; #endif #elif defined(__ANDROID__) std::cout << "Android" << std::endl; #elif defined(__FreeBSD__) std::cout << "FreeBSD" << std::endl; #else std::cout << "Unknown OS" << std::endl; #endif return 0; } ``` #### 2. **标准库功能检测** 通过标准库提供的功能间接判断(需要包含相关头文件): ```cpp #include <filesystem> // C++17 void detectViaFilesystem() { #ifdef __cpp_lib_filesystem namespace fs = std::filesystem; auto path = fs::path("/"); // 检查路径格式特性 if (path.preferred_separator == '\\') { std::cout << "Windows-like OS" << std::endl; } else { std::cout << "POSIX-like OS" << std::endl; } #endif } ``` #### 3. **系统调用接口检测** 通过系统调用接口判断(需包含平台相关头文件): ```cpp #include <sys/utsname.h> // POSIX #include <iostream> void detectViaSystemCall() { #ifdef __unix__ struct utsname sysInfo; if (uname(&sysInfo) == 0) { std::cout << "System: " << sysInfo.sysname << std::endl; std::cout << "Release: " << sysInfo.release << std::endl; } #endif } ``` #### 4. **构建系统级检测(推荐)** 通过 CMake 在构建时检测并生成配置头文件: **CMakeLists.txt** ```cmake include(CheckTypeSize) include(CMakeDetermineSystem) # 检测目标系统 if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(OS_LINUX 1) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(OS_WINDOWS 1) elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(OS_MACOS 1) endif() # 生成配置头文件 configure_file(config.h.in config.h) ``` **config.h.in** ```cpp #pragma once // 自动生成的平台定义 #cmakedefine OS_LINUX #cmakedefine OS_WINDOWS #cmakedefine OS_MACOS ``` **main.cpp** ```cpp #include "config.h" int main() { #ifdef OS_LINUX // Linux 专用代码 #elif defined(OS_WINDOWS) // Windows 专用代码 #elif defined(OS_MACOS) // macOS 专用代码 #endif } ``` ### 关键说明 1. **交叉编译兼容性** - 编译器宏(如 `__linux__`)由编译器根据**目标平台**自动定义 - 在交叉编译时,这些宏反映的是代码将要运行的平台,而非编译环境本身 2. **层级化检测原则** - 先检测特定系统(Android/iOS),再检测通用系统(Linux/macOS) - 示例: ```cpp #if defined(__ANDROID__) // Android #elif defined(__linux__) // 通用 Linux #endif ``` 3. **苹果平台特殊处理** - 必须包含 `<TargetConditionals.h>` - 使用 `TARGET_OS_*` 系列宏精确区分 macOS/iOS 4. **标准库方法限制** - 文件系统特性在 C++17 才完全支持 - 路径分隔符检测不能区分 Unix-like 系统的具体变种 ### 最佳实践建议 1. **优先使用构建系统检测**(如 CMake) - 最可靠的跨平台方案 - 清晰分离平台相关代码 2. **宏检测顺序建议** ```cpp Android -> Windows -> Apple -> Linux/BSD -> 其他 Unix ``` 3. **避免运行时检测** ```cpp // 不推荐 - 可能破坏交叉编译 std::string getOsName() { #ifdef _WIN32 return "Windows"; #else return "Unix-like"; #endif } ``` 4. **处理特殊场景** ```cpp // 嵌入式 Linux 检测 #if defined(__linux__) && !defined(__USE_POSIX) // 嵌入式特定代码 #endif ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值