How do I check OS with a preprocessor directive?

179,728

Solution 1

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__

Solution 2

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

Solution 3

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)

Solution 4

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.

Solution 5

#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
Share:
179,728

Related videos on Youtube

perimosocordiae
Author by

perimosocordiae

I enjoy a good crepe.

Updated on December 17, 2021

Comments

  • perimosocordiae
    perimosocordiae over 2 years

    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?

    • John_West
      John_West over 8 years
      @Cory Klein: No-no. this question has been asked years-before
    • ilgaar
      ilgaar over 5 years
      This is about C not C++
    • phuclv
      phuclv almost 5 years
    • Akib Azmain
      Akib Azmain over 3 years
      @CoryKlein No, that question is a duplicate of this question.
    • Cory Klein
      Cory Klein over 3 years
      @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!
  • hayalci
    hayalci over 15 years
    is there an easy way to check out if a function is defined ?
  • quinmars
    quinmars over 15 years
    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.
  • Gary Makin
    Gary Makin almost 10 years
    This site given does not include iOS, so it fails to be able to distinguish between iOS and OS X.
  • Sebi2020
    Sebi2020 over 7 years
    gcc: error: unrecognized command line option '--show-defines' gcc: fatal error: no input files compilation terminated.
  • PADYMKO
    PADYMKO about 7 years
    the dear @MD XF, please indicate versions of your Windows, MinGW and Cygwin
  • MD XF
    MD XF about 7 years
    Windows 7 Enterprise 6.1.7601. Cygwin 2.7.0-1. I can't find the MinGW version but I downloaded it yesterday.
  • MD XF
    MD XF about 7 years
    You should probably be made aware though - this program is standard C, so it should work on all compliant systems.
  • MD XF
    MD XF about 7 years
    That meta post was removed. Funny that a meta post asking about posts removed for reasons of moderation was removed for reasons of moderation.
  • PADYMKO
    PADYMKO about 7 years
    dear @MD XF, thank you for this information. I added you as contributor on top this answer.
  • Konstantin Burlachenko
    Konstantin Burlachenko about 7 years
    :) Yeah. Absolutely crazy
  • Victor Sergienko
    Victor Sergienko about 6 years
    Mac OS does not define __unix__. Why would you include it in the list?
  • katta
    katta over 5 years
    cpp -dM /dev/null will give you a list of all the gcc predefined macro on your version of installed gcc
  • David Given
    David Given over 5 years
    Cygwin defines the unix symbols and doesn't define the win32 ones, so be careful. OTOH it does define __CYGWIN__.
  • Alcaro
    Alcaro over 5 years
    @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.
  • phuclv
    phuclv about 5 years
    Windows and Unices are not the only OSes
  • Admin
    Admin about 4 years
    is __linux__ same as __ANDROID__ ??
  • Ayxan Haqverdili
    Ayxan Haqverdili almost 4 years
    Why is __linux not POSIX compliant?
  • Ayxan Haqverdili
    Ayxan Haqverdili almost 4 years
    The Windows link is broken
  • Mikhail Zakharov
    Mikhail Zakharov almost 4 years
    _AIX for IBM AIX respectively.
  • mklement0
    mklement0 almost 3 years
    That's handy, but note that unix, __unix__, __unix don't work on macOS, where only __APPLE__ and __MACH__ are defined.
  • Polluks
    Polluks almost 3 years
    @AyxanHaqverdili not enough underscores
  • mercury
    mercury about 2 years
    best answer as it covers cygwin.