Bild task ki automation har software project ke liye muhim hai; Gradle, apne Kotlin DSL ke saath, istisnai murarat provide karta hai. Hamari guftugu ke dauran, humne explore kiya ke kaise build logic ko centralize karke reuse kiya ja sake, khusus test reports ke liye, istemaal karte hueتمام پروژیکٹس, buildSrc, aur مخصوص کاموں میں Kotlin.

تنظیمات کو مرکزی بنائیں allprojects اور subprojects کے ساتھ

بلوک`allprojects` et `subprojects`آپ کے`build.gradle.kts`جڑیں بنیادی ہیں، عام کنفیگریشنز لاگو کرنے کے لیے آپ کے multi‑module پروجیکٹ میں پوری طرح۔

*allprojects { …​ }`کونفیگریشن کو لاگو کریںجذری پروجیکٹ اور اس کے تمام زیرِپروجیکٹوں. مثالي طور پر ایک چیز کو تعریف کرنے کے لئے`group, ایک`version`, یا`repositories`مشترک. *subprojects { …​ }`تنظیمات لاگو کریںصرف زیر منصوبوں تک, جڑ پروژہ کو خارج کردہ۔ ماڈیولز کے لیے مخصوص پلاگن لاگو کرنے کے لیےideal (جیسے`java ou kotlin-jvm) یا مشترکہ انحصارات آپ کی لائبریریوں کے لئے

یہ ایک مثالی نمونہ :

// build.gradle.kts (projet racine)
plugins {
    base // Appliqué au projet racine
}

allprojects {
    group = "com.example"
    version = "1.0.0"

    repositories {
        mavenCentral()
    }

    tasks.withType<org.gradle.api.tasks.testing.Test> {
        useJUnitPlatform() // Configuration commune des tests pour tous les projets
    }
}

subprojects {
    apply(plugin = "java")
    apply(plugin = "org.jetbrains.kotlin.jvm")

    dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    }

}

\==buildSrc: بِلڈ لوجیک کا سویس آرمی چاقو

جب آپ کے کاموں کی لوجک مُعقّد بن جاتی ہے یا دوبارہ استعمال کی جانی چاہیے,buildSrcیہ ترجیحی حل ہے۔ یہ ایک خاص Gradle ماڈیول ہے جو بنیادی بنڈ سکرپٹس سے پہلے کامپائل ہوتا ہے، جس کے نتیجے میں اس کی کلاسز آپ کے پوری بنڈ کے کلاس پتھ پر دستیاب ہو جاتی ہیں۔

استعمال کیوں`buildSrc`کاموں کے لیے؟

  • دوبارہ استعمال کرنے کی قابلیت: ایک معین شدہ کام`buildSrc`یہ بِلڈ کے کسی بھی پروجیکٹ پر لاگو کیا جا سکتا ہے۔

  • تنظیم: بِلڈ کوڈ کو مرکزی بناتا ہے، اسے صاف اور رکھنے میں آسان بناتا ہے۔

  • ٹائپ سیفٹی اور اوٹو کمپلیشنکورلین کا کوڈ میں`buildSrc`کمپائل ہوتا ہے، غلطیوں کی جانچ فراہم کرتا ہے اور آپ کے IDE کی خود تکمیل فراہم کرتا ہے، ترقی کے تجربے کو بہتر بناتا ہے۔

\=== فلو ڈائاگرام`buildSrc`(کوڈ PlantUML)

اس ڈائاگرام کو بنانے کے لیے نیچے دیے گئے کوڈ کوکپی کریں اور ایک آئٹ میں پیسٹ کریں جو PlantUML کو سپورٹ کرتا ہے۔

[source,plantuml]

@startuml skinparam خط کشیدہ سچ skinparam monochrome سچ

مستطیل "Gradle Build Process" { component "buildSrc" as BS { فائل "MyCustomTask.kt" کے طور پر T فائل "MyConventionPlugin.kt" به عنوان P } component "Root Project" as RP حصہ "Subproject A" کے طور پر SA حصہ "Subproject B" SB کے طور پر }

