Introducción

Público objetivo: Desarrolladores de Gradle enfrentados a la gestión de dependencias en proyectos multi-builds.

En nuestra búsqueda para crear el plugin`site-baker`, hemos buscado mantener una base de código limpia y centralizada. Una de las mejores prácticas en el ecosistema Gradle moderno es el uso delcatálogo de versiones(libs.versions.toml) para gestionar las dependencias. Pero, ¿qué ocurre cuando tu proyecto se vuelve más complejo, como unconstruir compuesto¿Dónde una compilación independiente (nuestro plugin) debe incluirse en otra ?

Fue allí donde nuestra aventura tomó un giro inesperado. Queríamos que nuestro plugin`site-baker`, que es él mismo un proyecto Gradle, utiliza el mismo catálogo de versiones que nuestro proyecto principal. Este artículo, el quinto de nuestra serie, cuenta cómo hemos resuelto este desafío.

El Catálogo de Versiones (libs.versions.toml) : Un Recordatorio

El archivo`gradle/libs.versions.toml`es una funcionalidad de Gradle que permite centralizar las versiones y las coordenadas de las dependencias de su proyecto. Generalmente se estructura en cuatro secciones:

  • [versions]: Define alias para los números de versión (ej:`kotlin = "1.9.20"`).

  • [libraries]: Define alias para las dependencias completas, utilizando las versiones definidas anteriormente (ej:`kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }`).

  • [bundles]: Agrupa varias bibliotecas bajo un solo alias (ej:`jackson = ["jackson-core", "jackson-databind"]`).

  • [plugins]: Define alias para los plugins Gradle.

Una vez definido, Gradle genera automáticamente accesores tipados, lo que hace que su`build.gradle.kts`mucho más legible :

dependencies {
    // Au lieu de : implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.20")
    implementation(libs.kotlin.stdlib)
}
toml flow
Figure 1. Flujo de datos del catálogo de versiones

2. El Problema: una compilación compuesta y dos mundos separados

Nuestra estructura de proyecto es unconstruir compuesto. El proyecto principal (thymeleaf.cheroliv.com) incluye el proyecto del plugin (site-baker) a través del comando`includeBuild("site-baker")en el archivo`settings.gradle.kts.

composite build
Figure 2. Estructura del build compuesto

El problema es que, por defecto, un build incluido es unmundo separado. Tiene su propia configuración, su propio ciclo de vida, y no ve el archivo`libs.versions.toml`del build principal. Nuestro`plugin/build.gradle.kts`intentaba utilizar`libs.plugins.kotlin.jvm`, pero el objeto`libs`no se estaba generando a partir del archivo TOML correcto, provocando errores de compilación.

3. La Solución: Compartir la Resolución de Dependencias

Después de varias investigaciones, la solución resultó ser una funcionalidad de Gradle diseñada precisamente para este caso:`dependencyResolutionManagement`.

En el archivo`settings.gradle.kts` du build incluido(site-baker/settings.gradle.kts), nosotros podemos decirle a Gradle dónde encontrar el catálogo de versiones que se debe usar.

Aquí está la configuración que hemos añadido a`site-baker/settings.gradle.kts`:

// site-baker/settings.gradle.kts

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

rootProject.name = "site-baker"
include("plugin")

Analicemos la parte crucial:

versionCatalogs {
    create("libs") { // Crée un catalogue nommé 'libs'
        from(files("../gradle/libs.versions.toml")) // En utilisant ce fichier
    }
}
  • create("libs"): Declaramos un catálogo de versiones que será accesible a través del alias`libs`.

  • from(files("../gradle/libs.versions.toml")): Es la magia. Le indicamos a Gradle que la fuente de este catálogo es el archivo TOML ubicado en el directorio`gradle` du proyecto padre(../).

Con esta configuración, el build`site-baker`sabe ahora que él debe utilizar el catálogo de versiones del proyecto principal. El objeto`libs`se genera correctamente, y las dependencias se resuelven como se esperaba.

4. Conclusión : El Poder de los Builds Compuestos Bien Gestionados

Esta experiencia ha sido rica en aprendizajes. El catálogo de versiones es una herramienta fantástica para la mantenibilidad, pero su comportamiento en escenarios de builds compuestos no siempre es intuitivo.

La clave es recordar que una compilación incluida sigue siendo una compilación independiente. Para compartir configuraciones como el catálogo de versiones, hay que utilizar los mecanismos explícitos proporcionados por Gradle, como el bloque.dependencyResolutionManagement`dentro de`settings.gradle.kts.

Al resolver este problema, no solo hemos hecho que nuestro build sea más limpio, sino que también hemos reforzado la coherencia de nuestro proyecto al asegurarnos de que el plugin y el proyecto principal compartan una única fuente de verdad para sus dependencias.

En el próximo artículo, continuaremos enriqueciendo nuestro plugin añadiéndole tareas más complejas, ahora que nuestra gestión de dependencias es sólida y centralizada.

Articles connexes