Skip to main content

Compilando una Biblioteca

⏱ Dedicación recomendada: 0 minutos
Esto considera el contenido visible y relevante, e ignora texto colapsado o marcado como opcional.


Empaquetado JAR

JAR


Un archivo JAR (Java Archive) es un formato de paquete que agrupa múltiples archivos de clase Java, metadatos y recursos (como textos, imágenes, etc.) en un único archivo para facilitar su distribución y despliegue. Los archivos JAR se basan en el formato ZIP y tienen una estructura similar.

En Gradle, la tarea jar es responsable de empaquetar los archivos de clase y recursos de un proyecto en un archivo JAR. Esta tarea se ejecuta automáticamente cuando se ejecuta la tarea build, y genera el archivo JAR dentro del directorio build/libs/ del proyecto.

A continuación, veremos cómo automatizar el proceso de empaquetado de la biblioteca y su uso en la aplicación:

  1. Empaquetar la biblioteca lib en un archivo JAR: Utilizaremos la tarea jar para generar el archivo JAR de la biblioteca.
  2. Copiar el archivo JAR al módulo app: Configuraremos una tarea que copie automáticamente el JAR generado en el directorio libs del módulo app.
  3. Configurar el módulo app para utilizar la biblioteca empaquetada: Actualizaremos las dependencias del módulo app para que utilice la biblioteca empaquetada en lugar de acceder a ella directamente.

Aunque podríamos realizar este proceso manualmente, aprovecharemos las capacidades de automatización de Gradle para hacerlo de manera eficiente y siguiendo las buenas prácticas.

Empaquetando la Biblioteca

El primer paso para automatizar el empaquetado de la biblioteca será crear un plugin de convenciones. Para ello, crearemos un nuevo archivo en convention-plugins/src/main/kotlin/compile.conventions.gradle.kts.

En este archivo, definiremos una tarea personalizada que copie los archivos JAR del directorio build/libs al directorio libs del módulo app. Como vimos en la lección sobre tareas personalizadas, comenzaremos con una tarea básica y luego la mejoraremos.

convention-plugins/src/main/kotlin/compile.conventions.gradle.kts
tasks.register<Copy>("copyLib") {
group = "build"
description = "Copia la biblioteca al directorio de la aplicación"

from("build/libs")
into("$rootDir/app/libs")

doLast {
println("Biblioteca copiada al directorio app/libs")
}
}

Y ahora aplicamos este plugin en el archivo lib/build.gradle.kts:

plugins {
id("compile.conventions")
}
// ...

Automatizando la Tarea

Ya que hemos definido la tarea copyLib, podemos hacer que esta se ejecute automáticamente antes de la tarea compileKotlin en el módulo de la aplicación. Esto garantiza que, cada vez que se compile la biblioteca, también se copie el archivo JAR al módulo app.

app/build.gradle.kts
// ...
tasks.named("compileKotlin") {
dependsOn(":lib:copyLib")
}

Ejecutando la Tarea

Cuando ejecutes la tarea build en el proyecto, se ejecutará primero la tarea compileKotlin, seguida de copyLib, que copiará el archivo JAR al directorio libs del módulo app.

Ejercicio

Ejecuta la tarea build y verifica si el archivo JAR de la biblioteca se copia correctamente al módulo app. Esto generará un error, ¿puedes identificar la causa?

Configurando la Dependencia

Para que el módulo app pueda utilizar la biblioteca empaquetada, actualizaremos las dependencias. Es similar a agregar una dependencia de una biblioteca externa, pero utilizaremos el archivo JAR local en lugar de un repositorio remoto.

app/build.gradle.kts
// ...
dependencies {
implementation(
fileTree("libs") {
include("lib-1.0.0.jar")
// include("...") // Agregar más bibliotecas si es necesario
}
)
}

Si ejecutas la tarea build todo debería funcionar, pero no lo hace debido a un error.

Ejercicio

Ejecuta la tarea build y analiza el error. ¿Puedes identificar la causa? ¿Cómo lo solucionarías?

Solución al error ¡No abrir si quieres resolverlo por tu cuenta!

El problema surge porque copyLib necesita que jar termine antes de ejecutarse. Gradle nos avisa que debemos hacer explícita la dependencia entre estas tareas.

./convention-plugins/src/main/kotlin/compile.conventions.gradle.kts
// ...
tasks.named("copyLib") {
dependsOn("jar")
}

Aplicando esta corrección, al ejecutar la tarea build, la biblioteca se empaquetará y copiará correctamente al módulo app, que podrá utilizarla como una dependencia local.

Ahora podemos probar la aplicación y verificar que funcione correctamente con la biblioteca empaquetada.

./gradlew :app:run --args="Hello, Gradle!"

Pero esto no va a funcionar, ¿puedes identificar la causa? En la siguiente lección, veremos cómo solucionar este problema y asegurarnos de que la aplicación pueda acceder a la biblioteca empaquetada.

¿Con qué nos vamos?

Al completar este proceso, hemos aprendido cómo empaquetar una biblioteca en un archivo JAR utilizando Gradle y cómo automatizar la copia de ese JAR al módulo de nuestra aplicación. También vimos cómo configurar el módulo app para que utilice el JAR empaquetado como una dependencia local.

Resumen de lo aprendido:

  1. Empaquetado JAR: Usamos la tarea jar para crear un archivo JAR con las clases y recursos del proyecto.
  2. Tarea personalizada copyLib: Definimos una tarea para copiar el JAR generado al directorio libs del módulo app.
  3. Configuración de dependencias: Configuramos el archivo build.gradle de app para que reconozca y use el archivo JAR copiado como una dependencia.
  4. Solución de errores: Identificamos y corregimos un error de dependencia entre tareas, asegurando que la tarea copyLib se ejecute después de que la tarea jar haya generado el archivo JAR.

Con esta base, ahora puedes automatizar aún más tu flujo de trabajo y aplicar estas técnicas para proyectos más complejos y modulares.

Bibliografías Recomendadas