Which Cross Platform Preprocessor Defines? (__WIN32__ or __WIN32 or WIN32 )?
Solution 1
It depends what you are trying to do. You can check the compiler if your program wants to make use of some specific functions (from the gcc toolchain for example). You can check for operating system ( _WINDOWS, __unix__ ) if you want to use some OS specific functions (regardless of compiler - for example CreateProcess on Windows and fork on unix).
You must check the documentation of each compiler in order to be able to detect the differences when compiling. I remember that the gnu toolchain(gcc) has some functions in the C library (libc) that are not on other toolchains (like Visual C for example). This way if you want to use those functions out of commodity then you must detect that you are using GCC, so the code you must use would be the following:
#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif
Solution 2
This article answers your question:
- C/C++ tip: How to detect the operating system type using compiler predefined macros (plus archive.org link in case it vanishes).
The article is quite long, and includes tables that are hard to reproduce, but here's the essence:
You can detect Unix-style OS with:
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
/* UNIX-style OS. ------------------------------------------- */
#endif
Once you know it's Unix, you can find if it's POSIX and the POSIX version with:
#include <unistd.h>
#if defined(_POSIX_VERSION)
/* POSIX compliant */
#endif
You can check for BSD-derived systems with:
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
/* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD). ----------- */
#endif
#endif
and Linux with:
#if defined(__linux__)
/* Linux */
#endif
and Apple's operating systems with
#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 on iPhone, iPad, etc. */
#elif TARGET_OS_MAC == 1
/* OS X */
#endif
#endif
Windows with Cygwin
#if defined(__CYGWIN__) && !defined(_WIN32)
/* Cygwin POSIX under Microsoft Windows. */
#endif
And non-POSIX Windows with:
#if defined(_WIN64)
/* Microsoft Windows (64-bit) */
#elif defined(_WIN32)
/* Microsoft Windows (32-bit) */
#endif
The full article lists the following symbols, and shows which systems define them and when: _AIX
, __APPLE__
, __CYGWIN32__
, __CYGWIN__
, __DragonFly__
, __FreeBSD__
, __gnu_linux
, hpux
, __hpux
, linux
, __linux
, __linux__
, __MACH__
, __MINGW32__
, __MINGW64__
, __NetBSD__
, __OpenBSD__
, _POSIX_IPV6
, _POSIX_MAPPED_FILES
, _POSIX_SEMAPHORES
, _POSIX_THREADS
, _POSIX_VERSION
, sun
, __sun
, __SunOS
, __sun__
, __SVR4
, __svr4__
, TARGET_IPHONE_SIMULATOR
, TARGET_OS_EMBEDDED
, TARGET_OS_IPHONE
, TARGET_OS_MAC
, UNIX
, unix
, __unix
, __unix__
, WIN32
, _WIN32
, __WIN32
, __WIN32__
, WIN64
, _WIN64
, __WIN64
, __WIN64__
, WINNT
, __WINNT
, __WINNT__
.
A related article (archive.org link) covers detecting compilers and compiler versions. It lists the following symbols: __clang__
, __GNUC__
, __GNUG__
, __HP_aCC
, __HP_cc
, __IBMCPP__
, __IBMC__
, __ICC
, __INTEL_COMPILER
, _MSC_VER
, __PGI
, __SUNPRO_C
, __SUNPRO_CC
for detecting compilers, and __clang_major__
, __clang_minor__
, __clang_patchlevel__
, __clang_version__
, __GNUC_MINOR__
, __GNUC_PATCHLEVEL__
, __GNUC__
, __GNUG__
, __HP_aCC
, __HP_cc
, __IBMCPP__
, __IBMC__
, __ICC
, __INTEL_COMPILER
, __INTEL_COMPILER_BUILD_DATE
, _MSC_BUILD
, _MSC_FULL_VER
, _MSC_VER
, __PGIC_MINOR__
, __PGIC_PATCHLEVEL__
, __PGIC__
, __SUNPRO_C
, __SUNPRO_CC
, __VERSION__
, __xlC_ver__
, __xlC__
, __xlc__
for detecting compiler versions.
Solution 3
Don't see why you have to. You might have to remember to specify the definition manually on your compiler's commandline, but that's all. For the record, Visual Studio's definition is _WIN32
(with one underscore) rather than __WIN32
. If it's not defined then it's not defined, and it won't matter.
Solution 4
I've rebuild my answer... Damn, editing berserk :P:
You don't need to use partical one. And probably for MacOSX, Linux and other Unix-likes you don't need to use any at all.
Most popular one is (as far as Google tells the truth) is _WIN32
.
You never define it "by hand" in your source code. It is defined in one of these ways:
as a commandline preprocessor/compiler flag (like g++ -D _WIN32
)
or it is predefined by compiler itself (most of Windows compilers predefine _WIN32
, and sometimes other like WIN32
or _WIN32_
too. -- Then you don't need to worry about defining it at all, compiler does the whole work.
And my old answer:
You don't 'have to' anything. It's just for multi-platform compatibility. Often version of code for all Unix-likes (including Linux, MacOSX, BSD, Solaris...) and other POSIX platform will be completely the same and there must be some changes for Windows. So people write their code generally for Unix-likes and put some Windows-only (eg. DirectX instructions, Windows-like file paths...) parts between #ifdef _WIN32
and #endif
.
If you have some parts eg. X-Window-system only, or MacOS-only, you do similar with something like #ifdef X_WINDOW
or #ifdef MACOS
. Then, you need set a proper preprocessor definition while compiling (with gcc using -D flag, like eg. gcc -D _WIN32
).
If you don't write any platform-dependent code, then you don't need to care for such a #ifdef, #else, #endif
blocks. And most of Windows compilers/preprocessors AFAIK have predefined some symbols like _WIN32
(most popular, as far as google tells the truth), WIN32
, _WIN32_
, etc. So compiling it on Windows most probably you don't need to make anything else than just compiling.
math
Updated on June 15, 2020Comments
-
math almost 4 years
I often see
__WIN32
,WIN32
or__WIN32__
. I assume that this depends on the used preprocessor (either one from visual studio, or gcc etc).Do I now have to check first for os and then for the used compiler? We are using here G++ 4.4.x, Visual Studio 2008 and Xcode (which I assume is a gcc again) and ATM we are using just
__WIN32__
,__APPLE__
and__LINUX__
. -
math almost 14 yearsSo I could write the
#ifdef __WIN32__
only once and not#ifdef WIN32 || __WIN32 || __WIN32__
-
math almost 14 yearsProbably my question is very unclear: I don't want to define WIN32 but to use it with
#ifdef
. And I wondered why there are so many variants and if there is one which should work with most of the compiliers. -
silmeth almost 14 yearsAs I said, people just use what they like, there is no standard. Anyway, you can define it when compiling yourself in commandline (and also in IDE options, etc.), so using "unsupported" WIN32__ instead of "good" _WIN32 isn't a problem. And, as I said, most compilers support _WIN32 and some support many others (mingw support WIN32 _WIN32 WIN32 __WIN32 MINGW32 WINNT WINNT __WINNT). See this one: stackoverflow.com/questions/142508/…
-
INS almost 14 yearsYou can create wrappers for different behaviors and use those wrappers. This way you deal with platform/compiler differences in just a few source files, which is (in my opinion) better that dealing with makefiles for each platform.
-
Billy ONeal almost 14 years@brubelsabs: Yes, but you'd have to remember to put in the preprocessor definition yourself on the commandline if you decided to use another compiler.
-
Chris K almost 14 yearsYou have a valid point. However, I can't conceive of a situation where you're supporting multiple platforms and aren't using Makefiles of some sort (gmake/cmake/qmake) anyway. Windows library definitions to link.exe are not the same as gcc -L -l. Nor are compiler optimization settings. I'd much rather deal with my platform flags in one Makefile (or a few by inclusion) than have to remember to include platform_magic.h in every header/source file. Boost does it your way - in boost/system/config.hpp it determines what platform it's running on. We'll just have to agree to disagree. :-D
-
rubenvb about 13 yearsAFAIK
_WIN32
is defined for all (modern) Windows compilers (excluding WinCE of course). No need to define it yourself... -
IInspectable over 9 years@math: Your
#ifdef
-expression is wrong. It should be#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
. See C Preprocessor directives and boolean operators for reference. -
math over 9 yearsLinks might get broken, and I just posting the link without any explanation I consider not a good QA style. Even it when this would be just a comment. Please try to sum up the article.
-
Charphacy over 9 yearsGood call. I've updated the article to give much more detail, and also provide links to archive.org to better handle the site vanishing.
-
Ben Voigt over 9 years@IInspectable: Or perhaps
#if WIN32 || _WIN32 || __WIN32__
. Undefined names are treated as zero. The question is what should be done in case of#define _WIN32 0
. -
IInspectable over 9 years@Ben: You have already answered, why your proposed
#if
-expression is inappropriate. If you want to check whether a preprocessor symbol is defined, it is best to check whether a preprocessor symbol is defined. -
Ben Voigt over 9 years@IInspectable: But why do you think it is more appropriate to treat
#define _WIN32 0
the same as#define _WIN32 1
, rather than#undef _WIN32
? -
IInspectable over 9 years@Ben: Because that is how it is specified and documented. Predefined Macros: "_WIN32 Defined for applications for Win32 and Win64."