Subproject vs source sets

I’m new to Gradle and am trying to figure out wither to use subprojects or sourcesets to partition my multi-module build.

My setup: - I have several modules, some of which depend on each other. - Each module has its own set of test files. - Each module has a different set of dependencies (e.g. dependencies from Maven and dependencies on JARs in the filesystem) - All the modules are versioned together (i.e. I release all the JARs together with the same version number, but users can decide which subset of the JARs they want to use).

Things that would be nice, but I can live without: - If some dependencies are not available (e.g. the Android JARs), I’d still like to be able to build all the modules that don’t need the missing dependency. - I’d like to be able to say “these three modules go into the same JAR” (I separate them out as modules so that my dependencies are cleaner, but I still ship them in a single JAR to make the set of JARs easier to understand for the user).

My first try used subprojects, but I ran into two small problems (that might be correctable): - I need to have a separate Gradle file in every subproject. Not a huge issue – just slightly harder to see what’s going on. - I end up with a ‘build’ directory in each subproject directory. I’m going to have lots of subprojects (one for each example) and it would be nice to be able to nuke the build output by just deleting one directory.

Anyway, I was hoping someone with more experience could suggest a Gradle setup that best fits my build setup. Thanks!

You should use subprojects for your setup. About your two issues with your multiproject build:

  • you can configure each subproject in the build.gradle file of your root project like:
project("subproject1"){
    //add the configuration of subproject1 here
 }
  project("subproject2"){
    //add the configuration of subproject2 here
 }

This way, you needn’t a build.gradle file for any of your subprojects. BTW, the spring guys use the same approach.

  • to have all build artifacts in one place you can add the following to your root build.gradle file:
subprojects {
 buildDir = new File(rootProject.buildDir, it.name)
}

This puts all build output of your subprojects into a directory named like your subproject directly in the build folder of your root project.

regards, René

Thanks! What you gave me fixed the two issues I listed with subprojects. However, I ran into another issue.

In addition to several Java modules in my library, there’s a documentation component (I run some tools that generate documentation HTML). All of these are subprojects of the top-level project. However, if I used the “subprojects { … }” to apply common configuration to the Java modules, this also applies to the documentation subproject, which I don’t want.

Is there another way to factor out the common parts of the Java subprojects? I’m guessing I can put all the common configuration in a function, but I’m not too familiar with exactly what’s going on with the object model (Groovy-wise) to figure out how to write that function.

You can configure any set of objects together. For example:

def javaProjects = subprojects - project(":docs")
  configure(javaProjects) {
  apply plugin: "java"
  ...
}

The other common approach is to have a build script for each subproject and selectively include other build scripts:

apply from: "../gradle/javaProject.gradle"