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 commandtouch 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. Ifunix
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
Is Kernel Space Mapped into User Space on Linux X86
Why Didn't I Get Segmentation Fault When Storing Past the End of the Bss
Explicitly Invoke Sig_Dfl/Sig_Ign Handlers on Linux
Deleting String Up to the First Occurrence of Certain Character
Command Substitution Within Sed Expression
How to Tell Qt to Use Different Openssl
Sed Returns "Sed: Command Garbled"
How to Parse Command Line Options in Bash Shell
Why Do My Results Different Following Along the Tiny Asm Example
Shell Script for Multithreading a Process
Emulating Slurm on Ubuntu 16.04
How to Not Transfer Changes Done to Files from a Branch to a Another in Git
Sed Command Working on Command Line But Not in Perl Script
Bash Foreach Loop Works Differently When Executed from .Sh File
(Master) at End of Terminal Prompt
Specify the from User When Sending Email Using the Mail Command