Gradle使用约定优于配置的方法来构建本机项目. 如果您来自另一个本机构建系统,那么这些概念起初可能并不熟悉,但是它们的目的是简化构建脚本的编写.

我们将在本章中详细介绍Swift项目,但是大多数主题也将适用于其他受支持的本地语言.

Introduction

Swift项目的最简单构建脚本将应用Swift应用程序插件或Swift库插件,并可以选择设置项目版本:

例子1.应用Swift插件
build.gradle
plugins {
    id 'swift-application' // or 'swift-library'
}

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

version = "1.2.1"

通过应用任何一个Swift插件,您将获得大量功能:

  • compileDebugSwiftcompileReleaseSwift任务分别编译src / main / swift下的Swift源文件,分别用于著名的调试和发布构建类型.

  • linkDebuglinkRelease任务, linkRelease任务将已编译的Swift对象文件链接到应用程序的可执行文件或库的共享库中,并具有调试和发布构建类型的共享链接.

  • createDebugcreateRelease任务将已编译的Swift对象文件组装到一个静态库中,这些库具有与调试和发布构建类型具有静态链接的库.

对于任何不平凡的斯威夫特项目,你可能有一些文件相关的和额外的配置具体到项目中.

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

本章的其余部分介绍了在构建库和应用程序时根据需要自定义构建的不同方法.

Introducing build variants

本机项目通常可以产生几种不同的二进制文件,例如调试或发布二进制文件,或针对特定平台和处理器体系结构的二进制文件. Gradle通过维度变体的概念来进行管理.

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

变体是这些维度的值的组合,每个维度恰好由一个值组成. 您可能具有" debug x86-64"或" release x86"变体.

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

Declaring your source files

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

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

对于仅在特定目标计算机上编译源的情况,您还可以为每个二进制版本配置源.

swift sourcesets compilation
图1.源代码和Swift编译

Managing your dependencies

绝大多数项目都依赖于其他项目,因此管理项目的依存关系是构建任何项目的重要组成部分. 依赖管理是一个大话题,因此我们在这里仅关注Swift项目的基础知识. 如果您想深入了解这些细节,请查看依赖管理的简介 .

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

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

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

  • 标识依赖项的信息(项目路径,Maven GAV)

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

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

例子2.声明依赖
build.gradle
application {
    dependencies {
        implementation project(':common')
    }
}
build.gradle.kts
application {
    dependencies {
        implementation(project(":common"))
    }
}

三个元素的Gradle术语如下:

  • 配置 (例如: implementation )-命名的依赖项集合,针对特定目标(如编译或链接模块)分组在一起

  • 项目引用 (例如: project(':common') )-指定路径引用的项目

您可以在此处找到更全面的依赖项管理术语表.

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

  • implementation -用于编译,链接和运行时

  • swiftCompile Variant -依赖关系所必需的编译你的产品代码,但不应该是链接或运行过程的一部分

  • nativeLinkVariant - for dependencies that are necessary to link your code but shouldn’t be part of the compilation or runtime process

  • nativeRuntime Variant -依赖关系所必需的运行您的组件,但不应该是编译或链接过程的一部分

您可以在本机插件参考章节中了解有关它们的更多信息以及它们之间的关系.

请注意, Swift库插件为编译和链接模块以及依赖于该模块的任何模块所需的依赖项创建了一个附加配置api .

我们仅在此处进行了介绍,因此,一旦您熟悉使用Gradle构建Swift项目的基础知识,我们建议您阅读专用的依赖管理章节 .

需要进一步阅读的一些常见方案包括:

您会发现Gradle具有丰富的API用于处理依赖关系-需要花费一些时间来掌握,但是对于常见情况却很容易使用.

如果遵循以下约定,则编译两个代码都非常容易:

  1. 将您的源代码放在src / main / swift目录下

  2. implementation配置中声明您的编译依赖性(请参阅上一节)

  3. 运行assemble任务

我们建议您尽可能遵循这些约定,但不必这样做.

有几种自定义选项,您将在下面看到.

所有SwiftCompile任务都是增量的并且可以缓存.

Supported tool chain

Gradle支持适用于macOS和Linux官方Swift工具链 . 当您构建本机二进制文件时,Gradle会尝试找到您的计算机上安装的可以构建二进制文件的工具链. Gradle选择可以为目标操作系统,体系结构和Swift语言支持构建的第一个工具链.

对于Linux用户,Gradle将使用系统PATH发现工具链.

Customizing file and directory locations

假设您要迁移遵循Swift Package Manager布局的库项目(例如,生产代码的Sources/ ModuleName _目录). 传统的目录结构不起作用,因此您需要告诉Gradle在哪里可以找到源文件. 您可以通过applicationlibrary脚本块来执行此操作.

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

例子3.设置Swift源集
build.gradle
    library {
        source.from file('src')
    }
build.gradle.kts
    extensions.configure<SwiftLibrary> {
        source.from(file("Sources/Common"))
    }

现在Gradle将仅在Sources / Common中直接搜索源.

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

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

示例4.为所有变体设置Swift编译器选项
build.gradle
tasks.withType(SwiftCompile).configureEach {
    // Define a preprocessor macro for every binary
    macros.add("NDEBUG")

    // Define a compiler options
    compilerArgs.add '-O'
}
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")
}

也可以通过applicationlibrary脚本块上的BinaryCollection查找特定变体的实例:

例子5.为每个变量设置Swift编译器选项
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'
    }
}
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")
    }
}

Selecting target machines

默认情况下,Gradle将尝试为主机操作系统和体系结构创建Swift二进制变体. 通过在applicationlibrary脚本块上指定TargetMachine的集合,可以覆盖此设置:

例子6.设置目标机器
build.gradle
application {
    targetMachines = [
        machines.linux.x86_64,
        machines.macOS.x86_64
    ]
}
build.gradle.kts
application {
    targetMachines.set(listOf(machines.linux.x86_64, machines.macOS.x86_64))
}

Packaging and publishing

在本地环境中,打包和潜在发布Swift项目的方式差异很大. Gradle具有默认值,但是自定义打包可以实现而没有任何问题.

  • Executable files are published directly to Maven repositories.

  • 共享库和静态库文件以及公共标头的压缩文件直接发布到Maven存储库.

  • 对于应用程序,Gradle还支持在已知位置安装和运行具有所有共享库依赖项的可执行文件.

Cleaning the build

Swift应用程序和库插件通过使用基本插件clean任务添加到您的项目中. 此任务只是删除$buildDir目录中的所有内容,因此为什么要始终将构建生成的文件放在其中. 该任务是Delete的一个实例,您可以通过设置其dir属性来更改其删除的dir .

Building Swift libraries

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

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

如果不确定API和实现依赖项之间的区别,请参阅Swift库插件一章中的详细说明.

Building Swift applications

有关更多详细信息,请参见" Swift应用程序插件"一章,但这是您所获得的快速摘要:

  • install创建一个目录,其中包含运行该目录所需的一切

  • Shell和Windows Batch脚本启动应用程序


1 . 不幸的是,Cocoapods仓库还没有被支持为核心功能