Статья 5: Приключение общего libs.versions.toml
Опубликовано 27 September 2025
Введение
В нашем стремлении создать плагин`site-baker`, мы стремились поддерживать чистую и централизованную кодовую базу. Одной из лучших практик в современной экосистеме Gradle является использованиекаталог версий(libs.versions.toml) для управления зависимостями. Но что происходит, когда ваш проект становится более сложным, какстроить композитгде независимая сборка (наш плагин) должна быть включена в другую ?
Именно там наше приключение приняло неожиданный оборот. Мы хотели, чтобы наш плагин`site-baker`, который сам по себе является проектом Gradle, использует тот же каталог версий, что и наш основной проект. Эта статья, пятая в нашей серии, рассказывает, как мы решили эту проблему.
1. Каталог версий (libs.versions.toml) : напоминание
Файл`gradle/libs.versions.toml`— это функция Gradle, позволяющая централизовать версии и координаты зависимостей вашего проекта. Обычно она состоит из четырёх разделов:
-
[versions]: Определяет псевдонимы для номеров версий (например:`kotlin = "1.9.20"`). -
[libraries]: Определяет псевдонимы для полных зависимостей, используя версии, указанные выше (например:`kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }`). -
[bundles]`Объединяет несколько библиотек под одним псевдонимом (например:`jackson = ["jackson-core", "jackson-databind"]). -
[plugins]: Определяет псевдонимы для плагинов Gradle.
После того как оно определено, Gradle автоматически генерирует типизированные аксессоры, что делает ваш`build.gradle.kts`гораздо более читаемый :
dependencies {
// Au lieu de : implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.20")
implementation(libs.kotlin.stdlib)
}
@startuml !theme plain file "gradle/libs.versions.toml" as Toml node "Грэдл" as G file "build.gradle.kts" as BuildScript Toml --> G : "читается" G --> BuildScript : "генерирует аксессор `libs" BuildScript -> G : "используй `libs` для объявления зависимостей" @enduml
2. Проблема: композитная сборка и два разделенных мира
Наша структура проекта — этопостроить композит. Главный проект (thymeleaf.cheroliv.com) включает проект плагина (site-baker) через команду`includeBuild("site-baker")в файле`settings.gradle.kts.
@startuml
!theme plain
package "Главный проект" {
file "settings.gradle.kts" as MainSettings
folder "Грэдл" {
file "libs.versions.toml" as MainToml
}
}
package "Плагин `site-baker` (Встроено)" {
file "settings.gradle.kts" as PluginSettings
file "build.gradle.kts" as PluginBuild
}
MainSettings -> PluginSettings : `includeBuild("site-baker")`
PluginBuild ..> MainToml : **Voulait accéder à...**
note right on link: ...mais ne pouvait pas !
@enduml
Проблема в том, что, по умолчанию, включённый build - этоотдельный мир. У него есть своя конфигурация, свой жизненный цикл, и он не видит файл`libs.versions.toml`главной сборки. Наш`plugin/build.gradle.kts`пытался использовать`libs.plugins.kotlin.jvm`, но объект`libs`Он не был сгенерирован из правильного файла TOML, что привело к ошибкам сборки.
3. Решение: Совместное использование разрешения зависимостей
После нескольких поисков решение оказалось функцией Gradle, специально разработанной для этого случая :`dependencyResolutionManagement`.
В файле`settings.gradle.kts` du включённая сборка(site-baker/settings.gradle.kts), мы можем указать Gradle, где найти каталог версий для использования.
Это конфигурация, которую мы добавили к`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")
Давайте проанализируем важную часть:
versionCatalogs {
create("libs") { // Crée un catalogue nommé 'libs'
from(files("../gradle/libs.versions.toml")) // En utilisant ce fichier
}
}
-
create("libs"): Мы объявляем каталог версий, который будет доступен через псевдоним`libs`. -
from(files("../gradle/libs.versions.toml"))`Это магия. Мы указываем Gradle, что источник этого каталога — файл TOML, расположенный в каталоге`gradledu родительский проект(
)../).
С этой конфигурацией сборка`site-baker`Теперь он знает, что ему нужно использовать каталог версий основного проекта. Объект`libs`сгенерировано правильно, и зависимости разрешены как ожидалось.
4. Вывод: Сила хорошо управляемых композитных сборок
Этот опыт был полон уроков. Каталог версий — фантастический инструмент для поддерживаемости, но его поведение в сценариях комбинированных сборок не всегда интуитивно понятно.
Ключ в том, чтобы помнить, что включённая сборка остаётся независимой. Чтобы делиться конфигурациями, такими как каталог версий, необходимо использовать явные механизмы, предоставляемые Gradle, такие как блок`dependencyResolutionManagement`в`settings.gradle.kts`.
Решив эту проблему, мы не только сделали нашу сборку более чистой, но и усилили целостность нашего проекта, убедившись, что плагин и основной проект используют единым источником правды для своих зависимостей.
В следующей статье мы продолжим обогащать наш плагин, добавляя более сложные задачи, поскольку теперь наше управление зависимостями надёжно и централизовано.