初始化脚本是在构建脚本执行之前运行的脚本。它们允许您自定义构建环境或在构建早期配置设置。
初始化脚本对于在多个项目中设置通用配置(例如仓库、插件或自定义 Task)非常有用。
使用初始化脚本
初始化脚本,也称为init 脚本,与 Gradle 中的其他脚本类似。初始化脚本在构建开始之前运行。
它们对于各种目的非常有用
-
设置企业范围的配置(例如,自定义插件位置)
-
根据环境配置属性(例如,开发者机器与 CI 服务器)
-
提供用户特定信息(例如,身份验证凭据)
-
定义机器特定细节(例如,JDK 位置)
-
注册构建监听器(例如,希望监听 Gradle 事件的外部工具可能会发现这很有用)
-
注册日志记录器(例如,自定义 Gradle 如何记录其生成的事件)
init 脚本的一个主要限制是它们无法访问 buildSrc
项目中的类。
调用初始化脚本
有几种方法可以调用初始化脚本(按优先级顺序)
-
在命令行上指定文件,使用选项
-I
或--init-script
,后跟脚本的路径。命令行选项可以出现多次,每次添加另一个初始化脚本。如果命令行上指定的任何文件不存在,构建将失败。
-
将名为
init.gradle(.kts)
的文件放在$GRADLE_USER_HOME/
目录中。 -
将名为
yourfilename.init.gradle(.kts)
的文件放在$GRADLE_USER_HOME/init.d/
目录中。 -
将名为
yourfilename.init.gradle(.kts)
的文件放在$GRADLE_HOME/init.d/
目录中。条目将按字母顺序评估。这允许您打包包含自定义构建逻辑和插件的自定义 Gradle 发行版。您可以将此与 Gradle Wrapper 结合使用,使自定义逻辑可用于企业中的所有构建。
如果找到多个初始化脚本,它们将按照上述指定的顺序全部执行。
给定目录中的脚本按字母顺序执行。例如,工具可以在命令行上指定一个初始化脚本,并在主目录中指定另一个初始化脚本以定义环境。当执行 Gradle 时,这两个脚本都将运行。
编写初始化脚本
与 Gradle 构建脚本一样,初始化脚本是 Groovy 或 Kotlin 脚本。每个初始化脚本都有一个与之关联的 Gradle 实例。初始化脚本中的任何属性引用和方法调用都将委托给此 Gradle
实例。
每个初始化脚本都实现 Script 接口。
编写初始化脚本时,请注意您尝试访问的引用的范围。例如,从 |
从初始化脚本配置项目
您可以使用初始化脚本来配置构建中的项目。这与在多项目构建中配置项目类似。
以下示例展示了如何在项目评估之前从初始化脚本执行额外的配置
repositories {
mavenCentral()
}
tasks.register('showRepos') {
def repositoryNames = repositories.collect { it.name }
doLast {
println "All repos:"
println repositoryNames
}
}
allprojects {
repositories {
mavenLocal()
}
}
repositories {
mavenCentral()
}
tasks.register("showRepos") {
val repositoryNames = repositories.map { it.name }
doLast {
println("All repos:")
println(repositoryNames)
}
}
allprojects {
repositories {
mavenLocal()
}
}
此示例使用此功能来配置一个额外的仓库,该仓库仅用于特定环境。
> gradle --init-script init.gradle.kts -q showRepos
All repos:
[MavenLocal, MavenRepo]
> gradle --init-script init.gradle -q showRepos
All repos:
[MavenLocal, MavenRepo]
添加外部依赖
初始化脚本还可以使用 initscript()
方法声明依赖项,传入一个声明初始化脚本类路径的闭包。
为初始化脚本声明外部依赖
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.apache.commons:commons-math:2.0")
}
}
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.apache.commons:commons-math:2.0'
}
}
传递给 initscript()
方法的闭包配置了一个 ScriptHandler 实例。您可以通过向 classpath
配置添加依赖项来声明初始化脚本类路径。
这与您声明 Java 编译类路径的方式相同。您可以使用声明依赖中描述的任何依赖类型,除了项目依赖项。
声明初始化脚本类路径后,您可以在初始化脚本中使用这些类,就像使用类路径上的任何其他类一样。以下示例添加到前面的示例中,并使用来自初始化脚本类路径的类。
具有外部依赖的初始化脚本
import org.apache.commons.math.fraction.Fraction
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.apache.commons:commons-math:2.0")
}
}
println(Fraction.ONE_FIFTH.multiply(2))
tasks.register("doNothing")
import org.apache.commons.math.fraction.Fraction
initscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.apache.commons:commons-math:2.0'
}
}
println Fraction.ONE_FIFTH.multiply(2)
tasks.register('doNothing')
> gradle --init-script init.gradle.kts -q doNothing
2 / 5
> gradle --init-script init.gradle -q doNothing
2 / 5
应用插件
插件可以像 Gradle 构建脚本或 Gradle Settings 文件一样应用于初始化脚本。
在初始化脚本中使用插件
apply<EnterpriseRepositoryPlugin>()
class EnterpriseRepositoryPlugin : Plugin<Gradle> {
companion object {
const val ENTERPRISE_REPOSITORY_URL = "https://repo.gradle.org/gradle/repo"
}
override fun apply(gradle: Gradle) {
// ONLY USE ENTERPRISE REPO FOR DEPENDENCIES
gradle.allprojects {
repositories {
// Remove all repositories not pointing to the enterprise repository url
all {
if (this !is MavenArtifactRepository || url.toString() != ENTERPRISE_REPOSITORY_URL) {
project.logger.lifecycle("Repository ${(this as? MavenArtifactRepository)?.url ?: name} removed. Only $ENTERPRISE_REPOSITORY_URL is allowed")
remove(this)
}
}
// add the enterprise repository
add(maven {
name = "STANDARD_ENTERPRISE_REPO"
url = uri(ENTERPRISE_REPOSITORY_URL)
})
}
}
}
}
repositories{
mavenCentral()
}
data class RepositoryData(val name: String, val url: URI)
tasks.register("showRepositories") {
val repositoryData = repositories.withType<MavenArtifactRepository>().map { RepositoryData(it.name, it.url) }
doLast {
repositoryData.forEach {
println("repository: ${it.name} ('${it.url}')")
}
}
}
apply plugin: EnterpriseRepositoryPlugin
class EnterpriseRepositoryPlugin implements Plugin<Gradle> {
private static String ENTERPRISE_REPOSITORY_URL = "https://repo.gradle.org/gradle/repo"
void apply(Gradle gradle) {
// ONLY USE ENTERPRISE REPO FOR DEPENDENCIES
gradle.allprojects { project ->
project.repositories {
// Remove all repositories not pointing to the enterprise repository url
all { ArtifactRepository repo ->
if (!(repo instanceof MavenArtifactRepository) ||
repo.url.toString() != ENTERPRISE_REPOSITORY_URL) {
project.logger.lifecycle "Repository ${repo.url} removed. Only $ENTERPRISE_REPOSITORY_URL is allowed"
remove repo
}
}
// add the enterprise repository
maven {
name = "STANDARD_ENTERPRISE_REPO"
url = ENTERPRISE_REPOSITORY_URL
}
}
}
}
}
repositories{
mavenCentral()
}
@Immutable
class RepositoryData {
String name
URI url
}
tasks.register('showRepositories') {
def repositoryData = repositories.collect { new RepositoryData(it.name, it.url) }
doLast {
repositoryData.each {
println "repository: ${it.name} ('${it.url}')"
}
}
}
> gradle --init-script init.gradle.kts -q showRepositories
repository: STANDARD_ENTERPRISE_REPO ('https://repo.gradle.org/gradle/repo')
> gradle --init-script init.gradle -q showRepositories
repository: STANDARD_ENTERPRISE_REPO ('https://repo.gradle.org/gradle/repo')
初始化脚本中的插件确保在运行构建时仅使用指定的仓库。
在初始化脚本中应用插件时,Gradle 会实例化插件并调用插件实例的 Plugin.apply(T) 方法。
gradle
对象作为参数传递,可用于配置构建的各个方面。当然,应用的插件可以作为外部依赖项解析,如初始化脚本的外部依赖项中所述