本文由 简悦SimpRead 转码, 原文地址 stefma.medium.com
构建脚本块
和你在一起是一段有趣的旅程。但现在是说再见的时候了 👋
构建脚本块
每个使用Gradle作为底层构建工具的开发者都知道buildscript块。或者至少知道如何使用它。在我深入探讨为什么我们应该摆脱它之前,我想解释一下它到底是什么以及它的作用。
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.1'
}
}
上面的build.gradle文件在你每次创建新项目(不含Kotlin)时都会由Android Studio自动生成,并存在于你项目的顶层目录中。
但这个块是做什么的呢?基本上它定义了构建本身所需的依赖关系。或者换句话说。它定义了构建你的应用程序(无论你的 "应用程序 "是什么(Android应用程序、Gradle插件、Swift桌面应用程序......))所需的依赖。
在我们的安卓例子中,我们必须定义安卓Gradle插件的依赖关系,以帮助我们构建一个APK。
// project/build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.1'
}
}
// project/app/build.gradle.kts
apply {
plugin("com.android.application")
}
既然我们知道它的作用,为什么要抛弃它呢?🤔
好吧,我并没有说我们不再需要它背后的逻辑(应用构建所需的依赖关系)。我更想说的是,我们必须用一些 "新 "东西来取代传统的buildscript块。
插件块的崛起
这个 "新 "的plugins块其实并不新鲜。它已经在Gradle 2.1中被引入。在那时,它显然没有得到那么多的关注。
然而。插件块更容易阅读和使用。
// project/app/build.gradle.kts
plugins {
id("org.gradle.java")
kotlin("jvm") version "1.2.40"
}
你可能注意到,这只是一个文件,而不是两个?
但也有一些 "限制"。默认情况下,plugin块只能解决属于以下两种情况的插件。
- 核心插件(由Gradle自己提供)。例如,这些是:
org.gradle.java,org.gradle.groovy,org.gradle.java-gradle-plugin等等... - 发布到Gradle Plugin Portal。
不幸的是,并不是所有的Gradle插件都能在插件门户上找到(看着你,Android Gradle Plugin! 😡).
我们怎样才能应用这些既不是 "核心 "也没有发布到Plugin Portal的插件呢?
有一个相当不错的技巧可以做到这一点。在我看来,这需要在settings.gradle.kts中编写一些 "模板代码",但这是值得做的。
pluginManagement {
repositories {
gradlePluginPortal()
jcenter()
google()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.android.application") {
useModule("com.android.tools.build:gradle:${requested.version}")
}
}
}
}
首先,我们必须定义所有 "plugin "块应该寻找插件的存储库(顺序很重要*)。在eachPlugin块中,我们可以查看每个应用的插件(从id("name")),并基于此进行操作。在我们的例子中,我们可以这样说。
"if id equals com.android.application then use "this" as module"。
*这个顺序其实并不 "重要"。但是Gradle会按照给定的顺序在这些仓库中寻找应用的插件。你可能想先添加有最多插件的仓库。
你可能会问useModule中的字符串是什么?它就是我们在传统的buildscript块中使用的classpath字符串。
有了这些信息,Gradle就知道在哪里看,如何在plugins块中搜索插件了。很酷,不是吗?😎
最后我们能够像这样应用Android Gradle插件。
plugins {
id("com.android.application") version "3.1.1"
}
是时候改变了,现在!
版本问题
Gradle是为模块化设计的。这意味着一个项目可以包含不同的模块,这些模块可以应用不同(或相同)的插件。如果你这样做,你可能会有这样的结局。
// project/app/build.gradle.kts
plugins {
id("com.android.application") version "3.1.1"
kotlin("android") version "1.2.40"
}
// project/library1/build.gradle.kts
plugins {
id("com.android.library") version "3.1.1"
kotlin("android") version "1.2.40"
}
// project/library2/build.gradle.kts
plugins {
id("com.android.library") version "3.1.1"
kotlin("android") version "1.2.40"
kotlin("kapt") version "1.2.40"
}
想象一下,你想更新应用的插件。在每个build.gradle.kts文件中跳转并更改版本,真的很烦人(除了可能导致错误之外。例如,你忘记了一个Gradle文件或使用了错误的版本)。但是有帮助。另一个时候,Gradle设置可以帮助我们。
有趣的事实:作为一个Android开发者,你可能从未接触过settings.gradle,甚至不知道它的存在,对吗? 😉
除了只添加useModule(用于插件门户中缺少的插件),我们还可以额外使用useVersion。对于所有的插件! 即使它们已经发布到插件门户(对于所有的Kotlin插件来说都是如此)。
pluginManagement {
repositories { ... }
eachPlugin {
if (requested.id.id.startsWith("com.android")) {
useModule("com.android.tools.build:gradle:3.1.1")
}
if (requested.id.id.startsWith("org.jetbrains.kotlin")) {
useVersion("1.2.31")
}
}
}
有了这个小小的改变,我们就可以在没有定义版本的情况下应用我们的插件。现在Gradle知道所有以 "com.android "和 "org.jetbrains.kotlin "开头的插件的具体版本。
plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
}
摘要
- 删除buildcript块
- 复制并粘贴上面的代码到你的settings.gradle中。
- 使用插件块和舞蹈 🕺