Gradle 在建置原生專案時採用慣例優於配置的方法。如果您來自其他原生建置系統,這些概念起初可能不太熟悉,但它們旨在簡化建置腳本的編寫。

本章將詳細介紹 Swift 專案,但大多數主題也適用於其他支援的原生語言。

簡介

Swift 專案最簡單的建置腳本是套用 Swift 應用程式外掛程式或 Swift 函式庫外掛程式,並選擇性地設定專案版本

build.gradle.kts
plugins {
    `swift-application` // or `swift-library`
}

version = "1.2.1"
build.gradle
plugins {
    id 'swift-application' // or 'swift-library'
}

version = '1.2.1'

套用任一 Swift 外掛程式,您將獲得許多功能

  • compileDebugSwiftcompileReleaseSwift 任務,分別編譯 *src/main/swift* 下的 Swift 原始碼檔案,用於眾所周知的 debug 和 release 建置類型。

  • linkDebuglinkRelease 任務,將編譯後的 Swift 物件檔連結成可執行檔(用於應用程式)或共享函式庫(用於具有共享連結的函式庫),用於 debug 和 release 建置類型。

  • createDebugcreateRelease 任務,將編譯後的 Swift 物件檔組合成靜態函式庫(用於具有靜態連結的函式庫),用於 debug 和 release 建置類型。

對於任何非簡單的 Swift 專案,您可能會有某些檔案相依性和特定於 *您的* 專案的其他配置。

Swift 外掛程式還將上述任務整合到標準生命週期任務中。產生開發二進制檔的任務已附加到 assemble。預設情況下,開發二進制檔是 debug 變體。

本章的其餘部分說明在建置函式庫和應用程式時,根據您的需求自訂建置的不同方法。

介紹建置變體

原生專案通常可以產生多個不同的二進制檔,例如 debug 或 release 版本,或針對特定平台和處理器架構的版本。Gradle 通過 *維度* 和 *變體* 的概念來管理這一點。

維度只是一個類別,其中每個類別都與其餘類別正交。例如,「建置類型」維度是一個包含 debug 和 release 的類別。「架構」維度涵蓋處理器架構,如 x86-64 和 x86。

變體是這些維度的值的組合,每個維度恰好包含一個值。您可能有「debug x86-64」或「release x86」變體。

Gradle 內建支援多個維度和每個維度內的多個值。您可以在原生外掛程式參考章節中找到它們的列表。

宣告您的原始碼檔案

Gradle 的 Swift 支援直接從應用程式函式庫腳本區塊使用 ConfigurableFileCollection 來配置要編譯的來源集。

函式庫區分私有(實作細節)和公共(匯出給消費者)標頭。

您還可以為每個二進制建置配置來源,以應對僅在某些目標機器上編譯來源的情況。

swift sourcesets compilation
圖 1. 來源和 Swift 編譯

管理您的相依性

絕大多數專案都依賴其他專案,因此管理專案的相依性是建置任何專案的重要組成部分。相依性管理是一個很大的主題,因此我們在這裡僅關注 Swift 專案的基礎知識。如果您想深入了解詳細資訊,請查看相依性管理簡介

Gradle 支援從 Gradle [1]發布的 Maven 儲存庫中使用預先建置的二進制檔。

我們將介紹如何在多建置專案中新增專案之間的相依性。

為您的 Swift 專案指定相依性需要兩條資訊

  • 相依性的識別資訊(專案路徑、Maven GAV)

  • 它需要的用途,例如編譯、連結、運行時或以上所有。

此資訊在 Swift 應用程式或函式庫腳本區塊的 dependencies {} 區塊中指定。例如,要告訴 Gradle 您的專案需要函式庫 common 來編譯和連結您的生產程式碼,您可以使用以下程式碼片段

範例 2. 宣告相依性
build.gradle.kts
application {
    dependencies {
        implementation(project(":common"))
    }
}
build.gradle
application {
    dependencies {
        implementation project(':common')
    }
}

Gradle 對於這三個元素的術語如下

  • 配置(例如:implementation)- 相依性的命名集合,為了特定目標(例如編譯或連結模組)而分組在一起

  • 專案參考(例如:project(':common'))- 由指定路徑參考的專案

您可以在這裡找到更全面的相依性管理術語詞彙表。

就配置而言,主要感興趣的是

  • implementation - 用於編譯、連結和運行時

  • swiftCompileVariant - 用於編譯生產程式碼所需的相依性,但不應成為連結或運行時過程的一部分

  • nativeLinkVariant - 用於連結程式碼所需的相依性,但不應成為編譯或運行時過程的一部分

  • nativeRuntimeVariant - 用於運行組件所需的相依性,但不應成為編譯或連結過程的一部分

您可以在原生外掛程式參考章節中了解有關這些以及它們之間如何關聯的更多資訊。

請注意,Swift 函式庫外掛程式會建立一個額外的配置 — api — 用於編譯和連結模組及其所依賴的任何模組所需的相依性。

我們在這裡只觸及了皮毛,因此我們建議您在熟悉使用 Gradle 建置 Swift 專案的基礎知識後,閱讀專門的相依性管理章節

一些需要進一步閱讀的常見場景包括

您會發現 Gradle 有一個豐富的 API 用於處理相依性 — 它需要時間來掌握,但在常見場景中直接使用。

如果您遵循慣例,編譯您的程式碼可以非常容易

  1. 將您的原始碼放在 *src/main/swift* 目錄下

  2. implementation 配置中宣告您的編譯相依性(請參閱上一節)

  3. 執行 assemble 任務

我們建議您盡可能遵循這些慣例,但您不必如此。

