myCustomSourceGenerator {
enable("Kotlin", "Java")
}
integrationTests {
db {
jdbcUrl = "…"
}
legacy {
}
}
Hans Dockter & Paul Merlin - KotlinConf 2018
myCustomSourceGenerator {
enable("Kotlin", "Java")
}
integrationTests {
db {
jdbcUrl = "…"
}
legacy {
}
}
Declarative elements describe the “what”
The underlying logic creates the “how”
Groovy provided an extensible DSL language
Hoped that ecosystem will eventually provide a solution
Underestimated the negative impact
Models hard to configure for developers
Models hard to refactor and evolve for build authors
A lot of non-idiomatic Gradle code because of this
speaker {
name = "Paul Merlin"
company = "Gradle"
oss = "Apache Polygene PMC, former chair",
successes = listOf(
"BASIC 'Hello, World!' in 1986",
"C 'Hello, World!' in 1989",
"Java 'Hello, World!' in 1996"
"Kotlin 'Hello, World!' in 2015",
"tools", "daemons", "apps", "frameworks", "libs"
),
failures = generateSequence(code) { bugs },
twitter = "@eskat0s",
github = "eskatos"
}
Gradle Build Tool in a nutshell
Type-safe build logic
What makes this possible?
Migrating from Groovy scripts
Taking a step back
Performance
Wrapping up
Gradle Build Tool is a build and automation tool
JVM based
Implemented in Java
100% Free Open Source - Apache Standard License 2.0
JVM ecosystem
Java, Kotlin, Groovy, Scala, Clojure …
Native ecosystem
C, C++, Swift, …
Android
Misc
Go, Python, JavaScript, Asciidoctor, …
> 6M downloads / month
#17 OSS projects worldwide says TechCrunch
35+ Gradle Engineers
300K builds/week @ LinkedIn
The company behind Gradle
Gradle Build Tool - gradle.org
Gradle Enterprise (Build Scans and Build Cache) - gradle.com
(Gradle consulting, support, development services etc.)
(Training: online, public and in-house)
Fully distributed development team
Exciting project used by millions
Build Tool team and Gradle Enterprise positions
If anything you hear from now on sounds like a great problem to solve,
Talk to us!
Groovy and Kotlin build scripts
Task configuration and execution
Dependency resolution
Work avoidance
Core Plugins (java
, jacoco
, maven-publish
…)
Community Plugins (kotlin
, android
, golang
, pygradle
, asciidoctor
…)
Gradle Plugins contribute
reusable and configurable Gradle Tasks
configurable Gradle Extensions
Gradle Plugins contribute a model to configure
in build scripts
using a DSL
plugins {
`java-library`
}
dependencies {
api("com.acme:foo:1.0")
implementation("com.zoo:monkey:1.1")
}
tasks.withType<JavaCompile> {
// ...
}
plugins {
`cpp-application`
}
application {
baseName = "my-app"
}
toolChains {
// ...
}
Developer experience
Authoring build logic
Troubleshooting build issues
IDE Support
Less surprises at runtime
shorter feedback loop
avoid the performance impact of dynamism
Kotlin, the language
Type safety & null safety
Great tooling and IDE support
Uniting a dynamic configuration model and a statically typed language
A build whose logic is entirely written in Kotlin
Type safety, null safety
API and model discoverability
Documentation and navigation to sources
Refactorings
Gradle Plugins contribute reusable and configurable models
This is a dynamic model
The Gradle Kotlin DSL provides a static view over that model
.kt
vs .kts
vs .gradle.kts
they all contain Kotlin code
.kt
files are assumed to be compiled by the kotlin compiler
.kts
files are assumed to be executed by the kotlin scripting support
.gradle.kts
files are assumed to be hosted by Gradle
.gradle.kts
Gradle Kotlin DSL in the classpath
Script compilation dependencies coming from Gradle
Implicit imports
Custom tailored IDE script editor support
Kotlin friendly extensions of the Gradle API
KClass<T>
, reified<T>()
Delegated properties for Gradle properties and collections
Dynamically generated Kotlin extensions
for model elements contributed by plugins (configurations, extensions, tasks etc…)
calculated right before evaluating the script body
Interoperability utilities
Type-safety
Discoverability
Documentation and navigation
Refactorings
Just like shared declarations (e.g. dependencies)
Don’t use extra properties
Move them to buildSrc
Get IDE support
Gradle Plugins may
expose untyped Groovy Closure
taking functions
rely on more Groovy dynamism
e.g. Dokka required the use of delegateClosureOf<T> {}
existing fix will go in the next release
closureOf<T> {}
and delegateClosureOf<T> {}
withGroovyBuilder {}
apply(from = "some-groovy-script.gradle")
Covered in detail in the Gradle user manual
Kotlin and Groovy build logic can coexist
mechanical step by step migration possible
migrating doesn’t block your team
Prepare your build to make it easier to migrate
by making your Groovy scripts closer to Kotlin
unify quotes, disambiguate properties/functions …
by applying Gradle fundamentals and best practices
use buildSrc
and plugins {}
etc…
Let Kotlin logic drive Groovy logic
not the other way around
Migration guide available at guides.gradle.org
Gradle user manual available at docs.gradle.org
both Groovy/Kotlin snippets
best place to learn how to do what with each DSL, and compare
A script plugin is a .gradle(.kts)
script
Applied from another one
apply(from = "some.gradle.kts")
Do not support the plugins {}
block, yet
Covered in detail in the Gradle user manual
Same as script plugins
Compiled as part of a Kotlin source set
Can be used in buildSrc
Can be used in binary plugins
Covered in detail in the Gradle user manual
buildSrc
Gradle Plugins, Gradle Plugins, Gradle Plugins
plugins {}
, plugins {}
, plugins {}
Basically, apply Gradle fundamentals and best practices
Profit
Plugins contribute to the DSL
They should do so in a type-safe manner
Don’t expose groovy.lang.Closure<*>
taking methods
Use explicit types instead, like Action<T>
If written in Kotlin, prefer Action<T>
over Kotlin lambdas
Again, apply Gradle fundamentals and best practices
Gradle configuration phase
Configuring your build when nothing has changed takes more than a second?
Make sure to check out the Gradle Performance Guide
We can help you pinpoints bottlenecks at https://github.com/gradle/gradle/issues/1628
In comparison with the Gradle Groovy DSL
when nothing has changed
Similar performance characteristics for most builds
~100ms gap on a large build with 500 sub projects
~2ms hit per project in that scenario, ymmv
first use, or, change in buildSrc
Slower in certain scenarios
first use (checkout, pulling changes, switching branches)
changes in the build logic, the worse being changing buildSrc
We are talking about ~3.5 times slower at the moment
~1min gap on a large build with 500 sub projects
~120ms per project in that scenario, ymmv
Script compilation is the main bottleneck
to the rescue
Script compilation can be cached in a Gradle Build Cache
Simply enable it
org.gradle.caching=true
in your gradle.properties
or use --build-cache
on the command line
Local and remote caches
In general, build cache helps with your overall build performance
Gradle provides a Docker image for a build cache node
Pair it with Gradle Enterprise to get
replication, monitoring, node management etc…
Compilation avoidance
Parallel script compilation
Faster Kotlin compilation
Targeted optimizations
Configuring your build when nothing has changed takes
more than a second?
Make sure to check out the
Gradle Performance Guide
We can help you pinpoints bottlenecks at
https://github.com/gradle/gradle/issues/1628
Gradle 5.0 is when the Gradle Kotlin DSL is ready for general use!
Please give it a try with Gradle 5.0-M1!
Chris Beams @cbeams
Rodrigo B. de Oliveira @rodrigobamboo
myself
contributors from other teams at Gradle
even from some Groovy commiters ツ
We wouldn’t be here without the community!
Very friendly and active Kotlin community
Bug reports, of course
But also pull-requests, code reviews, documentation, support to others
Join us at gradle.org/slack