Unterprojekte

Einige Plattformen stellen kein natives Paketverwaltungssystem bereit. In diesen Fällen ist es üblich, alle Drittanbieter-Bibliotheken in Ihrem Quellcodebaum zu bündeln. Dies wird normalerweise missbilligt, da es schwierig ist, solche Projekte in z. B. Linux-Distributionen zu integrieren, die gebündelte Bibliotheken verbieten.

Meson versucht, dieses Problem zu lösen, indem es extrem einfach ist, beides gleichzeitig bereitzustellen. Meson ermöglicht es Ihnen, jedes andere Meson-Projekt zu übernehmen und es zu einem Teil Ihrer Build-Umgebung zu machen, ohne (im Idealfall) Änderungen an seiner Meson-Konfiguration vorzunehmen. Es wird zu einem transparenten Teil des Projekts.

Es ist zu beachten, dass dies nur für Unterprojekte garantiert funktioniert, die mit Meson erstellt werden. Der Grund dafür ist die einfache Tatsache, dass es keine Möglichkeit gibt, dies zuverlässig mit gemischten Build-Systemen zu tun. Aus diesem Grund werden hier nur Meson-Unterprojekte beschrieben. CMake-basierte Unterprojekte werden ebenfalls unterstützt, aber die Funktionalität ist nicht garantiert.

Beispiel für ein Unterprojekt

Normalerweise bestehen Abhängigkeiten aus einigen Header-Dateien und einer zu verknüpfenden Bibliothek. Um diese interne Abhängigkeit zu deklarieren, verwenden Sie die Funktion declare_dependency.

Nehmen wir als Beispiel ein einfaches Projekt an, das eine Shared-Bibliothek bereitstellt. Seine meson.build würde wie folgt aussehen.

project('libsimple', 'c')

inc = include_directories('include')
libsimple = shared_library('simple',
  'simple.c',
  include_directories : inc,
  install : true)

libsimple_dep = declare_dependency(include_directories : inc,
  link_with : libsimple)

Namenskonvention für Abhängigkeitsvariablen

Idealerweise sollte der Name der Abhängigkeitsvariable die Form <projektname>_dep haben. Auf diese Weise kann sie verwendet werden, ohne die Build-Definitionen dieses Unterprojekts überhaupt zu betrachten.

In Fällen, in denen mehrere Abhängigkeiten deklariert werden müssen, sollte die Standardabhängigkeit als <projektname>_dep (z. B. gtest_dep) benannt werden, und andere können die Form <projektname>_<anderername>_<name>_dep haben (z. B. gtest_main_dep - gtest mit main-Funktion).

Es kann Ausnahmen von diesen Regeln geben, bei denen der gesunde Menschenverstand angewendet werden sollte.

Hinzufügen von Variablen zur Abhängigkeit

Neu ab 0.54.0

In einigen Fällen kann ein Projekt spezielle Variablen über pkg-config oder cmake definieren, die ein Aufrufer kennen muss. Meson bietet eine Methode dependency.get_variable, um zu verbergen, welche Art von Abhängigkeit bereitgestellt wird, und diese ist auch für Unterprojekte verfügbar. Verwenden Sie das Schlüsselwort variables, um ein Wörterbuch von Zeichenketten hinzuzufügen.

my_dep = declare_dependency(..., variables : {'var': 'value', 'number': '3'})

Welches ein anderes Projekt über

var = my_dep.get_variable(internal : 'var', cmake : 'CMAKE_VAR')

Die Werte des Wörterbuchs müssen Zeichenketten sein, da pkg-config und cmake Variablen als Zeichenketten zurückgeben.

Build-Optionen im Unterprojekt

Alle Meson-Funktionen des Unterprojekts, wie z. B. Projektoptionen, funktionieren weiterhin und können im Hauptprojekt eingestellt werden. Es gibt einige Einschränkungen, die wichtigste ist, dass globale Compiler-Argumente im Hauptprojekt gesetzt werden müssen, bevor das Unterprojekt aufgerufen wird. Unterprojekte dürfen keine globalen Argumente setzen, da dies über mehrere Unterprojekte hinweg nicht zuverlässig möglich ist. Um zu überprüfen, ob Sie als Unterprojekt laufen, verwenden Sie meson.is_subproject().

