本章描述的插件与配置缓存不兼容。

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 插件,您可以获得一整套功能:

  • compileDebugSwift以及分别为众所周知的调试和发布构建类型编译src/main/swiftcompileReleaseSwift下的 Swift 源文件的任务。

  • linkDebug以及linkRelease将已编译的 Swift 对象文件链接到应用程序的可执行文件或共享库(对于调试和发布构建类型具有共享链接的库)的任务。

  • createDebug以及createRelease将已编译的 Swift 对象文件组装到静态库中的任务,这些静态库具有针对调试和发布构建类型的静态链接。

对于任何重要的 Swift 项目,您可能会有一些特定于您的项目的文件依赖项和其他配置。

Swift 插件还将上述任务集成到标准生命周期任务中。生成开发二进制文件的任务附加到assemble。默认情况下,开发二进制文件是调试变体。

本章的其余部分解释了在构建库和应用程序时根据您的要求自定义构建的不同方法。

引入构建变体

本机项目通常可以生成多个不同的二进制文件,例如调试或发布二进制文件,或者针对特定平台和处理器架构的二进制文件。 Gradle 通过维度变体的概念来管理这一点。

维度只是一个类别,其中每个类别都与其他类别正交。例如,“构建类型”维度是包括调试和发布的类别。 “架构”维度涵盖 x86-64 和 x86 等处理器架构。

变体是这些维度的值的组合,每个维度仅包含一个值。您可能有“调试 x86-64”或“发布 x86”变体。

Gradle 内置支持多个维度以及每个维度内的多个值。您可以在本机插件参考章节中找到它们的列表。

声明您的源文件

Gradle 的 Swift 支持ConfigurableFileCollection直接使用应用程序脚本块来配置要编译的源集。

库区分私有(实现细节)和公共(导出给消费者)标头。

对于仅在某些目标计算机上编译源的情况,您还可以为每个二进制构建配置源。

快速源集编译
图 1. 源代码和 Swift 编译

管理您的依赖项

绝大多数项目都依赖于其他项目,因此管理项目的依赖关系是构建任何项目的重要部分。依赖管理是一个很大的话题,所以我们在这里只关注 Swift 项目的基础知识。如果您想深入了解详细信息,请查看依赖管理简介

Gradle 支持使用 Gradle 发布的 Maven 存储库中的预构建二进制文件[ 1 ]

我们将介绍如何在多重构建项目中添加项目之间的依赖关系。

指定 Swift 项目的依赖项需要两条信息:

  • 识别依赖项的信息(项目路径、Maven GAV)

  • 它需要什么,例如编译、链接、运行时或以上所有。

dependencies {}此信息在Swift 块applicationlibrary脚本块中指定。例如,要告诉 Gradle 您的项目需要库common来编译和链接您的生产代码,您可以使用以下片段:

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 将使用系统路径发现工具链。

自定义文件和目录位置

想象一下,您正在迁移一个遵循 Swift Package Manager 布局(例如生产代码的目录)的库项目。传统的目录结构不起作用,因此您需要告诉 Gradle 在哪里可以找到源文件。您可以通过or脚本块来完成此操作。Sources/ModuleName_applicationlibrary

每个组件脚本块以及每个二进制文件都定义了其源代码所在的位置。您可以使用以下语法覆盖约定值:

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

现在 Gradle 只会直接在Sources/Common中搜索源。

大多数编译器和链接器选项都可以通过相应的任务访问,例如、和。这些任务的类型分别为SwiftCompileLinkSharedLibraryCreateStaticLibrary。请阅读任务参考以获取最新且全面的选项列表。compileVariantSwiftlinkVariantcreateVariant

例如,如果要更改编译器为所有变体生成的警告级别,可以使用以下配置:

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块查找特定变体的实例:applicationlibrary

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 二进制变体。可以通过TargetMachineapplicationlibrary脚本块上指定集合来覆盖它:

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目录中的所有内容,因此您应该始终将构建生成的文件放在那里。该任务是删除的一个实例,您可以通过设置其dir属性来更改它删除的目录。

构建 Swift 库

库项目的独特之处在于它们被其他 Swift 项目使用(或“消耗”)。这意味着与二进制文件和标头一起发布的依赖元数据(以 Gradle 模块元数据的形式)至关重要。特别是,您的库的使用者应该能够区分两种不同类型的依赖项:仅编译您的库所需的依赖项和编译使用者也需要的依赖项。

Gradle 通过Swift Library Plugin管理这种区别,除了本章介绍的实现之外,它还引入了api配置。如果依赖项中的类型显示为静态库或公共标头中未解析的符号,则该依赖项将通过库的公共 API 公开,因此应将其添加到api配置中。否则,依赖项是内部实现细节,应添加到实现中。

如果您不确定 API 和实现依赖项之间的区别,Swift 库插件章节有详细的解释。此外,您还可以在相应的示例中看到构建 Swift 库的基本实用示例。

构建 Swift 应用程序

有关更多详细信息,请参阅Swift 应用程序插件一章,以下是您所获得内容的快速摘要:

  • install创建一个包含运行它所需的所有内容的目录

  • 用于启动应用程序的 Shell 和 Windows 批处理脚本

您可以在相应的示例中查看构建 Swift 应用程序的基本示例。


1 .不幸的是,Cocoapods 存储库尚未作为核心功能得到支持