Multiple plugins from source into buildSrc


(Thibault Kruse) #1

Hi, gradle allows to define plugins or other build behavior in the buildSrc folder of a gradle project. What I would like is to clone out multiple plugin projects from e.g. github into an application gradle project, and use and extend them there. Currently that is a bit of a hassle, because I seem to be able to only check out one such project at a time into buildSrc directly, and cannot have multiple or subprojects in buildSrc.

So as an example, I would like to have a folder structure like this

- myApp
-- src
--- ...
-- buildSrc
--- gradle-version-plugin (cloned from https://github.com/ben-manes/gradle-versions-plugin)
---- src
----- ...
--- gradle-node-plugin (cloned from https://github.com/srs/gradle-node-plugin)
---- src
----- ...
--- grails-gradle-plugin (https://github.com/grails/grails-gradle-plugin)
---- src
----- ...

And possibly some additional private plugins in the making.

I know I could have those projects independent and publish themto a local maven repo, and use them from there, but this makes for much slower development cycles when I ampatching stuff that goes wrong in the root myApp project.

I tried setting up a multiproject build in buildSrc using

myApp/buildSrc/setting.grade: include ‘gradle-versions-plugin’ myApp/buildSrc/build.gradle: // empty myApp/buildSrc/gradle-versions-plugin myApp/build.gradle: apply plugin ‘versions’

This actually builds the versions plugin in buildSrc, but then I get: > Plugin with id ‘versions’ not found.

I guess I could try copying the resulting files from myApp/buildSrc/gradle-versions-plugin/build/libs to

myApp/buildSrc/build/libs

but I thought it might be a good addition for gradle to either make it by default,or provide the ideal way to achieve what I want inthe documentation.

This way it will be easier for people to provide patches to custom plugins in the wild, improving the gradle ecosystem faster.

BTW: My current recipe is:

buildSrc/build.gradle

allprojects {
  // make sure subprojects have jar task at config time
  apply plugin: 'java'
}
  /**
 * gradle expects to read exploded files in build/resources and build/classes
 */
task copyDist(dependsOn: subprojects.jar) << {
  subprojects.each {project ->
    copy {
      from "$project.buildDir/classes"
      into "$buildDir/classes"
    }
    copy {
      from "$project.buildDir/resources"
      into "$buildDir/resources"
    }
  }
}
  build.dependsOn(copyDist)

And a settings.gradle, e.g. myApp/buildSrc/setting.grade: include ‘gradle-versions-plugin’


(Thibault Kruse) #2

Much easier recipe:

allprojects { project ->
  project.buildDir = buildDir
}

(Jan Sorensen) #3

You can add the github sources to the sourcesets in the buildSrc/build.gradle. Something like:

sourceSets {
 main {
  java {
   srcDir 'gradle-version-plugin/src'
   srcDir 'gradle-node-plugin/src'
  }
 }
}

I haven’t tested it but believe that should work for you.


(Thibault Kruse) #4

So I could get yyour approach to work with several modifications:

apply plugin: 'groovy'
  repositories {
    mavenCentral()
}
  dependencies {
    compile 'org.spockframework:spock-core:0.7-groovy-1.8'
}
  sourceSets {
  main {
    groovy {
      srcDir 'gradle-versions-plugin/src'
      srcDir 'gradle-node-plugin/src'
      srcDir 'gradle-grunt-plugin/src'
    }
    resources {
      srcDir 'gradle-versions-plugin/src/main/resources'
      srcDir 'gradle-node-plugin/src/main/resources'
      srcDir 'gradle-grunt-plugin/src/main/resources'
               }
  }
}

I had to apply groovy to be able to build at all, and declare groovy source sets. I had to declare the missing test dependency and reporistories (maybe I could also have further restricted the sourceset srcDir, but that is a pain with mixes of groovy and Java. I had to declare resource source sets pointing to the respective subfolders.

Basically following that approach would require copying build.gradle code from the subprojects to the main project, which seems generally a bad idea. Not sure if my recipe above is worse than that or not. And with your suggestion it does not seem easy to switch-in-switch-out plugins.


(Luke Daley) #5

You need to make the root buildSrc project effectively depend on all of the children.

You need something like this in your root project:

apply plugin: "java"
dependencies {
    runtime subprojects.collect { owner.project(it.path) }
}

(Thibault Kruse) #6

That works for me, without modifications, very nice. I would even recommend putting that into the docs,

Also, btw, I think there is a small mistake in the example at http://www.gradle.org/docs/current/userguide/multi_project_builds.html 56.6.3. Real life examples

I believe this change is required:

- task explodedDist(dependsOn: assemble) << {
+ task explodedDist(dependsOn: subprojects.assemble) << {

Else the subprojects’ assemble task do not get executed first.

And indeed the whole chapter should mention somewhere how a parent project task can depend on subprojects.


(Thibault Kruse) #7

Hm, ran into some additional problems doing so with this plugin: https://github.com/eriwen/gradle-js-plugin

* What went wrong:
Could not resolve all dependencies for configuration ':runtime'.
> Could not find com.google.javascript:closure-compiler:v20130227.
  Required by:
      :buildSrc:unspecified > com.eriwen:gradle-js-plugin:1.9.0

The only way I found to solve this was to makemy rot project (buildSrc/buildgradle) also declare repositories:

apply plugin: "java"
  repositories {
    jcenter()
    mavenCentral()
}
  dependencies {
    runtime subprojects.collect { owner.project(it.path) }
}

This could in theory get ugly if the plugin sources used unorthodox repositories, but for now that works for me. Not sure how else i can satisfy all subprojects with the repositories they define.