cpp via gfortran missing macros [duplicate] - fortran

Dear All I have a small Fortran program containing preprocessor macro. Below is a minimal example. On mac os x, it works well but when I compile it on windows 7 (64-bit) it always prints unknown operating system. I am using gfortran-4.8.0 (mingw32) on windows 7.
program foo
implicit integer(i-n), double precision (a-h,o-p),
+ character*8(x-z)
*
#ifdef _WIN64
zterm = 'wxt'
#elif _WIN32
zterm = 'wxt'
#elif __APPLE__
zterm = 'aqua'
#elif __linux
zterm = 'x11'
#elif __unix
zterm = 'x11'
#elif __posix
zterm = 'x11'
#else
print*, 'unknown operating system'
#endif
end program foo
Changing #ifdef _WIN64 to #if defined (_WIN64) did not help. Any suggestion will be appreciated.

This might be GFortran PR 42954. Since GFortran started using libcpp instead of running cpp in a separate process, many of these built-in macros are missing.
As a workaround, you can as part of your build process generate a file with these builtin macro definitions which you can then include. E.g. have a make target which runs
gcc -E -dM - < /dev/null > builtins.inc
Then your sources should depend on builtins.inc in the Makefile, and in the beginning of your source files you
#include "builtins.inc"

Related

How I can check that the system that I build is for linux or not? [duplicate]

