Introducción a Gradle

Gradle logo

Introducción

Gradle es una herramienta que ayuda a desarrollar un proyecto basado en el entorno de una JDK (Java, Kotlin, Xtend, Scala, Groovy, etc.) y que cumple con las siguientes funciones principales que vamos a explicar en las siguientes secciones:

Reificación de Proyecto

Java no trabaja la idea de proyecto, no lo representa como concepto, y esto se traslada a todos los lenguajes basados en la JDK. Entonces, cada uno de los IDEs pensados para Java agregan su propia forma de definirlo:

Gradle permite trabajar en cualquiera de estos IDEs con su propio modelo de proyecto, que se guarda en el archivo build.gradle.kts en el caso de trabajar utilizando el lenguaje Kotlin o build.gradle a secas, cuando la configuración se hace utilizando el lenguaje Groovy. A partir de ahora vamos a continuar la explicación asumiendo que estás usando Gradle con Kotlin.

Aclaración: los términos componente y artefacto son sinónimos de proyecto.

Identificación de un proyecto Gradle

Todo proyecto en Gradle tiene tres cosas que lo identifican:

Gradle tomó de Maven, su antecesor directo, esta misma forma de identificar un proyecto. Vemos cómo se definen estos valores en el archivo build.gradle.kts:

      group = "ar.edu.unsam.algo2"
version = "1.0-SNAPSHOT"

    

El artifact se define en el archivo settings.gradle:

      rootProject.name = "eg-seguros-kotlin"

    

Manejo de dependencias

Repositorios locales

Las dependencias son útiles para poder acceder a códigos escritos por otros (como la biblioteca Mockk o Apache Commons Collections). Cuando instalamos Gradle, se crea un repositorio local en una carpeta que por defecto suele ser HOME/.gradle, donde descargamos los componentes localmente una sola vez (muchos proyectos que usan la misma dependencia van a buscar el artefacto en ese mismo lugar). Podemos encontrar al componente cuyo identificador es io.kotest:kotest-assertions-core:5.1.0 en

      ~/.gradle
   └── caches
        └── modules-2
             └── files-2.1
                    └── io.kotest
                          └── kotest-assertions-core
                                ├─ 4.4.3 (otra versión)
                                └─ 5.1.0 --> dentro de esta carpeta estará el artefacto

    

Repositorios remotos

Ahora bien, ¿desde dónde descargamos las versiones 4.4.3 y 5.1.0 de io.kotest:kotest-assertions-core? Existen para eso repositorios remotos donde se publican artefactos:

En el archivo build.gradle.kts podés ver cómo se referencian los repositorios remotos:

      repositories {
    mavenCentral()
}

    

Definiendo dependencias en el proyecto

Las dependencias se definen dentro de un tag dependencies:

      val kotestVersion = "5.1.0"

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
    testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
}

    

En este caso, estamos definiendo que nuestro proyecto tiene como pre-requisitos:

Una vez que hagamos un cambio en las dependencias, nos aparece el botón para sincronizar las definiciones del archivo con el IntelliJ, como vemos en este video:

descarga componente local

Al agregar una dependencia lo hacemos con el formato “group:artifact:version” y también definimos el tipo de alcance (scope), que puede ser

Resumen general del manejo de dependencias de Gradle

manejo de dependencias de gradle

Fuente: https://docs.gradle.org/current/userguide/dependency_management.html

Al hacer el build de nuestro proyecto

gradle componente fallido

Dependencias transitivas

Un detalle no menor de la resolución de dependencias de Gradle es que también funciona para las dependencias transitivas.

Por ejemplo:

Al resolver las dependencias, el proyectoA necesitará descargar los componentes B, C, D, E y F. Incluso podríamos requerir diferentes versiones de los mismos componentes.


Noten que un proyecto comercial “normal” o mediano, puede incluir decenas y hasta cientos de dependencias. Esto se puede ver en IntelliJ desde la solapa Gradle, e inspeccionar

Gradle - Dependencias transitivas

Plugins

Si bien Gradle provee una plataforma para poder facilitar el manejo de dependencias, el build del proyecto y muchas otras actividades más, quienes verdaderamente se encargan de esta tarea son los plugins, que terminan resolviendo cada una de estas cosas.

Cada plugin permite

Podés ver en cualquiera de nuestros ejemplos qué contiene la sección plugins del build.gradle.kts:

      plugins {
    kotlin("jvm") version "1.6.10"
    jacoco
}

    

En este ejemplo


Para más información pueden consultar esta página.

Tareas

Una tarea de Gradle no es otra cosa que una porción de código que se ejecuta en un determinado contexto. Por ejemplo, si escribimos en el archivo build.gradle.kts estas líneas de código:

      tasks.register("saludar") {
    doLast {
        println("Hola, qué tal?")
    }
}

    

Podemos ejecutarlo desde el menú de IntelliJ:

Gradle Task

Como se ve, es código Kotlin lo que se ejecuta.

En particular, el plugin Kotlin define la mayoría de las tareas que vamos a utilizar:

Todas se pueden ejecutar de la misma manera que nuestra tarea custom saludar.

Temas adicionales

Gradle Wrapper

En lugar de trabajar directamente con Gradle, cada proyecto en IntelliJ va a trabajar con un script genérico que constituye el Gradle Wrapper o wrapper a secas, que tiene algunas ventajas:

La pregunta que podemos hacernos es: ¿esto cambia algo en mi forma de trabajar? No, en nada, pero es útil entender por qué utilizamos gradlew como ejecutable por consola en lugar de gradle, y qué hace esta estructura dentro de nuestro proyecto:

      .gradlew
.gradlew.bat
   └──gradle
        └──wrapper
            └──gradle-wrapper.jar
            └──gradle-wrapper.properties # link a la versión de Gradle que estamos usando

    

Para más información pueden ver esta página.

Ejecutando gradle desde la consola

Una alternativa es trabajar directamente con Gradle desde la consola, algo que puede ser útil para automatizar tareas, como cuando trabajemos con herramientas de integración continua.

      ./gradlew clean build

    

Esto ejecuta varios plugins en forma sincronizada:

Si queremos ver el árbol de dependencias transitivas, podemos escribir

      ./gradlew -q dependencies 

    

Documentación oficial

Para más información recomendamos leer

Links relacionados