Der Build läuft auf Linux durch, aber Archivierung, Simulator oder Signierung scheitern erst am Ende.

Schnellste Lösung: Bazel 9 kann Build-Aktionen steuern, ersetzt jedoch weder Xcode noch Apple SDKs. Für eine vollständige iOS-Auslieferung bleiben macOS, Simulator, Codesignatur und Paketexport auf einem echten Mac; Linux übernimmt plattformunabhängige Prüfungen, während ein Linux-plus-Remote-Mac-Verbund für mittlere und größere Teams meist die sauberste Architektur ist.

01

Für wen diese Entscheidung relevant ist

Dieser Beitrag richtet sich an Build-Engineers, die Bazel 9 in ein iOS-Projekt integrieren und die Grenze zwischen Linux- und macOS-Ausführung bestimmen müssen. Ebenso relevant ist er für DevOps-Teams mit bestehender Linux-CI sowie für technische Verantwortliche, die Apple-Buildkapazität erweitern möchten.

Ein kleines Team kann zunächst eine einzelne Remote-Mac-Instanz für den vollständigen Ablauf verwenden. Vor einer Skalierung sollte jedoch anhand von Action-Logs, Cache-Treffern, Signaturergebnissen und Wiederanlauftests nachgewiesen werden, welche Aufgaben tatsächlich einen Mac benötigen.

Zeitplan für die Entscheidung: In dieser Woche zuerst eine saubere Kompatibilitätsmatrix und einen Minimal-Build erstellen, anschließend die Actions nach Plattform sortieren und erst danach über zusätzliche Mac-Knoten entscheiden.
Letzte Aktualisierung: 29.08.2026; die Angaben wurden anhand der offiziellen Bazel-Dokumentation, der Veröffentlichungen von rules_apple und rules_swift sowie der Xcode-26-Dokumentation geprüft.

02

Die Werkzeugkette setzt die harte Grenze

Die zentrale Verwechslung lautet: Bazel ist ein Build-System, aber kein Ersatz für die Apple-Entwicklungsumgebung. Bazel beschreibt Abhängigkeiten, plant Actions und kann Toolchains sowie Plattformen auswählen. rules_apple stellt Regeln für Apple-Ziele bereit, während rules_swift Swift-spezifische Build-Integration liefert. Xcode bringt dagegen Apple SDKs, Compiler, Linker, Simulator-Komponenten, Signaturwerkzeuge und weitere Teile der offiziellen Plattformkette mit.

Bazel 9 ist laut offiziellem Bazel-Veröffentlichungsmodell ein Active-LTS-Zweig. Das sagt jedoch allein noch nicht aus, dass jede Kombination aus Bazel-Version, rules_apple, rules_swift, Xcode und macOS automatisch zusammenarbeitet. Die unterstützten Versionen müssen aus den jeweiligen offiziellen rules_apple-Releases, der Dokumentation von rules_swift und den Release Notes der eingesetzten Xcode-Version zusammengesetzt werden.

Apple hat Xcode 26 veröffentlicht; die zugehörigen SDK- und Plattformbedingungen stehen in den Xcode-26-Release-Notes. Zusätzlich sollten die jeweils geltenden Apple-Anforderungen für Plattform-Builds geprüft werden. Eine CI-Konfiguration gilt deshalb erst dann als kompatibel, wenn nicht nur bazel build startet, sondern ein reproduzierbares iOS-Artefakt erzeugt werden kann.

Bazel-Build für iOS ohne Xcode?

Für eine vollständige iOS-Anwendung ist Xcode beziehungsweise dessen installierte Toolchain praktisch nicht ersetzbar. Ein Linux-Knoten kann Bazel-Analyse, Regelauflösung oder Quelltextprüfungen erledigen. Sobald jedoch Apple SDK-Dateien, Xcode-Toolchains, Simulator-Runtimes, Objective-C- oder Swift-Linking, Codesignatur oder der Export eines installierbaren Pakets beteiligt sind, muss die Action auf ein passendes macOS-System mit der erwarteten Xcode-Installation gelangen.

