跳至內容

遷移 Xcode 專案

除非你使用 Tuist 建立新專案(這種情況下所有設定都會自動完成),否則你必須使用 Tuist 的基本元素來定義你的 Xcode 專案。這個過程有多繁瑣,取決於你的專案複雜程度。

如你所知,Xcode 專案隨著時間推移會變得雜亂且複雜:群組與目錄結構不符、檔案在不同目標之間共用,或檔案參照指向不存在的檔案(僅舉幾例)。這些累積的複雜性讓我們難以提供一個能可靠遷移專案的命令。

此外,手動遷移是清理並簡化專案的絕佳練習。不僅專案中的開發人員會因此受益,Xcode 也會因為處理和索引速度變快而受惠。當你完全採用 Tuist 後,它能確保專案定義一致且保持簡潔。

為了減輕這項工作,我們根據從使用者收到的回饋提供一些指引。

建立專案骨架#

首先,使用下列 Tuist 檔案為你的專案建立骨架:

javascript
import ProjectDescription
let tuist = Tuist()
javascript
import ProjectDescription
let project = Project(
name: "MyApp-Tuist",
targets: [
/** Targets will go here **/
]
)
javascript
// swift-tools-version: 5.9
import PackageDescription
#if TUIST
import ProjectDescription
let packageSettings = PackageSettings(
// Customize the product types for specific package product
// Default is .staticFramework
// productTypes: ["Alamofire": .framework,]
productTypes: [:]
)
#endif
let package = Package(
name: "MyApp",
dependencies: [
// Add your own dependencies here:
// .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
// You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
]
)

Project.swift 是用來定義專案的資訊清單檔案,而 Package.swift 是用來定義相依性的資訊清單檔案。Tuist.swift 檔案則可用來定義專案範圍內的 Tuist 設定。

專案名稱加上 -tuist 後綴

為了避免與現有的 Xcode 專案衝突,我們建議在專案名稱中加入 -Tuist 後綴。當你把專案完全遷移至 Tuist 後,就可以移除該後綴。

在 CI 中建置並測試 Tuist 專案#

為了確保每次變更的遷移都有效,我們建議擴充你的持續整合流程,以建置並測試由 Tuist 從資訊清單檔案產生的專案:

bash
tuist install
tuist generate
xcodebuild build {xcodebuild flags} # or tuist test

將專案建置設定提取到 .xcconfig 檔案中#

將專案的建置設定提取到 .xcconfig 檔案中,讓專案更精簡且更易於遷移。你可以使用以下命令將專案的建置設定提取到 .xcconfig 檔案:

bash
mkdir -p xcconfigs/
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -x xcconfigs/MyApp-Project.xcconfig

接著更新你的 Project.swift 檔案,使其指向你剛建立的 .xcconfig 檔案:

swift
import ProjectDescription
let project = Project(
name: "MyApp",
settings: .settings(configurations: [
.debug(name: "Debug", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"), // [!code ++]
.release(name: "Release", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"), // [!code ++]
]),
targets: [
/** Targets will go here **/
]
)

然後擴充你的持續整合管線,執行以下命令以確保對建置設定的變更直接寫入 .xcconfig 檔案:

bash
tuist migration check-empty-settings -p Project.xcodeproj

提取套件相依性#

將你專案的所有相依性提取到 Tuist/Package.swift 檔案中:

swift
// swift-tools-version: 5.9
import PackageDescription
#if TUIST
import ProjectDescription
let packageSettings = PackageSettings(
// Customize the product types for specific package product
// Default is .staticFramework
// productTypes: ["Alamofire": .framework,]
productTypes: [:]
)
#endif
let package = Package(
name: "MyApp",
dependencies: [
// Add your own dependencies here:
// .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
// You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
.package(url: "https://github.com/onevcat/Kingfisher", .upToNextMajor(from: "7.12.0")) // [!code ++]
]
)
產品類型

你可以透過將特定套件加入 PackageSettings 結構中的 productTypes 字典,來覆寫該套件的產品類型。預設情況下,Tuist 假設所有套件都是靜態框架。

決定遷移順序#

我們建議從被依賴程度最高的目標開始遷移,依序到被依賴程度最低的目標。你可以使用以下命令列出專案的目標,並依照相依性數量排序:

bash
tuist migration list-targets -p Project.xcodeproj

從清單頂端開始遷移目標,因為它們是被依賴程度最高的目標。

遷移目標#

逐一遷移目標。我們建議為每個目標建立拉取請求,以確保在合併前經過審查與測試。

將目標建置設定提取到 .xcconfig 檔案中#

如同處理專案建置設定時的做法,將目標的建置設定提取到 .xcconfig 檔案中,讓目標更精簡且更易於遷移。你可以使用以下命令將目標的建置設定提取到 .xcconfig 檔案:

bash
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -t TargetX -x xcconfigs/TargetX.xcconfig

在 Project.swift 檔案中定義目標#

在 Project.targets 中定義目標:

swift
import ProjectDescription
let project = Project(
name: "MyApp",
settings: .settings(configurations: [
.debug(name: "Debug", xcconfig: "./xcconfigs/Project.xcconfig"),
.release(name: "Release", xcconfig: "./xcconfigs/Project.xcconfig"),
]),
targets: [
.target( // [!code ++]
name: "TargetX", // [!code ++]
destinations: .iOS, // [!code ++]
product: .framework, // [!code ++] // or .staticFramework, .staticLibrary...
bundleId: "dev.tuist.targetX", // [!code ++]
sources: ["Sources/TargetX/**"], // [!code ++]
dependencies: [ // [!code ++]
/** Dependencies go here **/ // [!code ++]
/** .external(name: "Kingfisher") **/ // [!code ++]
/** .target(name: "OtherProjectTarget") **/ // [!code ++]
], // [!code ++]
settings: .settings(configurations: [ // [!code ++]
.debug(name: "Debug", xcconfig: "./xcconfigs/TargetX.xcconfig"), // [!code ++]
.debug(name: "Release", xcconfig: "./xcconfigs/TargetX.xcconfig"), // [!code ++]
]) // [!code ++]
), // [!code ++]
]
)
測試目標

如果目標有關聯的測試目標,你也應該在 Project.swift 檔案中定義它,並重複相同的步驟。

驗證目標遷移#

執行 tuist generate,接著執行 xcodebuild build 以確保專案可以建置,並執行 tuist test 以確保測試通過。此外,你可以使用 xcdiff 比較產生的 Xcode 專案與現有專案,以確保變更正確無誤。

重複#

重複上述步驟直到所有目標都完全遷移。完成後,我們建議更新你的 CI 與 CD 管線,使用 tuist generate 接著執行 xcodebuild build 與 tuist test 來建置並測試專案。

疑難排解#

因缺少檔案而導致編譯錯誤。#

如果與 Xcode 專案目標關聯的檔案並非全部位於代表該目標的檔案系統目錄中,可能會導致專案無法編譯。請確認使用 Tuist 產生專案後的檔案清單與 Xcode 專案中的檔案清單相符,並趁此機會將檔案結構與目標結構對齊。