Table des matières

প্রেক্ষাপট এবং উদ্দেশ্য

শুরুর বিন্দু

প্রকল্প`slider-gradle`Reveal.js প্রেজেন্টেশন AsciiDoc ফাইল থেকে Gradle প্লাগ এর মাধ্যমে তাইর করে`org.asciidoctor.jvm.revealjs`. প্রধান কাজের কনফিগারেশন`asciidoctorRevealJs`সরাসরি বিল্ডস্ক্রিপ্টের রুটে থাকতেছিল`build.gradle.kts`:

plugins { id("org.asciidoctor.jvm.revealjs") }

apply<slides.SlidesPlugin>()

project.tasks.getByName<AsciidoctorJRevealJSTask>(TASK_ASCIIDOCTOR_REVEALJS) {
    repositories { ruby { gems() } }
    revealjs {
        version = "3.1.0"
        templateGitHub {
            setOrganisation("hakimel")
            setRepository("reveal.js")
            setTag("3.9.1")
        }
    }
    revealjsOptions {
        // ... configuration complète
    }
}

লক্ষ্য

এই পুরো কনফিগারেশনকে`buildSrc/src/main/kotlin/slides/SlidesPlugin.kt`যাতে গ্রাহক বিল্ডসক্রিপ্টটি নিম্নে সীমিত হয়:

apply<slides.SlidesPlugin>()

প্লাগইনকে সম্পূর্ণরূপে স্বতন্ত্র হওয়া দরকার:它嫩え自己でそのプラグインの依存関係を適用し、リポジトリを設定し、Ruby の gems を管理します。

প্রথম বাধা: `ruby { gems() }

গ্রুভি সিনট্যাক্সিক চিনি যা গোপন করে

লাইন`repositories { ruby { gems() } }`একটি Groovy DSL এক্সটেনশন শুধুমাত্র buildscript-এর নিষ্পাদন Context-এ উপলব্ধ। একটি স্ট্যাটিক Kotlin API নয় যা buildSrc থেকে অ্যাক্সেসযোগ্য।

এটি ডাক করার চেষ্টায়`SlidesPlugin.kt`, কম্পাইলিং তৎক্ষণিকভাবে ব্যর্থ হয়।

যান্ত্রিক মেকানিজ্মের বিশ্লেষণ

Gradle ক্যাশ বিশ্লেষণের পর (~/.gradle/caches/modules-2/files-2.1/rubygems/), আমরা ফাইলে খুঁজে পাই`ivy-3.1.0.xml`:

<artifact type='gem' url='https://rubygems.org/gems/asciidoctor-revealjs-3.1.0.gem' />

`ruby { gems() }`আসলে করত ছিলতিনটি আলাদা অপারেশন:

  1. একটি আইভি রিপো সংরক্ষণ করুন যা নির্দেশ করে`https://rubygems.org/gems/`

  2. গ্রুপটি বাদ দিন`rubygems`মাভেন রিপোজিটরি çatকত্যা এড়াতে

  3. কনফিগারেশনে জেম সংরক্ষণ করুন`asciidoctorGems`python

print("��</tool_call> JRuby এটিকে লোড করে রানটাইমে")

এই তিনটি দায়িত্বকে Kotlin-এ পৃথকভাবে পুনরুত্পাদন করা উচিত।

তিন অংশের সমাধান

ভাগ ১ : Ivy রেপো রুবিজেমসের জন্য

project.repositories.mavenCentral() {
    content { excludeGroup("rubygems") }
}
project.repositories.ivy {
    url = project.uri("https://rubygems.org/gems/")
    patternLayout { artifact("[module]-[revision].gem") } (1)
    metadataSources { artifact() }
    content { includeGroup("rubygems") }
}
1 এক্সটেনশন`.gem`এটিকে hardcode করা উচিত।[ext]`ডিফল্টে সমাধান করে.jar`, যা একটি ত্রুটি তৈরি করে`Resource missing`.
Ivy রেপো সরাসরি ঘোষণা করা হয়েছে`project.repositories`এবং ব্লকে না`repositories { }`কারণ এই ব্লকের রিসিভারটি …​`RepositoryHandler`Gradle-এর স্ট্যান্ডার্ড কিন্তু একটি grolifant API এক্সটেনশনের সাথে অসঙ্গত`ivy`কটলিন ডিএসএল।