Dabei ist zwischen „Bazel kann den Befehl annehmen“ und „die Anwendung ist auslieferbar“ zu unterscheiden. Ein erfolgreicher unsignierter Kompiliervorgang beweist weder, dass ein Archiv erzeugt werden kann, noch dass das Profil zur Bundle-ID passt oder dass ein Export im unbeaufsichtigten CI-Prozess funktioniert.

Für jede geplante Kombination sollten drei Ergebnisse dokumentiert werden:

  1. Die Analyse und Toolchain-Auflösung endet ohne nicht deklarierte lokale Abhängigkeit.
  2. Das Ziel wird mit der erwarteten Apple SDK- und Xcode-Kombination kompiliert und gelinkt.
  3. Archiv, Signatur, Export und gegebenenfalls Simulator-Test laufen ohne manuelle grafische Anmeldung durch.

Wenn die verwendete Regelversion Bazel 9 nicht ausdrücklich abdeckt, ist zunächst ein Upgrade oder eine kontrollierte Rückstufung zu prüfen. Ein Migrationsstopp ist sinnvoller als ein produktiver Knoten, dessen Kombination nur zufällig auf einer einzelnen Entwickler-Maschine funktioniert. Die Bazel-9-Ankündigung sollte dabei gemeinsam mit den Release-Hinweisen der Regeln gelesen werden.

03

Aufgaben nach tatsächlichem Ausführungsort routen

Die Plattformzuordnung darf nicht anhand des Skriptnamens erfolgen. Ein Skript mit dem Namen test kann einen Simulator starten; ein Skript mit dem Namen build kann dagegen nur plattformneutrale Quellen generieren. Entscheidend ist die konkrete Bazel-Action, ihre Toolchain und der Ausführungsknoten.

Welche Aktionen auf Linux bleiben können

Linux ist für Aufgaben geeignet, die keine Apple-SDK-Dateien und keine macOS-spezifischen Werkzeuge benötigen. Typische Kandidaten sind:

  • Format- und Stilprüfungen für Quelltext;
  • statische Analyse ohne Apple-Linking;
  • Protobuf-, OpenAPI- oder sonstige Codegenerierung;
  • Prüfung von Abhängigkeiten und Build-Dateien;
  • Tests, die keine UIKit-, Simulator- oder Apple-Runtime voraussetzen;
  • Bazel-Analyse und Validierung der Plattform- und Toolchain-Auflösung.

Diese Zuordnung muss im konkreten Repository verifiziert werden. Eine plattformneutrale Regel kann durch eine transitive Abhängigkeit unerwartet ein Apple-Werkzeug anfordern. Deshalb sollte die CI nicht nur das Endergebnis, sondern auch Action-Informationen speichern.

Welche Aktionen auf macOS gehören

Auf den Mac gehören insbesondere:

  • Kompilierung und Linken eines iOS-Ziels mit Apple SDK;
  • Erstellung eines Archivs;
  • Simulator-Builds und Simulator-Tests;
  • Codesignatur und Provisioning;
  • Export des installierbaren Anwendungspakets;
  • Aktionen, die ausdrücklich Xcode, xcrun, simctl, codesign oder Apple-Toolchains aufrufen.

Die Regeln für Bazel-Plattformen und Toolchains helfen bei der deklarativen Auswahl. Sie ersetzen aber nicht die Prüfung, ob auf dem Zielknoten tatsächlich der erwartete Pfad, die richtige SDK-Version und die erforderliche Runtime vorhanden sind.

Ein einfaches Diagnosemuster kann zunächst die Umgebung und den Knoten sichtbar machen:

bazel info execution_root
bazel cquery //app:ios_binary --output=build
xcodebuild -version
xcrun --sdk iphoneos --show-sdk-path

Beispiel für eine auswertbare Ausgabe:

