Une chaîne de build et signature iOS/macOS sans matériel Apple
Contexte
Produire et signer du logiciel Apple — compilation, tests, signature,
soumission à l’App Store — suppose normalement un Mac. Le besoin ici était de
couvrir toute cette chaîne (xcodebuild, clang/swiftc, tests unitaires
non-UI, codesign, notarytool, packaging) sans acheter de matériel Apple :
une machine macOS virtualisée, persistante, pilotée entièrement en ligne de
commande sur un hôte Linux.
La contrainte dure, et non contournable : aucun GPU accéléré n’existe en virtualisation macOS moderne. macOS ne prend en charge aucun GPU NVIDIA depuis High Sierra, et l’iGPU de l’hôte n’est pas davantage supporté — le rendu reste logiciel. Cette limite matérielle irréductible détermine en cascade une bonne partie des choix qui suivent, à commencer par le modèle de machine émulé.
Démarche
Le dépôt est organisé en une quinzaine d’étapes numérotées, chacune documentée selon un même format — objectif, état des lieux, procédure, valeurs et justifications, vérification, mode d’échec, retour arrière — et outillée d’un script idempotent avec un mode de contrôle non destructif. Plusieurs blocages techniques réels ont dû être résolus, avec preuve à l’appui à chaque fois :
Le modèle de CPU choisi bloquait le démarrage sans message exploitable. Un modèle QEMU proche mais inadapté empêchait XNU de démarrer avant même l’initialisation de la console noyau. Diagnostic par introspection du modèle de CPU exposé, correction du modèle et du masquage de topologie.
Le journal de démarrage restait silencieux sans un bit d’option précis. Router les journaux noyau vers le port série demande un indicateur de debug spécifique en plus de l’option série elle-même — sans lui, aucune trace, donc aucun diagnostic possible sur les blocages suivants.
Une panique noyau causée par la combinaison identité machine / option de masquage. Le SMBIOS choisi (une classe de machine sans iGPU, précisément pour éviter un conflit avec l’absence de GPU) entrait en conflit avec une option de compatibilité activée par ailleurs. La règle de blocage d’OpenCore ne s’appliquait pas au cas précis, le composant fautif étant chargé après la mise en cache du noyau. Contournement construit sur mesure : un composant système factice généré par script, sans binaire réel, qui prend la priorité sur le composant problématique.
Xcode récent : le kit de développement présent ne signifie pas la plateforme installée. La commande standard de téléchargement de plateforme restait bloquée indéfiniment sur cette configuration. Diagnostic par échantillonnage de processus, puis contournement manuel complet : lecture du catalogue Apple, téléchargement direct, vérification d’intégrité croisée, déchiffrement et extraction, installation par l’outil de runtime — une chaîne reconstruite étape par étape là où l’outil officiel échouait silencieusement.
Signer à distance sans session graphique. Le trousseau de clés ne se déverrouille pas de lui-même : il faut le déverrouiller et compiler dans la même session distante, sinon la signature échoue sans message clair.
Limites assumées
Ce qui ne fonctionnera jamais sur cette configuration est annoncé en tête de la documentation, pas découvert en cours de route — tous hors de portée pour la raison matérielle déjà citée :
Accélération graphique native
Bloquée par l’absence de GPU exposé à la VM — la limite matérielle qui détermine cette liste.
Simulateur iOS
Indisponible pour la même raison matérielle.
Previews d’interface
Indisponibles pour la même raison matérielle.
Outils de profilage GPU
Sans objet pour la même raison matérielle.
Second choix assumé : l’identité de la machine virtuelle est un identifiant de test au format valide, mais délibérément non vérifié auprès d’Apple. Conséquence directe et annoncée : les services liés au compte Apple (messagerie, appels, synchronisation cloud) ne fonctionnent pas, et aucun contournement n’est proposé. Ce choix n’affecte en revanche ni la compilation, ni la signature, ni la soumission — ces opérations reposent sur le compte développeur et les certificats, pas sur l’identité machine. Une partie de la valeur de ce projet tient à cette distinction précise entre ce qui dépend de l’identité machine et ce qui dépend du compte développeur.
Troisième limite, documentée dans un audit de reproductibilité dédié : cinq opérations ne s’automatiseront jamais complètement (l’installation graphique initiale de macOS, un téléchargement derrière une session authentifiée, quelques écrans du portail développeur). Une revendication bornée plutôt qu’une automatisation totale surclamée.
Résultat
La chaîne a été validée de bout en bout jusqu’à l’acceptation réelle par Apple : build, signature et dépôt réussis sur App Store Connect. Un audit de reproductibilité volontaire a mesuré qu’une reprise complète sur une autre machine prendrait environ une demi-journée, dont l’essentiel en installation et téléchargements sans intervention active — et a corrigé en direct un défaut trouvé pendant cet audit (une sauvegarde manquante de l’identité de signature). Un temps de compilation de référence a été mesuré à moins de trois minutes pour une construction de vérification.