How to share code between plugins

I have the following situation:

  • gradle plugin ‘A’ have some code which can be reused by another plugin
  • gradle plugin ‘B’ have (currently) copied some code from ‘A’ which can be reused.

What I want to archive:

Both gradle pluings (‘A’ and ‘B’) should be “depends on” some “common” code.

The problem:

Each plugin should be work independent from each other. Additional the common code “can’t really work alone”.

Solutions which works but aren’t very “clean” in my opinion:

  • Create a “stand alone” gradle plugin and publish it. plugin ‘A’ and ‘B’ use (declare it as dependency) the ‘common’ plugin to use the common code.
  • Create a module with the common code from ‘A’ but include the code in ‘A’ (for only one artifact at the end). plugin ‘B’ can make a git submodule and include the common module in its own project like it plugin ‘A’ does.

Something to note:

Both plugins (‘A’ and ‘B’) should be 99% independent from each other. Imagine plugin ‘A’ is developed by company ‘C’ and plugin ‘B’ is developed by company ‘D’.

How can I solve that problem in a “clean”/gradle like way?!
Maybe there are other tips/tricks which can I use to solve it?!

Thanks :pray:

For me, the solution would depend on the nature of the shared code.
If the shared code functionally behaves like a base plugin that is further built upon by the other plugins, then I would do as you suggested and publish that shared functionality as a separate plugin. This is similar to how Gradle’s java plugin is actually made up of several plugins, each building on top of the previous. For example, applying the java plugin applies java-base, which applies base.
If the shared code is a collection of utilities or common logic and acts more as a library than a plugin, then I would still publish it, but not as a plugin. The plugins would then pull that library in as a dependency, just like any other library.

2 Likes

Thank you Chris :+1:

I think it is more like the second scenario you describe:

acts more as a library than a plugin

You say that you would publish it but “not as a plugin”. What do you mean exactly with that? :thinking:
Meaning that you would just publish “java classes” without any “gradle dependencies” (like gradleApi)?

Yes, just a plain old jar without any of the Gradle specifics (plugin descriptors aren’t needed in META-INF).
You create a normal java or groovy project that builds a jar and then publish that jar to an artifact repository that is available to your plugin users. For example, in my case I would publish it to an internal Artifactory server, for use by my internal plugins.
The build file for this project would include the gradleApi() dependencies in order to compile, run tests, etc, but the published artifact does not need to declare that dependency in its metadata (ie. a POM if using a Maven repo). The missing dependency won’t matter much since it will be available at runtime, and should also be available on the classpath of any plugin project trying to use the library as a dependency (it should be declaring a dependency on gradleApi() itself).

An example build file to create a Groovy based library:

apply plugin: 'groovy'
apply plugin: 'maven-publish'

dependencies {
        // the maven-publish plugin will not include these deps in the POM, similar
        // to how these do not appear in the dependencies task output
        compile gradleApi()
        compile localGroovy()
}
publishing {
    publications {
        lib( MavenPublication ) {
            from components.java
        }
    }
    repositories {
        ...
    }
}
1 Like