Build label: //app:ios_binary
Execution platform: //platforms:macos_arm64_xcode26
Xcode: 26.0
SDK path: /Applications/Xcode.app/.../iPhoneOS.sdk

Die Pfade sind hier absichtlich Platzhalter. In einer echten Pipeline sollten Repository, Benutzerkonto, Zertifikatsspeicher und Remote-Endpunkt nicht fest im Beispieltext stehen. Entscheidend ist, dass die CI die erkannte Execution Platform und die verwendete Toolchain als Artefakte ablegt.

Bazel 9 iOS CI unter Linux

Ein vollständiger Bazel-9-iOS-CI-Lauf kann nicht dauerhaft auf Linux beschränkt werden, wenn Archivierung, Simulator, Signatur oder Export Teil des Lieferprozesses sind. Linux kann aber sehr wohl ein vorgelagerter Teil der Pipeline bleiben. Dadurch werden fehlerhafte Abhängigkeiten früh erkannt, ohne jeden Commit an einen Mac-Knoten zu senden.

Die sichere Aufteilung lautet daher nicht „Linux oder Mac“, sondern „Linux für geeignete Actions, macOS für Apple-spezifische Actions“. Für die Remote-Ausführung beschreibt Bazel die relevanten Regeln in der Dokumentation zur Remote Execution. Zusätzlich sollte die Bazel-Dokumentation zu Remote Builds herangezogen werden.

04

Reproduzierbarkeit muss messbar sein

Die häufigste Ursache für einen scheinbar funktionierenden, später aber nicht reproduzierbaren Build liegt nicht im Bazel-Cache, sondern in einer unklaren Umgebung. PATH, globale Homebrew-Pakete, Dateien außerhalb des Repositorys, lokale Shell-Skripte und automatisch geladene Zertifikate können unbemerkt in Actions einfließen.

Bazel 9 verlangt außerdem eine gesonderte Prüfung der Abhängigkeitseinstiege, wenn ein Projekt bisher auf die alte WORKSPACE-Arbeitsweise vertraut hat. Die Migration auf den aktuellen Modulmechanismus mit MODULE.bazel darf nicht als reine Dateiumbenennung behandelt werden. Jede externe Regel, Version und Registry-Auflösung gehört in die Review.

Zweite Phase: eine prüfbare Versionsmatrix anlegen

Die Matrix sollte mindestens diese Einträge enthalten:

  • Bazel-9-Version und konkreter Patchstand;
  • Version von rules_apple;
  • Version von rules_swift;
  • Xcode-26-Version;
  • macOS-Version;
  • verwendete Apple SDKs;
  • Zielarchitektur des Knotens;
  • Signatur- und Provisioning-Quelle.

Die offizielle Unterstützung der Regeln ist eine notwendige, aber keine hinreichende Bedingung. Ein Release kann Bazel 9 unterstützen, während eine bestimmte Xcode-Unterversion oder ein unbehobener Community-Fehler zusätzliche Tests erforderlich macht. Nicht offiziell bestätigte Issue-Berichte sind daher nur Prüfhinweise und keine Freigabegrundlage.

Dritte Phase: den sauberen Wiederholungsbuild durchführen

Für den Nachweis der Reproduzierbarkeit sollte die Pipeline einen frischen Klon verwenden, lokale Ausgaben entfernen und den lokalen Cache leeren. Danach wird derselbe Zielaufbau erneut gestartet. Zu protokollieren sind:

  • aufgelöste Modul- und Regelversionen;
  • erkannte Execution Platform;
  • verwendete Xcode- und SDK-Pfade;
  • Unterschiede zwischen dem ersten und zweiten Artefakt;
  • nicht deklarierte Eingabedateien;
  • reproduzierbare Fehlermeldungen nach einem absichtlichen Knotenwechsel.

Ein Cache-Treffer ist kein Beweis dafür, dass der Build unabhängig von der Umgebung ist. Er kann lediglich verdecken, dass eine Action auf einem bestimmten Knoten zuvor bereits erfolgreich ausgeführt wurde.

