A C program can tell which OS it is compiling?

Asked

Viewed 671 times

10

I am developing a multi-platform C API and need to know if there is any way to know which OS is being compiled.

For example, it could be a pre compilation directive

#ifdef LINUX
#include<linuxlib.h>
#elif OSX
#include<osxlib.h>
#elif WINDOWS
#include<rwindowslib.h>

3 answers

10


Directives of the Preprocessor:

Windows: _WIN32 (which, despite the name, is also available in 64 bits)
OS X (also includes iOS): __APPLE__
Unix: __unix
Linux: __linux
Android Linux: __ANDROID__
iPhone: I can’t find anything, but for specific versions there is the __IPHONE_4_3, etc. Note that although they are specific versions they are checked at compile time.

I’m not sure iPhone macros are always available. Some sources refer to the Availability.h and the TargetConditionals.h so if it doesn’t work it might be worth trying to use those files.

At runtime, you can find out which Linux distribution is being used by reading, for example, the file /etc/lsb-release

4

Typically cross-platform Apis develop code specifically for each platform and do not check has run time. The code is only specified at compile time for a target platform.

For this, they usually define macros to verify which OS it is. Is what the Qt and the wxWidgets do.

In the header of your API you define:

#ifdef defined(__WIN32__) || defined(__NT__)
#    define MEU_API_WINDOWS
#  endif

#if defined(__linux__) || defined(__linux)
#  define MEU_API_LINUX
#endif

#if defined(__APPLE__)
#  defined MEU_API_OSX
#endif

void foo();

Hence you can define your code as follows:

void foo()
{
    #if defined(MEU_API_WINDOWS)
    // código para windows
    #elif defined(MEU_API_LINUX)
    // código para linux
    #elif defined(MEU_API_OSX)
    // código para OS X.
    #endif

    // etc
}

And with that you would need a single header and the foo() function would work on all platforms you planned.

Alternatively, you can set foo() in files. c different for each platform (gets more organized), doing the OS checks on each file.

For example, for the foo_linux.c:

#ifdef MEU_API_LINUX
#include <lib_do_linux.h>

void foo() 
{
// TODO
}
#endif

And in the foo_windows.c:

#ifdef MEU_API_WINDOWS
#include <lib_do_windows.h>

void foo() 
{
// TODO
}
#endif

I recommend you take a look at the implementations of Qt and wxWidgets as both handle this situation well.

0

You could create a build file for each system by calling make with a parameter, and define a build directive through a compiler parameter that you use, or else check the compiler documentation and the header files that it uses by default, to see if he no longer defines some directives for you.

One of these is the _WIN32, already enshrined since the emergence of Windows in 32 bits, to differentiate it from Windows 16 bits. Already for Windows 64 bits, you can use _WIN64, but note that _WIN32 will still be set.

Macros Predefined by VS2013

Default macros in GCC

  • Interesting Miguel Angelo as the suggestion of Makefile?

  • Inside the Makefile you will see the commands inside (e. g. gcc -o foo.o foo.c if you are using GCC) then just add in the command -d $(NOME_OS) reference, there would be a batchfile to start make on each OS: Win32.bat => make NOME_OS=WIN32; win-phone.bat => make NOME_OS=WINPHONE... reference and so on

  • But this does not prevent me from having to create a file for each platform =/ which in case would be the batch file.

  • No avoids, but it already makes the maintenance of these files absurdly simple... wants to support a new OS, just create a super-simple BATCH file. Otherwise, you will be at the mercy of the compiler defining the directives as _WINXX, __linux. Unless there is a command-line detector capable of doing this, and it is ported to the most diverse operating systems.

  • My answer was confused... I edited it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.