অংশ ২ : asciidoctorGems-এর নির্ভরতা

প্লাগইনটি`org.asciidoctor.jvm.gems`প্রথমে প্রয়োগ করা দরকার — এটি কনফিগারেশন তৈরি করে`asciidoctorGems`এবং কাজ`asciidoctorGemsPrepare`:

project.plugins.apply("org.asciidoctor.jvm.gems")
project.plugins.apply("org.asciidoctor.jvm.revealjs") (1)

project.dependencies {
    add("asciidoctorGems", "rubygems:asciidoctor-revealjs:3.1.0@gem") (2)
}
1 প্রয়োগের ক্রম গুরুত্বপূর্ণ :`gems`আগে`revealjs`. <2> বিশেষণ`@gem`নির্ভরতায় সঠিক এক্সটেনশন প্রযোজ্য করুন।

অংশ ৩: settings.gradle.kts

`dependencyResolutionManagement`মধ্যে`settings.gradle.kts`প্রকল্পগুলোকে নিজের নিজের সংগ্রহস্থল ঘোষণা করতে অনুমতি দিতে হবে :

@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
}

এই লাইন না থাকলে, Gradle প্লাগিনে ঘোষিত রেপোজিটারিগুলো উপেক্ষা করে এবং জেম্স সমাধান ব্যর্থ হয়।

API এর বাইটকোডের মাধ্যমে আত্ম-পরীক্ষণ

কেন javap ?

প্লাগইনটি`asciidoctor-gradle-jvm-slides`একটি সংস্করণে আছে`4.0.0-alpha.1`. এর নথি অস্তিত্বহীন অথবা অসম্পূর্ণ। একমাত্র বিশ্বাসযোগ্য উৎস হল সংকলিত ক্লাসের সরাসরি পরীক্ষণ।

টাস্কের হেরার্কি

javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.slides.AsciidoctorJRevealJSTask

ফল :

public class AsciidoctorJRevealJSTask
  extends org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask
  implements org.asciidoctor.gradle.base.slides.SlidesToExportAware

অনুসন্ধান `forkOptions

পরীক্ষণ কর dabei`AbstractAsciidoctorTask`:

javap -p -classpath asciidoctor-gradle-jvm-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask | grep -i "fork\|exec\|jvm"

পাওয়া যায়:

final org.ysb33r.grolifant.api.v4.JavaForkOptions javaForkOptions;
public void forkOptions(org.gradle.api.Action<org.ysb33r.grolifant.api.v4.JavaForkOptions>);
public static final org.asciidoctor.gradle.base.process.ProcessMode JAVA_EXEC;

JavaForkOptions এর API (grolifant)

`javaLauncher`এই কাজে মजूद নেই. বাস্তব API এর`org.ysb33r.grolifant.api.v4.JavaForkOptions`প্রকাশ :

public void executable(java.lang.Object);  (1)
public void setExecutable(java.lang.Object);
1 এই পদ্ধতি`executable(Object)`আসাইনমেন্টটি প্রতিস্থাপন করুন`executable = …​`কম্পাইল হয় না (`val`পরিবর্তন করা Jaya না).

RevealJS এক্সটেনশন

`revealjs { }`এটি কোনো কাজের পদ্ধতি নয়, বরং একটিপ্রকল্পের বিস্তার:

javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
  org.asciidoctor.gradle.jvm.slides.RevealJSExtension

এটি মধ্যমে অ্যাক্সেস করা যায় :

project.extensions.getByType<RevealJSExtension>().apply {
    version = "3.1.0"
    templateGitHub {
        setOrganisation("hakimel")
        setRepository("reveal.js")
        setTag("3.9.1")
    }
}

জাভা টুলচেইন কনফিগারেশন

JavaToolchainService এর সমস্যা

`JavaToolchainService`এটি কোন প্রকল্পের এক্সটেনশন নয়. নিম্নলিখিত কল ব্যর্থ হয়:

// ERREUR : Extension of type 'JavaToolchainService' does not exist
project.extensions.getByType<JavaToolchainService>()

ভালো APIটা`serviceOf`:

import org.gradle.kotlin.dsl.support.serviceOf

project.tasks.getByName<AsciidoctorJRevealJSTask>(TASK_ASCIIDOCTOR_REVEALJS) {
    setInProcess("JAVA_EXEC")
    forkOptions {
        executable(
            project.serviceOf<JavaToolchainService>()
                .launcherFor {
                    languageVersion.set(JavaLanguageVersion.of(17))
                    vendor.set(JvmVendorSpec.ADOPTIUM)
                }
                .get()
                .executablePath
                .asFile
                .absolutePath
        )
    }
}

ডকারের স্বয়ংক্রিয় শনাক্ত

প্রেক্ষাপট

Asciidoctor/JRuby প্লাগইন Java 17 দরকার। buildSrc-এ Kotlin 2.0.x Java 25 সমর্থন করে না (ভার্সন পার্সার ক্র্যাশ হয় উপর`"25.0.2"`) অতএব, Gradle ডেমনকে Java 17-এ চালানো উচিত অথবা Docker ব্যবহার করা উচিত।

কৌশল

  1. Docker disponible → exécution via container eclipse-temurin:17(ডিফল্ট আচরণ)

  2. ডকার অনুপস্থিত + Java 17 → স্থানীয় নিষ্পাদন

  3. Docker অনুপস্থিত + Java > 17 → স্পষ্ট ত্রুটি

val isDockerAvailable = try {
    Runtime.getRuntime().exec(arrayOf("docker", "info")).waitFor() == 0
} catch (e: Exception) {
    false
}

val javaVersion = JavaVersion.current().majorVersion.toInt()

when {
    isDockerAvailable -> project.tasks.register<Exec>(TASK_ASCIIDOCTOR_REVEALJS) {
        group = GROUP_TASK_SLIDER
        description = "Slider settings and generation (via Docker)"
        dependsOn(TASK_CLEAN_SLIDES_BUILD)
        finalizedBy(TASK_DASHBOARD_SLIDES_BUILD)
        commandLine(
            "docker", "run", "--rm",
            "-v", "${project.rootDir.absolutePath}:/workspace",
            "-v", "${System.getProperty("user.home")}/.gradle:/root/.gradle",
            "-w", "/workspace",
            "eclipse-temurin:17",
            "./gradlew", TASK_ASCIIDOCTOR_REVEALJS
        )
        workingDir = project.rootDir
    }
    javaVersion == 17 -> {
        project.repositories.mavenCentral() {
            content { excludeGroup("rubygems") }
        }
        project.repositories.ivy {
            url = project.uri("https://rubygems.org/gems/")
            patternLayout { artifact("[module]-[revision].gem") }
            metadataSources { artifact() }
            content { includeGroup("rubygems") }
        }
        project.extensions.getByType<RevealJSExtension>().apply {
            version = "3.1.0"
            templateGitHub {
                setOrganisation("hakimel")
                setRepository("reveal.js")
                setTag("3.9.1")
            }
        }
        project.tasks.getByName<AsciidoctorJRevealJSTask>(TASK_ASCIIDOCTOR_REVEALJS) {
            setInProcess("JAVA_EXEC")
            forkOptions {
                executable(
                    project.serviceOf<JavaToolchainService>()
                        .launcherFor {
                            languageVersion.set(JavaLanguageVersion.of(17))
                            vendor.set(JvmVendorSpec.ADOPTIUM)
                        }
                        .get()
                        .executablePath
                        .asFile
                        .absolutePath
                )
            }
            // ... reste de la configuration
        }
    }
    else -> error(
        "Docker est requis pour exécuter $TASK_ASCIIDOCTOR_REVEALJS " +
        "avec Java $javaVersion. Installez Docker ou utilisez Java 17."
    )
}

অন্তিম ফল

ব্যবহারকারী বিল্ডসক্রিপ্ট

apply<slides.SlidesPlugin>()

এইটাই। প্লগইন সম্পূর্ণ দায়িত্ব বহন করে।

settings.gradle.kts

pluginManagement {
    repositories {
        mavenLocal()
        gradlePluginPortal()
    }
}

plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
}

rootProject.name = "slider-gradle"

ফাঁস এবং সমাধানের সারাংশ

সমস্যা কারণ সমাধান

`ruby { gems() }`Kotlin-এ উপলব্ধ নয়

শুধুমাত্র Groovy DSL এক্সটেনশন

তিনটি আলাদা প্রণালী : repo Ivy + বর্জন Maven +asciidoctorGems

Gradle একটি খোঁজ করছে`.jar`একের পরিবর্তে`.gem`

`[ext]`এই সমাধান করে`jar`ডিফল্ট

হার্ডকোডার`.gem`আইভি প্যাটার্নেতে + বিশেষণ`@gem`

ivy { }`কম্পাইল হয় না`repositories { }

Receiver grolifant DSL Kotlin-এ অযোগ্য

সরাসরি কল`project.repositories.ivy { }`

`javaLauncher`অসমাধান

সুইতে না থাকা সম্পত্তি`AsciidoctorJRevealJSTask`

setInProcess("JAVA_EXEC")+forkOptions { executable(…​) }

`executable = …​`কম্পাইল হয় না

সম্পত্তি`val`ভিতরে`JavaForkOptions`গ্রোলিফান্ত

পদ্ধতি`executable(Object)`জায়গায়

JavaToolchainService`অনুবলব্ধ দ্বারা`extensions

এটি একটি Gradle পরিষেবা, এক্সটেনশন নয়।

project.serviceOf<JavaToolchainService>()

`revealjs { }`কর্মে সমাধানকৃত নয়

প্রকল্পের_বিস্তৃতি, কাজের পদ্ধতি না

project.extensions.getByType<RevealJSExtension>()

জাভা ২৫ দিয়ে বিল্ড crash হয়

Kotlin 2.0.x দুই অঙ্কের Java সংস্করণ parse করে না

স্বয়ংক্রিয় ডকার ডিটেকশন + ফallback জাভা ১৭

অনুসন্ধানের পদ্ধতি : জাভাপ দিয়ে অজানা একটি API পড়া

নীতি

যদি ডকুমেন্টেশন অনুপস্থিত বা অসম্পূর্ণ হয়, তবে বাইটকোডগুলি সত্যের উৎস। javap`এইটি JDK-এ স্ট্যান্ডার্ড টুল যা ফাইলগুলোকে ডিকম্পাইল করে.class`পড়া যায় এমন জাভা স্বাক্ষর, কোড সোর্স প্রয়োজন ছাড়াই.

ধাপ ১: গ্রেডল ক্যাশে মধ্যে jar ফাইলটি খুঁজুন

গ্রেডল তার সব নির্ভরতা ডাউনলোড করে মাঝে`~/.gradle/caches/modules-2/files-2.1/`. প্রথম ধাপ হলো যে জারটি পরিদর্শন করতে দরকারি ক্লাসটিকে ধারণ করেছে তা খুঁজে বের করা।

find ~/.gradle/caches -name "asciidoctor-gradle-jvm-slides*.jar" 2>/dev/null
fল :
/home/user/.gradle/caches/modules-2/files-2.1/org.asciidoctor/
asciidoctor-gradle-jvm-slides/4.0.0-alpha.1/.../
asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar

ধাপ 2: জারের ক্লাসগুলো তালিকা করা

একটি ক্লাসকে পরিদর্শনের আগে, আমরা যাচাই করি যে সেটি জারে সঠিকভাবে উপস্থিত আছে:

jar tf asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar | grep -i "RevealJS\|revealjs"

ধাপ ৩ : একটি শ্রেণি পরীক্ষা করুন

এটি সব উপলব্ধ শ্রেণী দেখায় : AsciidoctorJRevealJSTask, RevealJSExtension, RevealJSOptions, এটসেটরা
javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.slides.AsciidoctorJRevealJSTask

বিকল্প`-p`ব্যক্তিগত সদস্যদেরও অন্তর্ভুক্ত করে সব সদস্য দেখায় ফলাফল তৎক্ষণিকভাবে মূল লাইন দেখায়:

public class AsciidoctorJRevealJSTask
extends org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask

ধাপ ৪ : শ্রেণীবিন্যাসে উঠা

কাজটি প্রসারিত করে`AbstractAsciidoctorTask`. এটি অনুক্রমে পরীক্ষা করা হয় প্রথমে তার জারটি লোকালাইজ করলে :

find ~/.gradle/caches -name "asciidoctor-gradle-jvm-[0-9]*.jar" 2>/dev/null

javap -p -classpath asciidoctor-gradle-jvm-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask | grep -i "fork\|exec\|jvm\|java"

এখানেই আমরা আবিষ্কার করি`forkOptions`, JAVA_EXEC, et javaForkOptions প্রকারের`org.ysb33r.grolifant.api.v4.JavaForkOptions`.

ধাপ 5 : অজানা ধরনগুলো অনুসরণ করুন

`JavaForkOptions`একটি অজানা grolifant শ্রেণি। আমরা তার jar :

find ~/.gradle/caches -name "grolifant*.jar" 2>/dev/null

তারপর এটিকে পরিদর্শন করা Hoy :

javap -p -classpath grolifant40-legacy-api-2.0.0-alpha.6.jar \
org.ysb33r.grolifant.api.v4.JavaForkOptions

এখানে পাওয়া যায়`executable(java.lang.Object)— আহ্বানের সঠিক পদ্ধতি, বিপরীতভাবে`executable = …​`যা কম্পাইল হয় না কারণ এটি একটি প্রপার্টি`val.

ধাপ ৬: প্রকল্পের এক্সটেনশন যাচাই করুন

জন্য`revealjs { }`, প্রশ্ন ছিল : এটি কি একটি কাজের পদ্ধতি অথবা একটি প্রজেক্টের এক্সটেনশন ? পরিদর্শন`AsciidoctorJRevealJSTask` কোনো পদ্ধতি দেখায় না`revealjs`. তখন আমরা পরিদর্শন করি`RevealJSExtension`:

javap -p -classpath asciidoctor-gradle-jvm-slides-4.0.0-alpha.1.jar \
org.asciidoctor.gradle.jvm.slides.RevealJSExtension | head -5
public class RevealJSExtension implements groovy.lang.GroovyObject {
public static final java.lang.String NAME;

উপস্থিতির`NAME`যা নিশ্চিত করে যে এটি প্রকল্পে নিবন্ধিত একটি এক্সটেনশন, প্রবেশযোগ্য মাধ্যমে`project.extensions.getByType<RevealJSExtension>()`.

পদ্ধতির সারাংশ

একটি ধাপ কর্ম

1

find ~/.gradle/caches -name "*.jar"— জার খুঁজে বের করা

2

jar tf jar.jar | grep NomClasse— নিশ্চিত করুন যে শ্রেণি বিদ্যমান আছে

3

javap -p -classpath jar.jar NomCompletClasse— ক্লাসটি পরিদর্শন করুন

4

শনাক্তকারী`extends`এবং শ্রেণি উঠা

5

অজানা টাইপগুলোকে তাদের নিজস্ব জারে অনুসরণ করুন

6

খুঁ�া করা`NAME`প্রকল্পের এক্সটেনশন চিহ্নিত করতে

এই পদ্ধতি ডকুমেন্ট করা হয়নি এমন যেকোনো Gradle প্লাগিনের API-এর জন্য প্রযোজ্য। অথবা যেটির অ্যালফা সংস্করণ বর্তমান ডকুমেন্টেশনের সাথে মেলে না।

আগামী ধাপ

এই buildSrc প্লাগিনটি স্বাধীন প্রকল্পে নিষ্কাশন করা হবে যা Gradle Plugin Portal বা Maven Local-এ প্রকাশিত। উপভোক্তা বিল্ড স্ক্রিপ্ট তখন :

plugins { id("slides") version "1.0.0" }

Et settings.gradle.kts`তার সর্বনিম্নে হ্রাস করা হবে যাতে কোনো উল্লেখ চেয়ে`foojay-resolver-convention, JDK-এর প্রোভিশনিং প্লাগইন নিজেই পরিচালিত হয় বা পূর্বশর্ত হিসেবে নথিভুক্ত।

Articles connexes