معرفی

مخاطبان هدف: توسعه‌دهندگان Gradle که با مدیریت وابستگی در پروژه‌های multi-build روبرو هستند.

در جستجوی ما برای ایجاد افزونه`site-baker`, ما سعی کردیم تا پایهٔ کد تمیز و متمرکز را حفظ کنیم. یکی از بهترین روش‌ها در اکوسیستم Gradle مدرن استفاده ازفهرست نسخه‌ها(libs.versions.toml) برای مدیریت وابستگی‌ها. اما چه چیزی اتفاق می‌افتد وقتی پروژه شما پیچیده‌تر می‌شود، مثل یکساخت ترکیبیدر کجا یک build مستقل (پلاگین ما) باید در دیگری گنجانده شود؟

اینجاست که ماجرا ما به یک جهت غیرمنتظره تغییر کرد. ما می‌خواستیم که پلاگین ما`site-baker`، که خود پروژه Gradle است، از همان فهرس نسخه‌های پروژه اصلی ما استفاده می‌کند. این مقاله، پنجمین از سری ما، شرح می‌دهد که چگونه این مشکل را حل کردیم.

1. فهرست نسخه‌ها (libs.versions.toml) : یک یادآوری

فایل`gradle/libs.versions.toml`یک ویژگی Gradle است که امکان مرکزی‌سازی نسخه‌ها و مختصات وابستگی‌های پروژه شما را فراهم می‌کند. معمولاً در چهار بخش ساختاردهی شده است :

  • [versions]: تعریف می‌کند نام‌های مستعار برای شماره‌های نسخه (مثل:`kotlin = "1.9.20"`).

  • [libraries]: تعریف alias برای تمام وابستگی‌ها، با استفاده از نسخه‌های تعریف شده در بالا (مثل:`kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }`).

  • [bundles]: چند کتابخانه را تحت یک نام مستعار واحد گروه‌بندی می‌کند (مثل:`jackson = ["jackson-core", "jackson-databind"]`).

  • `[plugins]`نام‌های مستعار برای پلاگین‌های Gradle تعریف می‌شود.

پس از تعریف، Gradle به صورت خودکار دسترسی‌دهنده‌های typed ایجاد می‌کند که`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 "Gradle" 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 "gradle" {
    file "libs.versions.toml" as MainToml
  }
}

package "افزونه `site-baker` (Build Inclus)" {
  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 است که در دایرکتوری قرار دارد`gradle` du پروژه والد(../)

با این تنظیم، ساخت`site-baker`الان می‌داند که باید از فهرس نسخه‌های پروژه اصلی استفاده کند. شیء`libs`به درستی تولید می‌شود و وابستگی‌ها به‌طور مورد انتظار حل می‌شوند.

4. نتیجه : قدرت ساخت‌های ترکیبی به خوبی مدیریت‌شده

این تجربه غنی از دروس بوده است. فهرست نسخه‌های یک ابزار فوق‌العاده برای قابلیت نگهداری است، اما رفتار آن در سناریوهای ساخت‌های ترکیبی همیشه بديهي نیست.

کلید این است که به خاطر داشته باشیم که یک‌ساخت شامل (included build) همچنان یک‌ساخت مستقل است. برای به اشتراک‌گذاری تنظیمات مانند فهرس نسخه‌ها، باید از مکانیزماهای صریح فراهم‌شده توسط Gradle، مانند بلوک، استفاده کرد`dependencyResolutionManagement`در`settings.gradle.kts`.

با حل این مشکل، نه تنها build خود را تمیزتر کردیم، بلکه انسجام پروژه خود را نیز تقویت دادیم با اطمینان از اینکه پلاگین و پروژه اصلی یک منبع واحد حقیقت برای وابستگی‌هایشان به اشتراک می‌گذارند.

در مقاله بعدی، خواهیم پلاگین خود را با افزودن کارهای پیچیده‌تر غنی کرد، زیرا مدیریت وابستگی‌های ما الآن قوی و متمرکز شده است.

مقالات مرتبط