Verwendung eines Unterprojekts

Alle Unterprojekte müssen sich im Verzeichnis subprojects befinden. Das Verzeichnis subprojects muss sich auf der obersten Ebene Ihres Projekts befinden. Die Deklaration des Unterprojekts muss in Ihrer obersten meson.build erfolgen.

Ein einfaches Beispiel

Verwenden wir libsimple als Unterprojekt.

Erstellen Sie im obersten Verzeichnis Ihres Projekts ein Verzeichnis subprojects. Kopieren Sie dann libsimple in das Verzeichnis subprojects.

Die meson.build Ihres Projekts sollte wie folgt aussehen.

project('my_project', 'cpp')

libsimple_proj = subproject('libsimple')
libsimple_dep = libsimple_proj.get_variable('libsimple_dep')

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

Beachten Sie, dass das Unterprojekt-Objekt nicht als Abhängigkeit verwendet wird, sondern dass Sie die deklarierte Abhängigkeit daraus mit get_variable abrufen müssen, da ein Unterprojekt mehrere deklarierte Abhängigkeiten haben kann.

Umschalten zwischen Systembibliotheken und eingebetteten Quellen

Beim Erstellen von Distributionpaketen ist es sehr wichtig, dass Sie keine Quellen einbetten. Einige Distributionen haben eine Regel, die das Einbetten von Abhängigkeiten verbietet, sodass Ihr Projekt ohne diese baubar sein muss, sonst wird der Paketierer Sie hassen.

So verwenden Sie Systembibliotheken und greifen auf eingebettete Quellen zurück, wenn die Abhängigkeit nicht verfügbar ist.

project('my_project', 'cpp')

libsimple_dep = dependency('libsimple', required : false)

if not libsimple_dep.found()
  libsimple_proj = subproject('libsimple')
  libsimple_dep = libsimple_proj.get_variable('libsimple_dep')
endif

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

Da dies ein sehr häufiger Vorgang ist, bietet Meson eine Abkürzung für diesen Anwendungsfall.

dep = dependency('foo', fallback : ['subproject_name', 'variable_name'])

Das Schlüsselwortargument fallback nimmt zwei Elemente entgegen: den Namen des Unterprojekts und den Namen der Variable, die die Abhängigkeit enthält. Wenn Sie etwas Komplexeres tun müssen, z. B. mehrere verschiedene Variablen extrahieren, müssen Sie dies selbst mit der oben beschriebenen manuellen Methode tun.

Mit dieser Abkürzung würde die Build-Definition wie folgt aussehen.

project('my_project', 'cpp')

libsimple_dep = dependency('libsimple', fallback : ['libsimple', 'libsimple_dep'])

executable('my_project',
  'my_project.cpp',
  dependencies : libsimple_dep,
  install : true)

Sie können die Standard-Optionen des Unterprojekts ändern, indem Sie ein Schlüsselwortargument zur Invokation hinzufügen. Zum Beispiel, um den Standard-Bibliothekstyp zu ändern

libsimple_dep = dependency(
  'libsimple',
  fallback : ['libsimple', 'libsimple_dep'],
  default_options: ['default_library=static']
)

Mit dieser Einrichtung verwenden wir libsimple, wenn es vom System bereitgestellt wird, und ignorieren die Unterprojektoptionen vollständig (d. h. wir verknüpfen mit einer freigegebenen Systembibliothek). Wenn dies nicht der Fall ist, verwenden wir die eingebettete Version (die aus den Unterprojekten).

Beachten Sie, dass libsimple_dep auf eine externe oder interne Abhängigkeit verweisen kann, aber Sie müssen sich keine Gedanken über deren Unterschiede machen. Meson kümmert sich um die Details für Sie.