T --\> P : "تعریف کیا گیا ہے P --\> RP : "لاگو کیا جاتا ہے P --\> SA : "لگو کیا جاتا ہے P --\> SB : "لاگو کیا جاتا ہے

RP --|\> SA : "شامل ہے RP --|\> SB : "شامل

RP -up-\> BS : "بِلڈ منطق کے لیے مستند ہے SA -up-\> BS : "مُعَلق ہے (بیلڈ لوجک کے لیے) SB -up-\> BS : "depends on (for build logic)

T کے دائیں طرف نوٹ خُصُوصی کام کی کلاسیں (مثال: OpenTestReportTask) آخری نوٹ

P کے دائیں نوٹ کنوانشن پلاگین جسے کام ریکارڈ کرتے ہیں (Empty output)

@enduml

رپورٹ کے ابسٹرکٹ کاموں کی تخلیق

ٹیسٹ رپورٹس کو منیج کرنے کے لیے، ہم نے ایک مڈولرApproach تیار کیا ہے ایک ایبسٹریٹ ٹاسک کلاس استعمال کرتے ہوئے میں`buildSrc`. آپ کی ضرورت کے مطابق، یہ کلاس وراثت لے سکتی ہے`DefaultTask` ou de Exec.

\=== ابسرکٹ ٹاسک`OpenTestReportTask`(وارث ہونے والا`DefaultTask`)

یہ ٹریک اس وقت تجویز کی جاتی ہے جب آپ کو Kotlin کی مخصوص لوژک کی ضرورت ہو جو فائل سسٹم یا دیگر Gradle APIs کے ساتھ تعامل کرے اور اس کے بعد ایک بیرونی کمانڈ چلائی جائے۔

[source,kotlin]

پیکیج com.yourpackage

import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import java.io.File