接下來您將看到幾個自訂選項。

所有 SwiftCompile 任務都是增量的且可快取的。

支援的工具鏈

Gradle 支援 macOS 和 Linux 的官方 Swift 工具鏈。當您建置原生二進制檔時,Gradle 將嘗試找到安裝在您機器上的工具鏈,該工具鏈可以建置二進制檔。Gradle 選擇第一個可以為目標作業系統、架構和 Swift 語言支援建置的工具鏈。

對於 Linux 用戶,Gradle 將使用系統 PATH 發現工具鏈。

自訂檔案和目錄位置

想像一下,您正在遷移一個遵循 Swift Package Manager 佈局的函式庫專案(例如,生產程式碼的 `Sources/ModuleName_` 目錄)。傳統的目錄結構將不起作用,因此您需要告訴 Gradle 在哪裡找到原始碼檔案。您可以通過應用程式或函式庫腳本區塊來做到這一點。

每個組件腳本區塊以及每個二進制檔都定義了其原始碼所在的位置。您可以使用以下語法覆蓋慣例值

build.gradle.kts
extensions.configure<SwiftLibrary> {
    source.from(file("Sources/Common"))
}
build.gradle
library {
    source.from file('src')
}

現在 Gradle 將僅在 *Sources/Common* 中直接搜尋來源。

大多數編譯器和連結器選項都可以通過相應的任務訪問,例如 compileVariantSwiftlinkVariantcreateVariant。這些任務分別屬於 SwiftCompileLinkSharedLibraryCreateStaticLibrary 類型。閱讀任務參考以獲取最新和全面的選項列表。

例如,如果您想更改編譯器為所有變體產生的警告級別,您可以使用此配置

build.gradle.kts
tasks.withType(SwiftCompile::class.java).configureEach {
    // Define a preprocessor macro for every binary
    macros.add("NDEBUG")

    // Define a compiler options
    compilerArgs.add("-O")
}
build.gradle
tasks.withType(SwiftCompile).configureEach {
    // Define a preprocessor macro for every binary
    macros.add("NDEBUG")

    // Define a compiler options
    compilerArgs.add '-O'
}

也可以通過應用程式或函式庫腳本區塊上的 BinaryCollection 找到特定變體的實例

build.gradle.kts
application {
    binaries.configureEach(SwiftStaticLibrary::class.java) {
        // Define a preprocessor macro for every binary
        compileTask.get().macros.add("NDEBUG")

        // Define a compiler options
        compileTask.get().compilerArgs.add("-O")
    }
}
build.gradle
application {
    binaries.configureEach(SwiftStaticLibrary) {
        // Define a preprocessor macro for every binary
        compileTask.get().macros.add("NDEBUG")

        // Define a compiler options
        compileTask.get().compilerArgs.add '-O'
    }
}

選擇目標機器

預設情況下,Gradle 將嘗試為主機作業系統和架構建立 Swift 二進制變體。可以通過在應用程式或函式庫腳本區塊上指定 TargetMachine 集合來覆蓋此預設行為

build.gradle.kts
application {
    targetMachines = listOf(machines.linux.x86_64, machines.macOS.x86_64)
}
build.gradle
application {
    targetMachines = [
        machines.linux.x86_64,
        machines.macOS.x86_64
    ]
}

封裝和發布

您如何封裝和可能發布您的 Swift 專案在原生世界中差異很大。Gradle 帶有預設值,但可以毫無問題地實作自訂封裝。

  • 可執行檔直接發布到 Maven 儲存庫。

  • 共享和靜態函式庫檔案與公共標頭的 zip 檔案一起直接發布到 Maven 儲存庫。

  • 對於應用程式,Gradle 還支援在已知位置安裝和運行可執行檔及其所有共享函式庫相依性。

清理建置

基礎外掛程式 Swift 應用程式和函式庫外掛程式通過使用基礎外掛程式將 clean 任務新增到您的專案中。此任務只是刪除 layout.buildDirectory 目錄中的所有內容,因此您應該始終將建置產生的檔案放在那裡。該任務是 Delete 的一個實例,您可以通過設定其 dir 屬性來更改它刪除的目錄。

建置 Swift 函式庫

函式庫專案的獨特之處在於它們被其他 Swift 專案使用(或「消耗」)。這意味著與二進制檔和標頭一起發布的相依性元數據(以 Gradle 模組元數據的形式)至關重要。特別是,您的函式庫的消費者應該能夠區分兩種不同類型的相依性:僅編譯您的函式庫所需的相依性和也編譯消費者所需的相依性。

Gradle 通過 Swift 函式庫外掛程式管理這種區別,除了本章前面介紹的 *implementation* 之外,還引入了 *api* 配置。如果來自相依性的類型作為靜態函式庫的未解析符號或在公共標頭中出現,則該相依性通過您的函式庫的公共 API 公開,因此應新增到 *api* 配置中。否則,該相依性是內部實作細節,應新增到 *implementation* 中。

如果您不確定 API 和實作相依性之間的區別,Swift 函式庫外掛程式章節有詳細的解釋。此外,您可以在相應的範例中看到建置 Swift 函式庫的基本實用範例。

建置 Swift 應用程式

有關更多詳細資訊,請參閱 Swift 應用程式外掛程式章節,但以下是您獲得的功能的快速摘要

  • install 建立一個目錄,其中包含運行它所需的一切

  • Shell 和 Windows Batch 腳本,用於啟動應用程式

您可以在相應的範例中看到建置 Swift 應用程式的基本範例。


1. 遺憾的是,Cocoapods 儲存庫目前尚未作為核心功能支援