I need my code to do different things based on the operating system on which it gets compiled. I'm looking for something like this:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
Is there a way to do this? Is there a better way to do the same thing?
The Predefined Macros for OS site has a very complete list of checks. Here are a few of them, with links to where they're found:
Windows
_WIN32   Both 32 bit and 64 bit
_WIN64   64 bit only
__CYGWIN__
Unix (Linux, *BSD, but not Mac OS X)
See this related question on some of the pitfalls of using this check.
unix
__unix
__unix__
Mac OS X
__APPLE__ Also used for classic
__MACH__
Both are defined; checking for either should work.
Linux
__linux__
linux Obsolete (not POSIX compliant)
__linux Obsolete (not POSIX compliant)
FreeBSD
__FreeBSD__
Android
__ANDROID__
show GCC defines on Windows:
gcc -dM -E - <NUL:
on Linux:
gcc -dM -E - </dev/null
Predefined macros in MinGW:
WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386
on UNIXes:
unix __unix__ __unix
Based on nadeausoftware and Lambda Fairy's answer.
#include <stdio.h>
/**
* Determination a platform of an operation system
* Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
*/
#if defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows
#elif defined(_WIN64)
#define PLATFORM_NAME "windows" // Windows
#elif defined(__CYGWIN__) && !defined(_WIN32)
#define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#elif defined(__ANDROID__)
#define PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
#elif defined(__linux__)
#define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
#include <sys/param.h>
#if defined(BSD)
#define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
#endif
#elif defined(__hpux)
#define PLATFORM_NAME "hp-ux" // HP-UX
#elif defined(_AIX)
#define PLATFORM_NAME "aix" // IBM AIX
#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_IPHONE == 1
#define PLATFORM_NAME "ios" // Apple iOS
#elif TARGET_OS_MAC == 1
#define PLATFORM_NAME "osx" // Apple OSX
#endif
#elif defined(__sun) && defined(__SVR4)
#define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
#define PLATFORM_NAME NULL
#endif
// Return a name of platform, if determined, otherwise - an empty string
const char *get_platform_name() {
return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}
int main(int argc, char *argv[]) {
puts(get_platform_name());
return 0;
}
Tested with GCC and clang on:
Debian 8
Windows (MinGW)
Windows (Cygwin)
Microsoft C/C++ compiler (MSVC) Predefined Macros can be found here
I think you are looking for:
_WIN32 - Defined as 1 when the compilation target is 32-bit ARM, 64-bit ARM, x86, or x64. Otherwise, undefined
_WIN64 - Defined as 1 when the compilation target is 64-bit ARM or x64. Otherwise, undefined.
gcc compiler PreDefined MAcros can be found here
I think you are looking for:
__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Do a google for your appropriate compilers pre-defined.
In most cases it is better to check whether a given functionality is present or not. For example: if the function pipe() exists or not.
#ifdef _WIN32
// do something for windows like include <windows.h>
#elif defined __unix__
// do something for unix like include <unistd.h>
#elif defined __APPLE__
// do something for mac
#endif
On MinGW, the _WIN32 define check isn't working. Here's a solution:
#if defined(_WIN32) || defined(__CYGWIN__)
// Windows (x86 or x64)
// ...
#elif defined(__linux__)
// Linux
// ...
#elif defined(__APPLE__) && defined(__MACH__)
// Mac OS
// ...
#elif defined(unix) || defined(__unix__) || defined(__unix)
// Unix like OS
// ...
#else
#error Unknown environment!
#endif
For more information please look: https://sourceforge.net/p/predef/wiki/OperatingSystems/
There is no standard macro that is set according to C standard. Some C compilers will set one on some platforms (e.g. Apple's patched GCC sets a macro to indicate that it is compiling on an Apple system and for the Darwin platform). Your platform and/or your C compiler might set something as well, but there is no general way.
Like hayalci said, it's best to have these macros set in your build process somehow. It is easy to define a macro with most compilers without modifying the code. You can simply pass -D MACRO to GCC, i.e.
gcc -D Windows
gcc -D UNIX
And in your code:
#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
# error Unsupported operating system
#endif
Sorry for the external reference, but I think it is suited to your question:
C/C++ tip: How to detect the operating system type using compiler predefined macros
You can use Boost.Predef which contains various predefined macros for the target platform including the OS (BOOST_OS_*). Yes boost is often thought as a C++ library, but this one is a preprocessor header that works with C as well!
This library defines a set of compiler, architecture, operating system, library, and other version numbers from the information it can gather of C, C++, Objective C, and Objective C++ predefined macros or those defined in generally available headers. The idea for this library grew out of a proposal to extend the Boost Config library to provide more, and consistent, information than the feature definitions it supports. What follows is an edited version of that brief proposal.
For example
#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/os.h>
#if BOOST_OS_WINDOWS
#elif BOOST_OS_ANDROID
#elif BOOST_OS_LINUX
#elif BOOST_OS_BSD
#elif BOOST_OS_AIX
#elif BOOST_OS_HAIKU
...
#endif
The full list can be found in BOOST_OS operating system macros
Demo on Godbolt
See also How to get platform IDs from boost?
Use #define OSsymbol and #ifdef OSsymbol
where OSsymbol is a #define'able symbol identifying your target OS.
Typically you would include a central header file defining the selected OS symbol and use OS-specific include and library directories to compile and build.
You did not specify your development environment, but I'm pretty sure your compiler provides global defines for common platforms and OSes.
See also http://en.wikibooks.org/wiki/C_Programming/Preprocessor
Just to sum it all up, here are a bunch of helpful links.
GCC Common Predefined Macros
SourceForge predefined Operating Systems
MSDN Predefined Macros
The Much-Linked NaudeaSoftware Page
Wikipedia!!!
SourceForge's "Overview of pre-defined compiler macros for standards, compilers, operating systems, and hardware architectures."
FreeBSD's "Differentiating Operating Systems"
All kinds of predefined macros
libportable
I did not find Haiku definition here. To be complete, Haiku-os definition is simple __HAIKU__
Some compilers will generate #defines that can help you with this. Read the compiler documentation to determine what they are. MSVC defines one that's __WIN32__, GCC has some you can see with touch foo.h; gcc -dM foo.h
You can use pre-processor directives as warning or error to check at compile time you don't need to run this program at all just simply compile it .
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
#error Windows_OS
#elif defined(__linux__)
#error Linux_OS
#elif defined(__APPLE__) && defined(__MACH__)
#error Mach_OS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#error Unix_OS
#else
#error Unknown_OS
#endif
#include <stdio.h>
int main(void)
{
return 0;
}
I wrote an small library to get the operating system you are on, it can be installed using clib (The C package manager), so it is really simple to use it as a dependency for your projects.
Install
$ clib install abranhe/os.c
Usage
#include <stdio.h>
#include "os.h"
int main()
{
printf("%s\n", operating_system());
// macOS
return 0;
}
It returns a string (char*) with the name of the operating system you are using, for further information about this project check it out the documentation on Github.

How to detect apple platform in C++? [duplicate]

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?
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.
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__.
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
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.
Source: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
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
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.
See http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#OSXiOSandDarwin
#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.

C++ compiling on Windows and Linux: ifdef switch [duplicate]

This question already has answers here:
How do I check OS with a preprocessor directive?
(16 answers)
Closed 7 years ago.
I want to run some c++ code on Linux and Windows. There are some pieces of code that I want to include only for one operating system and not the other. Is there a standard #ifdef that once can use?
Something like:
#ifdef LINUX_KEY_WORD
... // linux code goes here.
#elif WINDOWS_KEY_WORD
... // windows code goes here.
#else
#error "OS not supported!"
#endif
The question is indeed a duplicate but the answers here are much better, especially the accepted one.
use:
#ifdef __linux__
//linux code goes here
#elif _WIN32
// windows code goes here
#else
#endif
You can do:
#if MACRO0
//code...
#elif MACRO1
//code...
#endif
…where the identifier can be:
__linux__ Defined on Linux
__sun Defined on Solaris
__FreeBSD__ Defined on FreeBSD
__NetBSD__ Defined on NetBSD
__OpenBSD__ Defined on OpenBSD
__APPLE__ Defined on Mac OS X
__hpux Defined on HP-UX
__osf__ Defined on Tru64 UNIX (formerly DEC OSF1)
__sgi Defined on Irix
_AIX Defined on AIX
_WIN32 Defined on Windows
I know it is not answer but added if someone looking same in Qt
In Qt
https://wiki.qt.io/Get-OS-name-in-Qt
QString Get::osName()
{
#if defined(Q_OS_ANDROID)
return QLatin1String("android");
#elif defined(Q_OS_BLACKBERRY)
return QLatin1String("blackberry");
#elif defined(Q_OS_IOS)
return QLatin1String("ios");
#elif defined(Q_OS_MAC)
return QLatin1String("osx");
#elif defined(Q_OS_WINCE)
return QLatin1String("wince");
#elif defined(Q_OS_WIN)
return QLatin1String("windows");
#elif defined(Q_OS_LINUX)
return QLatin1String("linux");
#elif defined(Q_OS_UNIX)
return QLatin1String("unix");
#else
return QLatin1String("unknown");
#endif
}
It depends on the used compiler.
For example, Windows' definition can be WIN32 or _WIN32.
And Linux' definition can be UNIX or __unix__ or LINUX or __linux__.
This response isn't about macro war, but producing error if no matching platform is found.
#ifdef LINUX_KEY_WORD
... // linux code goes here.
#elif WINDOWS_KEY_WORD
... // windows code goes here.
#else
#error Platform not supported
#endif
If #error is not supported, you may use static_assert (C++0x) keyword. Or you may implement custom STATIC_ASSERT, or just declare an array of size 0, or have switch that has duplicate cases. In short, produce error at compile time and not at runtime
It depends on the compiler. If you compile with, say, G++ on Linux and VC++ on Windows, this will do :
#ifdef linux
...
#elif _WIN32
...
#else
...
#endif
No, these defines are compiler dependent. What you can do, use your own set of defines, and set them on the Makefile. See this thread for more info.

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

This question already has answers here:
How do I check OS with a preprocessor directive?
(16 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
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?
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 __ANDROID__
// Below __linux__ check should be enough to handle Android,
// but something may be unique to Android.
#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).
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.
5 Jan 2021: link update thanks to #Sadap's comment.
Kind of a corollary answer: the people on this site have taken the time to make tables of macros defined for every OS/compiler pair.
For example, you can see that _WIN32 is NOT defined on Windows with Cygwin (POSIX), while it IS defined for compilation on Windows, Cygwin (non-POSIX), and MinGW with every available compiler (Clang, GNU, Intel, etc.).
Anyway, I found the tables quite informative and thought I'd share here.

Which macro to wrap Mac OS X specific code in C/C++

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?
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.
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__.
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
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.
Source: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
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
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.
See http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#OSXiOSandDarwin
#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.