Erfahrung aus der Fehlersuche: Wenn ein Build nur mit warmem Cache funktioniert, muss der Cache vor der Architekturentscheidung geleert werden. Sonst wird eine alte Ausgabe gemessen und nicht die tatsächliche Fähigkeit des neuen Mac-Knotens.

05

Cache, Remote Execution und Remote Mac getrennt bewerten

Diese drei Begriffe beschreiben unterschiedliche Ebenen:

  • Ein Remote Cache speichert Eingaben und Ausgaben von Actions, damit spätere Builds vorhandene Ergebnisse wiederverwenden.
  • Remote Execution startet eine Action auf einem entfernten Ausführungsdienst, der eine passende Plattform und Toolchain anbieten muss.
  • Ein Remote Mac ist ein tatsächlich erreichbarer macOS-Host, beispielsweise für SSH, VNC oder eine CI-Agent-Verbindung.

Ein Remote Cache macht Linux nicht zu macOS. Ebenso löst ein Mac-Knoten keine falsch deklarierte Action oder eine fehlende Signatur. Für die Kapazitätsplanung sollten mindestens Cache-Treffer, Warteschlangenzeit des Mac-Pools, Dauer der kritischen Build-Phasen und Wiederholungen nach Fehlern getrennt erfasst werden.

Ein hoher Cache-Treffer bei gleichzeitig langer Mac-Warteschlange deutet auf zu wenige Apple-Ausführungsknoten hin. Eine kurze Warteschlange bei langsamen Link- oder Export-Phasen weist eher auf I/O, Toolchain oder Projektstruktur hin. Viele Wiederholungen nach Verbindungsabbrüchen sprechen für ein Sitzungs- oder Agentproblem, nicht automatisch für fehlende Rechenleistung. Ohne diese Trennung wäre eine Erweiterung des Pools eine unbelegte Vermutung.

Für einen Remote-Mac-Einsatz sollte die CI-Verbindung zudem nicht von einer geöffneten VNC-Sitzung abhängen. SSH oder ein dedizierter Agent muss Jobs nach einer getrennten grafischen Sitzung fortsetzen können. VNC eignet sich für Diagnose und manuelle Fehleranalyse, ist aber kein Ersatz für einen reproduzierbaren, unbeaufsichtigten Auftragspfad.

Wer die technische Trennung von Cache, Remote Execution und macOS-Ausführung genauer in die eigene Pipeline übertragen möchte, sollte zunächst eine Anleitung zur Konfiguration eines Remote-Mac-CI-Systems als organisatorische Checkliste verwenden und anschließend die Bazel-Actions im eigenen Repository einzeln messen. Entscheidend bleibt, dass ein dort beschriebener Zugriffspfad nicht automatisch die korrekte Bazel-Plattformdeklaration ersetzt.

06

Signierung und Tests entscheiden über die Produktionsreife

Simulator-Tests und Produktionssignierung sind zwei verschiedene Freigabestufen. Ein Simulatorlauf kann die Funktion einer Anwendung validieren, beweist aber nicht, dass ein Archiv mit dem richtigen Team, Profil und Zertifikat exportiert wird. Umgekehrt kann ein signiertes Archiv erzeugt werden, obwohl ein wichtiger Simulator-Test nicht ausgeführt wurde.

Die Verwaltung sollte Zertifikate, Schlüsselbund und Build-Cache logisch trennen. Zugangsdaten gehören nicht in das Repository und nicht in frei lesbare Build-Logs. Für die fachliche Prüfung der Beziehung zwischen Zertifikat, privatem Schlüssel, Bundle-ID und Provisioning Profile dient Apples Technische Dokumentation zu Codesignatur und Provisioning Profiles.

Vierte Phase: die Abnahmekette ohne grafische Anmeldung prüfen

