Obwohl ich glaube, dass die Verwendung des Build-Systems für plattformübergreifende Dateien am besten ist, ist es möglich, einfach Ihre Quelle zu schreiben, um sie über den Präprozessor zu verarbeiten. Jedoch ist die sehr übliche, schnelle und schmutzige Methode, dies zu tun, wo Sie Plattform-Checks über den gesamten Code streuen, problematisch und sollte vermieden werden.
Stattdessen sollten Sie eine stärker strukturierte Methode zum Organisieren von plattformspezifischem Code verwenden, um Probleme zu vermeiden, wenn das Projekt größer wird.
Plattformspezifischer Code sollte auf Dateiebene eindeutig identifiziert werden: Verwenden Sie zum Beispiel eine Verzeichnisstruktur mit Verzeichnissen für jede Plattform und legen Sie alle plattformspezifischen Quelldateien in das entsprechende Verzeichnis. Quelldateien sollten keinen Code für mehrere Plattformen oder Präprozessor-Plattformprüfungen enthalten (außer für eine Ausnahme). Darüber hinaus sollte plattformspezifische Quelle in der Regel nicht direkt gebaut werden oder #include
d. Stattdessen sollte plattformspezifischer Code nur indirekt über nicht plattformspezifische Quelldateien verwendet werden, die nichts außer den Plattform-Checks und #include
s der plattformspezifischen Dateien enthalten.
Beispiel-Source-Organisation:
src/
main.cpp
foo.h
foo.cpp
windows/
foo.cpp.inc
posix/
foo.cpp.inc
Beispiel-Source-Inhalt:
// main.cpp
#include "foo.h"
int main() {
foo();
}
// foo.h
void foo();
// foo.cpp
#if defined(_WIN32)
# include "windows/foo.cpp.inc"
#elif __has_include(<unistd.h>)
# include<unistd.h>
# if defined(_POSIX_VERSION)
# include "posix/foo.cpp.inc"
# endif
#else
# error Unknown platform
#endif
// windows/foo.cpp.inc
#include "foo.h"
#include <iostream>
#include <Windows.h>
void foo() {
std::cout << "Windows\n";
}
// posix/foo.cpp.inc
#include "foo.h"
#include <iostream>
#include <unistd.h>
void foo() {
std::cout << "POSIX\n";
}
Windows-Build und Ausgang:
cl.exe /EHsc /W4 /WX src\main.cpp src\foo.cpp
main
Windows-
Linux bauen und Ausgang:
g++ -Wall -Wextra -Werror -Isrc src/main.cpp src/foo.cpp
./a.out
POSIX
Die im obigen Beispiel gezeigte Methode funktioniert recht gut, wenn Code für verschiedene Plattformen vernünftig die gleiche Dateiorganisation verwenden kann. Wenn der Code für verschiedene Plattformen so unterschiedlich ist, dass Sie für jede Plattform unterschiedliche Dateistrukturen benötigen, ist es schwieriger, diese Technik zu verwenden, und die Umstellung auf das Build-System zur Verwaltung des Codes für verschiedene Plattformen wird klarer.
Es ist auch möglich, diese Technik mit dem Build-System zu mischen; Code, der die Dateistruktur plattformübergreifend nutzt, kann dies verwenden, während Module, die für verschiedene Plattformen spezifisch sind, vom Build-System verarbeitet werden können.
Dies behandelt jedoch nicht die Aufnahme verschiedener Quelldateien im Build. Die Verwendung von CMake führt normalerweise zu einer entsprechenden Einstellung, aber Sie können auch plattformspezifische Quelldateien hinzufügen. Das ist einer der (vielen guten) Gründe, CMake überhaupt einzusetzen. –
Dies ist eine dieser Techniken, die einfach ist und für kleine Projekte gut funktioniert, die aber problematisch wird, wenn Projekte größer werden. _Großes Scale C++ Software Design_ empfiehlt gegen das Bestreuen von Plattformüberprüfungen in Ihrer gesamten Quelle. Ich denke, das Build-System zu verwenden, um plattformspezifischen Code zu verwalten, ist am besten, aber wenn Sie es in der Quelle selbst tun möchten, ist es ratsam, eine [stark strukturierte Organisation] zu verwenden (http://stackoverflow.com/a/31304341/365496). – bames53