دقة تبعية Gradle

تحدِّد ملفات الإنشاء التبعيات المباشرة، ولكن يمكن أن تتطلّب كل تبعية من هذه التبعيات تبعيات أخرى. تؤدي هذه التبعيات التراكمية إلى زيادة الرسم البياني العام للمهام التابعة بسرعة، وغالبًا ما يكون ذلك مع إصدارات متضاربة.

عند تغيير أجزاء minor (الميزات الجديدة) أو patch (إصلاحات الأخطاء)، من المرجّح أن تظل المكتبة متوافقة ومن غير المرجّح أن تؤثّر في تطبيقك.

على سبيل المثال، لنفترض أنّ تطبيقك يعتمد على المكتبة "أ" والمكتبة "ب"، اللتين تعتمدان بدورهما على إصدارات مختلفة من المكتبة "ج".

يعتمد تطبيقك على المكتبة "أ" والمكتبة "ب"، اللتين تعتمدان بدورهما على إصدارات مختلفة من المكتبة "ج". يختار Gradle أحدث إصدار من المكتبة C.
الشكل 1. تعارض في الإصدارات الانتقالية يحدِّد Gradle أحدث إصدار (تلقائيًا).

في هذه الحالة، يختار Gradle أحدث إصدار من المكتبة C تلقائيًا، ما قد يؤدي إلى حدوث مشاكل في عملية الترجمة أو وقت التشغيل. في هذا المثال، تم حلّ المكتبة "ج" إلى الإصدار 2.1.1، ولكن يُرجى العلم أنّ المكتبة "أ" طلبت المكتبة "ج" 1.0.3. تغيّر الجزء الرئيسي من رقم الإصدار، ما يشير إلى تغييرات غير متوافقة، مثل الدوالّ أو الأنواع التي تمت إزالتها. وقد يؤدي ذلك إلى تعطُّل المكالمات التي يتم إجراؤها من المكتبة "أ".

يمكن أن يتضمّن تطبيقك تبعيات مباشرة تكون أيضًا تبعيات غير مباشرة.

يعتمد تطبيقك على المكتبة "أ" والمكتبة "ج". تعتمد المكتبة "أ" على إصدار أحدث من المكتبة "ج". يختار Gradle أحدث إصدار من المكتبة C.
الشكل 2. تعارض آخر في الإصدارات الانتقالية في هذه الحالة، يحدِّد Gradle الإصدار القابل للنقل، ويظهر هذا الإصدار الأحدث لتطبيقك.

في مثل هذه الحالة، يمكن أن تلغي التبعيات الانتقالية الأحدث الإصدار الذي تطلبه مباشرةً في تطبيقك.

يفحص Gradle جميع الإصدارات المُحتمَلة لجميع التبعيات في الرسم البياني لتحديد أحدث إصدار من كل تبعية. يمكنك استخدام مهام Gradle الأساسية والأدوات الأكثر تقدمًا لتحديد الإصدارات التي حلّلها Gradle لكل تبعية. إنّ مقارنة التغييرات في هذا القرار هو أمر أساسي لفهم مخاطر الترقية والحدّ منها.

على سبيل المثال، يمكنك استخدام مهمة Gradle dependencies من خلال تشغيل ./gradlew app:dependencies لعرض شجرة لجميع التبعيات المستخدَمة في ملف ‎.jar الخاص بتطبيقك. عند تنفيذ هذا الإجراء على تطبيق يستخدم المكتبات كما هو موضّح في الشكل 2، نلاحظ

1: releaseRuntimeClasspath - Runtime classpath of /release.
2: +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0
3: |    +--- ... (omitted for brevity) ...
4: +--- com.sample:library.a:1.2.3
5: |    +--- com.sample:library.c:2.1.1
6: |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
7: |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
8: +--- com.sample:library.c:1.4.1 -> 2.1.1 (*)

يعرض هذا الجزء من التقرير بعض التبعيات التي تم حلّها لإعدادات releaseRuntimeClasspath.

عندما يظهر لك الرمز -> في تقرير العناصر الاعتمادية، يعني ذلك أنّ أحد مقدّمي الطلبات (تطبيقك أو مكتبة أخرى) يستخدم إصدارًا من هذه العناصر الاعتمادية لا يتوقعه. وفي معظم الحالات، لا يتسبب ذلك في أي مشاكل، لأنّ معظم المكتبات مكتوبة للتوافق مع الإصدارات القديمة. ومع ذلك، قد تُجري بعض المكتبات تغييرات غير متوافقة، ويمكن أن يساعدك هذا التقرير في تحديد مصدر المشاكل الجديدة في سلوك تطبيقك.

يمكنك الاطّلاع على مزيد من التفاصيل حول استخدام ميزة إعداد تقارير الملحقات في Gradle من خلال مقالة عرض الملحقات و تصحيح أخطاءها.

يمكنك تحديد الإصدارات المطلوبة مباشرةً، أو في قائمة إصدارات، أو في فاتورة مواد.

درجة دقة مواصفات الإصدار المباشر

تصبح إصدارات التبعيات التي تحدّدها مرشّحة لحلّ الإصدار.

على سبيل المثال، لطلب الإصدار 1.7.3 من مكتبة androidx.compose.ui:ui كأحد المكوّنات التي يعتمد عليها تطبيقك app/build.gradle.kts:

dependencies {
    implementation("androidx.compose.ui:ui:1.7.3")
}

يصبح الإصدار 1.7.3 إصدارًا مرشحًا. يحدِّد Gradle أحدث إصدار من بين الإصدار 1.7.3 والإصدارات الأخرى من المكتبة نفسها التي يطلبها التبعيات الانتقالية.

درجة دقة قائمة الإصدارات

تحدِّد كتالوجات الإصدارات متغيّرات لتتبُّع إصدار العناصر الاعتمادية المستخدَمة في جميع أنحاء تطبيقك. إذا كنت تستخدم متغيّرًا من قائمة الإصدارات، تتم إضافة التبعيات المحدّدة لهذا المتغيّر إلى المرشحين لتحديد الإصدار. ويتم تجاهل المتغيّرات غير المستخدَمة في قائمة الإصدارات.

على سبيل المثال، لتحديد الإصدار 1.7.3 من androidx.compose.ui:ui كأحد المتطلّبات في ملف gradle/libs.versions.toml:

[versions]
ui = "1.7.3"

[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }

يحدّد هذا المتغيّر الذي يحمل الاسم libs.androidx.compose.ui لتمثيل المكتبة. لا يُعتبر هذا الإصدار مرشحًا ما لم تستخدم المتغيّر لتحديد أحد التبعيات.

لطلب المكتبة وإصدارها في app/build.gradle.kts:

dependencies {
    implementation(libs.androidx.compose.ui)
}

يحلّ Gradle التبعيات بالطريقة نفسها التي يحلّ بها المواصفات المباشرة.

درجة دقة قائمة المواد

تصبح نُسخ جميع المكتبات التي تظهر في قائمة مواد العرض مرشّحة لتحديد الإصدار. يُرجى العِلم أنّه لا يتم استخدام المكتبات كتبعيات إلا إذا تم تحديدها على أنّها مباشرة أو غير مباشرة. ويتم تجاهل المكتبات الأخرى في قائمة مواد العرض.

تؤثر إصدارات قائمة مواد العرض في التبعيات المباشرة بالإضافة إلى جميع التبعيات الاستبدالية التي تظهر في قائمة مواد العرض.

على سبيل المثال، حدِّد قائمة مواد أساسية كتبعية للمنصّة في app/build.gradle.kts:

dependencies {
    implementation(platform("androidx.compose:compose-bom:2024.10.00"))
    implementation("androidx.compose.ui:ui")
}

لا تتطلّب أي مكتبات تريد استخدامها كتبعيات تحديدًا لإصدارها، لأنّ الإصدار المطلوب يأتي من قائمة مواد العرض.

تجدر الإشارة إلى أنّه يمكنك أيضًا استخدام كتالوج إصدارات لإنشاء متغيّرات لقائمة مواد العرض و المكتبات. إزالة أرقام الإصدار في قائمة الإصدارات للمكتبات التي تظهر في ملف BOM للتبعية

على سبيل المثال، يحتوي كتالوج الإصدارات على قائمة بمواد العرض ورقم إصدارها، ولكنه لا يحدّد إصدارًا للمكتبات التي تشير إليها من قائمة مواد العرض:

[versions]
composeBom = "2024.10.00"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }

يشير app/build.gradle.kts إلى قائمة مواد العرض والمكتبات باستخدام المتغيّرات المحدّدة في قائمة الإصدارات:

dependencies {
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.compose.ui)
}

يصبح إصدار هذه المكتبة المحدّد في ملف BOM مرشحًا لمعالجة IDE. بالإضافة إلى ذلك، تصبح جميع إصدارات المكتبة الأخرى المحدّدة في قائمة مواد العرض إصدارات مرشحة، سواء كنت تستخدمها مباشرةً كتبعيات أم لا.

على سبيل المثال، لنفترض أنّ قائمة مواد العرض تحدّد إصدارات المكتبات "أ" و"ب" و"ج". يريد تطبيقك استخدام المكتبة "أ" مباشرةً كعنصر معتمد، بالإضافة إلى المكتبة د. تستخدم المكتبة "د" المكتبة "ب" كتبعية. لا يستخدم أي عنصر المكتبة C.

يتضمّن مخطّط BOM إصدارات المكتبات A وB وC. يستخدم تطبيقك المكتبتَين "أ" و"د" كموارد تابعة. تستخدم المكتبة "د" المكتبة "ب" كتبعية. لا يتم استخدام المكتبة "ج" بشكل مباشر أو غير مباشر في هذا التطبيق.
الشكل 3. سيناريو قائمة مواد التصنيع

المكتبات "أ" و"ب" و"د" هي مكتبات تابعة للتطبيق، ويتم تجاهل المكتبة "ج". يستخدم Gradle إصدارَي المكتبتَين "أ" و"ب" المحدّدَين في ملف BOM كمرشحَين، حتى إذا لم تحدّد المكتبة "ب" مباشرةً كتبعية.

إذا طلبت المكتبة "د" إصدارًا من المكتبة "ب" أقل من 2.0.1، سيحلّ Gradle الإصدار 2.0.1. إذا طلبت المكتبة "د" إصدارًا أحدث من المكتبة "ب"، سيحلّ Gradle محلّ هذا الإصدار.