Zum Inhalt

macOS-App

Die offizielle macOS-App ist seit v2.0.0 die native SwiftUI/Metal-App (apple/PhysarumApp, macOS-Target) — derselbe Code wie auf iPad/iPhone, mit vollem Funktionsumfang: Authoring-Editor, native Audio-Reaktivität, Capture/Export (Bild, Video, Live Photo), adaptives Format, Vollbild. Sie löst den früheren WKWebView-Wrapper ab.

Bauen

./scripts/build-macos-app.sh

Voraussetzungen: Xcode (xcodebuild) und XcodeGen (brew install xcodegen). Das Script

  1. generiert das Xcode-Projekt (xcodegen generate; project.yml ist SSOT),
  2. archiviert das macOS-Target universal (arm64 + x86_64),
  3. exportiert die .app (Developer ID, sobald die Signing-Variablen gesetzt sind — siehe unten; sonst ad-hoc),
  4. notarisiert + stapelt die App (nur mit Notary-Profil) und
  5. packt alles als Disk-Image (.app + /Applications-Symlink + INSTALL.txt), dann DMG signieren → notarisieren → staplen → stapler/spctl-Prüfung.

Ergebnis:

  • dist-macos/Physarum.app — die App
  • dist-macos/Physarum.dmg — das verteilbare Disk-Image

Architektur

Die App ist das native Physarum-macOS-Target aus apple/PhysarumApp (SwiftUI + Metal, gemeinsame PhysarumEngine) — kein WebView, kein Electron, kein WebGPU. Gerendert wird direkt über Metal; die WGSL-Shader werden zur Build-Zeit nach MSL transpiliert (siehe apple/scripts/transpile-shaders.sh).

Systemvoraussetzung

macOS 14 (Sonoma) oder neuer. Natives Metal-Rendering — keine WebGPU- oder Browser-Abhängigkeit (der alte Wrapper brauchte macOS 26 + WebGPU). Universal Binary: läuft auf Apple Silicon und Intel.

Weitergabe

Offizielle Releases sind Developer-ID-signiert und Apple-notarisiert — die Physarum.dmg öffnet per Doppelklick ohne Gatekeeper-Warnung, online wie offline. INSTALL.txt im DMG beschreibt das Ziehen in den Programme-Ordner.

Ein lokal gebauter, unsignierter Build (Mitwirkende ohne Zertifikat) wird von Gatekeeper hingegen nicht stillschweigend akzeptiert. Seit macOS 15 Sequoia ist der Rechtsklick-→-„Öffnen"-Umweg weg; ein solcher Build muss einmal über Systemeinstellungen → Datenschutz & Sicherheit → „Trotzdem öffnen" freigegeben werden — oder im Terminal:

xattr -dr com.apple.quarantine /Applications/Physarum.app

Signieren & Notarisieren (Developer ID)

build-macos-app.sh fährt die ganze Kette, sobald zwei Umgebungsvariablen gesetzt sind; ohne sie entsteht ein ad-hoc-signierter Build (Default für Mitwirkende ohne Zertifikat).

Einmal-Setup

  1. Apple Developer Program (Individual, aktiv).
  2. „Developer ID Application"-Zertifikat im Login-Keychain — danach zeigt security find-identity -v -p codesigning die Identität.
  3. notarytool-Credentials einmal hinterlegen (App-spezifisches Passwort von account.apple.com):
    xcrun notarytool store-credentials "<PROFIL>" \
      --apple-id "<APPLE_ID>" --team-id "<TEAM_ID>" --password "<APP_PASSWORT>"
    

Notarisierten Build erzeugen

PHYSARUM_SIGN_IDENTITY=auto PHYSARUM_NOTARY_PROFILE=<PROFIL> \
  ./scripts/build-macos-app.sh

PHYSARUM_SIGN_IDENTITY="auto" nimmt die erste „Developer ID Application"- Identität aus dem Keychain. Nur die Identität (ohne Profil) → signiert, aber nicht notarisiert. Der Mac muss online sein (sicherer Timestamp + Notary-Upload). Reihenfolge: archivieren (Hardened Runtime + Entitlements) → exportieren (Developer ID) → App notarisieren → staplen, dann die DMG aus der gestaplten App, dann DMG signieren → notarisieren → staplen → stapler/spctl-Prüfung.

Entitlements & Hardened Runtime

Die App ist nicht sandboxed (Developer-ID-Direktvertrieb). Notarisierung braucht die Hardened Runtime (Signing-Flag ENABLE_HARDENED_RUNTIME=YES). Unter Hardened Runtime ist für den Mikrofon-Zugriff (Audio-Reaktivität) das Entitlement com.apple.security.device.audio-input nötig — es steht in apple/PhysarumApp/Physarum.macOS.entitlements und wird beim Archivieren via CODE_SIGN_ENTITLEMENTS gesetzt. Photos-Speichern (Capture → Fotos) läuft bei der unsandboxed App über die NSPhotoLibraryAddUsageDescription (TCC-Grant, kein Entitlement). Die Release-Signing-Settings werden als xcodebuild-Overrides im Script gesetzt; project.yml bleibt für lokale Dev-Builds ad-hoc.