Contents |
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:
Java no trabaja la idea de proyecto, no lo representa como concepto, y eso 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:
.classpath
y .project
.idea
.vscode
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.
Todo proyecto en Gradle tiene tres cosas que lo identifican:
ar.edu.unsam.algo2
.commons-collections
, eg-seguros-kotlin
, tp-futbol5-grupo01
, etc.Aclaración: los términos
componente
yartefacto
son sinónimos de proyecto.
RELEASE
(para versiones estables) o SNAPSHOT
(para versiones intermedias que pueden estar sujetas a cambios).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.kts
:
rootProject.name = "eg-seguros-kotlin"
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
\.gradle
.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()
}
Las dependencias se definen dentro de un tag dependencies
:
val kotestVersion = "5.8.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:
kotest-runner-junit5
y kotest-assertions-core
de io.kotest
. La versión se define en una referencia val
, el código que escribimos para definir el archivo de configuración es Kotlin.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:
Al agregar una dependencia lo hacemos con el formato “group:artifact:version” y también definimos el tipo de alcance (scope), que puede ser
testImplementation
) pero queremos tener un componente real que envía mails en la versión productiva (runtimeOnly
).
Fuente: https://docs.gradle.org/current/userguide/dependency_management.html
Al hacer el build de nuestro proyecto
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
src/main/kotlin
)runtimeOnly
. En Algoritmos 2 no vamos a levantar ninguna aplicación, pero sí más adelante en Algoritmos 3.testImplementation
, que sirven para ejecutar los tests.
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
src/main/kotlin
Podés ver en cualquiera de nuestros ejemplos qué contiene la sección plugins del build.gradle.kts
:
plugins {
kotlin("jvm") version "1.9.22"
jacoco
}
En este ejemplo
Para más información pueden consultar esta página.
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:
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:
build
construye el proyectojar
sirve para empaquetar las clases y generar un Java ARchive, un zip de archivos .classclean
elimina carpetas temporales, algo útil previo a un buildtest
ejecuta las pruebas unitarias, algo que igualmente se hace también desde el IDETodas se pueden ejecutar de la misma manera que nuestra tarea custom saludar
.
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.
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:
clean
borra el directorio build
donde estarán los archivos compilados.class
que una JRE pueda interpretarSi queremos ver el árbol de dependencias transitivas, podemos escribir
./gradlew -q dependencies
Para más información recomendamos leer