How to exclude Play subprojects from top-level build task

Hi there. I’m using Gradle in a multiproject, where each subproject should be able to be compiled individually, or all together using ./gradlew build.

api/ # Play application
cli/
moduleA/
moduleB/
...

The api/ project is being newly added, and is being built using the play plugin with the playBinary or runPlayBinary tasks. However, the sources in the api/ directory are being treated like ordinary sources during the build task, which is failing the build due to play template codegen not running.

$ ./gradlew build
> Task :api:compileScala
Pruning sources from previous analysis, due to incompatible CompileSetup.
.../api/app/controllers/ApiController.scala:8: object index is not a member of package views.html
    Ok(views.html.index())
                  ^
one error found

> Task :api:compileScala FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':api:compileScala'.
> Compilation failed

With this being the case, I would like to configure gradle to completely ignore the api/ subproject while executing the build task (and probably any other task that’s not playBinary or runPlayBinary). Is there any way I can go about doing this?

Thanks in advance! :slight_smile:

Some extra info: I’m using Gradle 5.1.1 and Play 2.6

I’ve also seen solutions like this one, but that requires passing a command-line argument to gradle each time. I’d like to be able to just always use the plain build task to build everything but api/.

This is what I would do based on my (limited) knowledge of Gradle

api/build.gradle

gradle.taskGraph.whenReady { taskGraph ->
    if (!taskGraph.hasTask(":api:playBinary") && !taskGraph.hasTask(":api:runPlayBinary")) {
        tasks.each { it.enabled = false }
    }
}

I think the code is pretty self-explanatory but here goes anyway: after the full list of tasks that will be executed is compiled Gradle will check whether those Play binary-related tasks are in the pipeline and if not then will disable/skip every task in the api project.

Hi @tonisostrat, thanks for the reply!

I went ahead and tried that, and it didn’t seem to do quite what I need. The sources in api/ were still being built. I tried printing out which tasks were present using

gradle.taskGraph.whenReady { taskGraph ->
    if (taskGraph.hasTask(":api:playBinary")) println("HAS PLAYBINARY")
    if (taskGraph.hasTask(":api:runPlayBinary")) println("HAS RUNPLAYBINARY")
    //if (!taskGraph.hasTask(":api:playBinary") && !taskGraph.hasTask(":api:runPlayBinary")) {
    //    tasks.each { it.enabled = false }
    //}
}

And I got HAS PLAYBINARY in the compile output of ./gradlew build, which I didn’t expect. I’m starting to wonder whether the play plugin hooks into the build task somehow, and whether it’s possible to “un-hook” that.

As I’ve been playing with this more, I’m also wondering whether my sourceSets configuration might have something to do with the problem. In api/build.gradle, I have the following source sets defined:

sourceSets {
    main {
        scala.srcDirs files("app")
        resources.srcDirs files("conf")
    }
    test {
        scala.srcDirs files("test")
    }
}

I did this so that IntelliJ could infer the correct sources based on the gradle model, but I’m wondering whether it’s causing these sources to be included in build.