Gradle és una eina d'automatització de compilació per al desenvolupament de programari

Introducció

Instal.la gradle amb Scoop:

> scoop install gradle

Tens un projecte "demo" a https://gitlab.com/xtec/kotlin/gradle

Init

Obre un terminal de Powershell

Verifica que gradle està instal.lat:

> gradle

Welcome to Gradle 8.10.1.

Directory 'C:\Users\david' does not contain a Gradle build.

Crea la carpetagradle i entra dins la carpeta

> md gradle
> cd gradle

Executa gradle init amb els paràmetres que es mostren a continuació per generar una aplicació Kotlin amb el nom gradle:

gradle init --package gradle --project-name gradle --java-version 21 --type kotlin-application --dsl kotlin --test-framework kotlintest --no-split-project --no-incubating --overwrite

Pots veure que s'han creat diferents fitxers:

> ls

Directory: C:\Users\david\gradle

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/10/2024      8:23                app
d-----         4/10/2024      8:23                gradle
-a----         4/10/2024      8:23            290 .gitattributes
-a----         4/10/2024      8:23            108 .gitignore
-a----         4/10/2024      8:23           8762 gradlew
-a----         4/10/2024      8:23           2966 gradlew.bat
-a----         4/10/2024      8:23            535 settings.gradle.kts

Gradle Wrapper

Al crear el projecte s'ha creat la carpeta gradle:

> ls .\gradle\wrapper\

Directory: C:\Users\david\gradle\gradle\wrapper

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----         4/10/2024      8:40          43583 gradle-wrapper.jar
-a----         4/10/2024      8:40            253 gradle-wrapper.properties

Aquesta carpeta té el fitxer JAR i la configuració del Gradle Wrapper.

Aquesta aplicació s'executa amb el fitxer gradlew.bat (per Windows) o gradlew (per macOs i Linux).

El "Gradle Wrapper" utilitza una versió concreta de Gradle, i si aquesta versió no està a l'ordinador, la baixa directament d'Internet.

D'aquesta manera qualsevol usuari que treballa amb el projecte utilitzarà la mateixa versió de Gradle, encara que no tingui instal.lat Gradle a l'ordinador.

Projecte

La configuració del projecte està en el fitxer settings.gradle.kts.

Si mires el contingut del fitxer pots veure que el nom del projecte és "gradle" i que inclou el subprojecte "app":

> gc .\settings.gradle.kts

rootProject.name = "gradle"
include("app")

Un projecte es composa de 1 o més subprojectes.

Quan has executat l'ordre gradle init, has dit que volies crear una aplicació Kotlin mitjançant el paràmetre --type kotlin-application.

En la carpeta app està el codi del teu subprojecte:

> ls .\app\

Directory: C:\Users\david\gradle\app

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/10/2024      9:09                src
-a----         4/10/2024      9:09           1409 build.gradle.kts

En aquesta carpeta tens:

  • El fitxer build.gradle.kts que té la configuració del subprojecte "app"
  • La carpeta src on està tot el codi del projecte.

Build

Executa aquesta ordre per executar la tasca build:

>  .\gradlew build

BUILD SUCCESSFUL in 4s
7 actionable tasks: 7 executed

Observació. Powershell executa l'script gradlew.bat encara que no posis .bat al final.

La primera vegada que executes el "wrapper", el "wrapper" baixa i guarda en cache els binaris Gradle si aquests no estan instal.lats a l'ordinador.

La tasca build utlitza el codi font i les seves dependències per construit l'aplicació.

Si executes l'ordre ls pots veure que s'han creat dos carpetes noves: .gradle i .kotlin.

>  ls

Directory: C:\Users\david\gradle

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/10/2024      8:54                .gradle
d-----         4/10/2024      8:54                .kotlin
d-----         4/10/2024      8:54                app
d-----         4/10/2024      8:51                gradle
-a----         4/10/2024      8:51            290 .gitattributes
-a----         4/10/2024      8:51            108 .gitignore
-a----         4/10/2024      8:51           8762 gradlew
-a----         4/10/2024      8:51           2966 gradlew.bat
-a----         4/10/2024      8:51            535 settings.gradle.kts

En la carpeta .gradle tens una instal.lació local de Gradle que es la que utilitza el projecte mitjançant l'script gradlew.

A més, la tasca build també ha generat la carpeta app\build:

> ls .\app\build\

Directory: C:\Users\david\gradle\app\build

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/10/2024      8:23                classes
d-----         4/10/2024      8:23                distributions
d-----         4/10/2024      8:23                kotlin
d-----         4/10/2024      8:23                libs
d-----         4/10/2024      8:23                reports
d-----         4/10/2024      8:23                scripts
d-----         4/10/2024      8:23                test-results
d-----         4/10/2024      8:23                tmp

En aquesta carpeta es guarda tot el que es genera a partir del codi que has escrit.

Run

El fitxer app/build.gradle.kts té configurat quina és la classe principal de l'aplicació:

application {
    mainClass = "gradle.AppKt"
}

Aquesta classe está a la ruta /app/src/main/kotlin/gradle/App.kt

Amb la tasca run pots executa l'aplicació:

> .\gradlew run                   

Hello World!

