Sur un Mac bare metal loué ou possédé, la question n’est pas seulement « quelle version de Xcode ? » mais si vous installez le bundle Xcode.app ou uniquement les Command Line Tools (CLT). Le CLT apporte clang, git et une chaîne minimale pour certains xcodebuild ; Xcode.app embarque les runtimes simulateur, l’interface de signature et les chemins que beaucoup de scripts supposent par défaut. Cette FAQ compare les deux approches pour des archives iOS en parallèle sur plusieurs dépôts, la gestion des runtimes simulateur, la dérive de xcode-select et l’empreinte disque NVMe. Pour la contention disque quand plusieurs xcodebuild cohabitent avec Bazel ou Gradle, enchaînez avec
2026 — Pool CI Mac entreprise : caches Bazel et Gradle distants, partitions NVMe et xcodebuild parallèle — FAQ
; pour les simulateurs et les workers de tests, voir
2026 — CI Mac d'entreprise : tests Xcode en parallèle, Test Plans et contention des simulateurs — FAQ.
1. CLT seul : gains réels et limites dures
Installer uniquement les CLT réduit la surface installée et évite de monter un .xip complet sur chaque nœud. C’est pertinent pour des jobs compilation Swift/ObjC sans simulateur ou des pipelines xcodebuild avec SDK device explicite. En revanche, les runtimes iOS/watchOS/tvOS livrés avec Xcode et les flux qui supposent /Applications/Xcode.app posent problème : soit le job échoue, soit vous bricolez des chemins non supportés. Sur Apple Silicon, le gain NVMe se mesure surtout si vous évitez plusieurs copies complètes de Xcode.app sur le même volume.
Xcode.app.2. Xcode.app complet : quand c’est le défaut raisonnable
Archive + export IPA, tests UI sur simulateur, installation de DeviceSupport ou de profils via des workflows éprouvés, et les outils qui lisent DEVELOPER_DIR en le fixant sur le bundle : autant de cas où Xcode.app simplifie la documentation interne. Sur un pool multi-dépôts, une image unique « Xcode 16.x + runtimes requis » réduit les tickets « ça marche sur ma machine ». Le coût est double : espace NVMe (plusieurs dizaines de Go par version) et temps de bake des images. Prévoyez un volume ou une partition dédiée aux CoreSimulator et aux caches dérivés, séparée des artefacts Git et des caches package managers.
3. Archives parallèles et multi-dépôts : disque avant CPU
Lancer deux ou trois xcodebuild archive simultanés sur un même hôte saturera vite les IOPS et le journal APFS, même avec un NVMe « rapide ». Isolez -derivedDataPath par job ou par dépôt, imposez des quotas de concurrence au niveau orchestrateur, et gardez une marge d’au moins un build froid par emplacement temporaire. Les signatures et l’export peuvent doubler les écritures transitoires : surveillez l’attente disque avant d’ajouter des cœurs. Si vous mélangez jobs « CLT légers » et jobs « Xcode complet », évitez qu’ils partagent le même répertoire DerivedData par défaut.
4. Runtimes simulateur et empreinte NVMe
Chaque runtime simulateur ajouté grossit fortement le volume système ou le dossier développeur. Sur une ferme bare metal, standardisez la liste des OS simulés (par exemple deux versions iOS) plutôt que d’installer « tout ce qui existe ». Planifiez un nettoyage après les montées de version Xcode : anciens runtimes, caches CoreSimulator orphelins, et modules dérivés. Comparez au budget artefacts CI (IPA, symboles) : les petits fichiers nombreux peuvent saturer les IOPS avant le débit séquentiel annoncé.
5. Dérive de xcode-select et automatisme
Un script ou un agent qui appelle sudo xcode-select -s sans garde-fou est une course critique entre jobs parallèles : un job bascule la chaîne globale pendant qu’un autre archive. Préférez DEVELOPER_DIR=/Applications/Xcode_16.app/Contents/Developer par processus, ou des environnements par worker (conteneur, utilisateur système dédié, ou répertoire d’installation unique par slot). Journalisez la valeur effective au début de chaque build et échouez tôt si elle ne correspond pas à l’étiquette d’image attendue. Après une mise à jour macOS mineure, vérifiez que le chemin du bundle n’a pas changé côté politique MDM.
- Interdire le
xcode-selectglobal dans les hooks partagés ; isoler par job ou par VM logique. - Étiqueter les runners avec la build number Xcode et la liste des runtimes installés.
- Tester un archive + export complet après chaque changement d’image, pas seulement
xcodebuild -version.
6. FAQ synthétique pour la plateforme
- Peut-on faire toute la CI iOS avec CLT seuls ? Rarement pour une chaîne complète archive + simulateur + distribution ; possible pour des sous-étapes ciblées si vous validez chaque chemin d’outils.
- Deux versions Xcode sur un même Mac ? Oui, avec bundles renommés et
DEVELOPER_DIRstrict ; surveillez l’espace NVMe et les mises à jour des runtimes. - Priorité quand le disque est plein ? Purger les DerivedData des branches mortes, puis les caches simulateur non utilisés, avant de retirer une version Xcode entière.
- Bare metal loué : qui gère les XIP ? Documentez la procédure d’upgrade (fenêtre, rollback, tests) ; une demi-journée d’indisponibilité vaut mieux qu’une image partiellement installée.
Apple Silicon, macOS et Mac mini : figer une pile de build réaliste
Les arbitrages CLT versus Xcode.app n’ont de sens que sur une pile stable : macOS et Xcode alignés, Apple Silicon avec mémoire unifière suffisante pour plusieurs linkers, et des mécanismes de sécurité (Gatekeeper, SIP, FileVault) qui rassurent l’équipe sécurité pour des runners distants. Un Mac mini silencieux et sobre convient pour reproduire en labo les mêmes chemins que vos nœuds cloud dédiés.
Pour valider vos images avant de les pousser sur tout le pool, le Mac mini M4 reste un repère simple et économe en énergie. Si vous comparez des hébergeurs, la page d’accueil Macstripe permet de choisir région et configuration sur du Mac cloud dédié — équipez votre équipe d’un Mac mini M4 pour aligner bench locale et production.