Compiler-Eigenschaften

Nicht alle Compiler und Plattformen sind gleich. Daher stellt Meson die Werkzeuge zur Verfügung, um Eigenschaften des Systems zur Konfigurationszeit zu erkennen. Um die meisten dieser Informationen zu erhalten, müssen Sie zuerst das Compiler-Objekt aus der Hauptvariable meson extrahieren.

compiler = meson.get_compiler('c')

Hier extrahieren wir den C-Compiler. Wir hätten auch das Argument cpp übergeben können, um den C++-Compiler zu erhalten, objc für den Objective-C-Compiler und so weiter. Der Aufruf ist für alle Sprachen gültig, die in der project-Deklaration angegeben sind. Der Versuch, einen anderen Compiler zu erhalten, führt zu einem nicht behebbaren Fehler.

Systeminformationen

Dies ist etwas komplex und wird auf der Seite über Cross-Kompilierung ausführlicher erklärt. Wenn Sie jedoch nur wissen möchten, auf welchem Betriebssystem Ihr Code ausgeführt wird, führen Sie diesen Befehl aus

host_machine.system()

Compiler-ID

Die Methode des Compiler-Objekts compiler.get_id() gibt einen Kleinbuchstaben-String zurück, der die "Familie" des Compilers beschreibt. Seit Version 0.53.0 gibt compiler.get_linker_id() einen Kleinbuchstaben-String mit dem Linker-Namen zurück. Da Compiler je nach Betriebssystem oft aus mehreren Linkern wählen können, kann get_linker_id nützlich sein, um die Auswirkungen bestimmter Linker zu handhaben oder abzumildern.

Das Compiler-Objekt hat auch eine Methode compiler.get_argument_syntax(), die einen Kleinbuchstaben-String von gcc, msvc oder einen anderen undefinierten String-Wert zurückgibt; sie identifiziert, ob die Compiler-Argumente die gleiche Syntax wie gcc oder msvc verwenden oder ob ihre Argumente nicht mit einem von beiden übereinstimmen. Dies sollte nur verwendet werden, um die Syntax der Argumente auszuwählen, z. B. für Tests mit compiler.has_argument().

Siehe Referenztabellen für eine Liste unterstützter Compiler-IDs und ihres Argumenttyps.

Kompiliert Code?

Manchmal ist der einzige Weg, das System zu testen, zu versuchen, Beispielcode zu kompilieren und zu sehen, ob er funktioniert. Dies kann zum Beispiel testen, ob ein "C++17"-Compiler tatsächlich ein bestimmtes C++17-Feature unterstützt, ohne auf die Pflege einer Feature-Liste im Verhältnis zu Compiler-Hersteller, Compiler-Version und Betriebssystem zurückgreifen zu müssen. Das Testen, ob ein Code-Snippet läuft, ist ein zweistufiger Vorgang. Zuerst definieren wir etwas Code mit dem mehrzeiligen String-Operator

code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''

Dann können wir den Test ausführen.

result = compiler.compiles(code, name : 'basic check')

Die Variable result enthält nun entweder true oder false, je nachdem, ob die Kompilierung erfolgreich war oder nicht. Das Schlüsselwort-Argument name ist optional. Wenn es angegeben ist, schreibt Meson das Ergebnis des Checks in sein Protokoll.

Manchmal ist es notwendig zu überprüfen, ob ein bestimmter Code-Fragment nicht nur kompiliert, sondern auch erfolgreich linkt, z. B. um zu überprüfen, ob ein Symbol tatsächlich in einer Bibliothek vorhanden ist. Dies kann mit der Methode compiler.links() wie folgt geschehen

code = '''#include<stdio.h>
void func() { printf("Compile me.\n"); }
'''

Dann können wir den Test ausführen.

result = compiler.links(code, args : '-lfoo', name : 'link check')

Die Variable result enthält nun entweder true oder false, je nachdem, ob die Kompilierung und das Linken erfolgreich waren oder nicht. Das Schlüsselwort-Argument name ist optional. Wenn es angegeben ist, schreibt Meson das Ergebnis des Checks in sein Protokoll.

Kompilieren und Ausführen einer Testanwendung

Hier wird gezeigt, wie eine kleine Testanwendung kompiliert und ausgeführt wird. Das Testen, ob ein Code-Snippet **läuft** im Gegensatz zum bloßen Linken, ist besonders wichtig für einige Abhängigkeiten wie MPI.

code = '''#include<stdio.h>
int main(int argc, char **argv) {
  printf("%s\n", "stdout");
  fprintf(stderr, "%s\n", "stderr");
  return 0;
}
'''
result = compiler.run(code, name : 'basic check')

Die Variable result kapselt den Zustand des Tests, der mit den folgenden Methoden extrahiert werden kann. Das Schlüsselwort-Argument name funktioniert genauso wie bei compiles.

