2026-04-30 Миграция iOS CI с Intel x86_64 на Apple Silicon ARM64 с xcodebuild на арендованном облачном Mac (HK / JP / KR / SG / US)
Apple по-прежнему поставляет Xcode для Intel, но 2026 — год, когда большинство мобильных команд перестаёт платить облачную надбавку за срезы x86_64, которые уже не уходят в прод. Если очередь всё ещё смотрит на старые Intel Mac mini, а продуктовые бинарники только arm64, вы финансируете дублирующие графы зависимостей и более медленные холодные старты xcodebuild test, чем у конкурентов, уже стандартизировавших Mac mini M4 в Гонконге, Токио, Сеуле, Сингапуре и США. Этот материал от 2026-04-30 — миграционный бриф для release-инженерии: инвентаризация «толстых» бинарников, нормализация ARCHS, пересборка CocoaPods без Intel-only вендоров, двойная полоса достаточно долго, чтобы доверять флейкам, затем переключение маршрута по умолчанию на ARM64 с резервной Intel-полосой для редких CLI. Он дополняет удалённые Archive, параллельные дорожки Xcode, мульти-Xcode матрицы и ограничения Swift 6 strict concurrency, которые иначе ведут себя под параллельной нагрузкой.
Снимок: почему «собирается на моём M3» недостаточно
Ноутбуки скрывают грехи: тёплые кэши модулей, прозрачный Rosetta и человеческое терпение. CI должен выставлять их напоказ за минуты. Три признака, что вы в середине миграции, а не в конце:
- Ошибки линкера с
undefined symbols for architecture arm64, покаlipo -archsвсё ещё показываетx86_64на вендорских фреймворках. - Дрейф целей симулятора: intel-эра destinations остались в YAML, хотя Apple убрал образы из новых бандлов Xcode.
- Лживые метки runner: теги GitHub Actions или Buildkite говорят
macos-intel, хотя shell уже arm64 из-за переиспользования имён.
xcodebuild build после нормализации ARM64 для среднего приложения; заложите 14 календарных дней наблюдения двойной очереди перед удалением Intel-ёмкости.
Инвентаризация бинарников: докажите оставшийся x86_64 до обвинений Swift
Пройдите каждый .framework, .a и предсобранный XCFramework под Carthage/Build, Pods/ или ThirdParty/. Две команды для каждого тикета миграции:
find . \( -name "*.framework" -o -name "*.a" -o -name "*.xcframework" \) -print0 | xargs -0 -I@ sh -c 'echo "@:"; lipo -info "@" 2>/dev/null || file "@"'
Если вендор всё ещё только Intel, открывайте коммерческий тред, а не хак с EXCLUDED_ARCHS=arm64, который тихо тащит Rosetta в прод для инженеров. На арендованных хостах с self-hosted runner централизуйте скрипт инвентаризации в одном infra-репо, чтобы каждый регион запускал один детектор; расхождение между узлами JP и US плодит «зелёно в Токио, красно в Вирджинии».
Матрица runner: ответственность Intel-полосы и ARM-полосы
В переходный период каждая полоса должна нести явные гарантии — не притворяйтесь, что обе CI одинаковы.
| Полоса | Владеет | Не должна владеть |
|---|---|---|
| ARM64 основная | PR по умолчанию, тесты симулятора, Archive в TestFlight | Legacy CLI без arm64, кроме изолированной песочницы |
| Intel аварийная | Вендорские бинарники в ожидании обновления, разовые проверки паритета | Долгосрочная подпись; не смешивайте прод-ключи |
| Дымовая гибридная | Скрипты file, проверяющие fat-срезы где нужно |
Тихая зависимость от Rosetta для целей iOS-приложения |
Флаги xcodebuild и настройки сборки как политика
Закодируйте ниже в общих фрагментах xcconfig или экспортах Fastlane: один раз спорите, везде наследуйте.
| Настройка | Рекомендуемое значение CI ARM64 | Заметки |
|---|---|---|
ARCHS |
arm64 |
Явное лучше «standard», когда схемы приложения и расширений расходятся. |
ONLY_ACTIVE_ARCH |
NO для CI в духе Release; YES для внутреннего Debug, если принимаете тонкие срезы. |
Расхождение даёт флейки симулятор против устройства. |
EXCLUDED_ARCHS[sdk=iphonesimulator*] |
Обычно пусто на Apple Silicon | Уберите intel-эра исключения, случайно убивающие arm64-симулятор. |
Свяжите флаги с закреплённым DEVELOPER_DIR на задачу по руководству по матрице xcode-select: ничто так не путает постмортем, как две версии Xcode, по-разному читающие один проект.
CocoaPods, SwiftPM и бинарные графы, сопротивляющиеся ARM64
Пользователям CocoaPods следует регенерировать Pods/ на arm64-хосте, а не rsync с Intel, чтобы script-фазы компилировались с правильной архитектурой. Командам SwiftPM стоит убедиться, что бинарные цели в Package.resolved действительно содержат arm64-apple-ios, где применимо. Когда фреймворки отстают, временные source-build или pin форка — проценты копятся ежедневно.
uname -m показывает arm64, а file $(which node) — x86_64, OpenClaw или JS-линтеры тихо идут через перевод: горит CPU, логи крашей нечитаемы.
Двойная полоса: глубина очереди, память, диск
Mac mini на Apple Silicon сияют, пока три тяжёлых Archive плюс UI-тесты не съедают 16 ГБ ОЗУ. На время миграции ограничьте одновременные xcodebuild на хост по измеренному давлению памяти: отдельные метки для «ARM только компиляция» и «ARM Archive». Диск: ARM64 не уменьшает DerivedData; сочетайте миграцию с изоляцией DerivedData, чтобы эксперименты не вытесняли кэши друг друга.
Восемь шагов переключения, которые SRE вставит в Jira
- Заморозить обновления зависимостей на 72 часа до выходных переключения.
- Запустить скрипт инвентаризации на каждом региональном хосте; зафиксировать diff в infra-репо.
- Применить политику xcconfig ко всем схемам, включая расширения.
- Пересобрать Pods/SwiftPM с чистых checkout на arm64.
- Включить две очереди с одинаковыми сидами; сравнить время стены, флейки, размеры артефактов.
- Переключить маршрут PR по умолчанию на ARM64, оставив Intel только для чтения.
- Наблюдать 14 дней; при всплеске сбоев откатывайте метки, а не секреты.
- Списать Intel или отвести на нишевые задачи с биллинг-тегами вне мобильных путей.
Таблица метрик: что считать успехом на арендованном M4
| Метрика | База Intel (пример) | Цель ARM64 |
|---|---|---|
| Чистая сборка p50 | 19,5 мин | 12,0 мин или лучше на том же коммите |
| UI-тесты симулятора p95 | 41 мин | 28–33 мин после нормализации целей |
| Прокси недельной энергозатрат | 1,00 (нормировано) | 0,62–0,78 с учётом простоя Вт и пропускной способности |
Замените примеры своими гистограммами Grafana или Buildkite — без сырых кривых не выпускайте миграционную презентацию.
FAQ: Rosetta, симуляторы, подпись
| Вопрос | Практический ответ на 2026-04-30 |
|---|---|
| Стоит ли гонять CI под Rosetta ради скорости? | Нет для компиляции iOS: нативные arm64-цепочки выигрывают; Rosetta — только для наследуемых вспомогательных CLI. |
| Нужны ли отдельные подписи на архитектуру? | Сами удостоверения не привязаны к arch, но профили и entitlements должны соответствовать фактически отгружаемым бинарникам — переэкспорт после изменения графа. |
Для автоматизации подписи продолжайте использовать Keychain и профили CI: миграции архитектуры часто вскрывают скрытые несоответствия профилей.
Почему ставка на bare-metal Mac mini M4 всё ещё выигрывает
ARM64 CI — не только тактовая частота: это детерминированное поведение тулчейна без лжи гипервизора. Арендованный Mac mini M4 с 1–2 ТБ NVMe в регионах MacXCode даёт место для двойных полос, нескольких деревьев DEVELOPER_DIR и всплесков DerivedData, пока инженеры спят в другом часовом поясе. Этот запас превращает миграцию в измеряемый и обратимый раскат, особенно с прозрачными ценами на второй узел вместо перегрузки первого. Для редких визуальных подтверждений — VNC; повседневная миграция остаётся SSH и grep по логам.
Поднимите нативные ARM64-билдеры рядом с legacy
Mac mini M4, HK / JP / KR / SG / US, SSH и опционально VNC