BUILD SUCCESSFUL in 2s
2 actionable tasks: 1 executed, 1 up-to-date

Obre el fitxer App.kt amb el "bloc de notes" del Windows:

notepad.exe .\app\src\main\kotlin\gradle\App.kt

Modifica el contingut del fitxer:

package gradle

fun main() {
    println("Hello World!")
}

Torna a executar l'aplicació:

> gradle run                                                                                            

Hello World!

BUILD SUCCESSFUL in 1s

Test

A continuació anem a crear un test.

Mofifica el fitxer AppTest.kt que està en la carpeta app/src/test/kotlin/gradle/AppTest.kt.

>  notepad.exe .\app\src\test\kotlin\gradle\AppTest.kt

Crea un test que no funciona:

package gradle

import kotlin.test.*

class AppTest {
    @Test fun myTest() {
         
        assertEquals(3, 5)
    }
}

Amb la tasca test verifica que no funciona:

> gradle test

AppTest > myTest() FAILED
    org.opentest4j.AssertionFailedError at AppTest.kt:8

1 test completed, 1 failed

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:test'.
> There were failing tests. See the report at: file:///C:/Users/david/gradle/app/build/reports/tests/test/index.html

* Try:
> Run with --scan to get full insights.

BUILD FAILED in 1s
3 actionable tasks: 1 executed, 2 up-to-date

El resultat és que at AppTest.kt:8 ... 😮, 3 no és igual a 5 😇

Obre en el navegador la URL file:///... i tens un "report" més bonic.

Modifica l'asserEquals perquè el test funcioni:

package gradle

import kotlin.test.*

class AppTest {
    @Test fun myTest() {
         
        assertEquals(5, 5)
    }
}

Verifica que funciona:

> gradle test

BUILD SUCCESSFUL in 1s
3 actionable tasks: 2 executed, 1 up-to-date

Dependències

Un projecte necessita moltes funcionalitats que no estan a les biblioteques estàndards.

Per exemple, si vull crear gràfics puc utilitzar la biblioteca Kandy.

En el fitxer build.gradle.kts del subprojecte "app" pots declarar dependències.

Modifica l'entrada dependencies i afegeix una dependència amb "Kandy":

dependencies {
   
    // ...

    implementation("org.jetbrains.kotlinx:kandy-lets-plot:0.7.0")
}

Modifica el fitxer App.kt per crea un diagrama de barres:

package gradle

import org.jetbrains.kotlinx.dataframe.api.*
import org.jetbrains.kotlinx.kandy.dsl.*
import org.jetbrains.kotlinx.kandy.letsplot.export.save
import org.jetbrains.kotlinx.kandy.letsplot.layers.bars

fun main() {
    val averageTemperature = dataFrameOf(
        "city" to listOf("New York", "London", "Berlin", "Yerevan", "Tokyo"),
        "average temperature" to listOf(12.5, 11.0, 9.6, 11.5, 16.0)
    )

    averageTemperature.plot {
        bars {
            x("city")
            y("average temperature") {
                axis.name = "Average Temperature (°C)"
            }
        }
    }.save("plot.png", path = ".")
}

Executa l'aplicació:

>  .\gradlew run

BUILD SUCCESSFUL in 3s
2 actionable tasks: 1 executed, 1 up-to-date

Obre el fitxer app\plot.png que s'acaba de crear:

>  mspaint.exe .\app\plot.png

Plugins

Gradle s'estructura al voltat de "plugins" que afegeixen funcionalitat.

Per exemple, si vols crear una distribució del teu projecte has d'afegir el "plugin" application.

Com que a l'inici has dit que el projecte és de tipus kotlin-application, en la secció plugins del fitxer build.gradle.kts del subprojecte "app" ja s'ha declarat el plugin:

Si executes la tasca distZip per crear una distribuxió del teu projecte:

> gradle distZip
BUILD SUCCESSFUL in 2s
4 actionable tasks: 3 executed, 1 up-to-date

En el "path" app/build/distributions/ està el fitxer:

 > ls .\app\build\distributions\

    Directorio: C:\Users\david\gradle\app\build\distributions

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        09/10/2024     17:08        4551293 app.zip

Descomprimeix el fitxer a la carpeta dist:

> Expand-Archive -Path .\app\build\distributions\app.zip dist

Ja pots executar l'aplicació directament:

> .\dist\app\bin\app
...

I, si elimines el plugin application del fitxer build.gradle.kts la tasca distZip desapareixerà:

> gradle distZip

Configure project :app
e: file:///C:/Users/ddemingo/gradle/app/build.gradle.kts:41:1: Expression 'application' cannot be invoked as a function. The function 'invoke()' is not found
...

Wrapper

https://docs.gradle.org/current/userguide/gradle_wrapper.html

The following command upgrades the Wrapper to the latest version:

> ./gradlew wrapper --gradle-version latest

The following command upgrades the Wrapper to a specific version:

$ ./gradlew wrapper --gradle-version 8.11

BUILD SUCCESSFUL in 4s
1 actionable task: 1 executed

Once you have upgraded the wrapper, you can check that it’s the version you expected by executing ./gradlew --version.

Don't forget to run the wrapper task again to download the Gradle distribution binaries (if needed) and update the gradlew and gradlew.bat files.