Methode Rückgabewert
compiled True, wenn die Kompilierung erfolgreich war. Wenn false, geben alle anderen Methoden undefinierte Werte zurück.
returncode Der Rückgabecode der Anwendung als Integer
stdout Standardausgabe des Programms als Text.
stderr Standardfehlerausgabe des Programms als Text.

Hier ist ein Anwendungsbeispiel

if result.stdout().strip() == 'some_value'
  # do something
endif

Existiert ein Header?

Header-Dateien, die von verschiedenen Plattformen bereitgestellt werden, variieren stark. Meson verfügt über Funktionalität, um zu erkennen, ob eine bestimmte Header-Datei auf dem System verfügbar ist. Der Test erfolgt durch den Versuch, ein einfaches Testprogramm zu kompilieren, das die angegebene Header-Datei einbindet. Der folgende Ausschnitt beschreibt, wie diese Funktion verwendet werden kann.

if compiler.has_header('sys/fstat.h')
  # header exists, do something
endif

Ausdrucksgröße

Oft müssen Sie die Größe eines bestimmten Elements (wie int, wchar_t oder char*) ermitteln. Mit der oben erwähnten compiler-Variable kann die Prüfung wie folgt durchgeführt werden.

wcharsize = compiler.sizeof('wchar_t', prefix : '#include<wchar.h>')

Dies legt die Größe von wchar_t, wie sie von sizeof gemeldet wird, in die Variable wcharsize. Das Schlüsselwort-Argument prefix ist optional. Wenn es angegeben ist, wird sein Inhalt am Anfang der Quelldatei platziert. Dieses Argument wird typischerweise verwendet, um #include-Direktiven in Konfigurationsdateien festzulegen.

In älteren Versionen (<= 0.30) wäre Meson ausgestiegen, wenn die Größe nicht bestimmt werden konnte. Seit Version 0.31 gibt es -1 zurück, wenn die Größe nicht bestimmt werden konnte.

Existiert eine Funktion?

Allein das Vorhandensein eines Headers sagt nichts über seinen Inhalt aus. Manchmal müssen Sie explizit prüfen, ob eine bestimmte Funktion existiert. So würden wir prüfen, ob die Funktion open_memstream in der Header-Datei stdio.h existiert

if compiler.has_function('open_memstream', prefix : '#include <stdio.h>')
  # function exists, do whatever is required.
endif

Beachten Sie, dass unter macOS Programme so kompiliert werden können, dass sie ältere macOS-Versionen anvisieren als die, auf der das Programm kompiliert wird. Es kann nicht davon ausgegangen werden, dass die OS-Version, auf der kompiliert wird, mit der OS-Version übereinstimmt, auf der die Binärdatei ausgeführt wird.

Daher ist es bei der Erkennung der Funktionsverfügbarkeit mit compiler.has_function() wichtig, den korrekten Header im prefix-Argument anzugeben.

Im obigen Beispiel wird die Funktion open_memstream erkannt, die in macOS 10.13 eingeführt wurde. Wenn der Benutzer auf macOS 10.13 baut, aber macOS 10.11 (-mmacosx-version-min=10.11) anvisiert, wird dies die Funktion korrekt als fehlend melden. Ohne den Header fehlte jedoch die notwendige Verfügbarkeitsinformation, und die Funktion wurde fälschlicherweise als verfügbar gemeldet.

Enthält eine Struktur ein Element?

Einige Plattformen haben unterschiedliche Standardstrukturen. Hier wird geprüft, ob eine Struktur namens mystruct aus der Header-Datei myheader.h ein Element namens some_member enthält.

if compiler.has_member('struct mystruct', 'some_member', prefix : '#include<myheader.h>')
  # member exists, do whatever is required
endif

Typausrichtung

Die meisten Plattformen können auf einige Datentypen nicht an beliebiger Adresse zugreifen. Zum Beispiel ist es üblich, dass ein char sich an jeder beliebigen Adresse befinden kann, ein 32-Bit-Integer jedoch nur an Adressen, die durch vier teilbar sind. Die Bestimmung der Ausrichtung von Datentypen ist einfach.

int_alignment = compiler.alignment('int') # Will most likely contain the value 4.

Hat Argument

Diese Methode testet, ob der Compiler ein bestimmtes Kommandozeilenargument unterstützt. Dies wird durch Kompilieren einer kleinen Datei mit dem gegebenen Argument implementiert.

has_special_flags = compiler.has_argument('-Wspecialthing')

Hinweis: Einige Compiler schlucken lautlos Kommandozeilenargumente, die sie nicht verstehen. Daher kann dieser Test nicht zu 100 % zuverlässig gemacht werden.

Die Ergebnisse der Suche sind