Writing Build Scripts
Use a build script to configure a project. Each Gradle project corresponds to a software component
that needs to be built, like a library or an application. Each build script is associated
with an object of type Project.
As the build script executes, it configures this Project
.
Build scripts, Settings scripts, and Init scripts
Build scripts define
|
Properties
Many top-level properties and blocks in a build script are part of the Project
API.
The following build script uses the Project.name
property to print the name of the project:
println(name)
println(project.name)
println name
println project.name
gradle -q check
> gradle -q check project-api project-api
Both println
statements print out the same property. The first uses the top-level reference
to the name
property of the Project
object. The other statement uses the project
property
available to any build script, which returns the associated Project
object.
Standard project properties
The Project
object exposes a standard set of properties in your build script.
The following table lists a few commonly used properties:
Name | Type | Default Value |
---|---|---|
|
The |
|
|
|
The name of the project directory. |
|
|
The absolute path of the project. |
|
|
A description for the project. |
|
|
The directory containing the build script. |
|
|
|
|
|
|
|
|
|
|
An |
Script with other targets
The build scripts described here target |
The Script API
When Gradle executes a Groovy build script (.gradle
), it compiles the script into a class that
implements Script. As a result, builds scripts
have access to all of the properties and methods declared by the Script
interface.
When Gradle executes a Kotlin build script (.gradle.kts
), it compiles the script into a subclass
of KotlinBuildScript.
As a result, builds scripts have access to all visible properties and functions declared by the KotlinBuildScript
type.
Declare Variables
Build scripts can declare two kinds of variables: local variables and extra properties.
Local Variables
Declare local variables with the val
keyword. Local variables are only visible in the scope where they have been declared. They are a feature of the underlying Kotlin language.
Declare local variables with the def
keyword. Local variables are only visible in the scope where they have been declared. They are a feature of the underlying Groovy language.
val dest = "dest"
tasks.register<Copy>("copy") {
from("source")
into(dest)
}
def dest = 'dest'
tasks.register('copy', Copy) {
from 'source'
into dest
}
Extra Properties
All of Gradle’s enhanced objects, including projects, tasks, and source sets, can hold user-defined properties.
Add, read, and set extra properties via the owning object’s extra
property. Alternatively, you can access extra properties via Kotlin delegated properties using by extra
.
Add, read, and set extra properties via the owning object’s ext
property. Alternatively, you can use an ext
block to add multiple properties at once.
plugins {
id("java-library")
}
val springVersion by extra("3.1.0.RELEASE")
val emailNotification by extra { "build@master.org" }
sourceSets.all { extra["purpose"] = null }
sourceSets {
main {
extra["purpose"] = "production"
}
test {
extra["purpose"] = "test"
}
create("plugin") {
extra["purpose"] = "production"
}
}
tasks.register("printProperties") {
val springVersion = springVersion
val emailNotification = emailNotification
val productionSourceSets = provider {
sourceSets.matching { it.extra["purpose"] == "production" }.map { it.name }
}
doLast {
println(springVersion)
println(emailNotification)
productionSourceSets.get().forEach { println(it) }
}
}
plugins {
id 'java-library'
}
ext {
springVersion = "3.1.0.RELEASE"
emailNotification = "build@master.org"
}
sourceSets.all { ext.purpose = null }
sourceSets {
main {
purpose = "production"
}
test {
purpose = "test"
}
plugin {
purpose = "production"
}
}
tasks.register('printProperties') {
def springVersion = springVersion
def emailNotification = emailNotification
def productionSourceSets = provider {
sourceSets.matching { it.purpose == "production" }.collect { it.name }
}
doLast {
println springVersion
println emailNotification
productionSourceSets.get().each { println it }
}
}
gradle -q printProperties
> gradle -q printProperties 3.1.0.RELEASE build@master.org main plugin
This example adds two extra properties to the project
object via by extra
. Additionally, this example adds a property named purpose
to each source set by setting extra["purpose"]
to null
. Once added, you can read and set all of these properties via extra
.
This example adds two extra properties to the project
object via an ext
block. Additionally, this example adds a property named purpose
to each source set by setting ext.purpose
to null
. Once added, you can read and set all of these properties just like predefined properties.
Gradle requires special syntax for adding a property so it can fail fast. For example, this allows Gradle to recognize when a script attempts to set a property that does not exist. You can access extra properties anywhere where you can access their owning object. This gives extra properties a wider scope than local variables. Subprojects can access extra properties on their parent projects.
For more information about extra properties, see ExtraPropertiesExtension in the API documentation.
Configure Arbitrary Objects
Configure arbitrary objects with configure()
:
class UserInfo(
var name: String? = null,
var email: String? = null
)
tasks.register("configure") {
val user = UserInfo().apply {
name = "Isaac Newton"
email = "isaac@newton.me"
}
doLast {
println(user.name)
println(user.email)
}
}
class UserInfo {
String name
String email
}
tasks.register('configure') {
def user = configure(new UserInfo()) {
name = "Isaac Newton"
email = "isaac@newton.me"
}
doLast {
println user.name
println user.email
}
}
gradle -q configure
> gradle -q configure Isaac Newton isaac@newton.me
Configure Objects in an External Script
You can also configure arbitrary objects using an external script:
Not supported in Kotlin
The Kotlin DSL does not support arbitrary object configuration using an external script. For more information, see gradle/kotlin-dsl#659. |
class UserInfo {
String name
String email
}
tasks.register('configure') {
def userInfo = new UserInfo()
// Apply the script
apply from: 'other.gradle', to: userInfo
doLast {
println userInfo.name
println userInfo.email
}
}
// Set properties.
name = "Isaac Newton"
email = "isaac@newton.me"
gradle -q configure
> gradle -q configure Isaac Newton isaac@newton.me
Helpful Groovy Syntax
Groovy provides many features to help create DSLs. These features can help you write more idiomatic build scripts, plugins, and tasks.
Looking for helpful Kotlin syntax? Check out the Kotlin reference documentation and Kotlin Koans. |
Convenience Methods
Groovy adds convenience methods to the standard Java classes.
For example, Iterable
gets an each
method, which iterates over the elements of the Iterable
:
// Iterable gets an each() method
configurations.runtimeClasspath.each { File f -> println f }
For more information, see the GDK documentation.
Automatic Property Accessors
Groovy automatically converts property references into getter or setter method calls:
// Using a getter method
println project.buildDir
println getProject().getBuildDir()
// Using a setter method
project.buildDir = 'target'
getProject().setBuildDir('target')
Optional Parentheses on Method Calls
Groovy doesn’t require parentheses for method calls:
test.systemProperty 'some.prop', 'value'
test.systemProperty('some.prop', 'value')
List and Map Instantiation Shortcuts
Groovy provides shortcuts to define List
and Map
instances.
For example, consider the “apply
” method, which accepts a map parameter.
When you apply a plugin (apply plugin:'java'
), you don’t use a map literal.
Plugin application uses "named parameters" instead. Named parameters and map
literals use similar syntax, but named parameters don’t use wrapping brackets.
When you call apply
, Groovy converts the named parameter list to a map.
// List literal
test.includes = ['org/gradle/api/**', 'org/gradle/internal/**']
List<String> list = new ArrayList<String>()
list.add('org/gradle/api/**')
list.add('org/gradle/internal/**')
test.includes = list
// Map literal.
Map<String, String> map = [key1:'value1', key2: 'value2']
// Groovy will coerce named arguments
// into a single map argument
apply plugin: 'java'
Last Closure Parameter Syntax
The Gradle DSL uses closures in many places. You can find out more about closures here. When the last parameter of a method is a closure, you can place the closure after the method call:
repositories {
println "in a closure"
}
repositories() { println "in a closure" }
repositories({ println "in a closure" })
Closure Delegates
Each closure has a delegate
object. Groovy uses this delegate to look up variable and method
references to nonlocal variables and closure parameters. Gradle uses this for configuration closures,
where the delegate
object refers to the object being configured.
dependencies {
assert delegate == project.dependencies
testImplementation('junit:junit:4.13')
delegate.testImplementation('junit:junit:4.13')
}
Default Imports
To make build scripts more concise, Gradle automatically adds a set of import statements to scripts.
As a result, instead of writing throw new org.gradle.api.tasks.StopExecutionException()
,
you can write throw new StopExecutionException()
instead.
Gradle implicitly adds the following imports to each script:
import org.gradle.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.component.*
import org.gradle.api.artifacts.dsl.*
import org.gradle.api.artifacts.ivy.*
import org.gradle.api.artifacts.maven.*
import org.gradle.api.artifacts.query.*
import org.gradle.api.artifacts.repositories.*
import org.gradle.api.artifacts.result.*
import org.gradle.api.artifacts.transform.*
import org.gradle.api.artifacts.type.*
import org.gradle.api.artifacts.verification.*
import org.gradle.api.attributes.*
import org.gradle.api.attributes.java.*
import org.gradle.api.attributes.plugin.*
import org.gradle.api.cache.*
import org.gradle.api.capabilities.*
import org.gradle.api.component.*
import org.gradle.api.credentials.*
import org.gradle.api.distribution.*
import org.gradle.api.distribution.plugins.*
import org.gradle.api.execution.*
import org.gradle.api.file.*
import org.gradle.api.flow.*
import org.gradle.api.initialization.*
import org.gradle.api.initialization.definition.*
import org.gradle.api.initialization.dsl.*
import org.gradle.api.initialization.resolve.*
import org.gradle.api.invocation.*
import org.gradle.api.java.archives.*
import org.gradle.api.jvm.*
import org.gradle.api.launcher.cli.*
import org.gradle.api.logging.*
import org.gradle.api.logging.configuration.*
import org.gradle.api.model.*
import org.gradle.api.plugins.*
import org.gradle.api.plugins.antlr.*
import org.gradle.api.plugins.catalog.*
import org.gradle.api.plugins.jvm.*
import org.gradle.api.plugins.quality.*
import org.gradle.api.plugins.scala.*
import org.gradle.api.provider.*
import org.gradle.api.publish.*
import org.gradle.api.publish.ivy.*
import org.gradle.api.publish.ivy.plugins.*
import org.gradle.api.publish.ivy.tasks.*
import org.gradle.api.publish.maven.*
import org.gradle.api.publish.maven.plugins.*
import org.gradle.api.publish.maven.tasks.*
import org.gradle.api.publish.plugins.*
import org.gradle.api.publish.tasks.*
import org.gradle.api.reflect.*
import org.gradle.api.reporting.*
import org.gradle.api.reporting.components.*
import org.gradle.api.reporting.dependencies.*
import org.gradle.api.reporting.dependents.*
import org.gradle.api.reporting.model.*
import org.gradle.api.reporting.plugins.*
import org.gradle.api.resources.*
import org.gradle.api.services.*
import org.gradle.api.specs.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.ant.*
import org.gradle.api.tasks.application.*
import org.gradle.api.tasks.bundling.*
import org.gradle.api.tasks.compile.*
import org.gradle.api.tasks.diagnostics.*
import org.gradle.api.tasks.diagnostics.configurations.*
import org.gradle.api.tasks.incremental.*
import org.gradle.api.tasks.javadoc.*
import org.gradle.api.tasks.options.*
import org.gradle.api.tasks.scala.*
import org.gradle.api.tasks.testing.*
import org.gradle.api.tasks.testing.junit.*
import org.gradle.api.tasks.testing.junitplatform.*
import org.gradle.api.tasks.testing.testng.*
import org.gradle.api.tasks.util.*
import org.gradle.api.tasks.wrapper.*
import org.gradle.api.toolchain.management.*
import org.gradle.authentication.*
import org.gradle.authentication.aws.*
import org.gradle.authentication.http.*
import org.gradle.build.event.*
import org.gradle.buildinit.*
import org.gradle.buildinit.plugins.*
import org.gradle.buildinit.tasks.*
import org.gradle.caching.*
import org.gradle.caching.configuration.*
import org.gradle.caching.http.*
import org.gradle.caching.local.*
import org.gradle.concurrent.*
import org.gradle.external.javadoc.*
import org.gradle.ide.visualstudio.*
import org.gradle.ide.visualstudio.plugins.*
import org.gradle.ide.visualstudio.tasks.*
import org.gradle.ide.xcode.*
import org.gradle.ide.xcode.plugins.*
import org.gradle.ide.xcode.tasks.*
import org.gradle.ivy.*
import org.gradle.jvm.*
import org.gradle.jvm.application.scripts.*
import org.gradle.jvm.application.tasks.*
import org.gradle.jvm.tasks.*
import org.gradle.jvm.toolchain.*
import org.gradle.language.*
import org.gradle.language.assembler.*
import org.gradle.language.assembler.plugins.*
import org.gradle.language.assembler.tasks.*
import org.gradle.language.base.*
import org.gradle.language.base.artifact.*
import org.gradle.language.base.compile.*
import org.gradle.language.base.plugins.*
import org.gradle.language.base.sources.*
import org.gradle.language.c.*
import org.gradle.language.c.plugins.*
import org.gradle.language.c.tasks.*
import org.gradle.language.cpp.*
import org.gradle.language.cpp.plugins.*
import org.gradle.language.cpp.tasks.*
import org.gradle.language.java.artifact.*
import org.gradle.language.jvm.tasks.*
import org.gradle.language.nativeplatform.*
import org.gradle.language.nativeplatform.tasks.*
import org.gradle.language.objectivec.*
import org.gradle.language.objectivec.plugins.*
import org.gradle.language.objectivec.tasks.*
import org.gradle.language.objectivecpp.*
import org.gradle.language.objectivecpp.plugins.*
import org.gradle.language.objectivecpp.tasks.*
import org.gradle.language.plugins.*
import org.gradle.language.rc.*
import org.gradle.language.rc.plugins.*
import org.gradle.language.rc.tasks.*
import org.gradle.language.scala.tasks.*
import org.gradle.language.swift.*
import org.gradle.language.swift.plugins.*
import org.gradle.language.swift.tasks.*
import org.gradle.maven.*
import org.gradle.model.*
import org.gradle.nativeplatform.*
import org.gradle.nativeplatform.platform.*
import org.gradle.nativeplatform.plugins.*
import org.gradle.nativeplatform.tasks.*
import org.gradle.nativeplatform.test.*
import org.gradle.nativeplatform.test.cpp.*
import org.gradle.nativeplatform.test.cpp.plugins.*
import org.gradle.nativeplatform.test.cunit.*
import org.gradle.nativeplatform.test.cunit.plugins.*
import org.gradle.nativeplatform.test.cunit.tasks.*
import org.gradle.nativeplatform.test.googletest.*
import org.gradle.nativeplatform.test.googletest.plugins.*
import org.gradle.nativeplatform.test.plugins.*
import org.gradle.nativeplatform.test.tasks.*
import org.gradle.nativeplatform.test.xctest.*
import org.gradle.nativeplatform.test.xctest.plugins.*
import org.gradle.nativeplatform.test.xctest.tasks.*
import org.gradle.nativeplatform.toolchain.*
import org.gradle.nativeplatform.toolchain.plugins.*
import org.gradle.normalization.*
import org.gradle.platform.*
import org.gradle.platform.base.*
import org.gradle.platform.base.binary.*
import org.gradle.platform.base.component.*
import org.gradle.platform.base.plugins.*
import org.gradle.plugin.devel.*
import org.gradle.plugin.devel.plugins.*
import org.gradle.plugin.devel.tasks.*
import org.gradle.plugin.management.*
import org.gradle.plugin.use.*
import org.gradle.plugins.ear.*
import org.gradle.plugins.ear.descriptor.*
import org.gradle.plugins.ide.*
import org.gradle.plugins.ide.api.*
import org.gradle.plugins.ide.eclipse.*
import org.gradle.plugins.ide.idea.*
import org.gradle.plugins.signing.*
import org.gradle.plugins.signing.signatory.*
import org.gradle.plugins.signing.signatory.pgp.*
import org.gradle.plugins.signing.type.*
import org.gradle.plugins.signing.type.pgp.*
import org.gradle.process.*
import org.gradle.swiftpm.*
import org.gradle.swiftpm.plugins.*
import org.gradle.swiftpm.tasks.*
import org.gradle.testing.base.*
import org.gradle.testing.base.plugins.*
import org.gradle.testing.jacoco.plugins.*
import org.gradle.testing.jacoco.tasks.*
import org.gradle.testing.jacoco.tasks.rules.*
import org.gradle.testkit.runner.*
import org.gradle.util.*
import org.gradle.vcs.*
import org.gradle.vcs.git.*
import org.gradle.work.*
import org.gradle.workers.*
Groovy Script Variables
Groovy has two types of script variables:
-
Variables declared with a type modifier or
def
are visible within closures but not visible within methods. -
Variables declared without a modifier are visible anywhere in the script.
Prefer declaring variables with def
to make their scope explicit.
String localScope1 = 'localScope1'
def localScope2 = 'localScope2'
scriptScope = 'scriptScope'
println localScope1
println localScope2
println scriptScope
closure = {
println localScope1
println localScope2
println scriptScope
}
def method() {
try {
localScope1
} catch (MissingPropertyException e) {
println 'localScope1NotAvailable'
}
try {
localScope2
} catch(MissingPropertyException e) {
println 'localScope2NotAvailable'
}
println scriptScope
}
closure.call()
method()
groovy scope.groovy
> groovy scope.groovy localScope1 localScope2 scriptScope localScope1 localScope2 scriptScope localScope1NotAvailable localScope2NotAvailable scriptScope
For more information about Groovy syntax, see the Groovy documentation. |