Условная компиляция в C++ на основе операционной системы

Я хотел бы написать кросс-платформенную функцию на C++, содержащую системные вызовы. Какие флаги условной компиляции можно проверить, чтобы определить, для какой операционной системы компилируется код? Меня интересуют в основном Windows и Linux, используя Visual Studio и GCC.

Я думаю, что это должно выглядеть примерно так:

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

#ifdef LINUX
    LinuxSystemCall();
#endif

#ifdef WINDOWS
    WindowsSystemCall();
#endif

    // Other code
}

4 ответов


My gcc (4.3.3) определяет следующие предопределенные макросы, связанные с Linux:

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

в VC++ (и многих других компиляторах Win32) также есть несколько предопределенных макросов, идентифицирующих платформу, в частности _WIN32. Более подробная информация:http://msdn.microsoft.com/en-us/library/b0084kay (VS.80).aspx


нет стандартного способа сделать это. Возможно, можно отключить определенные макросы, определенные для каждой платформы. Например, _WIN32 будет определен в Windows и почти наверняка не в Linux. Однако я не знаю ни одного соответствующего макроса Linux.

поскольку вы используете отдельные компиляторы, из этого следует, что у вас есть отдельные среды сборки. Почему бы просто не добавить макрос сам? Visual Studio и GCC поддерживают определение макросов из командной строки, поэтому просто определить их.


Я всегда стараюсь держать специфику платформы вне основного кода, делая это таким образом

.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
}

сейчас windows_platform.h и linux_platform.h вы typedef system_related_type к родному типу, и либо #define platform_SystemCall как собственный вызов или создайте небольшую функцию-оболочку, если аргумент, установленный с одной платформы на другую, слишком отличается.

если системные API для конкретной задачи дико отличаются между платформы, вам может потребоваться создать собственную версию API, которая разделяет разницу. Но по большей части существуют довольно прямые сопоставления между различными API в Windows и Linux.

вместо того, чтобы полагаться на какой-то конкретный компилятор #define для выбора платформы, я #define BUILD_PLATFORM в файле проекта или makefile, так как они должны быть уникальными по платформе в любом случае.


вот что я использую. Он работает под Visual Studio 2008 и 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