介绍源依赖项

这篇文章介绍了一个新的 Gradle 依赖管理功能,称为“源依赖项”。

通常,当您声明对库的依赖项时,Gradle 会在二进制存储库(如 JCenter 或 Maven Central)中查找库的二进制文件,并下载这些二进制文件以供构建使用。

源依赖项允许您让 Gradle 自动从 Git 中检出库的源代码,并在您的机器上本地构建二进制文件,而不是下载它们。

我们非常乐意收到您对该功能的反馈。请尝试一下,并告诉我们哪些对您有效以及您遇到的任何问题。您可以在 Gradle 论坛 上留下反馈,或在 Gradle native GitHub 仓库中提出问题。

您应该知道,此功能目前处于孵化阶段,可能会在 Gradle 的未来版本中以破坏性的方式发生更改。在该功能在未来版本中提升为稳定状态之前,请勿在生产环境中使用它。

如何尝试它?

您可以在 native-samples 仓库中找到许多使用源依赖项的示例。C++ 构建是使用源依赖项的自然场所,但这并非 C++ 特定的功能。源依赖项适用于使用 Gradle 依赖项管理功能的任何类型的构建,例如 Java、Kotlin 或 Android 构建。您可以使用最新的 Gradle 4.10nightly 尝试此功能。

让我们看一下 示例应用程序。此示例展示了一个使用位于单独 Git 仓库中的库的应用程序。

源依赖项在构建文件中看起来与二进制依赖项相同。您声明对特定版本的 模块(例如库)的依赖项。在这里,我们的示例需要“utilities”库的 1.0 版本

dependencies {
    implementation 'org.gradle.cpp-samples:utilities:1.0'
}

您还需要告诉 Gradle 在哪里可以找到库的源代码。这类似于您需要告诉 Gradle 在哪里可以找到二进制文件,方法是在构建中定义一些二进制存储库,但是语法不同。在 settings.gradle 文件中,我们定义了一个源映射

sourceControl {
    gitRepository("https://github.com/gradle/native-samples-cpp-library.git") {
        producesModule("org.gradle.cpp-samples:utilities")
    }
}

现在,当 Gradle 需要找到“utilities”库的版本时,它将查找 Git 存储库中匹配的标签。Gradle 将签出匹配的 Git 标签,构建二进制文件并使结果可用。这与 包含的构建 的工作方式相同。

以下是对此示例运行 gradle assemble 的结果

> Task :native-samples-cpp-library:list:compileDebugCpp
> Task :native-samples-cpp-library:utilities:compileDebugCpp
> Task :native-samples-cpp-library:list:linkDebug
> Task :compileDebugCpp
> Task :native-samples-cpp-library:utilities:linkDebug
> Task :linkDebug
> Task :installDebug
> Task :assemble

BUILD SUCCESSFUL in 4s
3 actionable tasks: 3 executed

Gradle 已克隆库的源代码,构建库二进制文件,然后将应用程序链接到这些二进制文件。

您也可以使用稍微不同的语法声明对分支的依赖关系。这个 示例应用程序 演示了如何做到这一点。

dependencies {
    implementation('org.gradle.cpp-samples:utilities') {
        version {
            branch = 'release'
        }
    }
}

源依赖关系也适用于插件,但目前需要在 settings.gradle 中进行一些额外的配置才能正常工作。这个 示例库 展示了如何做到这一点。

源依赖关系有什么用?

当您使用的模块的二进制文件在二进制存储库中不可用时,源依赖关系很有用。例如

  • 当您使用库的分支,并且该分支尚未发布二进制文件时。例如,您可能希望使用尚未合并或发布的分支中的某些错误修复。
  • 当您使用发布源代码但没有二进制文件的库时。这在 C++ 库(以及应用程序)中很常见,这些库仅以源代码形式发布,您必须自己构建二进制文件。
  • 当您使用未发布目标平台二进制文件的本地库时。C++ 库或应用程序通常只发布某些常见操作系统或工具链的二进制文件。要在其他平台上使用该库,您必须自己构建二进制文件。
  • 当您不想等待另一个系统(例如 CI 服务器)发布依赖项的二进制文件时。例如,您可能希望尝试对多个库进行更改。

源依赖关系使这些用例更易于实现。Gradle 会自动检出依赖项的正确版本,并在需要时确保构建二进制文件。它在运行构建的任何地方都这样做。检出的项目甚至不需要具有现有的 Gradle 构建。 此示例 展示了一个 Gradle 构建,它通过插件注入 Gradle 构建来使用两个没有构建系统的源依赖项。注入的配置可以执行常规 Gradle 插件可以执行的任何操作,例如包装现有的 CMake 或 Maven 构建。

源依赖关系可以与 Gradle 构建缓存 相结合,当您的团队中的每个人都从源代码构建相同的依赖项时,这些用例会变得更高效。Gradle 构建缓存确保一旦构建了二进制文件,它们就会在其他地方重复使用。

源依赖关系可以与二进制依赖关系一起使用,您可以混合匹配,以便某些依赖关系从源代码构建,而其他依赖关系则作为二进制文件下载。源依赖关系也与 复合构建 很好地协同工作。

这与复合构建有什么不同?

主要区别不大。源依赖基于 Gradle 的 复合构建 功能,并添加了源代码的自动配置,以帮助解决一些特定用例。

源依赖与包含构建在意图上有所不同。包含构建表示您当前正在处理的某个模块。无论构建中请求模块的哪个版本,依赖解析始终会使用包含构建中的二进制文件,以便您可以看到更改的效果。

另一方面,源依赖表示您使用的某个模块,但该模块恰好以源代码形式而不是二进制形式提供。依赖解析始终会选择与构建中请求的版本匹配的源依赖版本。使用包含构建,您可以修改源代码并直接查看更改,但使用源依赖,您需要提交并推送更改才能看到其效果。

缺少的功能

源依赖支持仍处于实验阶段,缺少一些重要功能

  • 构建扫描 尚未支持使用源依赖的构建。
  • IDE 支持目前尚不可用。大多数 IDE 集成在构建使用源依赖时会失败并报错。源依赖目前仅受 Gradle 的 Xcode C++ 集成支持。
  • 依赖锁定 不支持源依赖。
  • 源依赖也具有与包含构建相同的 限制
  • 您不能对包含包含构建的构建使用源依赖。但是,您可以对使用源依赖的构建使用源依赖。
  • 您目前还不能为特定模块混合使用源依赖和二进制依赖。每个模块必须来自 Git 仓库或二进制仓库,但不能同时来自两者。
  • 仅支持 Git 仓库。

路线图

我们希望得到您的反馈,并根据反馈实现上述缺少的功能。一旦我们对 DSL 和 API 的实用性和良好行为感到满意,我们将把该功能提升到稳定状态。请在 Gradle 论坛Gradle 原生 GitHub 仓库中告诉我们您的想法。

讨论