Conditional compilation in C++ based on operating system
Asked Answered
T

4

11

I would like to write a cross-platform function in C++ that contains system calls. What conditional compilation flags can I check to determine which operating system the code is being compiled for? I'm interested mostly in Windows and Linux, using Visual Studio and GCC.

I think it should look something like this:

void SomeClass::SomeFunction()
{
    // Other code

#ifdef LINUX
    LinuxSystemCall();
#endif

#ifdef WINDOWS
    WindowsSystemCall();
#endif

    // Other code
}
Tanyatanzania answered 24/5, 2009 at 21:56 Comment(0)
H
10

My gcc (4.3.3) defines the following Linux-related predefined macros:

$ gcc -dM -E - < /dev/null | grep -i linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

Under VC++ (and many other Win32 compilers) there are also a couple of predefined macros identifying the platform, most notably _WIN32. Further details: http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx

Heyday answered 24/5, 2009 at 22:9 Comment(1)
There is a gotcha when dealing with Win32 / Win64 conditional compilation - when compiling for Win64 you will find that _WIN32 is defined (!) so test against _WIN64 before you test against _WIN32Lewin
N
8

There is no standard way to do this. It may be possible to key off certain macros that are defined per platform. For instance, _WIN32 will be defined on Windows and almost certainly not Linux. However I don't know of any corresponding Linux macro.

Because you are using separate compilers, it follows that you have separate build environments. Why not just add the macro yourself? Both Visual Studio and GCC support defining macros from the command line so just define them.

Nananne answered 24/5, 2009 at 22:10 Comment(2)
I would like to use to most common macros for this, hopefully the defaults defined by the compilers themselves. It seems that _WIN32 and linux will suffice for my purposes.Tanyatanzania
Sure, but will that work for BSD and other UNIX flavors? It really is best to define it (in the makefile, build system etc) yourself. If you're unhappy, at least protect your code with something like #ifdef _WIN32 #define PLATFORM "Windows" #endif then have #ifndef PLATFORM #error PLATFORM undefined - check your configuration #endifFulgurating
B
7

I always try to keep the platform specifics out of the main code by doing it this way

platform.h:

#if BUILD_PLATFORM == WINDOWS_BUILD
#include "windows_platform.h"
#elif BUILD_PLATFORM == LINUX_BUILD
#include "linux_platform.h"
#else
#error UNSUPPORTED PLATFORM
#endif

someclass.c:

void SomeClass::SomeFunction()
{
   system_related_type t;
   // Other code
   platform_SystemCall(&t);
   // Other code
}

Now in windows_platform.h and linux_platform.h you typedef system_related_type to the native type, and either #define platform_SystemCall as the native call, or create a small wrapper function, if the argument set from one platform to the other is too different.

If the system APIs for a particular task are wildly different between platforms, you may need to create your own version API that splits the difference. But for the most part, there are fairly direct mappings between the various APIs on Windows and Linux.

Rather than relying on some particular compiler #define to select platform, I #define BUILD_PLATFORM xxx in the project file or makefile, since those have to be unique by platform anyway.

Bibbye answered 25/5, 2009 at 0:7 Comment(1)
This assumes that BUILD_PLATFORM is defined at all. If it is not, then WINDOWS_BUILD is likely not defined either, and this expression will evaluate to TRUE. The code really should be more like: #if defined(BUILD_PLATFORM) && BUILD_PLATFORM == WINDOWS_BUILDJade
M
1

Here's what I use. It works under Visual Studio 2008, and MinGW:

#ifdef __GNUC__
  #define LINUX
#else
  #define WINDOWS
#endif

#ifdef WINDOWS
  #include "stdafx.h"
#else
  #include <stdlib.h>
  #include <string.h>
  #include <stdio.h>
  #include <ctype.h>
  #include <assert.h>
  #include <malloc.h>
#endif  
Marriageable answered 30/6, 2010 at 16:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.