====== 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