流水線宣告使用 Xcode 26,日誌卻出現 Xcode 27 SDK。
最快解法:保留兩個獨立 Xcode 目錄,讓每條工作以 DEVELOPER_DIR 明確鎖定工具鏈,並記錄版本、建置編號、SDK 與 developer directory 作為驗收證據。
這篇適合仍要用 Xcode 26 發佈正式版本、同時驗證 Xcode 27 專案的行動開發團隊。
如果你負責遠端 Mac CI 路由、節點升級、容量或故障恢復,以下內容可直接作為共存 runbook。
Xcode 27 與 Xcode 26 共存:先判斷宿主系統,再決定安裝方式
Xcode 27 與 Xcode 26 共存的難點,不是把兩個 .app 拖進「應用程式」資料夾,而是確保每次建置都使用可追溯的工具鏈。Apple 的 Xcode 系統要求會隨 Beta 版本變更;截至 2026 年 9 月 1 日,Xcode 27 的具體 Beta 版本、元件行為與支援範圍仍可能更新,不能把測試版環境當成永久相容結論。
先核對以下邊界:
| 核對項目 | 安全做法 | 失敗時的處理 |
|---|---|---|
| 晶片架構 | 確認節點是相容的 Apple silicon Mac | 不以改包或非官方方式強行部署 |
| macOS 版本 | 逐一對照 Xcode 26 與 Xcode 27 的官方系統要求 | 暫緩安裝 Xcode 27,或改用獨立節點 |
| 安裝來源 | 保存官方下載頁、版本名稱與建置編號 | 不採用無法追溯的複製檔 |
| 應用程式目錄 | 使用清楚區分且不會被覆蓋的路徑 | 先停止更新,再重新整理路由 |
例如可以使用 /Applications/Xcode-26.app 與 /Applications/Xcode-27-Beta.app 作為示例路徑。正式環境中請依你的變更管理規範命名。首次安裝、覆蓋更新和自動更新是三種不同風險:首次安裝要驗證權限與元件,覆蓋更新可能破壞回滾路徑,自動更新則可能讓路徑名稱或內容在無人值守時改變。
Apple 的 Xcode 27 Release Notes與 Xcode 26 Release Notes應緊鄰你的變更紀錄保存。Beta 期間若系統要求或元件管理方式改變,先重新核對,再決定是否擴大使用範圍。
全域切換與工作級路由:共享遠端 Mac CI 應優先選後者
xcode-select 是節點層級設定。它適合你登入伺服器後進行人工維護,或作為沒有指定工具鏈時的預設值。問題是,若兩條工作同時執行,其中一條工作把全域路徑切到 Xcode 27,另一條原本要使用 Xcode 26 的工作就可能在同一時間讀到錯誤工具鏈。
DEVELOPER_DIR 的作用範圍較窄。你可以只讓單一 xcodebuild 或 CI 工作使用指定 Xcode,不改動其他工作。Apple 的 命令列工具設定文件說明了 Xcode 命令列工具的選擇方式;實作時應把選擇結果寫進工作日誌,而不是只在節點上口頭記錄。
| 路由方式 | 影響範圍 | 適用情境 | 主要風險 |
|---|---|---|---|
全域 xcode-select |
整個節點及未覆寫的程序 | 單一版本、人工維護 | 並行工作互相干擾 |
工作級 DEVELOPER_DIR |
單一工作或命令程序 | 多版本 CI、分支路由 | 路徑寫錯或未傳入子程序 |
| 固定專用節點 | 整個節點只服務一套工具鏈 | 高風險發佈、嚴格回滾 | 資源利用率與維護成本較高 |
工作設定可採用虛構的 BUILD_XCODE_ROOT 變數,避免把實際主機名稱或敏感資料寫入腳本:
export DEVELOPER_DIR="/Applications/Xcode-26.app/Contents/Developer"
xcodebuild -version
xcrun --find xcodebuild
xcrun --sdk iphoneos --show-sdk-path
swiftc --version
這些命令的輸出必須在建置前保存。你要看到的不只是「工作成功」,還包括 xcodebuild 實際來源、SDK 路徑、Swift 編譯器版本,以及 DEVELOPER_DIR 指向的 developer directory。若任何輸出與預期不符,立即停止工作,不要繼續產生來源不明的封存檔。
第一步:用唯讀預檢拆開版本選擇問題
先建立兩個獨立的預檢工作,分別只讀取環境,不進行安裝或修改全域設定。每個工作都應輸出:
DEVELOPER_DIR的完整路徑。xcodebuild -version的版本與建置編號。xcrun找到的工具實際位置。- 目標 SDK 路徑與可用平台。
- Swift 編譯器版本。
- Git 提交識別碼、Scheme 和建置設定名稱。
接著用目標專案執行最小化建置。不要只呼叫 xcodebuild 的預設 Scheme,因為不同 Scheme 可能需要不同平台元件、簽名設定或測試主機。對正式鏈和驗證鏈分別保存日誌,再比較它們是否真的使用預期的 SDK。
DEVELOPER_DIR 只在目前 Shell 或工作程序中生效,並不會替你安裝另一套 Xcode,也不會自動補齊模擬器執行時。這是常見誤判:路由正確,只代表「選到了某個工具鏈」,不代表該工具鏈已具備完成工作所需的全部元件。
第二步:元件、模擬器與首次啟動要分開驗收
「Xcode 可以開啟」不是 CI 可用的證明。歸檔、單元測試和 UI 測試需要的資源不同,安裝內容也不應一律堆在共享節點。
| 工作類型 | 最低核對方向 | 不應直接假設的事項 |
|---|---|---|
| 歸檔 | 目標 SDK、簽名身份、封存輸出 | UI 測試模擬器已可用 |
| 單元測試 | 測試 Scheme、編譯器與套件解析 | 所有平台執行時都已安裝 |
| UI 測試 | 指定模擬器裝置與執行時 | 另一個 Xcode 版本能直接使用同一狀態 |
| Beta 驗證 | Xcode 27 專用元件與測試專案 | Beta 行為等同正式版 |
元件安裝必須綁定正確的 Xcode 路徑。參照 Apple 的附加 Xcode 元件安裝文件,逐套確認安裝結果。若需要其他模擬器執行時,再依 Apple 的模擬器新增說明處理。
驗收標準應是「目標專案完成實際工作」:Xcode 26 正式 Scheme 能歸檔,Xcode 27 驗證 Scheme 能完成指定測試,且兩者的日誌都顯示正確 SDK。不要用一個版本成功開啟專案,代替另一個版本的測試結果。
第三步:隔離 DerivedData、套件與封存輸出
多個 Xcode 版本可能讀取相同的專案檔、套件來源和系統模擬器狀態,但你不應讓建置輸出無條件共用。舊的 DerivedData 可能掩蓋編譯器或 Build Settings 的變化;共用封存目錄則容易讓人工下載錯誤版本。
可以按版本和流水線建立輸出路徑:
export BUILD_ROOT="/var/tmp/ci-example/xcode-26/release"
export DERIVED_DATA_PATH="$BUILD_ROOT/derived-data"
export ARCHIVE_PATH="$BUILD_ROOT/archive/App.xcarchive"
xcodebuild \
-derivedDataPath "$DERIVED_DATA_PATH" \
-archivePath "$ARCHIVE_PATH" \
-scheme "ExampleRelease" \
archive
Xcode 27 的驗證工作使用另一組根目錄。不要只改 archivePath,而漏掉 DerivedData、測試結果、日誌和套件解析狀態。對需要長期保留的封存檔,應把版本、建置編號、提交識別碼和簽名結果寫入檔案名稱或中繼資料。
Apple 的 Build Settings Reference可用來核對自訂建置設定。你的 CI 還要檢查快取命中條件:快取鍵至少要能區分 Xcode 路徑、SDK、平台、依賴鎖定檔和提交識別碼。若無法可靠區分,寧可先以乾淨建置換取可追溯性。
簽名資產也不應因為多了一個 Xcode,就複製成多份難以管理的憑證。應在同一個受控身份邊界內,分別驗證兩套工具鏈是否能完成各自的簽名與匯出流程。正文和腳本都不要放入密碼、令牌、憑證內容或私鑰。
第四步:用回滾矩陣驗證重啟與更新後狀態
共存環境最容易在「第一次成功」之後出問題。你需要把正式鏈、驗證鏈和回滾鏈放在同一份驗收矩陣中,而不是只測一次建置。
| 驗收場景 | 必須記錄的證據 | 通過條件 |
|---|---|---|
| 正式鏈 | Xcode 26、SDK、Scheme、封存與簽名日誌 | 產物來源可追溯 |
| 驗證鏈 | Xcode 27 Beta、測試平台與提交識別碼 | 不改變正式鏈路由 |
| 節點重啟 | 應用程式路徑、環境變數、元件狀態 | 工作重派後仍選到正確版本 |
| Beta 更新 | 更新前後版本、建置編號與測試結果 | 失敗時可回到原目錄 |
| 回滾 | Xcode 26 預檢、乾淨建置、歸檔 | 正式工作可恢復,不依賴人工臨時切換 |
操作順序可以是:
- 先停止會修改全域
xcode-select的工作。 - 保存兩套 Xcode 的路徑、建置編號與系統要求核對結果。
- 分別執行預檢、乾淨建置、測試和歸檔。
- 重啟遠端 Mac,再重新派送同一組工作。
- 模擬 Xcode 27 Beta 更新失敗,把正式工作路由回 Xcode 26。
- 比對重啟前後的工具來源、元件狀態、輸出目錄與簽名結果。
這裡的「成功」不是單純回傳零,而是每一項證據都能對上預期版本。若重啟後 DEVELOPER_DIR 沒有被 CI 注入,或快取讓錯誤 SDK 沒有立刻暴露,就應先修正工作定義,再擴大共用節點的任務量。
哪些情況應該拆成兩台遠端 Mac?
你可以先用以下條件作決策:
- 若兩個版本的工作不會並行,而且每條工作都能在建置前輸出正確工具來源,則可先共用一台相容的 Apple silicon Mac。
- 若任何工作仍需依賴全域
xcode-select,或 CI 系統無法保證環境變數傳給所有子程序,則回退到專用節點。 - 若Xcode 27 Beta 的平台元件與正式鏈互相影響,或重啟後狀態不能穩定恢復,則不要在正式節點繼續擴大部署。
- 若正式發佈有嚴格的回滾要求,而 Beta 工作需要頻繁更新,則把 Xcode 27 放到獨立驗證節點。
- 若節點容量不足以同時保留兩套應用程式、輸出和快取,則先清理可重建快取,仍不足時改用獨立節點,而不是刪除 Xcode 26 回滾路徑。
如果你要評估遠端 Mac 的交付方式、SSH 或 VNC 連線及租期,可先查看 MacHTML 的支援說明與遠端 Mac 方案資訊。不要在正式節點尚未完成矩陣驗收前,直接以租用或新增資源替換原有發佈流程。
常見問題
FAQ 以可獨立執行的答案整理,方便你在實際維護遠端 Mac CI 時快速定位。
一台 Mac 可以同時保留兩個 Xcode 嗎?
可以,但必須先確認 Apple silicon 與 macOS 系統要求,再把 Xcode 26 和 Xcode 27 放入不同應用程式目錄。你還要分別驗證命令列工具、平台元件、模擬器、DerivedData、歸檔和簽名。只要宿主系統不相容,就不應透過修改套件或非官方方式硬裝。
CI 怎樣替不同任務固定 Xcode 版本?
每條工作都應保存自己的 Xcode 路徑,透過 DEVELOPER_DIR 傳入建置程序,並在執行前列印版本、SDK 和工具實際來源。這樣分支、倉庫或 Scheme 可以各自路由,不必更改節點全域設定。若 CI 無法保證變數傳遞到子程序,就應改用版本專用節點。
DEVELOPER_DIR 與 xcode-select 的差別是什麼?
xcode-select 改變節點的全域預設,適合單一工具鏈或人工維護;DEVELOPER_DIR 則把選擇限制在指定命令或工作範圍。多版本共享節點應優先採用後者,避免並行任務互相搶改全域狀態。無論選哪一種,都要用 xcodebuild 和 xcrun 輸出驗證。
多套 Xcode 會不會共用模擬器和 DerivedData?
它們可能接觸相同的系統模擬器資源,但這不代表平台執行時、裝置狀態或建置輸出可安全共用。DerivedData、測試結果、歸檔與日誌應按 Xcode 版本或流水線隔離。每個工作都要以實際目標 Scheme 驗證,不能只看 Xcode 是否能啟動。
升級 Xcode 27 前怎樣保留回滾環境?
把可用的 Xcode 26 目錄保留在不會被更新覆蓋的位置,記錄版本、建置編號、SDK、元件與簽名結果。更新後先執行乾淨建置、重複建置和節點重啟測試,再讓正式工作使用新版本。任何一項證據不完整,就先將正式路由固定回 Xcode 26。
如果你目前以單一 Linux 或 Windows 主機加上全域切換方式處理,常見缺點是無法提供 macOS 專屬工具鏈、並行工作容易污染全域狀態,而且要自行承擔硬體維護、系統更新與故障恢復。相比之下,租用 MacHTML 的遠端 Mac,可先準備獨立的 Xcode 27 驗證節點,保留 Xcode 26 正式鏈,並按你的測試週期安排存取與租期;但長期固定重負載或需要實體介面的團隊,仍應如實比較自購 Mac 與專用託管方案。
完成驗收矩陣後,再依並發衝突、回滾要求和容量決定是否新增節點。若你只需要臨時驗證 Xcode 27、測試一條新 CI 路由,或在沒有本地 Mac 時建立可回收的遠端環境,可以從 MacHTML 的方案頁核對交付條件,再把正式發佈節點與測試節點分開管理。
常見問題
為多版本 Xcode CI 配置穩定的遠端 Mac 環境
透過 MacHTML 遠端 Mac,靈活執行不同版本的 Xcode 建置與測試工作。 按專案需求配置獨立節點,降低正式版與測試版工具鏈互相影響的風險。 集中管理建置環境、快取與簽名驗證,讓團隊更有效率地維護 CI 流程。 立即了解 MacHTML 的 Mac 租賃與算力方案,為團隊建立彈性可靠的遠端開發環境。