Gradle提供了一种强大的机制,可以根据当前环境自定义构建. 该机制还支持希望与Gradle集成的工具.

请注意,这与" build-init "插件提供的" init "任务完全不同(请参阅Build Init插件 ).

Basic usage

初始化脚本(又称初始化脚本 )与Gradle中的其他脚本相似. 但是,这些脚本在构建开始之前运行. 以下是几种可能的用途:

  • 设置企业范围的配置,例如在哪里可以找到自定义插件.

  • 根据当前环境设置属性,例如开发人员的计算机与持续集成服务器.

  • 提供构建所需的有关用户的个人信息,例如存储库或数据库身份验证凭据.

  • 定义机器特定的详细信息,例如JDK的安装位置.

  • 注册构建侦听器. 希望监听Gradle事件的外部工具可能会发现这很有用.

  • 注册构建记录器. 您可能希望自定义Gradle如何记录它生成的事件.

初始化脚本的一个主要限制是它们不能访问buildSrc项目中的类(有关此功能的详细信息,请参见使用buildSrc提取命令式逻辑 ).

Using an init script

有几种使用初始化脚本的方法:

  • 在命令行上指定一个文件. 命令行选项是-I--init-script后跟--init-script路径. 命令行选项可以多次出现,每次添加另一个初始化脚本. 如果命令行上指定的任何文件不存在,则构建将失败.

  • 把称为文件init.gradle (或init.gradle.kts为科特林)在USER_HOME /.gradle/目录.

  • 将文件放在与两端.gradle (或.init.gradle.kts为科特林)在USER_HOME /.gradle/init.d/目录.

  • 将文件放在与两端.gradle (或.init.gradle.kts为科特林)在GRADLE_HOME /init.d/目录,在摇篮分布. 这使您可以打包包含一些自定义构建逻辑和插件的自定义Gradle发行版. 您可以将其与Gradle包装器结合使用,以使自定义逻辑可用于企业中的所有内部版本.

如果发现一个以上的初始化脚本,它们将全部按照上述指定的顺序执行. 给定目录中的脚本按字母顺序执行. 例如,这允许使用一种工具在命令行上指定一个初始化脚本,并且用户可以将一个脚本放入其主目录中以定义环境,并且在执行Gradle时,这两个脚本都将运行.

Writing an init script

类似于Gradle构建脚本,初始化脚本是Groovy或Kotlin脚本. 每个初始化脚本都有一个与之关联的Gradle实例. 初始化脚本中的任何属性引用和方法调用都将委托给此Gradle实例.

每个初始化脚本还实现脚本接口.

Configuring projects from an init script

您可以使用初始化脚本来配置构建中的项目. 这与在多项目构建中配置项目的方式类似. 以下示例显示了评估项目之前如何通过初始化脚本执行额外的配置. 此样本使用此功能来配置额外的存储库,以仅用于某些环境.

示例1.在评估项目之前,使用init脚本执行额外的配置
build.gradle
repositories {
    mavenCentral()
}

task showRepos {
    doLast {
        println "All repos:"
        println repositories.collect { it.name }
    }
}
init.gradle
allprojects {
    repositories {
        mavenLocal()
    }
}
build.gradle.kts
repositories {
    mavenCentral()
}

tasks.register("showRepos") {
    doLast {
        println("All repos:")
        //TODO:kotlin-dsl remove filter once we're no longer on a kotlin eap
        println(repositories.map { it.name }.filter { it != "maven" })
    }
}
init.gradle.kts
allprojects {
    repositories {
        mavenLocal()
    }
}

Output when applying the init script

> gradle --init-script init.gradle -q showRepos
All repos:
[MavenLocal, MavenRepo]
> gradle --init-script init.gradle.kts -q showRepos
All repos:
[MavenLocal, MavenRepo]

External dependencies for the init script

构建脚本的外部依赖关系中,说明了如何向构建脚本添加外部依赖关系. 初始化脚本也可以声明依赖关系. 您可以使用initscript()方法执行此操作,并传入一个声明初始化脚本类路径的闭包.

例子2.声明一个初始化脚本的外部依赖
init.gradle
initscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.apache.commons:commons-math:2.0'
    }
}
init.gradle.kts
initscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.apache.commons:commons-math:2.0")
    }
}

传递给initscript()方法的闭包可配置ScriptHandler实例. 您可以通过将依赖项添加到classpath配置中来声明初始化脚本类classpath . 这与您声明Java编译类路径的方式相同. 您可以使用声明依赖项中描述的任何依赖项类型,项目依赖项除外.

声明了初始化脚本的类路径后,您可以像使用该类路径上的任何其他类一样,使用初始化脚本中的类. 以下示例将添加到前面的示例中,并使用init脚本classpath中的类.

例子3.具有外部依赖关系的初始化脚本
init.gradle
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)
init.gradle.kts
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))

应用初始化脚本时的输出

> gradle --init-script init.gradle -q doNothing
2 / 5
> gradle --init-script init.gradle.kts -q doNothing
2 / 5

Init script plugins

Similar to a Gradle build script or a Gradle settings file, plugins can be applied on init scripts.

例子4.在初始化脚本中使用插件
init.gradle
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
                }
            }
        }
    }
}
build.gradle
/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// tag::show-repos-task[]
repositories{
    mavenCentral()
}

 task showRepositories {
     doLast {
         repositories.each {
             println "repository: ${it.name} ('${it.url}')"
         }
     }
}
// end::show-repos-task[]
init.gradle.kts
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)
                })
            }
        }
    }
}
build.gradle.kts
// tag::show-repos-task[]
repositories{
    mavenCentral()
}

tasks.register("showRepositories") {
    doLast {
        repositories.map { it as MavenArtifactRepository }.forEach {
            println("repository: ${it.name} ('${it.url}')")
        }
    }
}
// end::show-repos-task[]

应用初始化脚本时的输出

> gradle --init-script init.gradle -q showRepositories
repository: STANDARD_ENTERPRISE_REPO ('https://repo.gradle.org/gradle/repo')
> gradle --init-script init.gradle.kts -q showRepositories
repository: STANDARD_ENTERPRISE_REPO ('https://repo.gradle.org/gradle/repo')

初始化脚本中的插件可确保在运行构建时仅使用指定的存储库.

在初始化脚本中应用插件时,Gradle实例化插件并调用插件实例的Plugin.apply(T)方法. gradle对象作为参数传递,可用于配置构建的各个方面. 当然,可以将应用的插件解析为外部依赖项,如初始化脚本的外部依赖项中所述