Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add custom dependency handler in a gradle plugin?

Tags:

gradle

I would like to provide users of my gradle plugin a simple way to add all necessary dependencies. something like gradleApi() or localGroovy().

I found out that both - gradleApi and localGroovy - are defined in DependencyHandler and implemented in DefaultDependencyHandler. Can i provide a custom implementation of Dependencyhandler which extends DefaultDependencyHandler in my plugin? Or is there even a simplier way to achieve what i want?

thx in advance.

like image 860
Yevgeniy Avatar asked Aug 08 '14 20:08

Yevgeniy


2 Answers

One solution is to have the plugin install an extra method on the dependencies container:

def jarDir = ...

project.dependencies.ext.pluginDeps = { 
    project.fileTree(jarDir) // filter file tree if necessary 
}

Users can then do:

dependencies {
    compile pluginDeps()
}

Extra properties/methods are normally meant to be used by build scripts only (because they aren't backed by a model that can be discovered and reasoned about), but in this particular case (and as of Gradle 2.1) I can't think of a clearly better solution.

PS: Keep in mind that for file (rather than repository) based dependencies, no version conflict resolution will occur.

like image 59
Peter Niederwieser Avatar answered Nov 10 '22 12:11

Peter Niederwieser


I found another way to do this. You can rely on the convention mechanism to do it. First define a convention class:

class CustomDepsPluginConvention {
    // here you can return anything which configuration methods in the
    // `dependencies` block would accept, e.g. a string or a map
    fun customDependency(): Map<String, String> {
        return mapOf(
            "group" to "com.whatever",
            "name" to "whatever",
            "version" to "1.2.3"
        )
    }
}

Then you add this convention object to the project in the plugin apply() method:

open class CustomDepsPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // the identifier of the convention object does not matter,
        // as long as it is unique
        project.convention.plugins["customDeps"] = CustomDepsPluginConvention()
    }
}

After you apply this plugin, the convention object will be added to the project object, exposing all its methods and properties on the project object and thus making them available directly in the build script:

apply plugin: CustomDepsPlugin

dependencies {
    compile customDependency()
}

This approach is arguably cleaner; the only potential downside of it is that convention objects are kind of "deprecated" and are not recommended to be used. Also, it may cause issues with the Kotlin DSL (as far as I remember, convention objects are not really supported by Kotlin DSL); if you want to support Kotlin DSL, though, you can expose these dependency-generating functions as importable top-level functions and import them to your build script.

like image 28
Vladimir Matveev Avatar answered Nov 10 '22 14:11

Vladimir Matveev