How to allow user to change the version of the lib

2019-08-10 20:02发布

问题:

In my plugin I call static bootstrapping method MutationCoverageReport.main(arg) from a library which is a compile dependency of my plugin. I would like to allow a plugin user to change the version of the library which should be used (assuming the selected version has compatible API).

I could advice user to exclude a transitive dependency from my plugin and add a dependency to the library in the requested version manually to buildscript.dependencies.classpath in his build.gradle, but this is not very elegant:

buildscript {
    (...)
    dependencies {
        classpath('info.solidsoft.gradle.pitest:gradle-pitest-plugin:0.32.0') {
            exclude(group: 'org.pitest')
        }
        classpath 'org.pitest:pitest-command-line:0.33'
    }
}

I would like to be able to use libVersion parameter in my configuration closure, but I have some problems with two solutions I tried.

1. I could need to remove transitive dependencies from my plugin (an original library version and its dependencies) and add a library in requested version (from configuration closure) as a buildscript dependency.

In afterEvaluate it is to late (configurations are resolved) and I had problem to successfully hook with beforeEvaluate (is it triggered for single module project?).

2. I could change a classpath which is used to execute a static method from a library.

To do that I could create a custom class loader which would use my library classes (in requested version) before delegating to the parent class loader. I also would have to replace one liner with MutationCoverageReport.main(arg) with the reflection call using the new class loader.

Maybe there is a simpler way to modify a classpath by a plugin with which the mentioned method will be called?

Main questions. What would be the best way to allow plugin users to define the version of the library the plugin executes?

回答1:

I'm not sure this is what you're looking for, but here's how the Jacoco plugin allows the user to configure the library being used.

JacocoPluginExtension

class JacocoPluginExtension {
    // ...
    String toolVersion = '0.32.0'
    // ...
}

JacocoPlugin

class JacocoPlugin implements Plugin<Project> {
    // ...
    config.dependencies.add(this.project.dependencies.create("org.jacoco:org.jacoco.ant:${extension.toolVersion}"))
    // ...
}


回答2:

In another question about executing Java class with a separate classpath Peter Niederwieser provided 3 approaches. In the end modify my task to extend JavaExec. I set explicit set execution classpath which is separate from plugin execution classpath and can contain different library version.

The drawback is allows only to run main method, but it wasn't a problem in my case.