Die Abnahme sollte in dieser Reihenfolge erfolgen:

  1. Einen frischen Checkout auf dem vorgesehenen macOS-Knoten bereitstellen.
  2. Bazel-Analyse und plattformneutrale Vorprüfungen ausführen.
  3. Einen unsignierten iOS-Build mit der festgelegten Xcode-Toolchain erzeugen.
  4. Simulator-Build und relevante Tests ohne VNC-Anmeldung starten.
  5. Ein Archiv erzeugen und die Signaturinformationen maschinenlesbar ausgeben.
  6. Das Artefakt exportieren und Bundle-ID sowie Profilzuordnung prüfen.
  7. Den Knoten während eines kontrollierten Jobs neu starten oder die Verbindung unterbrechen.
  8. Den Auftrag nach Wiederherstellung fortsetzen oder reproduzierbar neu einreihen.

Die exakten Zertifikatsnamen, Pfade und Remote-Endpunkte bleiben organisationsabhängig und sollten in der CI als geschützte Variablen oder Secret-Referenzen erscheinen. Als Freigabebeleg genügen nicht „Bazel beendet sich mit Exit Code null“; erforderlich sind ein prüfbares Testergebnis, ein Archiv, Signaturinformationen und ein dokumentierter Wiederherstellungsversuch.

07

Fünfte Phase: den Remote-Mac-Knoten vor dem Ausbau abnehmen

Für die Frage, wie ein Remote Mac in einen Bazel-Mischcluster eingebunden wird, ist die Action-Routing-Regel wichtiger als die Zugriffsart. Der Knoten benötigt eine deklarierte macOS-Plattform, die kompatible Xcode-Toolchain, einen CI-Agenten oder einen unterstützten Ausführungspfad und eine Zugriffsmöglichkeit für Wartung. Die Linux-Seite muss Jobs, die Apple SDKs benötigen, zuverlässig an diese Plattform weiterleiten.

Vor der Freigabe sollten folgende Fälle geprüft werden:

  • Verbindung während Analyse, Build und Test getrennt;
  • Knoten-Neustart zwischen zwei Actions;
  • Wechsel auf eine zweite zulässige Toolchain;
  • Ersatz eines defekten Knotens;
  • leerer lokaler Cache;
  • abgelaufene oder absichtlich ungültige Signaturdaten;
  • parallele Aufträge mit klarer Isolation;
  • Wiederaufnahme ohne manuelle grafische Anmeldung.

Unter DSGVO-Gesichtspunkten gehört außerdem festgelegt, welche Quelltexte, Logs, Zertifikatsmetadaten und Artefakte den eigenen Kontrollbereich verlassen. Für sensible Projekte sind Aufbewahrung, Zugriff, Löschung und Mandantentrennung schriftlich zu prüfen. Root-Rechte auf einem gemieteten Host sind operativ hilfreich, erhöhen aber die Verantwortung für Schlüssel, Benutzerkonten, Firewall-Regeln und Protokolle.

Für Teams mit mehreren Xcode-Ständen sollte die Toolchain zudem nicht nur über den Hostnamen ausgewählt werden. Eine deklarierte Plattform oder ein eindeutig markiertes Agentenmerkmal verhindert, dass ein kompatibel wirkender Knoten versehentlich mit einer anderen Xcode-Umgebung baut. Ein zusätzlicher Leitfaden zur Isolation mehrerer Xcode-26-Buildumgebungen kann bei dieser organisatorischen Trennung helfen; die konkrete Bazel-Plattformdefinition und die reale Apple-SDK-Prüfung müssen im Repository erfolgen.

08

Architekturentscheidung nach messbaren Kriterien

Die folgende Gegenüberstellung ist kein pauschales Ranking. Sie zeigt, welche Bedingungen erfüllt sein müssen, bevor eine Option für den jeweiligen Einsatz vertretbar ist.

