Macros for Gcc/G++ to Differentiate Linux and MAC Osx

Macros for GCC/G++ to differentiate Linux and Mac OSX?

The next time you want to check out pre-defined macros supported by GCC on a platform, run the preprocessor with the flag -dM. It'll list out all the predefined macros available on the system. For example:

$ touch dummy.hxx
$ cpp -dM ./dummy.hxx
#define __DBL_MIN_EXP__ (-1021)
#define __FLT_MIN__ 1.17549435e-38F
#define __CHAR_BIT__ 8
#define __WCHAR_MAX__ 2147483647
#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
#define __FLT_EVAL_METHOD__ 0
#define __DBL_MIN_10_EXP__ (-307)
#define __FINITE_MATH_ONLY__ 0
#define __SHRT_MAX__ 32767
#define __LDBL_MAX__ 1.18973149535723176502e+4932L
#define __UINTMAX_TYPE__ long unsigned int
#define __linux 1
#define __unix 1
#define __linux__ 1
...

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

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).

How do I check OS with a preprocessor directive?

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__

Can I include different files based on platform?

Clang and GCC support the __has_include preprocessor condition, which you can use instead of testing platform defines:

#if __has_include(<endian.h>)
#include <endian.h>
#else
#include "endian.h"
#endif

One thing to watch for, though, is that as <endian.h> is not a standard header, it could be possible that it's present on another platform with different definitions that don't really help you.

This is related to this other answer that I wrote a few days ago.

GCC dump preprocessor defines

Yes, use -E -dM options instead of -c.
Example (outputs them to stdout):

 echo | gcc -dM -E -
echo | clang -dM -E -

For C++

 echo | g++ -dM -E -x c++ -
echo | clang++ -dM -E -x c++ -

From the gcc manual:

Instead of the normal output, generate
a list of `#define' directives for all
the macros defined during the
execution of the preprocessor,
including predefined macros. This
gives you a way of finding out what is
predefined in your version of the
preprocessor. Assuming you have no
file foo.h, the command

touch foo.h; cpp -dM foo.h

will show all the predefined macros.

If you use -dM without the -E option,
-dM is interpreted as a synonym for -fdump-rtl-mach.

What macro are predefined by gcc for different SPARC processors?

Take a look on gcc specs:

 gcc -dumpspecs

...skip...

%{msoft-float:-D_SOFT_FLOAT} %{mcypress:} %{msparclite:-D__sparclite__} %{mf930:-D__sparclite__} %{mf934:-D__sparclite__} %{mv8:-D__sparc_v8__} %{msupersparc:-D__supersparc__ -D__sparc_v8__} %{mcpu=sparclet:-D__sparclet__} %{mcpu=tsc701:-D__sparclet__} %{mcpu=sparclite:-D__sparclite__} %{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} %{mcpu=v8:-D__sparc_v8__} %{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} %{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} %{mcpu=sparclite86x:-D__sparclite86x__} %{mcpu=v9:-D__sparc_v9__} %{mcpu=ultrasparc:-D__sparc_v9__} %{mcpu=ultrasparc3:-D__sparc_v9__} %{mcpu=niagara:-D__sparc_v9__} %{mcpu=niagara2:-D__sparc_v9__} %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}}

There are a list of recognized mcpu's with the list of -D macroses.

And the next is

%{mcpu=sparclet:-Asparclet} %{mcpu=tsc701:-Asparclet} %{msparclite:-Asparclite} %{mf930:-Asparclite} %{mf934:-Asparclite} %{mcpu=sparclite:-Asparclite} %{mcpu=sparclite86x:-Asparclite} %{mcpu=f930:-Asparclite} %{mcpu=f934:-Asparclite} %{mv8plus:-Av8plus} %{mcpu=v9:-Av9} %{mcpu=ultrasparc:%{!mv8plus:-Av9a}} %{mcpu=ultrasparc3:%{!mv8plus:-Av9b}} %{mcpu=niagara:%{!mv8plus:-Av9b}} %{mcpu=niagara2:%{!mv8plus:-Av9b}} %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}}

for translating -mcpu to -A

Hope this helps

How can I determine if the operating system is POSIX in C?

The Single UNIX Specification requires the existence of unistd.h, which can tell you the POSIX version (via the _POSIX_VERSION macro).

But how can you include unistd.h if you don't know yet that you are in fact compiling on a UNIX?

That is where this GCC document comes handy. According to it, testing for the presence, or evaluation-to-true of __unix__ should tell you that the system is a UNIX. So:

#ifdef __unix__
/* Yes it is a UNIX because __unix__ is defined. */

#include <unistd.h>

/* You can find out the version with _POSIX_VERSION.
..
.. */

#endif

__unix__ is not defined on Mac OS X, so to account for that, you could instead do:

#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))

To get a list of system specific predefined macros on your system, you may execute:

cpp -dM /dev/null

For example, my GNU/Linux system also additionally defines __linux__ and __gnu_linux__ apart from __unix__ and a bunch of other stuff.


Another useful document that you must look at is this Wiki.

It goes on to present a way of detecting the presence and version of POSIX in a way similar to the one I described above.


EDIT: Since you really want to do all this because you want to decide which directory separator to use, look at this URL. It says:

Note File I/O functions in the Windows API convert "/" to "\" as part
of converting the name to an NT-style name, except when using the
"\?\" prefix as detailed in the following sections.

I don't program on Windows, or know much anything about it, so I can't say I've banked on this.

Are there any macros to determine if my code is being compiled to Windows?

[Edit: I assume you want to use compile-time macros to determine which environment you're on. Maybe you want to determine if you're running on Wine under Linux or something instead of Windows, but in general, your compiler targets a specific environment, and that is either Windows (DOS) or it isn't, but it's rarely (never?) both.]

Some compilers offer macros to indicate a Windows build environment. But these will vary from compiler to compiler, and even on the same compiler on Windows if the target environment is not exclusively windows. Usually it's __WIN32__, but not always.

#if defined (__WIN32__)
// Windows stuff
#endif

Sometimes it can be _WIN32, __CYGWIN32__, or possibly just the compiler indicator (_MSC_VER).

If you know the environment you'll be building in (from the makefile) then you can usually pass in the #define on the command line, like "g++ -D __WIN32__ yourfile.c".

A little more info here

Why for gcc 'UNIX' and 'unix' macros are not the same thing?

This query to a popular Internet search engine brings only a single page matching the word "unix" in the proper context: it's this page on system-specific macros.

That page hints at two things:

  • GCC does not guarantee that UNIX macro is defined.

  • The unix macro is described as being "common" but nothing is
    stated about the fact it has to be present:

    However, historically system-specific macros have had names with no special prefix; for instance, it is common to find unix defined on Unix systems. For all such macros, GCC provides a parallel macro with two underscores added at the beginning and the end. If unix is defined, __unix__ will be defined too.

In either case, identifiers in C are case-sensitive, and so are the symbols handled by its preprocessor, so unix and UNIX are two unrelated symbols.

In your case, I would supposedly reverse the logic and test for Windows, not the other way.

There, the symbol _WIN32 should be defined by both MinGW and MSVC.



Related Topics



Leave a reply



Submit