دقة تبعية 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 بنفس الطريقة التي تعاملت بها مع المواصفات المباشرة.

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

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

تؤثر إصدارات BOM على تبعياتك المباشرة وكذلك في جميع التبعيات المتعدِّدة التي تظهر في BOM.

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

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

لا تتطلّب أي مكتبات تريد استخدامها كملحقات مواصفات الإصدار، لأنّ الإصدار المطلوب يأتي من BOM.

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

على سبيل المثال، يحتوي كتالوج الإصدارات على BOM ورقم الإصدار الخاص به، ولكن لا يحدد إصدارًا للمكتبات التي تشير إليها من 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 إلى BOM والمكتبات باستخدام المتغيّرات المحدّدة في كتالوج الإصدارات:

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

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

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

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

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

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