Option Geeignete Aufgaben Stärken Kritische Nachweise Entscheidung
Einzelner Remote Mac Vollständiger Bazel-9-iOS-Build, Simulator, Signierung und Export Schneller Aufbau, eine klar kontrollierte Apple-Umgebung Sauberer Wiederholungsbuild, unbeaufsichtigte Signierung, Neustart- und Verbindungswiederherstellung Für kleine Teams und Pilotphasen wählen
Linux plus Remote Mac Prüfungen und Generierung auf Linux, Apple-Actions auf macOS Gute Trennung, vorhandene Linux-Kapazität bleibt nutzbar, Apple-Knoten werden gezielt eingesetzt Action-Logs, korrekte Plattformregeln, Cache-Verhalten, Warteschlange und Artefaktübergabe Für mittlere und größere Teams bevorzugen
Vorläufige Migration Linux-Vorprüfungen, aber kein verlässlicher Apple-Abschluss Verhindert eine unsichere Produktionsumstellung Fehlende Regelunterstützung, nicht reproduzierbare Toolchain oder ungeklärte Signatur Migration stoppen, Matrix und Toolchain zuerst klären
Zusätzliche Mac-Knoten Parallele Apple-Builds und verkürzte Wartezeiten Mehr Durchsatz bei belegtem Pool Wiederholt hohe Mac-Warteschlange bei ausreichender Cache- und Netzwerkleistung Erst nach Messung von Queue, Action-Dauer und Retries erweitern

Für die Wahl zwischen eigenem Mac mini, lokaler Hardware und Remote Mac sollten neben dem Kaufpreis auch Bereitstellung, Ausfallersatz, Standortzugriff, Stromversorgung, Wartung und sichere Schlüsselverwaltung berücksichtigt werden. Eine Übersicht zu den verfügbaren Mac-Mietoptionen von NodeMini kann als Ausgangspunkt für einen isolierten Pilotknoten dienen; sie ersetzt jedoch nicht die technische Abnahme mit dem eigenen Bazel-Projekt.

Ein Remote Mac ist nicht für jede Organisation die beste Dauerlösung. Wer über lange Zeit eine gleichmäßig hohe Last mit klarer Hardwarekontrolle, physischem USB-Zugriff oder eigener Sicherheitszone benötigt, kann mit gekaufter Hardware besser fahren. Für einen zeitlich begrenzten Migrationsversuch, zusätzliche Xcode-Umgebungen, Release-Spitzen oder eine räumlich getrennte CI-Stufe ist die Miete dagegen flexibler, weil kein vollständiger Hardwarekauf vor dem Kompatibilitätsnachweis erforderlich ist.

Der direkte Vergleich mit einer bestehenden Linux-CI zeigt die praktischen Nachteile der bisherigen Lösung: Linux kann Apple SDKs und Simulatoren nicht vollständig bereitstellen, Signatur- und Exportfehler werden oft erst spät sichtbar, und ein provisorischer virtueller oder lokaler Workaround erschwert Reproduzierbarkeit sowie Wartung. Ein gemieteter Remote Mac von NodeMini bietet für diesen begrenzten Zweck eine echte macOS-Ausführungsumgebung, sodass das Team zunächst Cache, Tests, Signierung und Neustartverhalten mit dem realen Projekt messen kann. Erst diese Ergebnisse sollten bestimmen, ob ein einzelner Knoten genügt oder ein gemischter Pool dauerhaft betrieben wird.

Für die Umsetzung empfiehlt sich als nächster Schritt ein isolierter Bazel-9-Lauf auf einer Remote-Mac-Instanz: Versionsmatrix festhalten, Actions klassifizieren, vollständiges Archiv erzeugen und den Knoten anschließend ohne manuelle Anmeldung wiederherstellen. Wenn die Abnahme erfolgreich ist, kann die Linux-plus-Mac-Architektur gezielt wachsen; wenn nicht, liegt die nächste Maßnahme bei Regelversion, Xcode-Kombination, Signaturverwaltung oder Action-Deklaration und nicht automatisch bei zusätzlicher Hardware.