Adding local plugin to a Gradle project
Asked Answered
B

5

54

I have a Gradle plugin that compiles and works as expected. I would like to distribute with the source code an example application using the Gradle plugin which would also allow me to test changes to the plugin easily. Now to do this I must add a classpath dependency to the buildScript block. Is it possible to add a dependent local plugin that will be compiled with the example project? The main issue I'm having now is that the plugin does not exist when trying to sync the example project resulting in a failure.

Brant answered 9/2, 2016 at 21:21 Comment(4)
if it is an example project to demonstrate how to use the plugin, or is it a sort of integration-test for the plugin? if it is the former, why not have it depend on the plugin from jcenter or gradle plugins portal repo? Why does it have to depend on the local plugin project?Khiva
If it is an integration test, you really should be going the ProjectBuilder wayKhiva
Hmm I suppose it could just be an integration test, that's ultimately what I'm trying to accomplish. I'll check out this ProjectBuilder and report back how it goes, thanks.Brant
@Brant Did you ever find a good way to do this?Finned
K
42

If writing integration tests is your eventual goal, I still recommend using ProjectBuilder. You can see an example of this in Section 39.5.4 here. There are a lot more real-world test implementation examples in gradle source. See here for instance.


That being said, I got curious about the literal question you posted and tried a few things. What did work for me is this:

buildscript{
    repositories{
        ...
    }

    dependencies{
        classpath files('relative/path/to/plugin.jar')
    }
}

apply plugin: fully.qualified.package.PluginClassName

Note that the class name is not enclosed in 'quotes' to make it a string.

This is not very useful since this declaration requires the plugin.jar to be built and available before the project consuming the plugin is built - but at this point, you might as well be depending on an external repo dependency.

A second problem with this is that the transitive dependencies of the plugin project are not added to your plugin-consumer project automatically.

I couldn't get a project dependency like classpath project(':plugin-project') to work inside buildscript.


One (extremely hacky) way to ensure that the plugin project is always build and available while building the plugin-consumer project is to have a "parent" build.gradle that always builds the plugin first before building the consumer project. I uploaded an example here.

Khiva answered 18/2, 2016 at 4:9 Comment(4)
This is a first good answer I found on the net, but can you please explain how to build plugin before other configurations get checked? Have a look at my question #50495208Myrwyn
when I add a separate task buildPluginProject in root, it still checks if plugin is built in other configsMyrwyn
@Myrwyn I haven't tried to build my sample project since I wrote it over 2 years ago, can you show your buildPluginProject task?Khiva
Thanks for being curios and taking the time to research for this answer. It saved me some hours.Expecting
A
19

I encounter when i want to debug my gradle plugin in Android Studio, I solve it finally.

First, upload your gradle plugin to local maven.

apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile gradleApi()
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"


group='com.egos.gradle.plugins'
name='plugintest'
version='0.0.1'

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('../repo'))
        }
    }
}

execute gradle uploadArchives . Then use local plugin.

buildscript {
    repositories {
        maven {
            url uri('../repo')
        }
    }
    dependencies {
        classpath group: 'com.egos.gradle.plugins',
                  name: 'plugintest',
                  version: '0.0.1'
    }
}

apply plugin: 'com.egos'
Absorptance answered 27/2, 2017 at 12:29 Comment(1)
How do I create a local maven repo? Could you detail more your answer? I'm just trying to use a local pluginBassesalpes
L
14

Found a clean way to do it with composite builds, as Doron noticed. These are the steps:

  • Define your plugin with a build.gradle that has group:
// some-plugin/build.gradle
...
group = "some.group.id"
...
  • Reference your project in the settings.gradle like this:
// settings.gradle
...
includeBuild 'some-plugin'
  • In your projects you can make use of the plugin by:
// some-project/build.gradle
buildscript {
  dependencies {
    classpath "some.group.id:some-plugin"
  }
}

apply(plugin: "your.plugin.id")

Notice how the classpath is made out of the group defined in the plugin's gradle file and the name of its directory.

Lebna answered 16/5, 2019 at 5:17 Comment(2)
I thin it would be better to mention that includeBuild expects the path to the plugin. Anyways, I did this and I'm getting an error about the kotlin version: #68189905 do you have any idea?Bassesalpes
Where does "your" come from in the apply plugin line?Caravan
G
9

With the current Gradle version (3.3 as of writing) you can use the Composite Build feature to substitute plugin dependencies.

For example, you can build your example project with the following command (run in the root of your example project): gradle build --include-build /path/to/local-plugin

This would pick up your plugin from your local directory. It would even build your plugin first, then build your example project with the just built plugin as dependency.

This feature is also supported by IDEs: Simple instructions for configuring Composite Build in IntelliJ

See docs here: https://docs.gradle.org/current/userguide/composite_builds.html

Notice that substituting plugins only works with the buildscript block but not with the plugins block.

Gerbil answered 14/2, 2017 at 23:12 Comment(1)
I did this but I get a kotlin version mismatch. The local plugin uses a version of kotlin and the android app uses another.Bassesalpes
M
3

Addition to above answer. You need to also add "gradlePlugin" along with "uploadArchives" something like below:

gradlePlugin {
    plugins {
        testgen {
            id = "com.egos.gradle.plugins"
            implementationClass = "com.egos.gradle.plugins.<PluginClassName>"
        }
    }
}

instead of this set your plugin classname. Rest remains same as above answer. Thanks!

Martijn answered 2/11, 2017 at 7:31 Comment(1)
for this we should add apply plugin: 'java-gradle-plugin' or plugins { id 'java-gradle-plugin' }Outmarch

© 2022 - 2024 — McMap. All rights reserved.