シンガポール・日本・韓国・香港・米東・米西の専用リモートMac(M4 / M4 Pro)でCIを運用しているのに、x86_64のみの静的ライブラリやレガシーCLT、ユニバーサル/ファット成果物に静かに依存しているケースは少なくありません。本稿では痛みの分解、意思決定マトリクス、6手順Runbook、測定可能な閾値、リースFinOpsを監査可能な形に整理し、Flutter/React Native同機、DerivedData衛生、CocoaPods/SPMミラーとディスクの各記事へ橋渡しします。
lipo -infoが単一アーキテクチャを示し、リンク時に「macOS-arm64向けにビルドしているがmacOS-x86_64向け成果物をリンクしようとしている」へ進みます。xcframework化、再ビルド配布、もしくは制御されたRosetta経路が必要です。arch=arm64や実機プールへの移行が前提です。本質はアーキテクチャ制約がバージョン管理に入っていないことです。専用機はピン留めに最適ですが、許容アーキ集合とREQUIRES_ROSETTAが無いとM4でも誤アーキの再試行と過剰cleanでリース分を浪費します。セルフホストRunnerの並列度と同格のゲートにしてください。
Rosettaは無料の互換レイヤではありません。起動コスト・ピークメモリ・SSD書き込み増幅が変わります。モバイル二系統と重なると「CPUは空いているのに赤い」症状が出やすく、RosettaをFinOps科目として計上してください。
リージョン選択は遅延とリース設計を直します。ミラー同区でも赤いなら、地域再配分より先にARCHS表へ戻ってください。多地域コスト/遅延ガイドと併読する際は、ping表より前にアーキゲートを置いてください。
SwiftPM ではバイナリターゲットやプリコンパイル済みモジュールがアーキテクチャ前提を隠しやすいため、swift build -v のログに出るリンク行をアーカイブし、MR ごとに差分比較できるようにしてください。Xcode 側では ARCHS と EXCLUDED_ARCHS を .xcconfig へ寄せ、ローカル上書きを禁止すると「誰の Mac でも同じ失敗」に揃い、専用リモート機上の再現性が上がります。
xcodebuild -showBuildSettings の出力から ARCHS / VALID_ARCHS / ONLY_ACTIVE_ARCH を抜き出し、ナイトリーでスナップショット比較する方法も有効です。差分が無いのにリンクだけ失敗した場合は、前段の lipo 結果と突き合わせ、Pods 以外(社内フレームワーク、サードパーティ .xcframework の取り込みミス)を疑う順序が短時間で効きます。
短期リースでは「クリーンの頻度」と「二アーキビルドの可否」をセットで決めてください。DerivedData のスナップショット戦略と矛盾しないよう、ユニバーサル検証用の派生データルートを別パスに分離し、PR 本線のキャッシュを汚染しない運用が安全です。
| 観点 | 全ネイティブarm64(既定) | 混在 / Rosetta(例外) | 赤線(並列停止または分割) |
|---|---|---|---|
| リンク整合性 | lipoが全域arm64、潜むx86子なし |
x86各バイナリにベンダ撤退日 | 同一schemeでarm64専用とx86専用静的庫が橋なし混在 |
| 壁時計の予測性 | 分散が低くSLO基線に適する | 分散許容だが別ダッシュボード必須 | ネットワーク無変更の連続noopで>35%ブレ |
| メモリと並列 | 統合メモリ表に沿い慎重に並列増 | 既定で並列−1、重いSimulator併用禁止 | 長寿命Rosetta補助とswap持続増 |
| ディスク/DerivedData | 伸び予測可能、プロジェクト別パス | ファット成果物は清掃頻度を上げる | ルート空き<12GBで二アーキ*.o嵐継続 |
| リースFinOps | 日次/週次で多くの反復を賄う | 短い互換バーンイン枠で本流を汚さない | 本契約がRosettaピークを科目なしで吸収 |
第一原理:Rosetta 2は動的二進翻訳であり「追加コア」ではありません。専用ホストではピーク形状と再現性が変わります。
uname -m、重要バイナリのfile、疑わしい.aへのlipo -info。ARCHS集合を凍結:EXCLUDED_ARCHSとONLY_ACTIVE_ARCHの既定と例外を文書化。REQUIRES_ROSETTA=1、期限超過で自動失敗。rm -rf ~/Library全面禁止。set -euo pipefail echo "machine: $(uname -m)" find "$WORKSPACE/Pods" -name "*.a" -maxdepth 6 2>/dev/null | head -n 40 | while read -r f; do echo "---- $f" lipo -info "$f" || file "$f" done xcodebuild -scheme "$SCHEME" -configuration Debug ONLY_ACTIVE_ARCH=YES ARCHS=arm64
数値の出典は社内ベースラインに置き換えてください。ここで示す 18% / 40% / 12% は「観測窓を固定したうえで週次レビューに載せるための仮置き閾値」であり、ベンダ製品の公式ベンチマークではありません。Rosetta 比率は powermetrics やジョブごとの CPU 秒集計から近似できますが、完全精度より週次の相対比較が目的です。
CocoaPods 利用時は post_install で各ターゲットの ARCHS を上書きしがちですが、上書き結果を pod install 後に再度 lipo で検証しないと「Podfile では arm64 と書いたつもり」が実際の .xcconfig では漏れることがあります。SwiftPM 併用リポジトリでは Xcode プロジェクトと Package 解決結果の両方に同じアーキ方針を流し込む必要があり、片方だけ arm64 にしてもリンク段階で元に戻ります。
リモート専用 Mac における実務上のコツは、インタラクティブセッションと CI ジョブで同じクリーンアップ関数を呼ぶことです。エンジニアが手動で試した後に Rosetta プロセスが残り、夜間バッチのピークと重なると、原因切り分けが一気に難しくなります。セッション終了フックで ./gradlew --stop や独自の翻訳ヘルパー停止を挟む運用は、モバイル二系統の Runbookとも整合します。
前者は監査不能なキャッシュ、後者はリース分散と原因切り分けを壊します。再現可能なアーキ契約はどちらも生みません。
アーキ方針・並列・清掃を同一ワークブックに置き、Git/成果物のホットパスをノード大区と揃えたい場合、MACCOMEのMacクラウドは物理Mac mini M4 / M4 Proと日/週/月/季の柔軟リースで六主要リージョンをカバーします。まずグラフとディスクピークを安定化し、その後にコンパイル並列を伸ばしてください。
ARCHS_POLICY.mdとBINARY_INVENTORY.csvをゲート添付にオンボーディングで答えられる三問:既定arm64-onlyか、ユニバーサルを出すパイプラインはどれか、署名素材に触れない清掃手順はどれか。Monorepo FinOpsと二重に予算衝突しないよう境界を書き分けます。
スプリント末の二点確認:潜むx86子は残っていないか、Rosetta並列が誤って有効化されていないか。
レビュー観点では、バイナリ成果物のハッシュとアーキテクチャ一覧を同じ表に載せると議論が早く収束します。「この週はネットが遅かった」ではなく「この週は x86 スライスが一つ増えた」といった因果が見えるからです。大企業のゲート審査に出す場合も、表形式の証跡があるとセキュリティレビュー側が追いやすくなります。
最後に、Rosetta を恒久的に前提にする設計は、Apple のプラットフォームロードマップに対して常にベットになります。移行計画が書けない依存は、技術的負債として利息が付き続けるため、日没日をカレンダーに載せない限り承認しない運用が安全です。専用リモート Mac は検証に最適ですが、負債の保管庫にはしないでください。
依存がすべてxcframework化済みでCIはiOS arm64のみ、macOSユニバーサル不要ならRunner/Simulator容量記事へ。月次でlipo -infoにx86が出るならPods/SPM記事と併置してください。