I am writing a Gradle plugin, let’s call it myPlugin, which, amongst other things, declares its own dependency. The Plugin will be used in a build.gradle with apply plugin: 'myPlugin'. It also adds a task, which will be invoked later.
Question is: I don’t want to hard code the version for the dependency in the plugin, but rather pass it from the build.gradle. I tried to use a PluginExtension, but it seems that it is too late, because I need the version already before/during apply.
Dependencies in Gradle are managed through dependency configurations. Start here.
Your plugin should create a custom dependency configuration during the Gradle Configuration phase, the configuration is not resolved and you can modify it and specify your dependency. For your use-case, it looks like you may benefit from default dependencies.
During the execution phase, you would resolve the configuration to a list of JARs and either use a custom classloader, or the javaExec() API/task to run your tool.
How exactly does this help me? How can I modify my dependency from my build.gradle?
I got the idea of default dependencies, but I would not like to force my build.gradle to declare the dependency itself, but rather only pass the version.
If you could provide some code snippets or point me to some example, that would be highly appreciated.
Configurations are evaluated on demand so the dependency closure will be executed after the buildscript has had a chance to overridde the default toolVersion
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
classpath // dependency to my plugin jar
}
}
apply plugin: 'my-plugin'
myPlugin {
version = '1.0.0'
}
...
jar.dependsOn doSomething
When I build, it will apply the default of my extension class. When I move apply plugin and the override of the version to buildscript section ist won’t find the plugin anymore.
Also I have no idea how dependencyManagement works. Probably best to remove that too as perhaps that’s causing the configuration to be resolved at configuration time… Not sure
Thanks for your help, I tried both, removing the dependsOn and the DependencyManagement, but still:
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all dependencies for configuration ':compileClasspath'.
> Could not find org.camunda.bpm.webapp:camunda-webapp-ee-plugins:23.5.6.
Required by:
project :
Which is correct, because 23.5.6 does not exist, I took that as default to notice at once when it is applied.
apply plugin: MyPlugin
repositories { jcenter() }
myPlugin {
// Can override version of default dependency.
toolVersion = '4.12'
}
// Alternatively, the option is open to the user to manually
// configure the dependencies of the tool and to ignore what
// you've specified.
/*
dependencies {
// Since there are dependencies declared, the defaults are not applied.
myConfig 'javax.inject:javax.inject:1'
}
*/
class MyExt {
String toolVersion = "3.8";
}
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.with {
MyExt myExt = extensions.create('myPlugin', MyExt)
configurations {
myConfig
}
configurations.myConfig.defaultDependencies { deps ->
deps.add(project.dependencies.create("junit:junit:$myExt.toolVersion"))
}
tasks.create("myTask") {
doLast {
println "myConfig=$configurations.myConfig.files"
}
}
}
}
}
The secret here is that the closure passed to defaultDependencies is not executed until the configuration participates in dependency resolution, if there are no defined dependencies.