Erstellung von OSX-Paketen

Meson bietet keine native Unterstützung für die Erstellung von OSX-Paketen, stellt aber alle Werkzeuge zur Verfügung, die Sie für die eigene Erstellung benötigen. Der Grund dafür ist, dass es sehr schwierig ist, ein System zu schreiben, das alle verschiedenen Möglichkeiten dafür abdeckt, aber es ist sehr einfach, einfache Skripte für jede Anwendung zu schreiben.

Beispielcode hierfür finden Sie in der Meson-Testsuite für manuelle Tests.

Erstellung eines App-Bundles

OSX-App-Bundles sind tatsächlich extrem einfach. Es handelt sich lediglich um Verzeichnisse von Dateien in einem bestimmten Format. Alle Details, die Sie wissen müssen, finden Sie auf dieser Seite, und es wird dringend empfohlen, diese zuerst zu lesen.

Nehmen wir an, wir erstellen unser App-Bundle unter /tmp/myapp.app. Angenommen, wir haben eine ausführbare Datei, die wir in Contents/MacOS installieren müssen. Wenn wir die ausführbare Datei wie folgt definieren

executable('myapp', 'foo1.c', ..., install : true)

dann müssen wir unseren Build-Baum einfach mit diesem Befehl initialisieren

$ meson --prefix=/tmp/myapp.app \
        --bindir=Contents/MacOS \
        builddir \
        <other flags you might need>

Wenn wir nun meson install ausführen, wird das Bundle ordnungsgemäß vorbereitet. Wenn Sie Ressourcen- oder Datendateien haben, müssen Sie diese entweder durch benutzerdefinierte Installationsbefehle oder durch Angabe weiterer Installationspfade für den Meson-Befehl in Contents/Resources installieren.

Als Nächstes müssen wir eine Info.plist-Datei und ein Symbol installieren. Dafür benötigen wir die folgenden beiden Meson-Definitionen.

install_data('myapp.icns', install_dir : 'Contents/Resources')
install_data('Info.plist', install_dir : 'Contents')

Das Format von Info.plist finden Sie im Link oder im oben genannten Beispielprojekt. Der einfachste Weg, ein Symbol im icns-Format zu erhalten, ist, Ihr Bild als TIFF zu speichern und dann die Hilfsanwendung tiff2icns zu verwenden, die mit XCode geliefert wird.

Einige Anwendungen gehen davon aus, dass das aktuelle Arbeitsverzeichnis des App-Prozesses dasselbe ist wie das Verzeichnis der ausführbaren Binärdatei. Wenn dies bei Ihnen der Fall ist, müssen Sie ein Wrapper-Skript erstellen, das wie folgt aussieht

#!/bin/bash

cd "${0%/*}"
./myapp

installieren Sie es mit diesem

install_data('myapp.sh', install_dir : 'Contents/MacOS')

und stellen Sie sicher, dass Sie myapp.sh als die auszuführende ausführbare Datei in Ihrer Info.plist angeben.

Wenn Sie keine externen Bibliotheken verwenden, ist dies alles, was Sie tun müssen. Sie haben jetzt ein vollständiges App-Bundle unter /tmp/myapp.app, das Sie verwenden können.

Externe Bibliotheken

Die meisten Anwendungen verwenden Drittanbieter-Frameworks und -Bibliotheken. Wenn dies bei Ihrem Projekt der Fall ist, müssen Sie diese zum Bundle hinzufügen, damit es auf den Computern anderer Personen funktioniert.

Als Beispiel verwenden wir das SDL2-Framework. Um es in unsere App einzubinden, geben wir zunächst ein Installationsskript an, das ausgeführt werden soll.

meson.add_install_script('install_script.sh')

Das Installationsskript tut zwei Dinge. Zuerst kopiert es das gesamte Framework in unser Bundle.

$ mkdir -p ${MESON_INSTALL_PREFIX}/Contents/Frameworks
$ cp -R /Library/Frameworks/SDL2.framework \
        ${MESON_INSTALL_PREFIX}/Contents/Frameworks

