Meson Häufig gestellte Fragen
Siehe auch Wie mache ich X mit Meson.
Warum heißt es Meson?
Als der Name ursprünglich gewählt wurde, gab es zwei Haupteinschränkungen: es durfte weder ein Debian-Paket noch ein Sourceforge-Projekt mit diesem Namen existieren. Dies schloss dutzende potenzieller Projektnamen aus. Irgendwann wurde der Name Gluon in Betracht gezogen. Gluonen sind Elementarteilchen, die Protonen und Neutronen zusammenhalten, ähnlich wie die Aufgabe eines Build-Systems darin besteht, Quellcode-Teile und einen Compiler zu nehmen und sie zu einem vollständigen Ganzen zu verbinden.
Leider war auch dieser Name bereits vergeben. Dann wurden die übrigen subatomaren Teilchen untersucht und Meson wurde als verfügbar befunden.
Was ist der richtige Weg, Threads (wie pthreads) zu verwenden?
thread_dep = dependency('threads')
Dies richtet alles für Sie ein. Leute, die von Autotools oder CMake kommen, wollen dies tun, indem sie manuell nach libpthread.so suchen. Tun Sie das nicht, es gibt knifflige Randfälle, insbesondere beim Cross-Kompilieren.
Wie verwende ich Meson auf einem Host, auf dem es nicht in den Systempaketen verfügbar ist?
Seit Version 0.29.0 ist Meson über den Python Package Index verfügbar, daher ist die Installation einfach eine Frage der Ausführung dieses Befehls
$ pip3 install <your options here> meson
Wenn Sie keinen Zugriff auf PyPI haben, ist das auch kein Problem. Meson wurde so konzipiert, dass es leicht aus einem extrahierten Quell-Tarball oder sogar einem Git-Checkout ausgeführt werden kann. Zuerst müssen Sie Meson herunterladen. Verwenden Sie dann diesen Befehl, um Ihr Build einzurichten, anstelle von einfachem meson.
$ /path/to/meson.py <options>
Danach müssen Sie sich nicht mehr um die Aufrufe von Meson kümmern. Es merkt sich, wo es ursprünglich aufgerufen wurde, und ruft sich selbst entsprechend auf. Als Benutzer müssen Sie nur noch in Ihr Build-Verzeichnis cd und meson compile aufrufen.
Warum kann ich keine Zieldateien mit einem Wildcard angeben?
Anstatt Dateien explizit anzugeben, scheinen die Leute dies tun zu wollen
executable('myprog', sources : '*.cpp') # This does NOT work!
Meson unterstützt diese Syntax nicht, und der Grund dafür ist einfach. Dies kann weder zuverlässig noch schnell gemacht werden. Mit zuverlässig meinen wir, dass Meson erkennen sollte, wenn der Benutzer eine neue Quelldatei zum Unterverzeichnis hinzufügt, und diese automatisch zum Build machen sollte.
Eine der Hauptanforderungen von Meson ist, dass es schnell sein muss. Das bedeutet, dass ein No-Op-Build in einem Baum mit 10.000 Quelldateien nicht länger als einen Bruchteil einer Sekunde dauern darf. Dies ist nur möglich, weil Meson die genaue Liste der zu prüfenden Dateien kennt. Wenn ein Ziel als Wildcard-Glob angegeben ist, ist dies nicht mehr möglich. Meson müsste den Glob jedes Mal neu auswerten und die erzeugte Dateiliste mit der vorherigen Liste vergleichen. Das bedeutet, den gesamten Quellcodebaum zu inspizieren (da das Glob-Muster src/\*/\*/\*/\*.cpp oder etwas Ähnliches sein könnte). Dies ist nicht effizient zu tun.
Das Haupt-Backend von Meson ist Ninja, das aus den gleichen Gründen auch keine Wildcard-Übereinstimmungen unterstützt.
Aus diesem Grund müssen alle Quelldateien explizit angegeben werden.
Aber ich möchte wirklich Wildcards verwenden!
Wenn der Kompromiss zwischen Zuverlässigkeit und Komfort für Sie akzeptabel ist, dann bietet Meson Ihnen alle notwendigen Werkzeuge für Wildcard-Globbing. Sie dürfen während der Konfiguration beliebige Befehle ausführen. Zuerst müssen Sie ein Skript schreiben, das die zu kompilierenden Dateien findet. Hier ist ein einfaches Shell-Skript, das alle .c-Dateien im aktuellen Verzeichnis schreibt, eine pro Zeile.
#!/bin/sh
for i in *.c; do
echo $i
done
Dann müssen Sie dieses Skript in Ihrer Meson-Datei ausführen, die Ausgabe in ein String-Array konvertieren und das Ergebnis in einem Ziel verwenden.
c = run_command('grabber.sh', check: true)
sources = c.stdout().strip().split('\n')
e = executable('prog', sources)
Das Skript kann jede ausführbare Datei sein, also kann es in Shell, Python, Lua, Perl oder was auch immer Sie wünschen geschrieben werden.
Wie bereits erwähnt, besteht der Kompromiss darin, dass das Hinzufügen neuer Dateien zum Quellverzeichnis sie nicht automatisch zum Build hinzufügt. Um sie hinzuzufügen, müssen Sie Meson anweisen, sich neu zu initialisieren. Der einfachste Weg ist, die Datei meson.build in Ihrem Quell-Root zu berühren. Dann konfiguriert sich Meson beim nächsten Ausführen des Build-Befehls neu. Fortgeschrittene Benutzer können sogar ein kleines Hintergrundskript schreiben, das eine Dateisystemereignis-Warteschlange wie inotify verwendet, um dies automatisch zu tun.
Soll ich subdir oder subproject verwenden?
Die Antwort ist fast immer subdir. Subprojects existieren für einen sehr spezifischen Anwendungsfall: das Einbetten externer Abhängigkeiten in Ihren Build-Prozess. Nehmen wir zum Beispiel an, wir schreiben ein Spiel und möchten SDL verwenden. Nehmen wir weiter an, SDL kommt mit einer Meson-Build-Definition. Nehmen wir noch weiter an, wir wollen keine vorgefertigten Binärdateien verwenden, sondern SDL selbst kompilieren.
In diesem Fall würden Sie subproject verwenden. Der Weg dorthin wäre, den Quellcode von SDL zu holen und ihn in Ihren eigenen Quellbaum zu legen. Dann würden Sie sdl = subproject('sdl') tun, was Meson veranlassen würde, SDL als Teil Ihres Builds zu erstellen und Ihnen dann erlauben würde, dagegen zu linken oder was auch immer Sie bevorzugen.
Für alle anderen Verwendungszwecke würden Sie subdir verwenden. Als Beispiel, wenn Sie eine gemeinsam genutzte Bibliothek in einem Verzeichnis erstellen und Tests dagegen in einem anderen Verzeichnis linken möchten, würden Sie etwas wie folgt tun
project('simple', 'c')
subdir('src') # library is built here
subdir('tests') # test binaries would link against the library here
Warum gibt es kein Make-Backend?
Weil Make langsam ist. Dies ist kein Implementierungsproblem, Make kann einfach nicht schnell gemacht werden. Für weitere Informationen empfehlen wir Ihnen, diesen Beitrag von Evan Martin, dem Autor von Ninja, zu lesen. Makefiles haben auch eine Syntax, die sehr unangenehm zu schreiben ist, was sie zu einer großen Wartungslast macht.
Der einzige Grund, warum man Make anstelle von Ninja verwenden würde, ist die Arbeit auf einer Plattform, die keinen Ninja-Port hat. Selbst in diesem Fall ist es um Größenordnungen weniger Arbeit, Ninja zu portieren, als ein Make-Backend für Meson zu schreiben.
Benutzen Sie einfach Ninja, Sie werden glücklicher sein. Ich garantiere es Ihnen.
Warum ist Meson nicht einfach ein Python-Modul, so dass ich meine Build-Einrichtung in Python codieren könnte?
Eine verwandte Frage dazu ist: *Warum ist Mesons Konfigurationssprache nicht Turing-vollständig?*
Dafür gibt es viele gute Gründe, von denen die meisten auf dieser Webseite zusammengefasst sind: Gegen die Verwendung von Programmiersprachen in Konfigurationsdateien.
Zusätzlich zu diesen Gründen macht das Nicht-Exponieren von Python oder jeder anderen "echten" Programmiersprache es möglich, die Implementierung von Meson in eine andere Sprache zu portieren. Dies könnte notwendig werden, wenn zum Beispiel Python zu einem Leistungsengpass wird. Dies ist ein tatsächliches Problem, das für GNU Autotools und SCons Komplikationen verursacht hat.
Wie mache ich das Äquivalent von Libtools export-symbol und export-regex?
Entweder durch die Verwendung von GCC-Symbol-Sichtbarkeit oder durch das Schreiben eines Linker-Skripts. Dies hat den zusätzlichen Vorteil, dass Ihre Symboldefinitionen in einer eigenständigen Datei liegen, anstatt in Ihren Build-Definitionen vergraben zu sein. Ein Beispiel finden Sie hier.
Mein Projekt funktioniert unter Linux und MinGW einwandfrei, schlägt aber mit MSVC wegen einer fehlenden .lib-Datei (fatal error LNK1181) fehl. Warum?
Mit GCC werden alle Symbole in Shared Libraries automatisch exportiert, es sei denn, Sie geben etwas anderes an. Mit MSVC werden standardmäßig keine Symbole exportiert. Wenn Ihre Shared Library keine Symbole exportiert, erstellt MSVC lautlos keine Import-Bibliotheksdatei, was zu Fehlern führt. Die Lösung besteht darin, Symbol-Sichtbarkeitsdefinitionen wie im GCC-Wiki angegeben hinzuzufügen.
Ich habe einige Compiler-Flags hinzugefügt und jetzt schlägt der Build mit seltsamen Fehlern fehl. Was passiert?
Sie haben wahrscheinlich das Äquivalent zu diesem getan
executable('foobar', ...
c_args : '-some_arg -other_arg')
Meson ist *explizit*. In diesem speziellen Fall werden Ihre Strings nicht automatisch nach Leerzeichen aufgeteilt, sondern stattdessen als Ganzes übernommen und extra hart daran gearbeitet, sie unverändert an den Compiler zu übergeben, einschließlich der korrekten Anführungszeichen bei Shell-Aufrufen. Dies ist zwingend erforderlich, damit z. B. Dateien mit Leerzeichen einwandfrei funktionieren. Um mehrere Kommandozeilenargumente zu übergeben, müssen Sie sie explizit in ein Array wie dieses einfügen
executable('foobar', ...
c_args : ['-some_arg', '-other_arg'])
Warum werden Änderungen an Standard-Projektoptionen ignoriert?
Sie hatten wahrscheinlich ein Projekt, das ungefähr so aussah
project('foobar', 'cpp')
Dies ist standardmäßig c++11 für GCC-Compiler. Angenommen, Sie möchten stattdessen c++14 verwenden, also ändern Sie die Definition zu diesem
project('foobar', 'cpp', default_options : ['cpp_std=c++14'])
Aber wenn Sie neu kompilieren, wird immer noch c++11 verwendet. Der Grund dafür ist, dass Standardoptionen nur berücksichtigt werden, wenn Sie ein Build-Verzeichnis zum allerersten Mal einrichten. Danach gilt die Einstellung als gesetzt und der Standardwert wird somit ignoriert. Um ein vorhandenes Build-Verzeichnis auf c++14 zu ändern, konfigurieren Sie entweder Ihr Build-Verzeichnis mit meson configure neu oder löschen Sie das Build-Verzeichnis und erstellen Sie es neu.
Der Grund, warum wir den Optionswert nicht automatisch ändern, wenn der Standardwert geändert wird, ist, dass es unmöglich ist, dies zuverlässig zu tun. Die eigentliche Frage, die wir lösen müssen, ist: "Wenn der Wert der Option foo ist und der Standardwert bar ist, sollten wir den Optionswert auch auf bar ändern". Es gibt viele Möglichkeiten
-
Wenn der Benutzer den Wert selbst vom Standardwert geändert hat, dann dürfen wir ihn nicht zurückändern
-
Wenn der Benutzer den Wert nicht geändert hat, aber den Standardwert ändert, dann scheint die Prämisse dieses Abschnitts darauf hinzudeuten, dass der Wert geändert werden sollte
-
Angenommen, der Benutzer ändert den Wert vom Standardwert zu foo, dann zurück zu bar und dann den Standardwert zu bar, dann ist der richtige Schritt an sich mehrdeutig
Um die letztere Frage zu lösen, müssten wir nicht nur den aktuellen und den alten Wert speichern, sondern auch all die Male, die der Benutzer den Wert geändert hat und von welchem Wert zu welchem anderen Wert. Da die Leute ihre eigenen Handlungen nicht so weit zurück erinnern, wäre das Wechseln zwischen Zuständen basierend auf einer langen Historie verwirrend.
Aus diesem Grund tun wir das Einfache und Verständliche: Standardwerte sind nur Standardwerte und werden niemals den Wert einer Option beeinflussen, sobald sie gesetzt ist.
Lädt Wrap Quellen hinter meinem Rücken herunter?
Das tut es nicht. Damit Meson beim Erstellen etwas aus dem Netz herunterladen kann, müssen zwei Bedingungen erfüllt sein.
Zuerst muss sich eine .wrap-Datei mit einer Download-URL im Verzeichnis subprojects befinden. Wenn keine vorhanden ist, wird Meson nichts herunterladen.
Die zweite Anforderung ist, dass eine explizite Subproject-Aufrufung in Ihren meson.build-Dateien vorhanden sein muss. Entweder subproject('foobar') oder dependency('foobar', fallback : ['foobar', 'foo_dep']). Wenn diese Deklarationen entweder in keiner Build-Datei vorhanden sind oder nicht aufgerufen werden (z. B. wegen if/else), wird nichts heruntergeladen.
Wenn Ihnen das nicht ausreicht, gibt es seit Version 0.40.0 eine Option namens wrap-mode, mit der Sie Wrap-Downloads mit --wrap-mode=nodownload vollständig deaktivieren können. Sie können auch Dependency-Fallbacks mit --wrap-mode=nofallback vollständig deaktivieren, was auch die Option nodownload impliziert.
Wenn Sie andererseits möchten, dass Meson immer den Fallback für Abhängigkeiten verwendet, auch wenn eine externe Abhängigkeit existiert und die Versionsanforderungen erfüllen könnte, um zum Beispiel sicherzustellen, dass Ihr Projekt erstellt wird, wenn Fallbacks verwendet werden, können Sie seit 0.46.0 --wrap-mode=forcefallback verwenden.
Warum ist Meson in Python und nicht in [Programmiersprache X] implementiert?
Weil Build-Systeme in besonderer Weise einzigartig sind, wie normale Anwendungen es nicht sind.
Vielleicht ist die größte Einschränkung, dass Meson Software auf den untersten Ebenen des Betriebssystems verwendet, um Software zu erstellen, und Teil des Kern-Bootstraps für neue Systeme ist. Immer wenn Unterstützung für eine neue CPU-Architektur hinzugefügt wird, muss Meson auf dem System laufen, bevor Software, die es verwendet, nativ kompiliert werden kann. Diese Anforderung fügt zwei harte Einschränkungen hinzu.
Die erste ist, dass Meson die minimale Anzahl von Abhängigkeiten haben muss, da diese alle während des Bootstraps gebaut werden müssen, damit Meson funktioniert.
Die zweite ist, dass Meson alle CPU-Architekturen unterstützen muss, sowohl bestehende als auch zukünftige. Als Beispiel haben viele neue Programmiersprachen nur einen LLVM-basierten Compiler verfügbar. LLVM hat eine begrenzte CPU-Unterstützung im Vergleich zu z. B. GCC, und daher würde das Bootstrapping von Meson auf solchen Plattformen zuerst das Hinzufügen neuer Prozessorunterstützung zu LLVM erfordern. Dies ist in den meisten Fällen nicht machbar.
Eine weitere Einschränkung ist, dass wir möchten, dass Entwickler auf so vielen Plattformen wie möglich zu Meson-Entwicklung beitragen, indem sie die Standardwerkzeuge ihres Betriebssystems verwenden. In der Praxis bedeutet dies, dass Windows-Entwickler nichts anderes als Visual Studio verwenden können sollten.
Zum Zeitpunkt der Erstellung (April 2018) gibt es nur drei Sprachen, die diese Anforderungen erfüllen könnten
- C
- C++
- Python
Von diesen haben wir Python gewählt, weil es am besten zu unseren Bedürfnissen passt.
Aber ich möchte wirklich eine Version von Meson, die kein Python verwendet!
Ökosystem-Diversität ist gut. Wir ermutigen interessierte Benutzer, diese konkurrierende Implementierung von Meson selbst zu schreiben. Seit September 2021 gibt es 3 Projekte, die versuchen, genau das zu tun
Ich habe eine proprietäre Compiler-Toolchain X, die nicht mit Meson funktioniert. Wie kann ich sie zum Laufen bringen?
Meson muss mehrere Details über jeden Compiler kennen, um Code damit zu kompilieren. Dazu gehören Dinge wie, welche Compiler-Flags für jede Option verwendet werden sollen und wie der Compiler aus seiner Ausgabe erkannt werden kann. Diese Informationen können nicht über eine Konfigurationsdatei eingegeben werden, stattdessen erfordert es Änderungen am Quellcode von Meson, die an das Meson-Master-Repository übermittelt werden müssen. Theoretisch können Sie Ihre eigene geforkte Version mit benutzerdefinierten Patches ausführen, aber das ist keine gute Nutzung Ihrer Zeit. Bitte reichen Sie den Code upstream ein, damit jeder die Toolchain nutzen kann.
Die Schritte zum Hinzufügen eines neuen Compilers für eine vorhandene Sprache sind ungefähr die folgenden. Zur Vereinfachung nehmen wir einen C-Compiler an.
-
Erstellen Sie eine neue Klasse mit einem geeigneten Namen in
mesonbuild/compilers/c.py. Schauen Sie sich die Methoden an, die andere Compiler für dieselbe Sprache haben, und duplizieren Sie, was sie tun. -
Wenn der Compiler nur für Cross-Kompilierung verwendet werden kann, stellen Sie sicher, dass er als solcher gekennzeichnet ist (siehe Beispiele für vorhandene Compiler-Klassen).
-
Fügen Sie Erkennungslogik zu
mesonbuild/environment.pyhinzu, suchen Sie nach einer Methode namensdetect_c_compiler. -
Führen Sie die Testsuite aus und beheben Sie Probleme, bis die Tests erfolgreich sind.
-
Reichen Sie einen Pull-Request ein, fügen Sie das Ergebnis der Testsuite zu Ihrem MR hinzu (ein Link zu einer vorhandenen Seite ist in Ordnung).
-
Wenn der Compiler frei verfügbar ist, ziehen Sie in Betracht, ihn zum CI-System hinzuzufügen.
Warum gibt die Erstellung meines Projekts mit MSVC statische Bibliotheken namens libfoo.a aus?
Die Namenskonvention für statische Bibliotheken unter Windows ist normalerweise foo.lib. Leider werden auch Importbibliotheken foo.lib genannt.
Dies führt zu Namenskollisionen mit dem Standardbibliothekstyp, bei dem wir sowohl freigegebene als auch statische Bibliotheken erstellen, und auch zu Kollisionen bei der Installation, da alle Bibliotheken standardmäßig im selben Verzeichnis installiert werden.
Um dies zu lösen, haben wir uns entschieden, standardmäßig statische Bibliotheken der Form libfoo.a zu erstellen, wenn mit MSVC erstellt wird. Dies hat folgende Vorteile
- Namenskollisionen werden vollständig vermieden.
- Das Format für MSVC-Statikbibliotheken ist
ar, was dasselbe wie das GNU-Statikbibliotheksformat ist, daher ist die Verwendung dieser Erweiterung semantisch korrekt. - Das Dateiformat für statische Bibliotheken ist jetzt auf allen Plattformen und mit allen Toolchains gleich.
- Sowohl Clang- als auch GNU-Compiler können nach
libfoo.asuchen, wenn sie eine Bibliothek als-lfooangeben. Dies funktioniert nicht für alternative Benennungsschemata für statische Bibliotheken wielibfoo.lib. - Da
-lfoosofort funktioniert, funktionieren Pkgconfig-Dateien für Projekte, die mit MSVC, GCC und Clang unter Windows erstellt wurden, korrekt. - MSVC hat keine Argumente zur Suche nach Bibliotheksdateinamen, und es ist ihm egal, welche Erweiterung sie hat, so dass die Angabe von
libfoo.aanstelle vonfoo.libden Arbeitsablauf nicht ändert und eine Verbesserung darstellt, da sie weniger mehrdeutig ist. - Projekte, die mit dem MinGW-Compiler erstellt werden, sind vollständig mit MSVC kompatibel, solange sie dieselbe CRT verwenden (z. B. UCRT mit MSYS2). Diese Projekte nennen ihre statischen Bibliotheken ebenfalls
libfoo.a.
Wenn Sie aus irgendeinem Grund wirklich möchten, dass Ihr Projekt statische Bibliotheken der Form foo.lib ausgibt, wenn mit MSVC erstellt wird, können Sie das Schlüsselwortargument name_prefix: auf '' und das Schlüsselwortargument name_suffix: auf 'lib' setzen. Um das Standardverhalten für jedes zu erhalten, können Sie entweder das Schlüsselwortargument nicht angeben oder [] (ein leeres Array) übergeben.
Muss ich meine Header wie bei Autotools zur Quellenliste hinzufügen?
Autotools verlangt, dass Sie private und öffentliche Header zur Quellenliste hinzufügen, damit es weiß, welche Dateien in das von make dist generierte Tarball aufgenommen werden sollen. Mesons dist-Befehl sammelt einfach alles, was in Ihrem Git/Hg-Repository committet wurde, und fügt es dem Tarball hinzu, sodass das Hinzufügen von Headern zur Quellenliste zwecklos ist.
Meson verwendet Ninja, das Compiler-Abhängigkeitsinformationen verwendet, um Abhängigkeiten zwischen C-Quellen und Headern automatisch zu ermitteln, sodass es Dinge korrekt neu erstellt, wenn sich ein Header ändert.
Die einzige Ausnahme hierbei sind generierte Header, für die Sie Abhängigkeiten korrekt deklarieren müssen.
Wenn Sie aus irgendeinem Grund Nicht-generierte Header zur Quellenliste eines Ziels hinzufügen, wird Meson sie einfach ignorieren.
Wie teile ich Meson mit, dass meine Quellen generierte Header verwenden?
Nehmen wir an, Sie verwenden ein custom_target(), um die Header zu generieren, und binden sie dann in Ihrem C-Code ein. Hier erfahren Sie, wie Sie sicherstellen, dass Meson die Header generiert, bevor es versucht, Quellen im Build-Ziel zu kompilieren
libfoo_gen_headers = custom_target('gen-headers', ..., output: 'foo-gen.h')
libfoo_sources = files('foo-utils.c', 'foo-lib.c')
# Add generated headers to the list of sources for the build target
libfoo = library('foo', sources: [libfoo_sources + libfoo_gen_headers])
Nehmen wir nun an, Sie haben ein neues Ziel, das gegen libfoo linkt
libbar_sources = files('bar-lib.c')
libbar = library('bar', sources: libbar_sources, link_with: libfoo)
Dies fügt eine Linkzeit-Abhängigkeit zwischen den beiden Zielen hinzu, aber beachten Sie, dass die Quellen der Ziele keine Kompilierzeit-Abhängigkeiten haben und in beliebiger Reihenfolge erstellt werden können; was die Parallelität verbessert und die Builds beschleunigt.
Wenn die Quellen in libbar auch foo-gen.h verwenden, ist das eine Kompilierzeit-Abhängigkeit, und Sie müssen libfoo_gen_headers auch für libbar zu sources: hinzufügen
libbar_sources = files('bar-lib.c')
libbar = library('bar', sources: libbar_sources + libfoo_gen_headers, link_with: libfoo)
Alternativ, wenn Sie mehrere Bibliotheken mit Quellen haben, die gegen eine Bibliothek linken und auch deren generierte Header verwenden, ist dieser Code äquivalent zu oben
# Add generated headers to the list of sources for the build target
libfoo = library('foo', sources: libfoo_sources + libfoo_gen_headers)
# Declare a dependency that will add the generated headers to sources
libfoo_dep = declare_dependency(link_with: libfoo, sources: libfoo_gen_headers)
...
libbar = library('bar', sources: libbar_sources, dependencies: libfoo_dep)
Hinweis: Sie sollten nur Header zu sources: hinzufügen, während Sie eine Abhängigkeit deklarieren. Wenn Ihr benutzerdefiniertes Ziel sowohl Quellen als auch Header ausgibt, können Sie die Indexnotation verwenden, um nur den/die Header zu erhalten
libfoo_gen_sources = custom_target('gen-headers', ..., output: ['foo-gen.h', 'foo-gen.c'])
libfoo_gen_headers = libfoo_gen_sources[0]
# Add static and generated sources to the target
libfoo = library('foo', sources: libfoo_sources + libfoo_gen_sources)
# Declare a dependency that will add the generated *headers* to sources
libfoo_dep = declare_dependency(link_with: libfoo, sources: libfoo_gen_headers)
...
libbar = library('bar', sources: libbar_sources, dependencies: libfoo_dep)
Ein gutes Beispiel für einen Generator, der sowohl Quellen als auch Header ausgibt, ist gnome.mkenums().
Wie deaktiviere ich Exceptions und RTTI in meinem C++-Projekt?
Mit den Optionen cpp_eh und cpp_rtti. Ein typischer Aufruf würde wie folgt aussehen
meson -Dcpp_eh=none -Dcpp_rtti=false <other options>
Die RTTI-Option ist erst seit Meson Version 0.53.0 verfügbar.
Sollte ich in meinen Build-Dateien nach buildtype oder einzelnen Optionen wie debug suchen?
Das hängt stark davon ab, was Sie tatsächlich erreichen möchten. Die Option buildtype ist dafür gedacht, die Absicht des aktuellen Builds zu beschreiben. Das heißt, wofür er verwendet werden wird. Einzelne Optionen dienen dazu, den genauen Zustand zu bestimmen. Dies wird anhand einiger Beispiele deutlicher.
Angenommen, Sie haben eine Quelldatei, von der bekannt ist, dass sie bei der Verwendung von -O3 falsch kompiliert und eine Umgehung erfordert. Dann würden Sie so etwas schreiben
if get_option('optimization') == '3'
add_project_arguments('-DOPTIMIZATION_WORKAROUND', ...)
endif
Andererseits, wenn Ihr Projekt zusätzliche Protokollierung und Sanity Checks hat, die Sie während der täglichen Entwicklungsarbeit (die den debug Build-Typ verwendet) aktivieren möchten, würden Sie stattdessen Folgendes tun
if get_option('buildtype') == 'debug'
add_project_arguments('-DENABLE_EXTRA_CHECKS', ...)
endif
Auf diese Weise werden die zusätzlichen Optionen während der Entwicklung automatisch verwendet, aber nicht in Release-Builds kompiliert. Beachten Sie, dass (seit Meson 0.57.0) Sie die Optimierung in Ihren Debug-Builds beispielsweise auf 2 setzen können, wenn Sie möchten. Wenn Sie versuchen würden, dieses Flag basierend auf dem Optimierungsgrad festzulegen, würde dies in diesem Fall fehlschlagen.
Wie verwende ich eine Bibliothek, bevor ich sie deklariere?
Dies ist gültiger (und guter) Code
libA = library('libA', 'fileA.cpp', link_with : [])
libB = library('libB', 'fileB.cpp', link_with : [libA])
Aber es gibt derzeit keine Möglichkeit, so etwas zum Laufen zu bringen
libB = library('libB', 'fileB.cpp', link_with : [libA])
libA = library('libA', 'fileA.cpp', link_with : [])
Das bedeutet, dass Sie Ihre library(...)-Aufrufe in der Reihenfolge schreiben MÜSSEN, in der die Abhängigkeiten fließen. Während es Ideen gibt, willkürliche Reihenfolgen zu ermöglichen, wurden diese abgelehnt, da die Neuanordnung der library(...)-Aufrufe als der "richtige" Weg angesehen wurde. Siehe hier für die Diskussion.
Warum hat meson keine benutzerdefinierten Funktionen/Makros?
Die tl;dr-Antwort darauf ist, dass Mesons Design darauf ausgerichtet ist, spezifische Probleme zu lösen, anstatt eine universelle Sprache zur Erstellung komplexer Code-Lösungen in Build-Dateien bereitzustellen. Build-Systeme sollten schnell zu schreiben und schnell zu verstehen sein, Funktionen trüben diese Einfachheit.
Die lange Antwort ist zweigeteilt
Erstens zielt Meson darauf ab, eine reichhaltige Auswahl an Werkzeugen bereitzustellen, die häufige Probleme einfach "out of the box" lösen. Dies ähnelt der "batteries included"-Mentalität von Python. Indem wir Werkzeuge bereitstellen, die gängige Probleme auf die einfachste Weise in Meson lösen, lösen wir dieses Problem für alle, anstatt jeden zu zwingen, dieses Problem immer wieder selbst zu lösen, oft schlecht. Ein Beispiel hierfür sind Mesons Dependency-Wrapper um verschiedene Config-Tool-Executables (sdl-config, llvm-config, etc.). In anderen Build-Systemen schreibt jeder Benutzer dieser Abhängigkeit einen Wrapper und kümmert sich um die Randfälle (oder auch nicht, wie oft der Fall ist), in Meson kümmern wir uns intern darum, jeder erhält Fehlerbehebungen und die Randfälle werden für alle ausgebügelt. Die Bereitstellung von benutzerdefinierten Funktionen oder Makros widerspricht diesem Designziel direkt.
Zweitens machen Funktionen und Makros das Build-System schwieriger zu durchschauen. Wenn Sie auf einen Funktionsaufruf stoßen, können Sie im Handbuch nachsehen, um diese Funktion und ihre Signatur zu finden. Anstatt frustrierende Stunden damit zu verbringen, einen Teil m4 zu interpretieren oder langen Include-Pfaden zu folgen, um herauszufinden, was function1 (die function2 aufruft, die function3 aufruft, ad infinitum) tut, wissen Sie, was das Build-System tut. Es sei denn, Sie entwickeln aktiv Meson selbst, es ist nur ein Werkzeug zur Orchestrierung des Builds, um das, was Sie eigentlich interessiert. Wir möchten, dass Sie sich so wenig wie möglich um Build-Systeme kümmern, damit Sie mehr Zeit für Ihren Code aufwenden können.
Oft werden benutzerdefinierte Funktionen aufgrund fehlender Schleifen oder weil Schleifen in der Sprache mühsam zu verwenden sind, verwendet. Meson hat sowohl Arrays/Listen als auch Hashes/Dicts nativ. Vergleichen Sie den folgenden Pseudocode
func(name, sources, extra_args)
executable(
name,
sources,
c_args : extra_args
)
endfunc
func(exe1, ['1.c', 'common.c'], [])
func(exe2, ['2.c', 'common.c'], [])
func(exe2_a, ['2.c', 'common.c'], ['-arg'])
foreach e : [['1', '1.c', []],
['2', '2.c', []],
['2', '2.c', ['-arg']]]
executable(
'exe' + e[0],
e[1],
c_args : e[2],
)
endforeach
Die Schleife ist sowohl weniger Code als auch viel einfacher zu verstehen als die Funktionsversion, insbesondere wenn die Funktion in einer separaten Datei leben würde, wie es in anderen beliebten Build-Systemen üblich ist.
Build-System-DSLs werden auch tendenziell schlecht als generische Programmiersprachen durchdacht. Meson versucht, die Verwendung externer Skripte oder Programme zur Bewältigung komplexer Probleme zu vereinfachen. Auch wenn man Build-Logik nicht immer in eine Skriptsprache (oder kompilierte Sprache) umwandeln kann, ist dies oft eine bessere Lösung, wenn es möglich ist. Externe Sprachen sind in der Regel gut durchdacht und getestet, entwickeln sich im Allgemeinen nicht zurück und Benutzer haben wahrscheinlich Domänenwissen darüber. Sie haben auch tendenziell bessere Werkzeuge (wie Autovervollständigung, Linting, Testlösungen), was sie auf lange Sicht zu einem geringeren Wartungsaufwand macht.
Warum wirken sich die Argumente, die an add_project_link_arguments übergeben werden, nicht aus?
Angesichts eines Codes wie diesem
add_project_link_arguments(['-Wl,-foo'], language : ['c'])
executable(
'main',
'main.c',
'helper.cpp',
)
Man könnte überrascht sein, dass -Wl,-foo nicht auf die Verknüpfung der main-Executable angewendet wird. Hier arbeitet Meson wie erwartet, da Meson versucht, den richtigen Linker automatisch zu ermitteln. Dies vermeidet Situationen wie in Autotools, wo Dummy-C++-Quellen zu einigen Kompilierungszielen hinzugefügt werden müssen, um die richtige Verknüpfung zu erhalten. Im obigen Fall wird also der C++-Linker anstelle des C-Linkers verwendet, da helper.cpp wahrscheinlich nicht mit dem C-Linker verknüpft werden kann.
Generell ist der beste Weg, dies zu lösen, die cpp-Sprache zum Aufruf von add_project_link_arguments hinzuzufügen.
add_project_link_arguments(['-Wl,-foo'], language : ['c', 'cpp'])
executable(
'main',
'main.c',
'helper.cpp',
)
Um dennoch die Verwendung des C-Linkers zu erzwingen, kann das Schlüsselwortargument link_language verwendet werden. Beachten Sie, dass dies zu einem Kompilierungsfehler führen kann, wenn Symbole vorhanden sind, die der C-Linker nicht auflösen kann.
add_project_link_arguments(['-Wl,-foo'], language : ['c'])
executable(
'main',
'main.c',
'helper.cpp',
link_language : 'c',
)
Wie ignoriere ich das Build-Verzeichnis in meinem VCS?
Das müssen Sie nicht, vorausgesetzt, Sie verwenden Git oder Mercurial! Meson >=0.57.0 erstellt eine .gitignore und eine .hgignore Datei für Sie, in jedem Build-Verzeichnis. Es globt "*", da alle generierten Dateien nicht in Git eingecheckt werden sollten.
Benutzer älterer Meson-Versionen müssen möglicherweise Ignore-Dateien selbst einrichten.
Wie füge ich Präprozessor-Defines zu einem Ziel hinzu?
Fügen Sie einfach -DFOO zu c_args oder cpp_args hinzu. Dies funktioniert für alle bekannten Compiler.
mylib = library('mylib', 'mysource.c', c_args: ['-DFOO'])
Obwohl die MSVC-Dokumentation /D für Präprozessor-Defines verwendet, akzeptiert ihre Kommandozeilensyntax - anstelle von /. Es ist nicht notwendig, Präprozessor-Defines in Meson speziell zu behandeln (GH-6269).
Die Ergebnisse der Suche sind