Gradle provides a powerful mechanism for customizing the build based on the current environment.

This mechanism also supports tools that wish to integrate with Gradle.

Basic usage

Initialization scripts (a.k.a. init scripts) are similar to other scripts in Gradle. These scripts, however, are run before the build starts.

Here are several possible uses:

  • Set up enterprise-wide configuration, such as where to find custom plugins.

  • Set up properties based on the current environment, such as a developer’s machine vs. a continuous integration server.

  • Supply personal information about the user required by the build, such as repository or database authentication credentials.

  • Define machine-specific details, such as where JDKs are installed.

  • Register build listeners. External tools that wish to listen to Gradle events might find this useful.

  • Register build loggers. You could customize how Gradle logs the events that it generates.

One main limitation of init scripts is that they cannot access classes in the buildSrc project.

Using an init script

There are several ways to use an init script:

  • Specify a file on the command line. The command line option is -I or --init-script followed by the path to the script.

    The command line option can appear more than once, each time adding another init script. The build will fail if any files specified on the command line do not exist.

  • Put a file called init.gradle (or init.gradle.kts for Kotlin) in the $GRADLE_USER_HOME/ directory.

  • Put a file that ends with .gradle (or .init.gradle.kts for Kotlin) in the $GRADLE_USER_HOME/init.d/ directory.

  • Put a file that ends with .gradle (or .init.gradle.kts for Kotlin) in the $GRADLE_HOME/init.d/ directory, in the Gradle distribution.

    This lets you package a custom Gradle distribution containing custom build logic and plugins. You can combine this with the Gradle wrapper to make custom logic available to all builds in your enterprise.

If more than one init script is found, they will all be executed in the order specified above.

Scripts in a given directory are executed in alphabetical order. For example, a tool can specify an init script on the command line and another in the home directory for defining the environment. Both scripts will run when Gradle is executed.

Writing an init script

Like a Gradle build script, an init script is a Groovy or Kotlin script. Each init script has a Gradle instance associated with it. Any property reference and method call in the init script will delegate to this Gradle instance.

Each init script also implements the Script interface.

When writing init scripts, pay attention to the scope of the reference you are trying to access. For example, properties loaded from gradle.properties are available on Settings or Project instances but not on the Gradle one.

Configuring projects from an init script

You can use an init script to configure the projects in the build. This works similarly to configuring projects in a multi-project build.

The following sample shows how to perform extra configuration from an init script before the projects are evaluated:

build.gradle.kts
repositories {
    mavenCentral()
}

tasks.register("showRepos") {
    val repositoryNames = repositories.map { it.name }
    doLast {
        println("All repos:")
        println(repositoryNames)
    }
}
init.gradle.kts
allprojects {
    repositories {
        mavenLocal()
    }
}
build.gradle
repositories {
    mavenCentral()
}

tasks.register('showRepos') {
    def repositoryNames = repositories.collect { it.name }
    doLast {
        println "All repos:"
        println repositoryNames
    }
}
init.gradle
allprojects {
    repositories {
        mavenLocal()
    }
}

This sample uses this feature to configure an additional repository to be used only for specific environments.

Output when applying the init script

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

External dependencies for the init script

Init scripts can also declare dependencies with the initscript() method, passing in a closure that declares the init script classpath.

Declaring external dependencies for an init script:

init.gradle.kts
initscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.apache.commons:commons-math:2.0")
    }
}
init.gradle
initscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.apache.commons:commons-math:2.0'
    }
}

The closure passed to the initscript() method configures a ScriptHandler instance. You declare the init script classpath by adding dependencies to the classpath configuration.

This is the same way you declare, for example, the Java compilation classpath. You can use any of the dependency types described in Declaring Dependencies, except project dependencies.

Having declared the init script classpath, you can use the classes in your init script as you would any other classes on the classpath. The following example adds to the previous example and uses classes from the init script classpath.

An init script with external dependencies:

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))
build.gradle.kts
tasks.register("doNothing")
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)
build.gradle
tasks.register('doNothing')

Output when applying the init script:

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

Init script plugins

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

Using plugins in init scripts:

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
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}')")
        }
    }
}
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
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}')"
        }
    }
}

Output when applying the init script:

> 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')

The plugin in the init script ensures that only a specified repository is used when running the build.

When applying plugins within the init script, Gradle instantiates the plugin and calls the plugin instance’s Plugin.apply(T) method.

The gradle object is passed as a parameter, which can be used to configure all aspects of a build. Of course, the applied plugin can be resolved as an external dependency as described in External dependencies for the init script