Which macro to wrap Mac OS X specific code in C/C++
C++CXcodeMacosMacrosC++ Problem Overview
While reading various C and C++ sources, I have encountered two macros __APPLE__
and __OSX__
. I found plenty of use of __OSX__
in various codes, especially those originating from *BSD
systems.
However, sometimes I find that testing __OSX__
only is not sufficient and I have to complete tests with __APPLE__
macro.
The Porting Command Line Unix Tools to Mac OS X guides specifies __APPLE__
and additionally __APPLE_CC__
but does not mention __OSX__
.
The Porting from GCC guide says:
> * Use #ifdef __GNUC__
to wrap any GCC-specific code.
> * Use #ifdef __APPLE_CC__
to wrap any Mac OS X-specific code.
Again, no mention about __OSX__
macro.
What macro is predefined on Mac OS X platform and XCode development environment that should be used to distinguish OSX-specific code in C/C++ programs?
Where is the __OSX__
macro defined? Is it *BSD
specific macro?
C++ Solutions
Solution 1 - C++
It all depends.
Each macro specifies something different in meaning.
See: https://developer.apple.com/library/mac/documentation/Porting/Conceptual/PortingUnix/compiling/compiling.html#//apple_ref/doc/uid/TP40002850-SW13
> __APPLE__
> This macro is defined in any Apple computer.
> __APPLE_CC__
> This macro is set to an integer that represents the version number of > the compiler. This lets you distinguish, for example, between compilers > based on the same version of GCC, but with different bug fixes or features. > Larger values denote later compilers.
> __OSX__
> Presumably the OS is a particular variant of OS X
So given the above definitions I would use __APPLE__
to distinguish apple specific code.
Solution 2 - C++
Here is a nice list of macros for operating systems.
There's little info on __OSX__
on the web. You'll be safe with __APPLE__
.
Solution 3 - C++
I normally use __MACH__
for this. It's been defined since the earliest version of OS X (and even before, presumably).
If you want to exclude the possibility that you might be compiling for some other OS that uses the Mach kernel then you can use @scravy's suggestion of:
#if defined(__APPLE__) && defined(__MACH__)
Note also that if you're compiling generic C/C++ code, i.e. no Apple-speacific headers, so you are just interested in pre-defined compiler macros, you can check these as follows:
$ gcc -dM -E - < /dev/null | egrep -i 'os_|mac|apple'
#define __APPLE_CC__ 6000
#define __APPLE__ 1
#define __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ 120000
#define __ENVIRONMENT_OS_VERSION_MIN_REQUIRED__ 120000
#define __MACH__ 1
#define __VERSION__ "Apple LLVM 13.1.6 (clang-1316.0.21.2.3)"
#define __apple_build_version__ 13160021
Solution 4 - C++
Use
#if defined(__APPLE__) && defined(__MACH__)
to distinguish Apple operating systems.
You can further use TARGET_OS_MAC
and TARGET_OS_IPHONE
to distinguish between macOS and iOS.
Full example:
#if defined(__APPLE__) && defined(__MACH__)
/* Apple OSX and iOS (Darwin). */
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
/* iOS in Xcode simulator */
#elif TARGET_OS_IPHONE == 1
/* iOS */
#elif TARGET_OS_MAC == 1
/* macOS */
#endif
#endif
Regarding the question of "where does __OSX__
come from?":
> Some on-line lists of compiler macros (like this one) list __MACOSX__
. Some forum comments (like these) claim __OSX__
exists. These are incorrect. There are no such macros predefined by OSX compilers, but they may be defined by specific project Makefiles and platform-detector scripts like GNU autoconf.
Update – the above link is broken, see version in web archive: https://web.archive.org/web/20180331065236/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#OSXiOSandDarwin
Solution 5 - C++
For anyone coming across this question >= 2019, I found there's a header "Availability.h".
In that header, are #defines like:
#define __MAC_10_0 1000
#define __MAC_10_1 1010
#define __MAC_10_2 1020
#define __MAC_10_3 1030
#define __MAC_10_4 1040
#define __MAC_10_5 1050
#define __MAC_10_6 1060
#define __MAC_10_7 1070
#define __MAC_10_8 1080
#define __MAC_10_9 1090
#define __MAC_10_10 101000
#define __MAC_10_10_2 101002
#define __MAC_10_10_3 101003
#define __MAC_10_11 101100
#define __MAC_10_11_2 101102
So you CAN tell if you're compiling on a particular MacOS platform.
Solution 6 - C++
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_MAC
...
#endif /* TARGET_OS_MAC */
#endif /* __APPLE__ */
Note that __OSX__
does NOT exist, at least as of Xcode 9.
Also note that it is #if TARGET_OS_MAC
not #ifdef
. It is always defined, but is 0 when not macOS.