Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect reliably Mac OS X, iOS, Linux, Windows in C preprocessor? [duplicate]

If there's some cross-platform C/C++ code that should be compiled on Mac OS X, iOS, Linux, Windows, how can I detect them reliably during preprocessor process?

like image 489
eonil Avatar asked May 07 '11 08:05

eonil


People also ask

How does C++ detect operating system?

To check the operating system of the host in a C or C++ code, we need to check the macros defined by the compiler (GNU GCC or G++). For example, on Windows platform, the compiler has a special macro named _WIN32 defined. So, if the macro _WIN32 is defined, we are on Windows.

Is MacOS based on C?

Mac mainly makes use of Objective C, as much of the Cocoa is implemented in Objective-C, which is nothing but a superset of the legendary programming language C. At the kernel level, the Mac is developed mostly using the C programming language, and the PnP subsystem is Embedded in C++.


2 Answers

There are predefined macros that are used by most compilers, you can find the list here. GCC compiler predefined macros can be found here. Here is an example for gcc:

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)    //define something for Windows (32-bit and 64-bit, this part is common)    #ifdef _WIN64       //define something for Windows (64-bit only)    #else       //define something for Windows (32-bit only)    #endif #elif __APPLE__     #include <TargetConditionals.h>     #if TARGET_IPHONE_SIMULATOR          // iOS, tvOS, or watchOS Simulator     #elif TARGET_OS_MACCATALYST          // Mac's Catalyst (ports iOS API into Mac, like UIKit).     #elif TARGET_OS_IPHONE         // iOS, tvOS, or watchOS device     #elif TARGET_OS_MAC         // Other kinds of Apple platforms     #else     #   error "Unknown Apple platform"     #endif #elif __linux__     // linux #elif __unix__ // all unices not caught above     // Unix #elif defined(_POSIX_VERSION)     // POSIX #else #   error "Unknown compiler" #endif 

The defined macros depend on the compiler that you are going to use.

The _WIN64 #ifdef can be nested into the _WIN32 #ifdef because _WIN32 is even defined when targeting the Windows x64 version. This prevents code duplication if some header includes are common to both (also WIN32 without underscore allows IDE to highlight the right partition of code).

like image 51
Evgeny Gavrin Avatar answered Oct 10 '22 17:10

Evgeny Gavrin


As Jake points out, TARGET_IPHONE_SIMULATOR is a subset of TARGET_OS_IPHONE.

Also, TARGET_OS_IPHONE is a subset of TARGET_OS_MAC.

So a better approach might be:

#ifdef _WIN64    //define something for Windows (64-bit) #elif _WIN32    //define something for Windows (32-bit) #elif __APPLE__     #include "TargetConditionals.h"     #if TARGET_OS_IPHONE && TARGET_OS_SIMULATOR         // define something for simulator         // (although, checking for TARGET_OS_IPHONE should not be required).     #elif TARGET_OS_IPHONE && TARGET_OS_MACCATALYST         // define something for Mac's Catalyst     #elif TARGET_OS_IPHONE         // define something for iphone       #else         #define TARGET_OS_OSX 1         // define something for OSX     #endif #elif __linux     // linux #elif __unix // all unices not caught above     // Unix #elif __posix     // POSIX #endif 

Note that above checks TARGET_OS_SIMULATOR macro because TARGET_IPHONE_SIMULATOR macro got deprecated since iOS 14.

like image 42
PatchyFog Avatar answered Oct 10 '22 17:10

PatchyFog