Условная компиляция в C++ на основе операционной системы
Я хотел бы написать кроссплатформенную функцию на C++, которая содержит системные вызовы. Какие флаги условной компиляции я могу проверить, чтобы определить, для какой операционной системы код компилируется? Мне интересны в основном Windows и Linux, использующие Visual Studio и GCC.
Я думаю, это должно выглядеть примерно так:
void SomeClass::SomeFunction()
{
// Other code
#ifdef LINUX
LinuxSystemCall();
#endif
#ifdef WINDOWS
WindowsSystemCall();
#endif
// Other code
}
4 ответа
Мой 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 поддерживают определение макросов из командной строки, поэтому просто определите их.
Я всегда стараюсь держать специфику платформы вне основного кода, делая это таким образом
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
}
Сейчас в windows_platform.h
а также linux_platform.h
вы печатаете system_related_type
на родной тип, и либо #define platform_SystemCall
как собственный вызов, или создайте небольшую функцию-обертку, если аргумент, устанавливаемый с одной платформы на другую, слишком отличается.
Если системные API для конкретной задачи сильно различаются на разных платформах, вам может потребоваться создать собственный API версии, который разделяет разницу. Но по большей части существует довольно прямое сопоставление между различными API в Windows и Linux.
Вместо того, чтобы полагаться на какой-то конкретный компилятор #define для выбора платформы, я #define BUILD_PLATFORM в файле проекта или make-файле, так как в любом случае они должны быть уникальными для платформы.
Вот что я использую. Работает под 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