Unterprojekte, die von anderen Unterprojekten abhängen

Unterprojekte können andere Unterprojekte verwenden, aber alle Unterprojekte müssen sich im Verzeichnis subprojects auf oberster Ebene befinden. Rekursive Nutzung von Unterprojekten ist jedoch nicht erlaubt, sodass Sie kein Unterprojekt a haben können, das Unterprojekt b verwendet und b ebenfalls a verwendet.

Beziehen von Unterprojekten

Meson wird mit einem Abhängigkeitssystem geliefert, um Abhängigkeitsunterprojekte automatisch zu beziehen. Es ist im Handbuch des Wrap-Abhängigkeitssystems dokumentiert.

Befehlszeilenoptionen

Die Verwendung von Unterprojekten kann von Benutzern und Distributionen mit den folgenden Befehlszeilenoptionen gesteuert werden.

  • --wrap-mode=nodownload

    Meson verwendet das Netzwerk nicht, um Unterprojekte herunterzuladen oder Wrap-Informationen abzurufen. Nur bereits vorhandene Quellen werden verwendet. Dies ist nützlich (hauptsächlich für Distributionen), wenn Sie nur die Quellen verwenden möchten, die von einer Software-Version bereitgestellt werden, und fehlende Abhängigkeiten manuell behandeln oder bereitstellen möchten.

  • --wrap-mode=nofallback

    Meson verwendet keine Unterprojekt-Fallbacks für Deklarationen von Abhängigkeiten in den Build-Dateien und sucht nur im System danach. Beachten Sie, dass dies nicht für bedingungslose subproject()-Aufrufe gilt, die für Quellen gedacht sind, die nicht vom System bereitgestellt werden können, wie z. B. copylibs.

    Diese Option kann durch --force-fallback-for für bestimmte Abhängigkeiten überschrieben werden.

  • --wrap-mode=forcefallback

    Meson sucht nicht im System nach Abhängigkeiten, für die Unterprojekt-Fallbacks verfügbar sind, und verwendet nur Unterprojekte für diese. Dies ist nützlich, wenn Sie Ihr Fallback-Setup testen möchten oder speziell gegen die Bibliotheksquellen Ihrer Unterprojekte bauen möchten.

  • --force-fallback-for=liste,von,abhängigkeiten

    Meson sucht nicht im System nach den dort aufgeführten Abhängigkeiten, vorausgesetzt, ein Fallback wurde bei der Deklaration der Abhängigkeit bereitgestellt.

    Diese Option hat Vorrang vor --wrap-mode=nofallback und funktioniert in Kombination mit --wrap-mode=nodownload nur, wenn die Abhängigkeit bereits heruntergeladen wurde.

    Dies ist nützlich, wenn Ihr Projekt viele Fallback-Abhängigkeiten hat, Sie aber nur gegen die Bibliotheksquellen für einige davon bauen möchten.

    Warnung: Dies kann dazu führen, dass System- und Unterprojektversionen derselben Bibliothek im selben Prozess gemischt werden. Nehmen Sie diesen Fall als Beispiel

    • Die Bibliotheken glib-2.0 und gstreamer-1.0 sind auf Ihrem System installiert.
    • gstreamer-1.0 hängt von glib-2.0 ab, die pkg-config-Datei gstreamer-1.0.pc hat Requires: glib-2.0.
    • In Ihrer Anwendungs-Build-Definition tun Sie
      executable('app', ...,
        dependencies: [
          dependency('glib-2.0', fallback: 'glib'),
          dependency('gstreamer-1.0', fallback: 'gstreamer')],
      )
      
    • Sie konfigurieren mit --force-fallback-for=glib. Dies führt dazu, dass zwei verschiedene Versionen der Bibliothek glib-2.0 verknüpft werden, da dependency('glib-2.0', fallback: 'glib') die Unterprojekt-Abhängigkeit zurückgibt, aber dependency('gstreamer-1.0', fallback: 'gstreamer') nicht auf das Fallback zurückgreift und die Systemabhängigkeit zurückgibt, einschließlich der glib-2.0-Bibliothek. Um diese Situation zu vermeiden, müssen alle Abhängigkeiten, die selbst von glib-2.0 abhängen, ebenfalls zum Fallback gezwungen werden, in diesem Fall mit --force-fallback-for=glib,gsteamer.
  • --wrap-mode=nopromote

    Seit 0.56.0 Meson verwendet automatisch Wrap-Dateien, die in Unterprojekten gefunden werden, und kopiert sie in das Hauptprojekt. Dieses neue Verhalten kann durch Übergabe von --wrap-mode=nopromote deaktiviert werden. In diesem Fall werden nur Wraps verwendet, die im Hauptprojekt gefunden werden.

