Зависимости, специфичные для плагина Gradle

Я хочу реализовать плагин с дополнительными зависимостями, предоставляемыми пользователем, например, как некоторые плагины Gradle, которые позволяют:

dependencies {
    // ...
    dokkaPlugin(libs.dokka.versioning.plugin)
}

Мне удалось создать configuration в проекте с именем myPlugin:

val config = project.configurations.create("myPlugin")

Итак, теперь в клиентских проектах, использующих мой плагин, я могу делать:

dependencies {
    myPlugin("com.example:example:1.0.0")
}

Вопрос в том, как применить мою конфигурацию для запуска некоторого Java-кода с путем к классам, содержащим myPlugin зависимости?

Вот еще код для контекста:

class MyPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        val extension = project.extensions.create<MyPluginExtension>("myPlugin")
        val config = project.configurations.create("myPlugin")

        val task = project.tasks.register<MyTask>("myTask") {
            // ...
        }
    }
}

class MyTask : DefaultTask() {
    @TaskAction
    fun execute() {
        val config = project.configurations.getByName("myPlugin")
        // How to run some java code using this config?
    }
}

Я понимаю, что во время компиляции моего плагина эти клиентские зависимости не будут доступны, поэтому я не смогу использовать классы из com.example:example напрямую. Но я все еще хочу создать несколько экземпляров с помощью отражения или получить их с помощью ServiceLoader API.

Gradle за прокси-сервером
Gradle за прокси-сервером
Создайте проект Gradle под сетевым прокси.
"DevOps: Jenkins & AWS Series, часть 5: Установка Gradle на Ubuntu 22.04
"DevOps: Jenkins & AWS Series, часть 5: Установка Gradle на Ubuntu 22.04
В этой статье блога мы проведем вас через процесс установки Gradle на Ubuntu 22.04, интеграции его с Jenkins и создания задания Gradle. Мы...
0
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Configuration расширяет FileCollection, то есть является оберткой группы файлов. Вы можете разрешить эту конфигурацию, когда будете готовы, и добавить ее в путь к классам.

Запуск как отдельной программы Java

В Gradle есть встроенная задача JavaExec, которую вы можете использовать для создания собственных задач, выполняющих программы Java.

Таким образом, вы можете зарегистрировать новую задачу и настроить ее со всеми теми же элементами, которые вы бы добавили, как если бы вы запускали команду java из командной строки:

tasks.register<JavaExec>("myRunTask") {
    args("something the program needs to know")
    classpath(
        theJarsWithTheCompiledCodeOfMyProgram, // Build this in a separate project
        myNewConfiguration // Defined in the plugin for user's use
    )
    mainClass.set("the.main.clazz")
}

Чтобы получить theJarsWithTheCompiledCodeOfMyProgram, вы можете создать дополнительный подпроект MyPluginApp к вашему плагину в мультипроектном проекте; и укажите MyPluginApp JAR как зависимость проекта, в котором применяется плагин, используя координаты MyPluginApp Maven, гарантируя, что целевой проект имеет доступ к репозиторию с этим JAR в нем (или он находится в той же сборке Gradle).

Внутри плагина

Если все это кажется слишком сложным, альтернативно вы можете запустить все в плагине, разрешив новую конфигурацию и используя полученные файлы для создания нового экземпляра URLClassLoader и загрузив из них все, что вам нужно.

Такой код будет запускаться из метода @TaskAction задачи, который вы определяете.

Как создать theJarsWithTheCompiledCodeOfMyProgram, когда программа создается как родственный подпроект? Мне удалось сделать это следующим образом: classpath(project.buildscript.configurations.getByName("clas‌​spath"), config) учитывая, что плагин находится в пути к классу сценария сборки. Интересно, есть ли способ сузить project.buildscript.configurations.getByName("classpath"), путь к классам самого плагина?

Kirill Gagarski 08.03.2024 13:48

Я бы не рекомендовал таким образом разрешать путь к классам buildscript. В ответе я объяснил вам еще несколько вариантов.

Simon Jacobs 08.03.2024 16:43

Боюсь, я до сих пор не понял предложенный вами подход. Если я добавлю конфигурацию в скрипт сборки плагина (configurations { create("myPluginApp") {} }), она не будет доступна внутри кода плагина. И если я разрешаю его «в файл» в своем сценарии сборки, то плагин нельзя будет использовать за пределами родительского проекта.

Kirill Gagarski 08.03.2024 19:36

Итак, мне удалось сделать следующее: - создать конфигурацию myPluginApp в коде плагина (не построить скрипт) - программно добавить зависимость myPluginApp к project - теперь у меня есть две конфигурации, которые я могу использовать для запуска своего приложения из плагина. Однако необходимо сделать один трюк, чтобы выполнить версию my-plugin-app, соответствующую версии my-pluign. Для этого я использовал предложенный вами подход: сохраните версию плагина в файле ресурсов во время сборки и используйте эту версию на шаге 2, чтобы указать версию приложения. Что вы думаете?

Kirill Gagarski 08.03.2024 20:00

Я согласен, что первоначально предложенный подход не подходил для опубликованного плагина. Я внес поправки, чтобы показать подход к вводу координат Maven (думаю, вы тоже об этом говорите). Я думаю, что это «правильный» способ сделать это :)

Simon Jacobs 08.03.2024 20:24

Другие вопросы по теме