6

Ich möchte eine plattformübergreifende Funktion in C++ schreiben, die Systemaufrufe enthält. Welche konditionellen Kompilierungsflags kann ich überprüfen, um festzustellen, für welches Betriebssystem der Code kompiliert wird? Ich bin hauptsächlich an Windows und Linux interessiert und verwende Visual Studio und GCC.Bedingte Kompilierung in C++ basierend auf dem Betriebssystem

ich denke, es wie folgt aussehen sollte:

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

#ifdef LINUX 
    LinuxSystemCall(); 
#endif 

#ifdef WINDOWS 
    WindowsSystemCall(); 
#endif 

    // Other code 
} 

Antwort

7

Meine gcc (4.3.3) definiert die folgenden Linux-bezogene vordefinierte Makros:

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

Unter VC++ (und viele andere Win32 Compiler) gibt es auch ein paar vordefinierte Makros, die die Plattform identifizieren, vor allem _WIN32. Weitere Details: http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx

+3

Es gibt eine Gotcha ist, wenn sie mit Win32/Win64 bedingter Kompilierung zu tun - wenn für Win64 Kompilieren Sie werden feststellen, dass _WIN32 ist so definiert, Test gegen _WIN64, bevor Sie Test (!) gegen _WIN32 –

7

Es gibt keinen Standard Weg, dies zu tun. Es kann möglich sein, bestimmte Makros abzuschliessen, die pro Plattform definiert sind. Zum Beispiel wird _WIN32 unter Windows und fast sicher nicht unter Linux definiert. Allerdings kenne ich kein entsprechendes Linux-Makro.

Da Sie separate Compiler verwenden, folgt daraus, dass Sie separate Build-Umgebungen haben. Warum nicht einfach das Makro selbst hinzufügen? Sowohl Visual Studio als auch GCC unterstützen die Definition von Makros über die Befehlszeile, also definieren Sie sie einfach.

+0

Ich würde gerne die meisten gängigen Makros dafür verwenden, hoffentlich die Standardwerte, die von den Compilern selbst definiert werden. Es scheint, dass _WIN32 und Linux für meine Zwecke ausreichen werden. –

+1

Sicher, aber wird das für BSD und andere UNIX-Varianten funktionieren? Es ist am besten, es selbst zu definieren (im Makefile, Build-System usw.). Wenn Sie unglücklich sind, schützen Sie Ihren Code mit etwas wie #ifdef _WIN32 #define PLATFORM "Windows" #endif dann haben Sie #ifndef PLATFORM #error PLATFORM undefined - überprüfen Sie Ihre Konfiguration #endif – plinth

5

Ich versuche immer, aus dem Hauptcode, um die Plattform Besonderheiten zu halten, indem es auf diese Weise

tun

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 
} 

Jetzt in windows_platform.h und linux_platform.h Sie typedef system_related_type auf den systemeigenen Typ und entweder #define platform_SystemCall als systemeigener Aufruf oder erstellen Sie eine kleine Wrapper-Funktion wenn das von einer Plattform auf die andere gesetzte Argument zu unterschiedlich ist.

Wenn sich die System-APIs für eine bestimmte Aufgabe zwischen Plattformen stark unterscheiden, müssen Sie möglicherweise eine eigene Version-API erstellen, die die Unterschiede aufteilt. In den meisten Fällen gibt es jedoch ziemlich direkte Zuordnungen zwischen den verschiedenen APIs unter Windows und Linux.

Anstatt sich auf einen bestimmten Compiler #define zu verlassen, um die Plattform auszuwählen, definiere ich BUILD_PLATFORM in der Projektdatei oder im Makefile, da diese sowieso für jede Plattform eindeutig sein müssen.

0

Hier ist, was ich benutze. Es funktioniert unter Visual Studio 2008 und 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