meson subprojects Befehl

Seit 0.49.0

meson subprojects verfügt über verschiedene Unterbefehle zur Verwaltung aller Unterprojekte. Wenn der Unterbefehl bei einem Unterprojekt fehlschlägt, wird die Ausführung mit anderen Unterprojekten fortgesetzt. Alle Unterbefehle akzeptieren das Argument --sourcedir, das auf das Wurzelverzeichnis des Hauptprojekts zeigt.

Seit 0.56.0 alle Unterbefehle akzeptieren das Argument --types <file|git|hg|svn>, um die Unterbefehle nur für Unterprojekte der angegebenen Typen auszuführen. Mehrere Typen können als durch Kommas getrennte Liste angegeben werden, z. B. --types git,file.

Seit 0.56.0 Wenn der Unterbefehl bei einem Unterprojekt fehlschlägt, wird am Ende ein Fehlercode zurückgegeben, anstatt Erfolg zurückzugeben.

Unterprojekte herunterladen

Seit 0.49.0

Meson lädt benötigte Unterprojekte während der Konfiguration automatisch herunter, es sei denn, die Option --wrap-mode=nodownload wird übergeben. Es ist manchmal vorzuziehen, alle Unterprojekte im Voraus herunterzuladen, damit die Meson-Konfiguration offline durchgeführt werden kann. Der Befehl meson subprojects download kann dafür verwendet werden, er lädt alle fehlenden Unterprojekte herunter, aktualisiert aber keine bereits heruntergeladenen Unterprojekte.

Unterprojekte aktualisieren

Seit 0.49.0

Sobald ein Unterprojekt heruntergeladen wurde, aktualisiert Meson es nicht automatisch. Wenn die Wrap-Datei z. B. einen Git-Zweig verfolgt, werden keine neuen Commits abgerufen.

Um die neueste Version all Ihrer Unterprojekte auf einmal abzurufen, führen Sie einfach den Befehl aus: meson subprojects update.

  • Wenn die Wrap-Datei von WrapDB stammt, wird die neueste Version der Wrap-Datei abgerufen und beim nächsten Mal verwendet, wenn Meson das Projekt neu konfiguriert. Dies kann mit meson --reconfigure ausgelöst werden. Der vorherige Quellcodebaum wird nicht gelöscht, um Verluste lokaler Änderungen zu vermeiden. Seit 0.58.0 Wenn --reset angegeben ist, wird der Quellcodebaum gelöscht und der neue Quellcode extrahiert.
  • Wenn sich das Unterprojekt derzeit im separaten Modus befindet, wird ein Checkout der Revision aus der Wrap-Datei durchgeführt. Seit 0.56.0 Es wird auch ein Rebase durchgeführt, falls die Revision bereits lokal existierte, aber veraltet war. Wenn --reset angegeben ist, wird stattdessen ein harter Reset durchgeführt.
  • Wenn sich das Unterprojekt derzeit im selben Zweig befindet, wie im Wrap-File angegeben, wird ein Rebase auf den origin-Commit durchgeführt. Seit 0.56.0 Wenn --reset angegeben ist, wird stattdessen ein harter Reset durchgeführt.
  • Wenn sich das Unterprojekt derzeit in einem anderen Zweig befindet, als im Wrap-File angegeben, wird es übersprungen, es sei denn, die Option --rebase wird übergeben, in welchem Fall ein Rebase auf den origin-Commit durchgeführt wird. Seit 0.56.0 das Argument --rebase ist veraltet und hat keine Auswirkung. Stattdessen wird ein Checkout der Revision aus der Wrap-Datei durchgeführt und ein Rebase durchgeführt, falls die Revision bereits lokal existierte, aber veraltet war. Wenn --reset angegeben ist, wird stattdessen ein harter Reset durchgeführt.
  • Seit 0.56.0 Wenn die in der Wrap-Datei angegebene url von der für origin eingestellten URL für ein Git-Repository abweicht, wird sie nicht aktualisiert, es sei denn, --reset ist angegeben, in welchem Fall die URL von origin zuerst zurückgesetzt wird.
  • Seit 0.56.0 Wenn das Unterprojekt-Verzeichnis kein Git-Repository ist, aber ein [wrap-git] hat, wird das Unterprojekt ignoriert, es sei denn, --reset ist angegeben, in welchem Fall das Verzeichnis gelöscht und das neue Repository geklont wird.

