Gradle — Cheat Sheet

Tag: gradle, build, jvm, java, android, groovy, kotlin

Livello: intermedio

TL;DR: Build automation tool flessibile e performante, standard de facto per Android e molto diffuso nel mondo JVM. Basato su un modello a task configurabile tramite Groovy o Kotlin DSL.

Concetti chiave

Utilizza un Domain Specific Language (DSL) per gli script di build (build.gradle in Groovy, build.gradle.kts in Kotlin).

Struttura basata su Plugin: i plugin estendono le capacità di Gradle aggiungendo task, estensioni e convenzioni predefinite.

Gradle Wrapper (gradlew): script integrato nel repository che scarica e usa una versione specifica di Gradle, garantendo build riproducibili senza installazioni globali.

Fasi della build: Initialization (determina i progetti inclusi), Configuration (costruisce il DAG - Directed Acyclic Graph dei task), Execution (esegue i task).

Build incrementale: Gradle salta l'esecuzione dei task se gli input e gli output non sono cambiati dall'ultima esecuzione.

Gradle Daemon: un processo in background che mantiene in memoria le informazioni strutturali per velocizzare le build successive.

Supporto nativo per multi-project builds, definiti all'interno del file settings.gradle.

Domande tipiche e risposte pronte

Q: Qual è la differenza principale tra Maven e Gradle?R: Maven usa un POM in XML fortemente convenzionale e rigido. Gradle usa uno script dichiarativo ma programmabile, offrendo performance superiori grazie a build cache e incremental builds.

Q: A cosa serve il file settings.gradle?R: Viene valutato nella fase di initialization. Serve a definire il nome del progetto root e a dichiarare quali sotto-progetti partecipano alla build multi-modulo.

Q: Qual è la differenza tra configuration e execution phase per un task?R: La configuration phase valuta lo script per preparare il grafo delle dipendenze, mentre l'execution phase esegue la logica effettiva. Codice fuori da doFirst o doLast gira in configuration.

Q: Perché è fondamentale usare il Gradle Wrapper?R: Garantisce che il progetto venga compilato con l'esatta versione di Gradle prevista dagli autori, evitando rotture dovute ad aggiornamenti locali dell'ambiente di CI o degli sviluppatori.

Insidie e errori comuni

Inserire logica pesante o chiamate di rete nel blocco di configurazione del task, rallentando l'intera build per ogni comando eseguito.

Usare versioni dinamiche per le dipendenze (es. 1.2.+), rendendo la build non deterministica e soggetta a rotture improvvise.

Non dichiarare correttamente input e output nei custom task, vanificando la build incrementale e costringendo Gradle a rieseguirli sempre.

Snippet e comandi

# Esegue una build pulita
./gradlew clean build

# Elenca tutti i task disponibili e le loro descrizioni
./gradlew tasks

# Mostra l'albero delle dipendenze di un progetto
./gradlew dependencies

# Esegue la build generando un report di profilazione delle performance
./gradlew build --profile

Kotlin

// Esempio build.gradle.kts per un custom task
tasks.register("hello") {
    // Fase di configurazione
    println("Configuring hello task")

    doLast {
        // Fase di esecuzione
        println("Hello from execution phase!")
    }
}

Da ripassare

[ ] Implementazione e gestione del Dependency Locking per bloccare le versioni transitive.

[ ] Configurazione della Remote Build Cache per condividere gli artefatti tra sviluppatori e CI.

Jarvis Interviews
Jarvis