Dann muss es den Suchpfad für Bibliotheken unserer ausführbaren Datei(en) ändern. Dies teilt OSX mit, dass die Bibliotheken, die Ihre App benötigt, sich in Ihrem Bundle befinden. Im Fall von SDL2 sieht der Aufruf wie folgt aus

$ install_name_tool -change @rpath/SDL2.framework/Versions/A/SDL2 \
    @executable_path/../FrameWorks/SDL2.framework/Versions/A/SDL2 \
    ${MESON_INSTALL_PREFIX}/Contents/MacOS/myapp

Dies ist der Teil der OSX-App-Bündelung, den Sie immer manuell durchführen müssen. OSX-Abhängigkeiten gibt es in vielen Formen und Größen, und leider gibt es keine zuverlässige automatische Methode, um zu bestimmen, wie jede Abhängigkeit behandelt werden soll. Frameworks gehen in das Verzeichnis Frameworks, während einfache .dylib-Dateien normalerweise in Contents/Resources/lib gehen (aber Sie können sie dort platzieren, wo Sie möchten). Um dies zu erreichen, müssen Sie überprüfen, gegen was Ihr Programm mit otool -L /path/to/binary verlinkt ist, und die Kopiervorgänge und Korrekturschritte manuell zu Ihrem Installationsskript hinzufügen. Kopieren Sie jedoch keine Systembibliotheken in Ihr Bundle.

Danach haben Sie ein voll funktionsfähiges, in sich geschlossenes OSX-App-Bundle, das zur Verteilung bereit ist.

Qt

Qt bietet ein Bereitstellungstool namens macdeployqt an, das die Bündelung von Qt-Bibliotheken in Ihrem Anwendungsordner automatisiert und optional den finalen .dmg-Installer erstellt.

# cd into the folder that contains the `myapp.app` folder
macdeployqt myapp.app -executable=myapp.app/Contents/MacOS/myapp

Dies kopiert die benötigten Qt-Bibliotheken in die richtigen Unterordner innerhalb von myapp.app. Das Argument -executable=myapp.app/Contents/MacOS/myapp dient dazu, den Suchpfad der ausführbaren Datei myapp.app/Contents/MacOS/myapp für die Qt-Bibliotheken automatisch zu ändern. Man kann auch das Argument -dmg übergeben, um aus dem aktualisierten myapp.app-Ordner einen .dmg-Installer zu erstellen. Weitere Informationen finden Sie auf der Dokumentationsseite des Tools.

Erstellung eines .dmg-Installers

Ein .dmg-Installer ist ebenfalls recht einfach. Im Kern handelt es sich im Grunde um ein schickes komprimiertes Archiv. Eine gute Beschreibung finden Sie auf dieser Seite. Bitte lesen Sie diese und erstellen Sie eine Vorlagen-Image-Datei gemäß den Anweisungen.

Der eigentliche Prozess der Erstellung des Installers ist sehr einfach: Sie mounten das Vorlagen-Image, kopieren Ihr App-Bundle hinein, unmounten es und konvertieren das Image in ein komprimiertes Archiv. Die eigentlichen Befehle dafür sind nicht besonders interessant, Sie können sie gerne von der oben verlinkten Seite oder vom Beispielskript in der Meson-Testsuite übernehmen.

Alles zusammenfügen

Es gibt viele Möglichkeiten, den .dmg-Installer zusammenzustellen, und verschiedene Leute werden es auf unterschiedliche Weise tun. Der verlinkte Beispielcode macht dies, indem er zwei verschiedene Skripte verwendet. Dies trennt die verschiedenen Teile, die den Installer generieren, in logische Einheiten.

install_script.sh befasst sich nur mit dem Einbetten von Abhängigkeiten und der Korrektur der Pfade zu den Bibliotheken.

build_osx_installer.sh richtet den Build mit den richtigen Pfaden ein, kompiliert, installiert und generiert das .dmg-Paket.

Der Hauptgrund dafür ist, dass Sie, um ein vollständiges OSX-Installer-Paket aus dem Quellcode zu erstellen, einfach nur in den Quellbaum wechseln und ./build_osx_installer.sh ausführen müssen. Um Pakete auf anderen Plattformen zu erstellen, würden Sie Skripte wie build_windows_installer.bat usw. schreiben.

Die Ergebnisse der Suche sind