Einen Themenzweig über alle Git-Unterprojekte starten

Seit 0.49.0

Die Befehlszeile meson subprojects checkout <branch_name> checkt einen Zweig aus oder erstellt ihn mit dem Argument -b in jedem Git-Unterprojekt. Dies ist nützlich, wenn Sie lokale Änderungen über mehrere Unterprojekte hinweg starten. Es liegt weiterhin in Ihrer Verantwortung, in jedem Repository, in dem Sie lokale Änderungen vorgenommen haben, zu committen und zu pushen.

Um zur im Wrap-File angegebenen Revision (d. h. Master) zurückzukehren, führen Sie einfach meson subprojects checkout ohne Angabe eines Zweignamens aus.

Seit 0.56.0 Alle ausstehenden Änderungen werden nun gestashed, bevor ein neuer Zweig ausgecheckt wird.

Einen Befehl auf allen Unterprojekten ausführen

Seit 0.51.0

Die Befehlszeile meson subprojects foreach <command> [...] führt einen Befehl in jedem Unterprojekt-Verzeichnis aus. Dies kann beispielsweise nützlich sein, um den Status von Unterprojekten zu überprüfen (z. B. mit git status oder git diff), bevor andere Aktionen darauf ausgeführt werden.

Warum müssen alle Unterprojekte in einem einzigen Verzeichnis liegen?

Es gibt mehrere Gründe.

Erstens muss das System, um irgendeine Art von Vernunft aufrechtzuerhalten, verhindern, dass mit subdir() oder Variationen davon in andere Unterprojekte eingegriffen wird. Wenn die Unterprojekte an gut definierten Orten liegen, ist dies einfach. Wenn Unterprojekte überall liegen könnten, wäre es wesentlich schwieriger.

Zweitens ist es für Endbenutzer extrem wichtig, leicht erkennen zu können, welche Unterprojekte ein Projekt hat. Da sie an einem und nur an einem Ort liegen, wird die Überprüfung einfach.

Dies ist auch eine Frage der Konvention. Da alle Meson-Projekte die gleiche Struktur in Bezug auf Unterprojekte haben, wird der Wechsel zwischen Projekten einfacher. Sie müssen keine Zeit damit verbringen, in einem neuen Projekt den Quellcodebaum nach Unterprojekten zu durchforsten. Sie befinden sich immer am selben Ort.

Schließlich erhöht die Möglichkeit, Unterprojekte überall zu haben, die Wahrscheinlichkeit, viele verschiedene (möglicherweise inkompatible) Versionen einer Abhängigkeit in Ihrem Quellcodebaum zu haben. Dann kann das Ändern von Code (z. B. das Ändern der Reihenfolge, in der Sie Verzeichnisse durchlaufen) versehentlich zu einer völlig anderen Version des Unterprojekts führen.

Die Ergebnisse der Suche sind