Gradle is a build tool mainly used for Kotlin, Java and other JVM languages. The best way to use it is with the IntelliJ IDEA IDE.
It also supports other languages like Swift and C/C++
Extending Gradle
Plugins
| Script plugin | Defined in build.gradle.kts | Local plugin |
| Precompiled script plugin | Defined in Convention plugin | Local plugin |
| Binary plugin | Defined in Project | Standard |
Gradle Docs — Types of Plugins
Plugin Development Build Script
plugins {1 collapsed line
`java` Apply a JVM language plugin
`java-gradle-plugin` Apply the Gradle plugin development plugin
Gradle Docs — Gradle Plugin Development Plugin
}
gradlePlugin { The Gradle plugin development plugin can be configured here
Gradle Docs — Gradle Plugin Development Extension
3 collapsed lines
website = "https://github.com/OWNER/REPO" vcsUrl = "https://github.com/OWNER/REPO.git"
plugins { val pluginName by registering { id = "me.username.plugin-name" implementationClass = "me.username.PluginName"3 collapsed lines
displayName = "Plugin Name" description = "Describe the plugin" tags = setOf() } }}Gradle Docs — Gradle Plugin Development Plugin · Usage
Plugin class
package me.username.plugin
import org.gradle.api.Plugin
class GradlePlugin: Plugin<Project> {
override fun apply(project: Project) { val extension = project.extensions.create( "extensionName", GradleExtension::class.java ) }}plugins { apply("me.username.plugin-name")}Extension class
package me.username.plugin
import org.gradle.api.Actionimport org.gradle.api.file.DirectoryPropertyimport org.gradle.api.file.RegularFilePropertyimport org.gradle.api.model.ObjectFactoryimport org.gradle.api.provider.Propertyimport org.gradle.api.provider.SetPropertyimport org.gradle.api.provider.MapPropertyimport org.gradle.api.tasks.Inputimport org.gradle.api.tasks.InputDirectoryimport org.gradle.api.tasks.InputFileimport org.gradle.api.tasks.Nestedimport org.gradle.api.tasks.Optionalimport javax.inject.Inject
abstract class GradleExtension {
@get:Input abstract val property: Property<String>
@get:Input @get:Optional abstract val optionalProperty: Property<String>
@get:Input abstract val propertySet: SetProperty<String>
@get:Input abstract val propertyMap: MapProperty<String, String>
// files
@get:InputFile abstract val fileProperty: RegularFileProperty
@get:InputDirectory abstract val dirProperty: DirectoryProperty}
abstract class AdvancedGradleExtension @Inject constructor(private val objects: ObjectFactory) {
// nested properties
@get:Nested abstract val nestedProperties: NestedProperties
fun nestedProperties(action: Action<in NestedProperties>) { action.execute(nestedProperties) }
// nested properties list
@get:Input val nestedPropertiesList = objects.setProperty(NestedPropertyItem::class.java)
fun nestedPropertiesList(action: Action<NestedPropertyList>) { val container = objects.newInstance(NestedPropertyList::class.java) action.execute(container) nestedPropertiesList.addAll(container.items) }}
abstract class NestedPropertyList @Inject constructor(private val objects: ObjectFactory) {
val items = mutableSetOf<NestedPropertyItem>()
fun property(action: Action<NestedPropertyItem>) { val license = objects.newInstance(NestedPropertyItem::class.java) action.execute(license) items.add(license) }}
abstract class NestedPropertyItem {
@get:Input abstract val property: Property<String>}
abstract class NestedProperties {
@get:Input abstract val property: Property<String>} Gradle Docs — Annotating inputs and outputs
Gradle Docs — Property convention
Task class
-
plugins
- init/config/exec
- local/published
- bin/script
- tasks
- property/providers
- extensions
-
projct templates
- gradle init
- intellij
https://www.jetbrains.com/help/idea/gradle-settings.html
Build Lifecycle
- Initialization (evaluate settings.gradle.kts)
- Configuration (evaluate **/gradle.build.kts)
- Execution (execute tasks) (doFirst, doLast)
Task
-
Input
@Input -
Output
@Output -
Action
@TaskAction -
Daemon https://docs.gradle.org/current/userguide/gradle_daemon.html
-
https://docs.gradle.org/current/userguide/build_environment.html#sec:the_gradle_properties_file
-
https://kotlinlang.org/docs/gradle-configure-project.html#kotlin-gradle-plugin-data-in-a-project
- Project
- build — build directory configurable
- gradle
- wrapper
- libs.versions.toml
- src/sourceSet — source directory (default
src/mainandsrc/test) configurable- source — source code directories (per language
java,kotlin…) - resources — resource files directory (configs, data, assets, scripts)
- source — source code directories (per language
- settings.gradle.kts — project configuration script (name & modules)
- build.gradle.kts — build configuration script
Minimal project structure
- Project
- build — build directory configurable
- src/sourceSet — source directory (default
src/mainandsrc/test) configurable- source — source code directories (per language
java,kotlin…) - resources — resource files directory (configs, data, assets, scripts)
- source — source code directories (per language
- settings.gradle.kts — project configuration script (name & modules)
- build.gradle.kts — build configuration script
Minimal Gradle Wrapper project structure
- Project
Gradle Wrapper-
gradle/wrapper
- gradle-wrapper.jar — downloader
- gradle-wrapper.properties — version
- gradlew — executable for Linux/MacOS
- gradlew.bat — executable for Windows
Project- build — build directory
- src — source directory
- sourceSet
- source
- resources
- sourceSet
- settings.gradle.kts — project configuration script (name & modules)
- build.gradle.kts — build configuration script
Complete project structure
- gradle
- wrapper — Gradle Wrapper
- gradle-wrapper.jar — Gradle Wrapper downloader
- gradle-wrapper.properties — Gradle Wrapper version
- libs.versions.toml
- wrapper — Gradle Wrapper
- build
- src
- sourceSet
- source
- resources
- sourceSet
- gradle.properties
- settings.gradle.kts
- build.gradle.kts
- gradlew — Gradle Wrapper executable for Linux/MacOS
- gradlew.bat — Gradle Wrapper executable for Windows
Tasks
gradle initinitialize gradle project./gradlew buildbuild project./gradlew taskslists available tasks./gradlew cleanremovesbuilddirectory https://docs.gradle.org/current/userguide/gradle_directories_intermediate.html#dir:build_dir
Gradle Build Script
Build script.
build.gradle.kts
/** Plugins list */plugins { ... }
/** */repositories {
/* common repositories */ mavenCentral() // https://repo.maven.apache.org/maven2 ...}
/** Dependency list */dependencies {
"group:name:version" // module // version: // 0.0 <- >= equal or greater // 0.0!! <- == strictly // 0.+ <- // 0.0-SNAPSHOT <- project(":module")
// dependency configurations implementation(...) api(...) runtimeOnly(...) compileOnly(...)
}
// ---
subprojects { ... }
allprojects { ... }
// configure existing tasktasks.named<Test>("test") {
}
// register new tasktasks.register("task-name") { group = "Custom" description = "A lovely greeting task."
dependsOn("other-task") doFirst { ... } doLast { ... }}IntelliJ: Advanced Settings -> Build Tools. Gradle -> Download sources
Common Gradle Build Scripts
~ source set tasks
* lifecycle tasks
Build log
Executing ':classes :testClasses'…
> Task :compileJava> Task :processResources> Task :classes> Task :compileTestJava> Task :processTestResources> Task :testClasses
BUILD SUCCESSFULSource Sets
main— source code compiled into jartest— test source code
Java (Simple)
build.gradle.kts
plugins { id("java")}
sourceSets {
/** move src/main -> src */ main { java { setSrcDirs(listOf("src/java")) } resources { setSrcDirs(listOf("src/resources")) } }
/** remove src/test */ test { java { setSrcDirs(emptyList<String>()) } resources { setSrcDirs(emptyList<String>()) } }}
tasks {
/** skip :testClasses */ testClasses { enabled = false }
/** skip :compileTestJava */ compileTestJava { enabled = false }
/** skip :processTestResources */ processTestResources { enabled = false }}├─ settings.gradle.kts├─ build.gradle.kts└─ src ├─ java └─ resourcesJava Library
build.gradle.kts
plugins { `java-library`}+ api() dependency configuration
Projects
root project -> sub project
- Build
- Dependencies
projects plugins, tasks (input -> action -> output)
UP-TO-DATE REUSED SKIPPED OUTPUT-REUSED
x
- latest version
- ides, gradle init
Gradle Settings Script
settings.gradle.kts
/* * See https://docs.gradle.org/current/userguide/settings_file_basics.html * See https://docs.gradle.org/current/userguide/plugins_intermediate.html#sec:plugin_management */pluginManagement { plugins { ... } resolutionStrategy { ... } repositories { ... }}
/** Root Project name (usually same as root folder) */rootProject.name = "root-project"
/** Sub projects (folder names) */include("sub-project-a", "sub-project-b", "sub-project-c")Publishing
Extending Gradle
Custom Tasks
(input -> action -> output)
https://docs.gradle.org/current/userguide/writing_tasks_intermediate.html
build.gradle.kts
// Extend the DefaultTask class to create a HelloTask classabstract class HelloTask : DefaultTask() { @TaskAction fun hello() { println("hello from HelloTask") }}
// Register the hello Task with type HelloTasktasks.register<HelloTask>("hello") { group = "Custom tasks" description = "A lovely greeting task."}Custom Plugins
Multi-Project Build buildSrc
Must be in the root project
├─ settings.gradle.kts└─ buildSrc ├─ build.gradle.kts └─ src/main/kotlin └─ myproject.java-conventions.gradle.ktsComposite Build build-logic
Can be in any sub-projects
├─ build.gradle.kts└─ build-logic ├─ settings.gradle.kts ├─ build.gradle.kts └─ src/main/kotlin └─ myproject.java-conventions.gradle.ktsPre-Compiled Script Plugin
Binary Plugin
build.gradle.kts
abstract class SamplePlugin : Plugin<Project> { override fun apply(project: Project) { project.tasks.register("ScriptPlugin") { doLast { println("Hello world from the build file!") } } }}
apply<SamplePlugin>()plugins { id("myproject.java-conventions")}https://docs.gradle.org/current/userguide/pre_compiled_script_plugin_advanced.html
Community/Local/Custom Plugins
Convention Plugins
Plugin Extensions
java {}Dataflow API / Actions
buildSrc
https://docs.gradle.org/current/userguide/plugins_intermediate.html#sec:buildsrc_plugins_dsl
Multi-Project Builds <> Composite Builds
buildSrc <> build-logic
https://docs.gradle.org/current/userguide/multi_project_builds_intermediate.html
Optimization
Transitive Dependencies
Incremental Builds https://docs.gradle.org/current/userguide/gradle_optimizations.html#sec:incremental_builds_basics
Build Caching https://docs.gradle.org/current/userguide/gradle_optimizations.html#sec:build_caching_basics
Build Scan https://docs.gradle.org/current/userguide/build_scans.html
Task Classification: Actionable task <> Lifecycle task
Gradle Build Lifecycle (init > config > exec) https://docs.gradle.org/current/userguide/build_lifecycle_intermediate.html
Managed Types https://docs.gradle.org/current/userguide/gradle_managed_types_intermediate.html
GRADLE_USER_HOME
~/.gradle or C:\Users\<USERNAME>\.gradle
https://docs.gradle.org/current/userguide/gradle_directories_intermediate.html#gradle_user_home
Constrait versions https://docs.gradle.org/current/userguide/dependencies_intermediate.html#sec:enforce_constrain_versions
Init script https://docs.gradle.org/current/userguide/init_scripts.html#init_scripts
System properties
Gradle Docs — System properties reference
Oracle Docs — System Properties
- Gradle Properties
- System Properties
- Project properties
Reference
- Gradle Docs — Getting Started
- Gradle Guides
- Gradle Enterprise University - Gradle
- JetBrains Guide — Working with Gradle
Gradle Wrapper
Version Catalog
Settings Script
Build Script
Tasks
Plugins
- Gradle Docs — Core Plugins
- Gradle Plugin Portal
- Gradle Docs — Plugin Basics
- Gradle Docs — Plugins
- Gradle Docs — Creating Plugins