这篇文章介绍了一个新的Gradle依赖性管理功能,叫做 "源依赖性"。
通常,当你声明对一个库的依赖时,Gradle会在二进制仓库中寻找该库的二进制文件,比如JCenter或Maven Central,并下载二进制文件用于构建。
源码依赖允许你让Gradle自动从Git中检出库的源代码,并在你的机器上构建二进制文件,而不是下载它们。
我们很想得到你对这个功能的反馈。请试一试,让我们知道哪些功能适合你,以及你遇到的任何问题。你可以在Gradle论坛上留下反馈,或在Gradle本地GitHub仓库中提出问题。
你应该知道,这个功能目前正在孵化中,在未来的Gradle版本中可能会有一些突破性的变化。请不要在生产中使用该功能,直到该功能在未来的版本中被提升为稳定版。
你怎样才能尝试呢?
你可以在native-samples资源库中找到许多使用源码依赖的样本。C++ 构建是使用源码依赖的一个自然场所,但这并不是 C++ 的特定功能。源码依赖对任何使用Gradle依赖性管理功能的构建都有效,比如Java、Kotlin或Android构建。你可以用最新的Gradle 4.10或夜间版试试这个功能。
让我们来看看一个应用程序的例子。这个例子展示了一个使用库的应用程序,这个库住在一个单独的Git仓库里。
在构建文件中,源依赖和二进制依赖看起来是一样的。你要声明对某个模块的特定版本的依赖,比如一个库。这里,我们的样本需要1.0版的 "utilities "库:
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仓库告诉我们你的想法。