====== Plattform-Makros ====== ...für Plattform- und Compilerübergreifende Programme (Stichwort: **Portabilität**) :!: Zuerst kommt die Ermittlung/Bestimmung des Compilers und danach der Plattform, weil viele Makros vom Compiler selbst gesetzt werden und sind deshalb Compiler-abhängig. Eine große Übersicht von Makros im Bezug auf Compiler und Plattforme sind hier zu finden: * "C/C++ tip: How to detect the operating system type using compiler predefined macros" (Stand: 03.01.2012): [[http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system]] * "C/C++ tip: How to list compiler predefined macros" (Stand: 07.12.2011): [[http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros]] ===== Compiler ===== Anhand folgender Makros läßt sich feststellen, mit welchem Compiler der Quelltext übersetzt wird: ^Makro ^Kommentar ^ |%%__GNUC__%%\\ \\ %%__GNUC_MINOR__%%\\ %%__GNUC_PATCHLEVEL__%% |Der **GNU C**-Compiler setzt diese Makros.\\ \\ Beispiel: // Test for GCC > 3.2.0 #if __GNUC__ > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ > 0)) #endif ...oder: #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) // Test for GCC > 3.2.0 #if GCC_VERSION > 30200 #endif | |%%__GNUG__%% |Der **GNU C++**-Compiler setzt dieses Makro.\\ Es ist equivalent zum Test auf %%(__GNUC__ && __cplusplus)%%. | |%%__CYGWIN__%%\\ %%__CYGWIN32__%% |Der **Cygwin**-Compiler (POSIX, Portierung von GCC unter Windows) setzt diese Makros. | |%%__MINGW32__%%\\ %%__MINGW64__%% |Der **MinGW**-Compiler (non-POSIX, minimalistische Portierung von GCC unter Windows) setzt diese Makros. | |%%_MSC_VER%% |Der MS **VisualStudio**-Compiler (häufig "VC" oder "MSVC" genannt) setzt dieses Makro mit dem Wert, der gleichzeitig der internen Compiler-Version entspricht.\\ Hier ist die Auflistung, welche Werte welcher Version des MSVC-Compilers entsprechen:\\ [[https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering]] | Quelle: [[https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html]] Weitere Compiler: FIXME Sprach-Level: ^Makro ^Kommentar ^ |%%__cplusplus%% |Definiert nur, wenn der Text von einem **C++**-Compiler übersetzt wird.\\ Einige Werte, die dieses Makro haben kann:\\ **201103L** = "C++11",\\ **201402L** = "C++14".\\ \\ Beispiel 1: Prüfung, ob der passende Compiler verwendet wird: // Es muss mindestens C++11 sein: #if (__cplusplus < 201103L) #error ---------- C++11 features not available - use the GCC-option -std=c++11 ---------- #endif \\ Beispiel 2: das Template **make_unique** gibt es erst ab GCC 4.9, deshalb bei Bedarf "nachrüsten": #if (__cplusplus < 201402L) // vor C++14 #include namespace std { template std::unique_ptr make_unique(Args&& ...args) { return std::unique_ptr(new T(std::forward(args)...)); } } #endif | ===== Plattform ===== :!: **IN ARBEIT** - Anfang FIXME Unterscheidung auf **HW-Ebene**: * Prozessorarchitektur (z.B. "x86" oder "sparc") - welche Kürzel? * Bit-Breite (z.B. 32- oder 64-Bit) * Endianes (z.B. Big-/Little-Endian) HW = Prozessorarchitektur + Bit-Breite + Endianes Folgende Makros können für die Bestimmung der HW-Ebene herangezogen werden: * Prozessorarchitektur: Dieses Makros werden durch den MS VisualStudio-Compiler gesetzt: ^Makro ^Kommentar ^ |%%_M_AMD64%% |Definiert, wenn Target ein **x64**-Prozessor ist. | |%%_M_ARM%% |Definiert, wenn Target ein **ARM**-Prozessor ist. | |%%_M_IX86%% |Definiert, wenn Target ein **x86**-Prozessor ist. Bei dem x64-Prozessor ist dieses Makro __nicht__ definiert. | |%%_M_X64%% |Definiert, wenn Target ein **x64**-Prozessor ist. | * Bit-Breite: ^Makro ^Kommentar ^ | | | * Endianes: ^Makro ^Kommentar ^ |%%__BYTE_ORDER__%%\\ \\ Mögliche Werte:\\ %%__ORDER_LITTLE_ENDIAN__%%\\ %%__ORDER_BIG_ENDIAN__%%\\ %%__ORDER_PDP_ENDIAN__%% |Das Makro "%%__BYTE_ORDER__%%" nimmt wahlweise den Wert den anderen 3 Makros, je nachdem welches Endianes das Target hat.\\ \\ Ein Beispiel: // Test for a little-endian machine: #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #endif | Unterscheidung auf **SW-Ebene**: * OS-Familie (z.B. "unix", "linux", "windows") * OS-Name/-Derivat (innerhalb der Familie, z.B. "solaris", "debian") * Namenszusatz (z.B. Nummer 6 bei RHEL6 oder 10 bei Windows10) * Bit-Breite (z.B. 32- oder 64-Bit) OS = OS-Familie + OS-Name + Namenszusatz + Bit-Breite ^Makro ^Kommentar ^ ^Windows-Familie ^MS VisualStudio-Compiler ^ |%%_WIN32%% |Definiert für **Win32**- und **Win64**-Anwendungen. (Immer definiert.)\\ Hinweis:\\ Nicht mit "%%WIN32%%" (ohne Unterstrich) verwechseln! "%%_WIN32%%" wird durch den Compiler gesetzt, "%%WIN32%%" durch das SDK oder Build Environment. | |%%_WIN64%% |Definiert nur für **Win64**-Anwendungen. | ^UNIXoide ^^ |%%__unix%%\\ %%__unix__%% |Definiert auf allen / meisten UNIX-artigen Betriebssystemen. | |%%_AIX%% |Definiert unter AIX. | |%%sun%%\\ %%__sun%%\\ %%__sun__%%\\ %%__SVR4%% |:?: Definiert unter SunOS / Solaris. (:!: Klären: SunOS versus Solaris.) | |%%__FreeBSD__%% |FreeBSD. | |%%__NetBSD__%% |NetBSD. | |%%__OpenBSD__%% |OpenBSD. | |%%__hpux%% |HP-UX. | |%%__APPLE__%%\\ %%__MACH__%% |Definiert unter OSX, iOS und Darwin.\\ Zur weiteren Unterscheidung werden Makros aus **TargetConditionals.h** herangezogen:\\ %%TARGET_OS_EMBEDDED%%, %%TARGET_OS_IPHONE%%, %%TARGET_OS_MAC%% und %%TARGET_IPHONE_SIMULATOR%% | ^Linux ^^ |%%__linux__%%\\ %%__gnu_linux__%% |Definiert auf Linux-Derivaten.\\ Eigentlich gehört die Linux-Familie auch zu den UNIXoiden, wird hier jedoch übersichtshalber und aufgrund großer Anzahl verschiedener Distributionen separat behandelt.\\ :!: Die Makros "%%__unix%%" und "%%__unix__%%" sind unter Linux ebenfalls definiert. | %%_WINDOWS%%\\ %%__i386%%\\ %%__i386__%%\\ %%i386%%\\ %%x86%%\\ %%x64%%\\ %%_X64%%\\ %%__x86_64%%\\ %%__sparc%%\\ %%__sparc__%%\\ %%sparc%%\\ %%_SPARC%%\\ ^Makro ^Kommentar ^ |%%__ELF__%% |Dieses Makro ist definiert, wenn Target nutzt das Object-Format ELF. | Fazit: Plattform-ID (oder einfach Plattform) = HW + OS :!: **IN ARBEIT** - Ende FIXME :!: Viele Plattform-Makros sind im HeaderFile **gtest-port.h** (aus GoogleTest) enthalten und können sehr gut als Anhaltspunkte verwendet werden. ---- Stand: 27.09.2019\\ --- //[[feedback.jk-wiki@kreick.de|: Jürgen Kreick]]// EOF