4

I have created a custom herpderp Gradle task:

task herpderp(type: HerpDerpTask)

class HerpDerpTask extends DefaultTask {
    @TaskAction
    def herpderp() {
        println "Herp derp!"
    }
}

With this, I can add this task to other Gradle builds an use it inside build invocations for other projects:

gradle clean build herpderp

Now, I have the following multi-project setup:

myapp/
    myapp-client/
        build.gradle
        src/** (omitted for brevity)
    myapp-shared/
        build.gradle
        src/** (omitted for brevity)
    myapp-server
        build.gradle
        src/** (omitted for brevity)
    build.gradle
    settings.gradle

Where myapp/build.gradle is:

subprojects {
    apply plugin: 'groovy'
    sourceCompatibility = '1.7'
    targetCompatibility = '1.7'

    repositories {
        mavenLocal()
        mavenCentral()
    }

    dependencies {
        compile (
            'org.codehaus.groovy:groovy-all:2.3.7'
        )
    }
}

And where myapp/settings.gradle is:

include ':myapp-shared'
include ':myapp-client'
include ':myapp-server'

I would like to be able to navigate to the parent myapp directory, and run gradler clean build herpderp and have the herpderp task only run on the myapp-client and myapp-shared projects (not the server project).

So it sounds like I need either another custom task or some type of closure/method inside myapp/build.gradle that:

  1. Runs clean build; then
  2. Drops (cd) into myapp-client and runs herpderp; and then
  3. Drop into myapp-shared and runs herpderp.

What do I need to add to any of my files in order to get herpderp invoked from the parent build command, but only executed in the client and shared subprojects?

smeeb
  • 27,777
  • 57
  • 250
  • 447
  • You can run `herpderp` task in a given module with: `gradle :myapp-shared:herpderp` – Opal Dec 28 '14 at 17:55
  • Thanks @Opal - so are you saying something like `gradle clean build :myapp-client:herpderp :myapp-shared:herpderp`? If so, is there something I could do to *wrap* that (its a bit nasty looking) so that I could have a simplified build invocation? Perhaps a way to wrap `herpderp` so that `gradle clean build smartHerpDerp` is the same as `gradle clean build :myapp-client:herpderp :myapp-shared:herpderp`. Any ideas? Thanks again! – smeeb Dec 28 '14 at 18:03
  • Yes, that is what is thinking about. What you can also do is to add `herpderp` to the specified subprojects only. Will try to do it in a moment. – Opal Dec 28 '14 at 18:19

2 Answers2

7

The following piece of code can do the trick (should be placed in myapp/build.gradle):

allprojects.findAll { it.name in ['myapp-client', 'myapp-shared'] }. each { p ->
   configure(p) {
      task herpderp(type: HerpDerpTask)
   }
}

class HerpDerpTask extends DefaultTask {
    @TaskAction
    def herpderp() {
        println "Herp derp from ${project.name}!"
    }
}
Opal
  • 81,889
  • 28
  • 189
  • 210
  • Thank you so much @Opal (I'd upvote you if I had the rep to do so)! But what would my build invocation be inside the parent `myapp` directory? Just **`gradle clean build`**? Thanks again! – smeeb Dec 28 '14 at 18:35
  • In `myapp` directory just run `gradle clean build herpderp` then `clean` and `build` will be invoked in all projects and `herpderp` only in the specified (`shared` and `client`). – Opal Dec 28 '14 at 18:40
  • You don't have to answer this @Opal (I already accepted your answer - and thanks again!) but I'm just curious as to what is happening here. If I run `gradle clean build herpderp`, how does Gradle know to execute your `findAll` closure and *only* configure `HerpDerpTask` for the selected subprojects? – smeeb Dec 28 '14 at 18:56
  • It requires longer explanation: let's continue in chat: http://chat.stackoverflow.com/rooms/info/67808/question-27679044?tab=general – Opal Dec 28 '14 at 19:05
  • Thanks, but it looks like I don't have enough rep to join a chat room (SO claims the minimum is 20). – smeeb Dec 28 '14 at 19:08
  • You've joined the room but probably you can't talk. Ok. All the scripts are evaluated before tasks are run (I mean build along with settings scripts). When `findAll` all is executed projects are already evaluated and one can pick (via name here) required projects. `configure` comes from Project class (see gradle API) and enables configuring particular project. That's all and it's very general :/ – Opal Dec 28 '14 at 19:15
1

As indicated in the Gradle documentation, you can filter subprojects and configure them this way:

configure(subprojects.findAll { it.name.endsWith("server") }) {
    apply plugin: 'com.google.cloud.tools.jib'
    jib {
       from {
          image = 'openjdk:alpine'
       }
    }
    ...
}
LionH
  • 194
  • 6