Benutzer-Werkzeuge

Webseiten-Werkzeuge


edv:prg:c:tipp:plattform-makros

Inhaltsverzeichnis

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:

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 <memory>
namespace std
{
	template<typename T, typename ...Args>
	std::unique_ptr<T> make_unique(Args&& ...args)
	{
		return std::unique_ptr<T>(new T(std::forward<Args>(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
: Jürgen Kreick

EOF

edv/prg/c/tipp/plattform-makros.txt · Zuletzt geändert: 2020/01/11 01:23 von 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki