I want to implement a plugin with optional user-provided dependencies, for example like some Gradle other plugins allow to:
dependencies {
// ...
dokkaPlugin(libs.dokka.versioning.plugin)
}
I managed to create a configuration in the project with name myPlugin:
val config = project.configurations.create("myPlugin")
So now, in client projects using my plugin I can do:
dependencies {
myPlugin("com.example:example:1.0.0")
}
The question is: how to apply my configuration to run some java code with classpath containing myPlugin dependencies?
Here is some more code for context:
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?
}
}
I understand that during compile time of my plugin these client-provided dependencies won't be available, so I won't be able to use classes from com.example:example directly. But I still want to create some instances using reflection or get them using ServiceLoader API.
ConfigurationextendsFileCollection, so it's a wrapper around a group of files. You can resolve that configuration when you are ready and add it to a classpath.Running as a separate Java program
Gradle has a built-in task JavaExec that you can use to create your own tasks executing Java programs.
So you can register a new task and configure it with all the same items you would add as if you were running a
javacommand from the command line:To get your hands on
theJarsWithTheCompiledCodeOfMyProgram, you can create a additional subprojectMyPluginAppto your plugin in a multiproject project; and specify theMyPluginAppJAR as a dependency of the project the plugin is applied in usingMyPluginApp's Maven coordinates, ensuring that the target project has access to a repository with that JAR in it (or it is in the same Gradle build).Within the plugin
If that all seems like too much, alternatively you can run everything within the plugin by resolving your new configuration and using the resulting files to create a new URLClassLoader instance and load what you need from them.
Such code would be triggered from the
@TaskActionmethod of task you define.