abstract class OpenTestReportTask : DefaultTask() {

----
----
----
----
init {
    group = "verification"
    description = "Opens a test report in Firefox."
    dependsOn("check") // Assure que les rapports sont générés
}

@get:Input
abstract var reportPath: String

@TaskAction
fun openReport() {
    val separator = File.separator
    val reportFile = project.layout.projectDirectory.asFile.toPath()
        .resolve(reportPath.replace("/", separator))
        .toAbsolutePath()
        .toFile()

    if (!reportFile.exists()) {
        logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.")
        return
    }

    project.exec {
        commandLine("firefox", "--new-tab", reportFile.absolutePath)
    }
    logger.lifecycle("Opened test report: ${reportFile.absolutePath}")
}
----

## }

\=== ملموس تنفیذ

اس کلاسوں abstrait taske سے وراثت لیتی ہیں اور رپورٹ کے مخصوص راستے کا تعین کرتی ہیں۔

## [source,kotlin]

پیکیج com.yourpackage

abstract class ReportUnitTestsTask : OpenTestReportTask() { شروع { Firefox میں یونٹ ٹیسٹ رپورٹ کھلتا ہے reportPath = "build/reports/tests/test/index.html } }

پیکج com.yourpackage

## abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = "فیرفاکس میں فائنکشنل ٹیسٹ رپورٹ کھولتا ہے۔" reportPath = "build/reports/tests/functionalTest/index.html" } }

\=== کاموں کا ریکارڈنگ

میں`build.gradle.kts`آپ کے اصلی project :

## [source,kotlin]

tasks.register\<com.yourpackage.ReportUnitTestsTask\>("reportTests") {} tasks.register\<com.yourpackage.ReportFunctionalTestsTask\>("reportFunctionalTests") {}

\=== رپورٹ کے کاموں کا UML ڈائگرام (PlantUML کوڈ)

نیچے دیے گئے کوڈ کو کپی کریں اور PlantUML کو سپورٹ کرنے वाले ٹول میں پیسٹ کریں۔

## [source,plantuml]

@startuml skinparam خط دست true skinparam ایک رنگ sach

ابسٹریکٹ کلاس DefaultTask { }

ابسٹریکٹ کلاس Exec { \+ commandLine(args: String...) \+ exec() }

اب کلاس OpenTestReportTask DefaultTask کی وراثت کرتا ہے { \+ گروپ: سٹرنگ = "تصدیق \+ تفصیل: سٹرنگ \+ منصر ہے("check") + mere? I'm done. + openReport() : void }

ابسٹریکٹ کلاس AbstractJbakeExecTask Exec سے extend کرتی ہے { \+ group: String = "تصدیق \+ توضیح: String \+ dependsOn("check") \+ abstract reportRelativePath: String \+ exec() : void }

class ReportUnitTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/test/index.html }

class ReportFunctionalTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/functionalTest/index.html }

کلاس ReportJbakeTestsTask امداد AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/test/index.html }

class ReportJbakeFunctionalTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/functionalTest/index.html }

OpenTestReportTask \<-- ReportUnitTestsTask OpenTestReportTask \<-- ReportFunctionalTestsTask

AbstractJbakeExecTask \<-- ReportJbakeTestsTask AbstractJbakeExecTask \<-- ReportJbakeFunctionalTestsTask

DefaultTask \<|-- OpenTestReportTask Exec \<|-- AbstractJbakeExecTask DefaultTask \<|-- Exec

## @enduml

\== ابстраکٹ ٹاسک`AbstractJbakeExecTask`(وراثت میں`Exec`)

اگر آپ کا کام صرف ایک با buharā command کو متغیر آرگیومینڈز کے ساتھ چلانے پر مشتمل ہو، تو اس سے مستقیماً وراثت لین**اےکسیک**ζeta

## [source,kotlin]

package com.yourpackage

import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import java.io.File

abstract class AbstractJbakeExecTask : Exec() {

----

init { group = "verification" description = "Opens a Jbake project report in Firefox." dependsOn("check") }

@get:Input abstract var reportRelativePath: String

override fun exec() { val separator = File.separator val reportFile = project.layout.projectDirectory.asFile.toPath() .resolve(reportRelativePath.replace("/", separator)) .toAbsolutePath() .toFile()

if (!reportFile.exists()) { logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.") return }

commandLine("firefox", "--new-tab", reportFile.absolutePath) logger.lifecycle("Attempting to open report: ${reportFile.absolutePath}") super.exec() // Appelle la méthode exec() de la super-classe Exec }

## }

\=== ملموس تطبيق کے لیے`Exec`

## [source,kotlin]

پیکج com.yourpackage

خالص کلاس ReportJbakeTestsTask : خالص JbakeExecTask() init { Firefox میں Jbake یونٹ ٹیسٹ رپورٹ کھلتا ہے. reportRelativePath = "build/reports/tests/test/index.html } }

پیکج com.yourpackage

abstract class ReportJbakeFunctionalTestsTask : AbstractJbakeExecTask() { init { description = "فائر فاکس میں فنگیشنل ٹیسٹ رپورٹ کھولتا ہے۔" reportRelativePath = "build/reports/tests/functionalTest/index.html" } }

\== ٹاسکس کی واضحیت`buildSrc`

آپ جو کام اور کلاسیں تعريف کرتے ہیں میں**buildSrc**ہیں :

***دیکھنے میں مرئی اور استعمال کرنے کے قابل**آپ کے بنیادی build کے تمام پروژکس (جڑ اور زیر‑پروجیکٹس). اس لیے آپ استعمال کر سکتے ہیں`com.yourpackage.ReportUnitTestsTask`میں`allprojects { ... }`. (empty)**غیر قابل اجرا**مستقیم طور پر buildSrc کی ٹاسکوں (مثلاً,`gradle :buildSrc:reportTests`إذا کام مخصوص طور پر ریکارڈ نہ کیا گیا تو یہ کام نہیں چلے گا`buildSrc/build.gradle.kts`).`buildSrc`یہ کمپائلنگ ماڈیول ہے، قابلِ 실행 تطبيق ماڈیول نہیں،ان مقامی بنیادی构建 کے کاموں کے لیے۔

\=== ٹیسٹس کے لیے ایک رپورٹ چلاؤ`buildSrc`خود

Si `buildSrc`اس کے اندر自己 کے ٹیسٹس ہیں اور یہ رپورٹس بناتا ہے؛ آپ ایک رپورٹ کا کام (یا ٹاسک) کو صرف میں ریکارڈ کر سکتے ہیں`buildSrc/build.gradle.kts`:

## [source,kotlin]

پلاگ‑ینز { `kotlin-jvm` }

ریپوزٹرز { mavenCentral() }

tasks.withType\<Test\> { useJUnitPlatform() reports.html.outputLocation.set(layout.buildDirectory.dir("reports/tests")) }

import com.yourpackage.ReportJbakeTestsTask // اپنی ٹاسک کلاس درآمد کریں

tasks.register<ReportJbakeTestsTask>("reportBuildSrcTests") { // المسار معرف مسبقًا في الفئة، سيشير إلى تقارير buildSrc }

آپ پھر نافذ کر سکتے ہو گے :`./gradlew :buildSrc:test`کے بعد`./gradlew :buildSrc:reportBuildSrcTests`.

ان طریقوں کو اپنائے، تو آپ Kotlin DSL میں Gradle بنائیں گے جو نہ صرف طاقتور ہوں گے بلکہ انتہائی ماڈیولر، مرمت پذیر اور سمجھنے میں آسانی سے قابلِ فہم بھی ہوں گے۔
----

## }

\=== ٹھوس نفاذ (Concrete Implementations)

یہ کلاسز تجریدی ٹاسک (abstract task) سے ورثہ کرتی ہیں اور رپورٹ کا مخصوص راستہ (specific path) متعین کرتی ہیں۔

## [ذریعہ,kotlin]

package com.yourpackage

abstract class ReportUnitTestsTask : OpenTestReportTask() { init { description = "Firefox میں یونٹ ٹیسٹ رپورٹ کھولتا ہے۔ reportPath = "build/reports/tests/test/index.html } }

package com.yourpackage

## abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = "Firefox میں فنکشنل ٹیسٹ رپورٹ کھولتا ہے۔" reportPath = "build/reports/tests/functionalTest/index.html" } }

\=== ٹاسک کی رجسٹریشن

میں`build.gradle.kts`آپ کے روٹ پروجیکٹ کے:

## [source,kotlin]

## tasks.register\<com.yourpackage.ReportUnitTestsTask\>("reportTests") {} tasks.register\<com.yourpackage.ReportFunctionalTestsTask\>("reportFunctionalTests") {}

\=== رپورٹ کے ٹاسک کا UML ڈایاگرام (Code PlantUML)

نیچے دیا گیا کوڈ کاپی کریں اور اسے PlantUML کو سپورٹ کرنے والے ٹول میں پیسٹ کریں۔

## [سورس,plantuml]

@startuml skinparam handwritten true skinparam monochrome true

abstract class DefaultTask { }

abstract class Exec { \+ commandLine(args: String...) \+ exec() }

abstract class OpenTestReportTask extends DefaultTask { \+ group: String = "verification \+ description: String \+ dependsOn("check") پر منحصر ہے \+ abstract reportPath: String \+ openReport() : void }

abstract class AbstractJbakeExecTask extends Exec { \+ group: String = "verification \+ description: String \+ dependsOn("check") \+ abstract reportRelativePath: String \+ exec() : void }

class ReportUnitTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/test/index.html }

class ReportFunctionalTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/functionalTest/index.html }

class ReportJbakeTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/test/index.html }

class ReportJbakeFunctionalTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/functionalTest/index.html }

OpenTestReportTask \<-- ReportUnitTestsTask OpenTestReportTask \<-- ReportFunctionalTestsTask

AbstractJbakeExecTask \<-- ReportJbakeTestsTask AbstractJbakeExecTask \<-- ReportJbakeFunctionalTestsTask

DefaultTask \<|-- OpenTestReportTask Exec \<|-- AbstractJbakeExecTask DefaultTask \<|-- Exec

## @enduml

\== تجریدی کام`AbstractJbakeExecTask`(وراثت میں ملا ہوا`Exec`)

اگر آپ کا کام بنیادی طور پر متغیر دلائل کے ساتھ ایک بیرونی کمانڈ چلانے تک محدود ہے، تو براہ راست اس سے وراثت لیں**ایگزیک (Exec)**زیادہ براہ راست ہے۔

## [ذریعہ,kotlin]

package com.yourpackage

import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import java.io.File

abstract class AbstractJbakeExecTask : Exec() {

----

init { group = "verification" description = "Opens a Jbake project report in Firefox." dependsOn("check") }

@get:Input abstract var reportRelativePath: String

override fun exec() { val separator = File.separator val reportFile = project.layout.projectDirectory.asFile.toPath() .resolve(reportRelativePath.replace("/", separator)) .toAbsolutePath() .toFile()

if (!reportFile.exists()) { logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.") return }

commandLine("firefox", "--new-tab", reportFile.absolutePath) logger.lifecycle("Attempting to open report: ${reportFile.absolutePath}") super.exec() // Appelle la méthode exec() de la super-classe Exec }

## }

\=== کے لیے ٹھوس نفاذ (Concrete Implementations)`Exec`

## [ماخذ,kotlin]

package com.yourpackage

abstract class ReportJbakeTestsTask : AbstractJbakeExecTask() { init { description = "Firefox میں Jbake یونٹ ٹیسٹ رپورٹ کھولتا ہے۔ reportRelativePath = "build/reports/tests/test/index.html } }

package com.yourpackage

## abstract class ReportJbakeFunctionalTestsTask : AbstractJbakeExecTask() { init { description = "Opens the functional test report in Firefox." reportRelativePath = "build/reports/tests/functionalTest/index.html" } }

\== ٹاسک کی نمایاںگی (Visibilité des Tâches)`buildSrc`

ٹاسک اور کلاسز جو آپ اس میں بیان کرتے ہیں**buildSrc**ہیں:

آپ ایک پیشہ ور مترجم ہیں۔ فرانسیسی سے اردو میں ترجمہ کریں۔ تمام بیکٹک کوڈ اسپینز (`...`) کو بالکل ویسے ہی محفوظ رکھیں — بیکٹک مواد، سپیسنگ، یا پوزیشن میں کبھی تبدیلی نہ کریں۔ یہ متن ایک بڑے جملے کا جزو ہو سکتا ہے — مزید سیاق و سباق طلب کیے بغیر اس جزو کا ترجمہ کریں۔ صرف ترجمہ شدہ متن فراہم کریں — کوئی وضاحت، کوئی تبصرہ، کوئی تعارف، کوئی متبادل، کوئی آپشن نہیں۔**قابلِ دید اور قابلِ استعمال**آپ کے مین بلڈ (روٹ اور سب-پروجیکٹس) کے تمام پراجیکٹس کے ذریعے ہے۔ اسی لیے آپ استعمال کر سکتے ہیں`com.yourpackage.ReportUnitTestsTask`میں`allprojects { ... }`آپ ایک پیشہ ور مترجم ہیں۔ فرانسیسی سے اردو میں ترجمہ کریں۔ تمام بیک ٹِک کوڈ سپینز (`...`) کو بالکل ویسے ہی محفوظ رکھیں — بیک ٹِک کے مواد، سپیسنگ، یا پوزیشن میں کبھی تبدیلی نہ کریں۔ یہ متن ایک بڑے جملے کا حصہ ہو سکتا ہے — مزید سیاق و سباق طلب کیے بغیر اس ٹکڑے کا ترجمہ کریں۔ صرف ترجمہ شدہ متن فراہم کریں — کوئی وضاحت، کوئی تبصرہ، کوئی تعارف، کوئی متبادل، یا کوئی آپشن نہ دیں۔ براہ کرم اپنی زبان منتخب کریں اور `Start` پر کلک کریں۔**غیر قابلِ اجرا (Non-executables)**براہ راست buildSrc کے ٹاسکس کے طور پر (مثلاً،`gradle :buildSrc:reportTests`کام نہیں کرے گا اگر ٹاسک خاص طور پر `...` میں محفوظ نہیں ہے`buildSrc/build.gradle.kts`).`buildSrc`ایک کمپائلیشن ماڈیول ہے، نہ کہ ان مین بلڈ ٹاسکس کے لیے ایک ایگزیکیوٹیبل ایپلیکیشن ماڈیول۔

... کے ٹیسٹ کے لیے رپورٹ چلائیں`buildSrc`وہ خود

Si `buildSrc`اپنے ٹیسٹوں اور رپورٹیں تیار کرتا ہے، آپ رپورٹ کے ٹاسک کو براہ راست محفوظ کر سکتے ہیں`buildSrc/build.gradle.kts`آپ ایک پیشہ ور مترجم ہیں۔ فرانسیسی سے اردو میں ترجمہ کریں۔ تمام بیک ٹِک کوڈ اسپینز (`...`) کو بالکل ویسے ہی محفوظ رکھیں — بیک ٹِک کے مواد، سپیسنگ یا پوزیشن میں کبھی تبدیلی نہ کریں۔ یہ متن کسی بڑے جملے کا ایک حصہ ہو سکتا ہے — مزید سیاق و سباق کی درخواست کیے بغیر اس حصے کا ترجمہ کریں۔ صرف ترجمہ شدہ متن فراہم کریں — کوئی وضاحت، کوئی تبصرہ، کوئی تعارف، کوئی متبادل یا کوئی آپشن نہیں ہونا چاہیے۔

## [source,kotlin]

plugins { `kotlin-jvm` }

repositories { mavenCentral() }

tasks.withType\<Test\> { useJUnitPlatform() reports.html.outputLocation.set(layout.buildDirectory.dir("reports/tests")) }

import com.yourpackage.ReportJbakeTestsTask // اپنی ٹاسک کلاس امپورٹ کریں

## tasks.register\<ReportJbakeTestsTask\>("reportBuildSrcTests") { // راستہ پہلے ہی کلاس میں بیان کیا گیا ہے، یہ buildSrc کی رپورٹس کی طرف اشارہ کرے گا }

اس کے بعد آپ چلا سکتے ہیں:`./gradlew :buildSrc:test`کے بعد`./gradlew :buildSrc:reportBuildSrcTests`آپ ایک پیشہ ور مترجم ہیں۔ فرانسیسی سے اردو میں ترجمہ کریں۔ تمام بیک ٹِک کوڈ اسپینز (`...`) کو بالکل ویسا ہی رکھیں جیسا کہ وہ ہیں — بیک ٹِک کے مواد، اسپیسنگ یا پوزیشن میں کبھی تبدیلی نہ کریں۔ یہ متن ایک بڑے جملے کا حصہ ہو سکتا ہے — مزید سیاق و سباق طلب کیے بغیر اس ٹکڑے کا ترجمہ کریں۔ صرف ترجمہ شدہ متن فراہم کریں — کوئی وضاحت، کوئی تبصرہ، کوئی تعارف، کوئی متبادل یا کوئی آپشن نہیں ہونا چاہیے۔

ان طریقوں کو اپنا کر، آپ Kotlin DSL میں ایسے Gradle بلڈ سسٹم بنائیں گے جو نہ صرف طاقتور ہوں گے، بلکہ ناقابلِ یقین حد تک ماڈیولر، قابلِ دیکھ بھال اور سمجھنے میں آسان بھی ہوں گے۔

متعلقہ مضامین