2026-04-24 レンタル・クラウド Mac 上の xcodebuild CI における Swift 6 厳格並行性、Sendable と @MainActor
HK / JP / KR / SG / US ですでに Apple Silicon ホストを採用した iOS / macOS ビルドオーナーは、二段目の負荷に直面しています。Swift 6 言語モデルと 厳格並行性チェックは、温まったノート PC と、レンタル SSH Mac 上の 冷えて並列化された xcodebuild ジョブの間に、「自分のマシンでは通る」 を測定可能な差に変えます。本稿(2026-04-24)は言語チュートリアルではなく、ビルド設定(SWIFT_STRICT_CONCURRENCY、Swift 言語バージョン)、DerivedData と index store の隔離、並列と セルフホスト Runner トポロジで爆発する Sendable / nonisolated / MainActor ノイズの 段階的移行を対応付けます。tmp DerivedData + xcresult 隔離および リモートアーカイブとクロスリンクし、シンガポールの同じ Node が 米国シャードがプライベートだと思っていた共有 ModuleCache をスラッシングしないようにしてください。
ヘッドレス CI で Swift 6 厳格並行性が違って見える理由
厳格チェックは、シミュレータが決して踏まない データ競合を浮かび上がらせます。UI メインスレッドが捕捉した var の寿命を覆い隠すからです。CI では 並列 swift-frontend ジョブと whole-module 最適化が診断の順序を入れ替えます。64 GB の開発用ノートで一晩コンパイルできた同じ パッケージが、インクリメンタルがオフの -warnings-as-errors レーンで落ちることがあります。厳格並行性は、すでに扱っている アーカイブ bitcode 廃止や CLT とフル Xcode のパリティと同じく、固定した DEVELOPER_DIR を持つ 別パイプラインステージと、SWIFT_STRICT_CONCURRENCY=targeted のまま残してよいターゲットの書面ポリシーとして扱ってください。
インデックス再構築の工数も見積もってください。新しい DerivedData に対する初回 Swift 6 フルビルドでは、App Intents や大きめの WidgetKit 拡張を同梱するアプリは ExtractAppIntentsMetadata などのステップに数分多く使うことがあります。ウォールクロックの跳ね上がりは並行性の失敗ではありません。初回 SwiftPM レジストリ のウォームと同じ冷キャッシュ系で、PM にあらかじめ同じ温度感で伝えてください。移行前後の p95 をダッシュボードに残し、「Swift 6 週」がクラウド容量の回帰に見えないようにします。
ビルド設定:言語バージョンと厳格並行性モード
プロジェクトまたは xcconfig で三つのつまみを揃えます。(1) 出荷する Swift 6 ツールチェーンに SWIFT_VERSION;(2) マージブロッキングレーンでは SWIFT_STRICT_CONCURRENCY を complete、レガシー ベンダー静的 lib は注釈が付くまで targeted かもしれない;(3) Swift 6 のターゲットごとの デフォルト隔離で、UIKit / SwiftUI モジュールは明示的な @MainActor カバレッジを欲しがります。CI YAML ではスキームがまだ持てないときだけオーバーライドを渡します。例:助言レーンでは OTHER_SWIFT_FLAGS=-warn-concurrency。ビット再現が要るリリースアーカイブに 黙って混ぜないでください。パッケージプラグインとアプリターゲットの違いを文書化してください。プラグインビルドログは、重要なバイナリに -strict-concurrency=complete を有効にするまでエラーを隠すことがあります。
xcodebuild 呼び出し:アーカイブ vs ビルド vs 解析
ホストで DEVELOPER_DIR=/Applications/Xcode.app を一つに固定し、明示的な -configuration と -destination でスキームのドリフトを避けます。UI テストの前のコンパイルのみの 厳格ゲートなら xcodebuild -scheme App build -destination 'platform=iOS Simulator,name=iPhone 16' に CODE_SIGNING_ALLOWED=NO を付け、コンパイラ信号だけ欲しいときに使い—二番目のジョブで署名を戻した シミュレータテストを回し、XCTest + xcresult ガイドと同じ分割にします。最小の厳格ゲート:
DEVELOPER_DIR=/Applications/Xcode.app xcodebuild build -workspace App.xcworkspace -scheme App -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 16' -derivedDataPath "$CI_DERIVED/Swift6Gate" OTHER_SWIFT_FLAGS='$(inherited) -warn-concurrency'
Sendable で二回連続同一失敗は実コード欠陥として扱い、Xcode の幽霊ではない。
並列レーン、DerivedData、インデックスストア
扇状に広げるときは(M4 扇出を参照)子ジョブごとにプライベートな -derivedDataPath を与え、厳格ステージでは インクリメンタルをオフにして HK / JP / KR / SG / US ビルダー間で診断を 決定的にすることも検討してください。NFS 的マウントで共有 DerivedData は、リトライで消える幻の 「cannot assign through subscript: base is not a concurrent value」 エラーを生む最短ルートです—まさに 隔離記事が xcresult について警告しているフレークパターンです。コストで 必須共有なら、少なくとも Index/DataStore を $(CI_JOB_ID) 接頭の per-job プレフィックスへ。
移行マトリクス:警告、エラー、オーナー
| シグナル | アクション | オーナー |
|---|---|---|
Sendable クロージャ捕捉 |
値型へリファクタ、型を Sendable にする、または actor へ逃がす | フィーチャースクワッド |
| MainActor 隔離のドリフト | UI 更新を小さなファサード型に集約 | クライアントリード |
| Sendable なしのサードパーティバイナリ | モジュール境界でラップ、ベンダー issue を固定、またはフォーク | ビルドプラットフォーム |
並行性エラーではないとき
一部の失敗は Swift 6 問題に見せかけます。プロビジョニングとキーチェーンの不調は CodeSign 中に swift-frontend 行とインタリーブします。dSYM 欠落はシンボリケーションを壊し、コンパイラではありません。dSYM 衛生を厳格レーンと同じ週次レビューに含めないと、オンコールが誤った diff を追います。
署名、エンタイトルメント、同じビルドでの「厳格」
コンパイラチェックを増やすリリース列車と プロビジョニングローテーションを同時に入れるのはリスクが高いです。順序:(1) 捨てカナリアで署名が緑であることを証明、(2) 厳格ステージを有効化、(3) その後でデフォルトスキームに SWIFT_STRICT_CONCURRENCY=complete を強制するフィーチャーフラグをマージ。同じ SSH Mac mini M4 プールが両方をホストできても、ジョブを一つのワークスペースフォルダでインタリーブしないでください。並列性は、すでに アーカイブと シムの文書に従っているときだけ強みになります。
関連 MacXCode ガイド
並行性失敗が実は 依存グラフ不一致なら SwiftPM + レジストリキャッシュと Ruby + CocoaPods の決定性から始めてください。Xcode Cloud と専用ホストを混在させるチームは両方で言語フラグを揃えないと、専用の厳格レーンだけが Xcode Cloud が見なかったマージを拒否します。
FAQ:共有ビルダー上の Swift 6
| 質問 | 実務的な答え |
|---|---|
| まず SPM パッケージから有効にすべき? | 多くの場合そう—境界をマップしてからアプリターゲット。テスト専用コードを分けるならパッケージ特性を利用。 |
| VNC は必須? | 通常いいえ—視覚デバッグのブレークグラスは VNC。厳格ビルドログ用ではない。 |
| インデックス用ディスクは? | 大きな SwiftUI プレビューをオフにしても大きな Index 木を残すなら 1〜2 TB ホストを選ぶ。厳格レーンが成果物チャーンを 3× にしたら 料金を参照。 |
並行性負荷の高いコンパイルにベアメタル Mac mini M4 が合う理由
厳格チェックは CPU と I/O に負荷がかかります。コンパイラはグラフを書き換え、index は膨らみ、index store はアーカイブ用にすでに予算しているのと同じ NVMe を活かします。ソケットスタックが 騒がしい隣人なしなら、レーンがパッケージ解決中にリモート キャッシュや レジストリと話すときのテールレイテンシも下がります。厳格パイプラインが安定したら、共有 DerivedData にレーンを戻す前に、同じリージョンで二台目の Mac mini M4 を スケールアウトしてください—2026 の本線は決定的シグナルに値し、宝くじビルドには値しません。