306

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?

phuclv
  • 37,963
  • 15
  • 156
  • 475
perimosocordiae
  • 17,287
  • 14
  • 60
  • 76
  • 11
    @Cory Klein: No-no. this question has been asked years-before – John_West Jan 03 '16 at 19:53
  • This is about `C` not `C++` – ilgaar Jan 21 '19 at 17:08
  • [How to detect reliably Mac OS X, iOS, Linux, Windows in C preprocessor?](https://stackoverflow.com/q/5919996/995714), [Detect Windows or Linux in C, C++](https://stackoverflow.com/q/8666378/995714) – phuclv Jun 02 '19 at 15:38
  • @CoryKlein No, that question is a duplicate of this question. – Akib Azmain Turja Oct 10 '20 at 11:22
  • @AkibAzmain You’ve pulled me back into history! Wow what an old question. It was already 5 years old when I first commented 7 years ago! Interestingly, comparative age isn’t definitive criteria for selecting which is the duplicate, but in this case it looks like the other was marked as the duplicate ages ago so it’s a moot question. Have a good day! – Cory Klein Oct 10 '20 at 12:13
  • see also [OS specific instructions in CMAKE](https://stackoverflow.com/questions/9160335/os-specific-instructions-in-cmake-how-to) (CMAKE_SYSTEM_NAME) – milahu Jan 27 '23 at 10:53
  • Are you sure you want to detect the OS the compiler is running **on**, or do you rather want to figure out what OS the compiler is compiling **for**? – Thomas Weller Jun 28 '23 at 05:44

17 Answers17

440

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__

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
Lambda Fairy
  • 13,814
  • 7
  • 42
  • 68
85

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
MD XF
  • 7,860
  • 7
  • 40
  • 71
qwer
  • 959
  • 6
  • 4
64

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)
Simon Kissane
  • 4,373
  • 3
  • 34
  • 59
PADYMKO
  • 4,217
  • 2
  • 36
  • 41
9

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.

Community
  • 1
  • 1
Martin York
  • 257,169
  • 86
  • 333
  • 562
9

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/

anakod
  • 127
  • 1
  • 4
8

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.

MD XF
  • 7,860
  • 7
  • 40
  • 71
quinmars
  • 11,175
  • 8
  • 32
  • 41
  • 3
    is there an easy way to check out if a function is defined ? – hayalci Sep 26 '08 at 23:59
  • 1
    If you are using autoconfig you can check for functions with AC_CHECK_FUNCS(). AC_CHECK_FUNCS(pipe sqrt) will define HAVE_PIPE and HAVE_SQRT if the functions are available. I don't know how it is with other building tools, but I guess they also support this in a way. – quinmars Sep 27 '08 at 00:14
  • @MDXF As of C++17, there is __has_include. I don't think it's standardized in C yet, but all major compilers (GCC, Clang, ICC, MSVC) implement it as a vendor-specific extension, even in C mode. – Alcaro Jan 04 '19 at 12:17
8
#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
MD XF
  • 7,860
  • 7
  • 40
  • 71
Arjun Sreedharan
  • 11,003
  • 2
  • 26
  • 34
4

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
Mecki
  • 125,244
  • 33
  • 244
  • 253
3

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

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59
Konstantin Burlachenko
  • 5,233
  • 2
  • 41
  • 40
3

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?

phuclv
  • 37,963
  • 15
  • 156
  • 475
2

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

MD XF
  • 7,860
  • 7
  • 40
  • 71
devio
  • 36,858
  • 7
  • 80
  • 143
1

I did not find Haiku definition here. To be complete, Haiku-os definition is simple __HAIKU__

TadejP
  • 912
  • 11
  • 21
1
#ifdef _WIN32
    std::cout << "Running on Windows" << std::endl;
#elif __linux__
    std::cout << "Running on Linux" << std::endl;
#elif __APPLE__
    std::cout << "Running on macOS" << std::endl;
#else
    std::cout << "Unknown operating system" << std::endl;
#endif
pinche
  • 21
  • 4
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 25 '23 at 11:57
0

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

MD XF
  • 7,860
  • 7
  • 40
  • 71
davenpcj
  • 12,508
  • 5
  • 40
  • 37
  • 2
    gcc: error: unrecognized command line option '--show-defines' gcc: fatal error: no input files compilation terminated. – Sebi2020 Aug 24 '16 at 14:44
  • The MSVC link above currently redirects to https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?redirectedfrom=MSDN&view=msvc-170 - and that lists a `_WIN32` macro but not `__WIN32__`. I've also looked at an archived version - https://web.archive.org/web/20100422132954/http://msdn.microsoft.com:80/en-us/library/b0084kay(VS.80).aspx - and that also lists `_WIN32` but not `__WIN32__`. – AJM Nov 02 '22 at 15:52
0

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;
}
Haseeb Mir
  • 928
  • 1
  • 13
  • 22
  • I don't know why this was down-voted. Great idea here, not needing to run it just for checking prep's. I suppose you need to enable all warnings in the compiler. For gcc, use `-Wall`. `#warning` may be even better, to avoid stopping the compile, but only seem to work in GCC and not MSVC. – not2qubit Nov 26 '22 at 23:09
-1

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.

Abraham
  • 8,525
  • 5
  • 47
  • 53