Die Struktur von macOS-Apps
(eclecticlight.co)- macOS-Anwendungen besitzen komplexere Bestandteile als Kommandozeilenprogramme und verwalten Oberflächenressourcen wie Fenster und Menüs in einer separaten Struktur
- In Classic Mac OS wurden ausführbarer Code und Ressourcen im Ressourcen-Fork einer Datei gespeichert, ab Mac OS X erfolgte jedoch der Wechsel zur Bundle-Struktur
- Ein App-Bundle ist um das Verzeichnis Contents herum aufgebaut und besteht aus Unterordnern wie MacOS, Resources und Frameworks sowie zentralen Dateien wie Info.plist
- Später kamen Code Signing, App-Store-Belege und Notarisierung (notarization) hinzu, wodurch sich die Struktur zur Stärkung von Sicherheit und Integrität weiterentwickelte
- Diese in sich geschlossene Struktur (App-Bundle) bildet die zentrale Grundlage dafür, Installation, Updates und Entfernen zu vereinfachen und Sicherheit sowie Wartungseffizienz zu erhöhen
Die App-Struktur von Classic Mac OS
- In frühen Mac-OS-Versionen wurden UI-Ressourcen wie Fenster und Menüs getrennt von der ausführbaren Datei im Ressourcen-Fork (resource fork) gespeichert
- Als Beispiel werden die Ressourcen von QuarkXPress 4.11 in ResEdit angezeigt
- Der ausführbare Code ist in CODE-Ressourcen enthalten; zusätzlich werden Dateityp (type) und Ersteller (creator) gespeichert, damit der Finder die Datei erkennen kann
Die Bundle-Struktur von Mac OS X
- Mac OS X führte die von NeXTSTEP stammende Bundle-Struktur ein
- Eine App ist ein Verzeichnis mit der Endung
.appund enthält darin den Ordner Contents - Der Ordner MacOS enthält die ausführbare Datei der GUI-App und Kommandozeilenwerkzeuge
- Im Ordner Resources werden Ressourcendateien wie App-Symbole und GUI-Komponenten gespeichert
- Einige Apps enthalten zusätzlich einen Ordner Frameworks und betten dylib-Dateien (dynamische Bibliotheken) ein
- Eine App ist ein Verzeichnis mit der Endung
- Die Datei Info.plist ist zwingend erforderlich und definiert unter anderem den Namen der ausführbaren Datei, das Symbol, die minimale macOS-Version, Dokumenttypen und Versionsnummern
- Die Datei PkgInfo bewahrt die Typ-/Erstellerinformationen aus Classic Mac OS, ist aber nicht zwingend erforderlich
- Beim Start einer App startet launchd den ausführbaren Code, während LaunchServices und RunningBoard anhand der Informationen aus Info.plist die Initialisierung durchführen
Sicherheit und Erweiterungen unter macOS
- Ab Mac OS X 10.5 Leopard (2007) wurde Code Signing eingeführt, wodurch der Ordner _CodeSignature hinzukam
- Die Datei CodeResources enthält den Code-Directory-Hash (CDHash) zur Prüfung der App-Integrität
- Über den App Store verteilte Apps enthalten im Ordner _MASReceipt den Store-Beleg
- Seit 2018 gibt es Notarisierung (notarization); ein von Apple ausgestelltes Ticket kann per „Stapling“ an das Bundle in der CodeResources-Datei angeheftet werden
- Moderne App-Bundles enthalten Komponenten selbst, die früher in Systemordnern installiert wurden
- Ordner Library: LaunchDaemons, LoginItems usw.
- Ordner XPCServices: separate ausführbare Dienste, die von der App verwendet werden
- Ordner Plugins / Extensions: App-Erweiterungen und App Intents
- In einigen Apps gibt es außerdem eine Datei version.plist
Vorteile von App-Bundles
- Durch die Integration aller Komponenten im Bundle werden Installation, Updates und Entfernen einfacher
- Die Wahrscheinlichkeit fehlender Komponenten sinkt, und durch Signatur- und Notarisierungsschutz wird die Sicherheit erhöht
- App-Store-Apps enthalten zusätzlich Belege und Notarisierungs-Tickets und gewinnen so an Vertrauenswürdigkeit
- Zwischen Intel- und Arm-Architekturen gibt es keinen strukturellen Unterschied; die Mach-O-Datei wird als Universal Binary (fat binary) gespeichert und kann Code für beide Plattformen enthalten
- In derselben Datei befinden sich auch die jeweiligen Signaturen (signatures) für jede Architektur
Visueller Überblick über die App-Struktur
- Im Diagramm markiert hellgelb Komponenten, die zwingend oder in fast allen Apps vorhanden sind
- Grün steht für Elemente, die nur in über den App Store verteilten Apps vorkommen, Blau für optionale Notarisierungs-Tickets
- Zusätzlich können weitere Elemente wie Automator-Workflows oder Skripte enthalten sein
- Insgesamt haben sich macOS-Apps zu einer in sich geschlossenen, sicherheitsorientierten Struktur entwickelt
1 Kommentare
Hacker-News-Kommentar
Der blau markierte Teil ist das notarisation ticket; faktisch ist es aber nicht optional
Nicht notarisierte Apps sind für Nutzer so umständlich, dass man am Ende doch die jährliche Apple-Entwicklergebühr von 99 $ zahlen muss
Wenn man nur für den Eigengebrauch baut und ausführt, ist es okay, aber für die Distribution zeigt macOS Warnfenster an, sodass die App wie kaputt wirkt
Früher konnte man sie noch per Rechtsklick starten, heute muss man dafür sogar in die Systemeinstellungen gehen
Relevante Screenshots gibt es in der Apple-Support-Dokumentation und in den Developer News
Ich mag Apples Sicherheitsphilosophie, aber das Notarisierungssystem für Apps außerhalb des App Store schadet meiner Meinung nach allen Beteiligten
Ich habe keinen Fall gefunden, in dem Notarisierung tatsächlich ein Sicherheitsproblem verhindert hätte
Ich fand die macOS-Notarisierung schon lästig, aber als ich für Windows distribuiert habe, war es noch schlimmer
Um das Vertrauen von Windows Defender zu bekommen, muss man ein Zertifikat kaufen, und sowohl Firmen als auch Privatpersonen müssen eine gründliche Identitätsprüfung durchlaufen
Man muss mit einem Hardware-Token signieren, sodass nur eine Person Releases verteilen kann
Außerdem kann die Zertifizierungsstelle Schlüssel willkürlich sperren; wenn das passiert, während man einen Sicherheitspatch ausliefern muss, ist das furchtbar
In dieser Hinsicht wirkt das macOS-Ökosystem deutlich besser
Ich entwickle gerade eine Programmiersprache, die für mehrere Plattformen kompiliert wird, und Signierung und Notarisierung passen überhaupt nicht zu diesem Prozess
Solche Signatursysteme sind nur ein Kontrollinstrument und bergen Missbrauchsrisiken wie im Fall Epic
Wenn unsignierte Binärdateien nicht auf vernünftige Weise ausgeführt werden können, betrachte ich die Plattform als geschlossen und unterstütze sie nicht
Geschlossene Plattformen wie iOS oder Android lassen sich teilweise durch PWAs ersetzen
Allerdings ist mein Vertrauen geschwunden, dass Google das Ausführen selbst signierter Apps weiter zulässt
Ich kenne nur zwei Fälle, in denen Apple Zertifikate für Apps außerhalb des App Store widerrufen hat
Einer war Facebooks Research App, der andere Googles Screenwise Meter
Beide waren spyware-artige Apps, die auf Jugendliche abzielten, und durch den Zertifikatswiderruf wurden sogar interne Tools lahmgelegt
Danach scheint Screenwise Meter wieder im App Store gelandet zu sein
Relevante Artikel: Wired, EFF
Etwa die Hälfte der Apps in meinem App-Ordner ist nicht notarisiert, und in der Praxis ist das überhaupt kein Problem
Nach der Notarisierung ist ein stapled ticket optional
Wenn man das Ticket nicht anheftet, muss der Nutzer den Notarisierungsstatus über eine Internetverbindung prüfen lassen
Während ich AppBundler.jl entwickle, stört mich vieles an der macOS-App-Struktur
Die erzwungene Frameworks-Ordnerstruktur sieht zwar sauber aus, in der Praxis ist das Bundling aber umständlich, daher weiche ich auf einen Libraries-Ordner aus
Das größte Problem ist die Codesignierung — jede Binärdatei einzeln zu signieren fühlt sich verschwenderisch an
Es ist schwer zu verstehen, warum man es so kompliziert macht, wenn man doch einfach Dateihashes sammeln und nur einmal signieren könnte
Auch dass entitlements nur am Launcher-Binary hängen, ist ineffizient
Da die Notarisierungsanforderungen mit der Zeit verschärft werden, kann es passieren, dass eine App später plötzlich nicht mehr durchkommt
Ich bin dem Apple Developer Program beigetreten, um eine Tauri-App zu signieren und zu notarisieren, und scheitere jetzt seit drei Wochen
Da ich keinen Mac habe, habe ich es über GitHub Actions versucht, aber die erste Notarisierung soll oft lange dauern
Allein für GitHub habe ich fast 100 $ ausgegeben, und die Notarisierung ist immer noch nicht durch
Der Apple-Support verweigert Hilfe, weil ich keinen Mac habe und Tauri benutze
Auch der Authentifizierungsprozess für die Notarisierungs-API ist albtraumhaft — man muss mit PKCS8 ein JWT bauen, aber es gibt kaum Dokumentation, also musste ich selbst ein Node-Programm schreiben
Das war die schlimmste Developer Experience (DX), die ich bisher erlebt habe
Das ohne Apple-Hardware lösen zu wollen, sei Zeitverschwendung
Beim ersten OS-Screenshot ist mir kurz das Herz stehen geblieben
Früher war das eine praktische und saubere UI, heute verschwenden abgerundete Ecken und blasenartige Icons nur Platz
Trotzdem ist die Mac-Hardware qualitativ so gut, dass ich nicht auf ein ThinkPad wechseln kann
Abgerundete Ecken sind eher eine für das menschliche Sehen vorteilhafte Eigenschaft
Es gibt Studien, wonach kantige Ecken visuelle Ermüdung verursachen
Relevanter Artikel: Round Rects Are Everywhere
Ich mag aktuelles macOS auch nicht besonders, aber dieser Screenshot ist ebenfalls nicht perfekt
Es gibt zu viele Linien und zu wenig Farbe, wodurch der Blick zerstreut wird
Persönlich fand ich die Aqua UI aus der Leopard-Ära gut ausbalanciert zwischen Informationsdichte und visueller Tiefe
Nach Pixelverhältnis hat die alte UI sogar mehr Platz eingenommen
Bei 5K-Auflösung ist das moderne MacBook Pro effizienter
Auch klassische Macs hatten bereits leicht abgerundete Ecken
Siehe: Infinite Mac
Computer sind nicht nur Werkzeuge für die Arbeit, sondern auch Werkzeuge für Freude
Allerdings wirkt die heutige UI so, als hätte sie sich zu weit von der Praktikabilität entfernt
Der Großteil des Bildschirms besteht aus nutzlosen Informationen wie 101101, daher ist es schwer, das als praktisch zu bezeichnen
Die Aussage, dass beim Ausführen von Kommandozeilen-Tools unter macOS launchd der eigentliche Starter sei, ist falsch
Tatsächlich erfolgt der Start wie auf anderen UNIX-Systemen aus der Shell per fork/spawn
Das Bundle-System von NeXTSTEP hat das Design von JAR-Dateien in Java inspiriert
In klassischen Mac-OS-Power-Mac-Apps wurde PPC-Code im Data Fork gespeichert
Bei CFM-68K-Binärdateien war es genauso, und CODE-Ressourcen wurden nur für älteren 68K-Code verwendet
Ich erinnere mich gern an die Zeit, als man Apps noch mit ResEdit bearbeitet hat
Wenn wie im letzten Diagramm die Bürokratie explodiert, ist das kein gutes Zeichen
Es gibt damit einen weiteren Grund weniger, auf macOS 26 zu „upgraden“
Die aktuelle Struktur ist zwar der „Standard“ unter macOS, aber nicht die einzige Möglichkeit
Wenn man RPATH sauber setzt, kann man Bibliotheken auch in beliebige Unterordner legen und trotzdem durch die Notarisierung kommen
Zum Beispiel funktioniert auch der Pfad AppName.App/Contents/Libraries
Der praktische Nutzen dieses Ansatzes ist allerdings gering; unter den rund 100 Apps auf meinem System nutzt keine einen /Libraries-Ordner
Statt
.dylibmuss zwingend das.framework-Format verwendet werden, und das ist eine undokumentierte RegelBei der Einreichung kann das automatisch erkannt und abgelehnt werden