# Chapter 42. Multi-project Builds

The powerful support for multi-project builds is one of Gradle's unique selling points. This topic is also the most intellectually challenging.

## 42.1. Cross project configuration

Let's start with a very simple multi-project build. After all Gradle is a general purpose build tool at its core, so the projects don't have to be java projects. Our first examples are about marine life.

### 42.1.1. Defining common behavior

We have the following project tree. This is a multi-project build with a root project `water` and a subproject `bluewhale`.

Example 42.1. Multi-project tree - water & bluewhale projects

Build layout

    water/
      build.gradle
      settings.gradle
      bluewhale/

Note: The code for this example can be found at `samples/userguide/multiproject/firstExample/water` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'bluewhale'

And where is the build script for the `bluewhale` project? In Gradle build scripts are optional. Obviously for a single project build, a project without a build script doesn't make much sense. For multiproject builds the situation is different. Let's look at the build script for the `water` project and execute it:

Example 42.2. Build script of water (parent) project

`build.gradle`

    Closure cl = { task -> println "I'm $task.project.name" }
    task hello << cl
    project(':bluewhale') {
        task hello << cl
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale

Gradle allows you to access any project of the multi-project build from any build script. The Project API provides a method called `project()`, which takes a path as an argument and returns the Project object for this path. The capability to configure a project build from any build script we call cross project configuration. Gradle implements this via configuration injection.

We are not that happy with the build script of the `water` project. It is inconvenient to add the task explicitly for every project. We can do better. Let's first add another project called `krill` to our multi-project build.

Example 42.3. Multi-project tree - water, bluewhale & krill projects

Build layout

    water/
      build.gradle
      settings.gradle
      bluewhale/
      krill/

Note: The code for this example can be found at `samples/userguide/multiproject/addKrill/water` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'bluewhale', 'krill'

Now we rewrite the `water` build script and boil it down to a single line.

Example 42.4. Water project build script

`build.gradle`

    allprojects {
        task hello << { task -> println "I'm $task.project.name" }
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    I'm krill

Is this cool or is this cool? And how does this work? The Project API provides a property `allprojects` which returns a list with the current project and all its subprojects underneath it. If you call `allprojects` with a closure, the statements of the closure are delegated to the projects associated with `allprojects`. You could also do an iteration via `allprojects.each`, but that would be more verbose.

Other build systems use inheritance as the primary means for defining common behavior. We also offer inheritance for projects as you will see later. But Gradle uses configuration injection as the usual way of defining common behavior. We think it provides a very powerful and flexible way of configuring multiproject builds.

## 42.2. Subproject configuration

The Project API also provides a property for accessing the subprojects only.

### 42.2.1. Defining common behavior

Example 42.5. Defining common behaviour of all projects and subprojects

`build.gradle`

    allprojects {
        task hello << {task -> println "I'm $task.project.name" }
    }
    subprojects {
        hello << {println "- I depend on water"}
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    - I depend on water
    I'm krill
    - I depend on water

### 42.2.2. Adding specific behavior

You can add specific behavior on top of the common behavior. Usually we put the project specific behavior in the build script of the project where we want to apply this specific behavior. But as we have already seen, we don't have to do it this way. We could add project specific behavior for the `bluewhale` project like this:

Example 42.6. Defining specific behaviour for particular project

`build.gradle`

    allprojects {
        task hello << {task -> println "I'm $task.project.name" }
    }
    subprojects {
        hello << {println "- I depend on water"}
    }
    project(':bluewhale').hello << {
        println "- I'm the largest animal that has ever lived on this planet."
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    - I depend on water
    - I'm the largest animal that has ever lived on this planet.
    I'm krill
    - I depend on water

As we have said, we usually prefer to put project specific behavior into the build script of this project. Let's refactor and also add some project specific behavior to the `krill` project.

Example 42.7. Defining specific behaviour for project krill

Build layout

    water/
      build.gradle
      settings.gradle
      bluewhale/
        build.gradle
      krill/
        build.gradle

Note: The code for this example can be found at `samples/userguide/multiproject/spreadSpecifics/water` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'bluewhale', 'krill'

`bluewhale/build.gradle`

    hello.doLast { println "- I'm the largest animal that has ever lived on this planet." }

`krill/build.gradle`

    hello.doLast {
        println "- The weight of my species in summer is twice as heavy as all human beings."
    }

`build.gradle`

    allprojects {
        task hello << {task -> println "I'm $task.project.name" }
    }
    subprojects {
        hello << {println "- I depend on water"}
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    - I depend on water
    - I'm the largest animal that has ever lived on this planet.
    I'm krill
    - I depend on water
    - The weight of my species in summer is twice as heavy as all human beings.

### 42.2.3. Project filtering

To show more of the power of configuration injection, let's add another project called `tropicalFish` and add more behavior to the build via the build script of the `water` project.

#### 42.2.3.1. Filtering by name

Example 42.8. Adding custom behaviour to some projects (filtered by project name)

Build layout

    water/
      build.gradle
      settings.gradle
      bluewhale/
        build.gradle
      krill/
        build.gradle
      tropicalFish/

Note: The code for this example can be found at `samples/userguide/multiproject/addTropical/water` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'bluewhale', 'krill', 'tropicalFish'

`build.gradle`

    allprojects {
        task hello << {task -> println "I'm $task.project.name" }
    }
    subprojects {
        hello << {println "- I depend on water"}
    }
    configure(subprojects.findAll {it.name != 'tropicalFish'}) {
        hello << {println '- I love to spend time in the arctic waters.'}
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    - I depend on water
    - I love to spend time in the arctic waters.
    - I'm the largest animal that has ever lived on this planet.
    I'm krill
    - I depend on water
    - I love to spend time in the arctic waters.
    - The weight of my species in summer is twice as heavy as all human beings.
    I'm tropicalFish
    - I depend on water

The `configure()` method takes a list as an argument and applies the configuration to the projects in this list.

#### 42.2.3.2. Filtering by properties

Using the project name for filtering is one option. Using dynamic project properties is another.

Example 42.9. Adding custom behaviour to some projects (filtered by project properties)

Build layout

    water/
      build.gradle
      settings.gradle
      bluewhale/
        build.gradle
      krill/
        build.gradle
      tropicalFish/
        build.gradle

Note: The code for this example can be found at `samples/userguide/multiproject/tropicalWithProperties/water` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'bluewhale', 'krill', 'tropicalFish'

`bluewhale/build.gradle`

    arctic = true
    hello.doLast { println "- I'm the largest animal that has ever lived on this planet." }

`krill/build.gradle`

    arctic = true
    hello.doLast {
        println "- The weight of my species in summer is twice as heavy as all human beings."
    }

`tropicalFish/build.gradle`

    arctic = false

`build.gradle`

    allprojects {
        task hello << {task -> println "I'm $task.project.name" }
    }
    subprojects {
        hello {
            doLast {println "- I depend on water"}
            afterEvaluate { Project project ->
                if (project.arctic) { doLast {
                    println '- I love to spend time in the arctic waters.' }
                }
            }
        }
    }

Output of `gradle -q hello`

    > gradle -q hello
    I'm water
    I'm bluewhale
    - I depend on water
    - I'm the largest animal that has ever lived on this planet.
    - I love to spend time in the arctic waters.
    I'm krill
    - I depend on water
    - The weight of my species in summer is twice as heavy as all human beings.
    - I love to spend time in the arctic waters.
    I'm tropicalFish
    - I depend on water

In the build file of the `water` project we use an `afterEvaluate` notification. This means that the closure we are passing gets evaluated after the build scripts of the subproject are evaluated. As the property `arctic` is set in those build scripts, we have to do it this way. You will find more on this topic in Section 42.6, “Dependencies - Which dependencies?”

## 42.3. Execution rules for multi-project builds

When we have executed the `hello` task from the root project dir things behaved in an intuitive way. All the `hello` tasks of the different projects were executed. Let's switch to the `bluewhale` dir and see what happens if we execute Gradle from there.

Example 42.10. Running build from subproject

Output of `gradle -q hello`

    > gradle -q hello
    I'm bluewhale
    - I depend on water
    - I'm the largest animal that has ever lived on this planet.
    - I love to spend time in the arctic waters.

The basic rule behind Gradle's behavior is simple. Gradle looks down the hierarchy, starting with the current dir, for tasks with the name `hello` an executes them. One thing is very important to note. Gradle always evaluates every project of the multi-project build and creates all existing task objects. Then, according to the task name arguments and the current dir, Gradle filters the tasks which should be executed. Because of Gradle's cross project configuration every project has to be evaluated before any task gets executed. We will have a closer look at this in the next section. Let's now have our last marine example. Let's add a task to `bluewhale` and `krill`.

Example 42.11. Evaluation and execution of projects

`bluewhale/build.gradle`

    arctic = true
    hello << { println "- I'm the largest animal that has ever lived on this planet." }

    task distanceToIceberg << {
        println '20 nautical miles'
    }

`krill/build.gradle`

    arctic = true
    hello << { println "- The weight of my species in summer is twice as heavy as all human beings." }

    task distanceToIceberg << {
        println '5 nautical miles'
    }

Output of `gradle -q distanceToIceberg`

    > gradle -q distanceToIceberg
    20 nautical miles
    5 nautical miles

Here the output without the `-q` option:

Example 42.12. Evaluation and execution of projects

Output of `gradle distanceToIceberg`

    > gradle distanceToIceberg
    :bluewhale:distanceToIceberg
    20 nautical miles
    :krill:distanceToIceberg
    5 nautical miles

    BUILD SUCCESSFUL

    Total time: 1 secs

The build is executed from the `water` project. Neither `water` nor `tropicalFish` have a task with the name `distanceToIceberg`. Gradle does not care. The simple rule mentioned already above is: Execute all tasks down the hierarchy which have this name. Only complain if there is no such task!

## 42.4. Running tasks by their absolute path

As we have seen, you can run a multi-project build by entering any subproject dir and execute the build from there. All matching task names of the project hierarchy starting with the current dir are executed. But Gradle also offers to execute tasks by their absolute path (see also Section 42.5, “Project and task paths”):

Example 42.13. Running tasks by their absolute path

Output of `gradle -q :hello :krill:hello hello`

    > gradle -q :hello :krill:hello hello
    I'm water
    I'm krill
    - I depend on water
    - The weight of my species in summer is twice as heavy as all human beings.
    - I love to spend time in the arctic waters.
    I'm tropicalFish
    - I depend on water

The build is executed from the `tropicalFish` project. We execute the `hello` tasks of the `water`, the `krill` and the `tropicalFish` project. The first two tasks are specified by there absolute path, the last task is executed on the name matching mechanism described above.

## 42.5. Project and task paths

A project path has the following pattern: It starts always with a colon, which denotes the root project. The root project is the only project in a path that is not specified by its name. The path `:bluewhale` corresponds to the file system path `water/bluewhale` in the case of the example above.

The path of a task is simply its project path plus the task name. For example `:bluewhale:hello`. Within a project you can address a task of the same project just by its name. This is interpreted as a relative path.

Originally Gradle has used the `'/'` character as a natural path separator. With the introduction of directory tasks (see Section 12.1, “Directory creation”) this was no longer possible, as the name of the directory task contains the `'/'` character.

## 42.6. Dependencies - Which dependencies?

The examples from the last section were special, as the projects had no Execution Dependencies. They had only Configuration Dependencies. Here is an example where this is different:

### 42.6.1. Execution dependencies

#### 42.6.1.1. Dependencies and execution order

Example 42.14. Dependencies and execution order

Build layout

    messages/
      settings.gradle
      consumer/
        build.gradle
      producer/
        build.gradle

Note: The code for this example can be found at `samples/userguide/multiproject/dependencies/firstMessages/messages` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'consumer', 'producer'

`consumer/build.gradle`

    task action << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

`producer/build.gradle`

    task action << {
        println "Producing message:"
        rootProject.producerMessage = 'Watch the order of execution.'
    }

Output of `gradle -q action`

    > gradle -q action
    Consuming message: null
    Producing message:

This did not work out. If nothing else is defined, Gradle executes the task in alphanumeric order. Therefore `:consumer:action` is executed before `:producer:action`. Let's try to solve this with a hack and rename the producer project to `aProducer`.

Example 42.15. Dependencies and execution order

Build layout

    messages/
      settings.gradle
      aProducer/
        build.gradle
      consumer/
        build.gradle

`settings.gradle`

    include 'consumer', 'aProducer'

`aProducer/build.gradle`

    task action << {
        println "Producing message:"
        rootProject.producerMessage = 'Watch the order of execution.'
    }

`consumer/build.gradle`

    task action << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

Output of `gradle -q action`

    > gradle -q action
    Producing message:
    Consuming message: Watch the order of execution.

Now we take the air out of this hack. We simply switch to the `consumer` dir and execute the build.

Example 42.16. Dependencies and execution order

Output of `gradle -q action`

    > gradle -q action
    Consuming message: null

For Gradle the two `action` tasks are just not related. If you execute the build from the `messages` project Gradle executes them both because they have the same name and they are down the hierarchy. In the last example only one `action` was down the hierarchy and therefore it was the only task that got executed. We need something better than this hack.

#### 42.6.1.2. Declaring dependencies

Example 42.17. Declaring dependencies

Build layout

    messages/
      settings.gradle
      consumer/
        build.gradle
      producer/
        build.gradle

Note: The code for this example can be found at `samples/userguide/multiproject/dependencies/messagesWithDependencies/messages` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'consumer', 'producer'

`consumer/build.gradle`

    dependsOn(':producer')

    task action << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

`producer/build.gradle`

    task action << {
        println "Producing message:"
        rootProject.producerMessage = 'Watch the order of execution.'
    }

Output of `gradle -q action`

    > gradle -q action
    Producing message:
    Consuming message: Watch the order of execution.

Running this from the `consumer` directory gives:

Example 42.18. Declaring dependencies

Output of `gradle -q action`

    > gradle -q action
    Producing message:
    Consuming message: Watch the order of execution.

We have now declared that the `consumer` project has an execution dependency on the `producer` project. For Gradle declaring execution dependencies between projects is syntactic sugar. Under the hood Gradle creates task dependencies out of them. You can also create cross project tasks dependencies manually by using the absolute path of the tasks.

#### 42.6.1.3. The nature of project dependencies

Let's change the naming of our tasks and execute the build.

Example 42.19. Project execution dependencies

`consumer/build.gradle`

    dependsOn(':producer')

    task consume << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

`producer/build.gradle`

    task produce << {
        println "Producing message:"
        rootProject.producerMessage = 'Watch the order of execution.'
    }

Output of `gradle -q consume`

    > gradle -q consume
    Consuming message: null

Oops. Why does this not work? The `dependsOn` command is created for projects with a common lifecycle. Provided you have two Java projects where one depends on the other. If you trigger a compile for the dependent project you don't want that all tasks of the other project get executed. Therefore a `dependsOn` creates dependencies between tasks with equal names. To deal with the scenario above you would do the following:

Example 42.20. Cross project task dependencies

`consumer/build.gradle`

    task consume(dependsOn: ':producer:produce') << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

`producer/build.gradle`

    task produce << {
        println "Producing message:"
        rootProject.producerMessage = 'Watch the order of execution.'
    }

Output of `gradle -q consume`

    > gradle -q consume
    Producing message:
    Consuming message: Watch the order of execution.

### 42.6.2. Configuration time dependencies

Let's have one more example with our producer-consumer build before we enter Java land. We add a property to the producer project and create now a configuration time dependency from consumer on producer.

Example 42.21. Configuration time dependencies

`consumer/build.gradle`

    message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'

    task consume << {
        println("Consuming message: " + message)
    }

`producer/build.gradle`

    rootProject.producerMessage = 'Watch the order of evaluation.'

Output of `gradle -q consume`

    > gradle -q consume
    Consuming message: null

The default evaluation order of the projects is alphanumeric (for the same nesting level). Therefore the `consumer` project is evaluated before the `producer` project and the `key` value of the `producer` is set after it is read by the `consumer` project. Gradle offers a solution for this.

Example 42.22. Configuration time dependencies - evaluationDependsOn

`consumer/build.gradle`

    evaluationDependsOn(':producer')

    message = rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'

    task consume << {
        println("Consuming message: " + message)
    }

Output of `gradle -q consume`

    > gradle -q consume
    Consuming message: Watch the order of evaluation.

The command `evaluationDependsOn` triggers the evaluation of `producer` before `consumer` is evaluated. The example is a bit contrived for the sake of showing the mechanism. In this case there would be an easier solution by reading the key property at execution time.

Example 42.23. Configuration time dependencies

`consumer/build.gradle`

    task consume << {
        println("Consuming message: " +
                (rootProject.hasProperty('producerMessage') ? rootProject.producerMessage : 'null'))
    }

Output of `gradle -q consume`

    > gradle -q consume
    Consuming message: Watch the order of evaluation.

Configuration dependencies are very different to execution dependencies. Configuration dependencies are between projects whereas execution dependencies are always resolved to task dependencies. Another difference is that always all projects are configured, even when you start the build from a subproject. The default configuration order is top down, which is usually what is needed.

On the same nesting level the configuration order depends on the alphanumeric position. The most common use case is to have multi-project builds that share a common lifecycle (e.g. all projects use the Java plugin). If you declare with `dependsOn` a execution dependency between different projects, the default behavior of this method is to create also a configuration dependency between the two projects. Therefore it is likely that you don't have to define configuration dependencies explicitly.

### 42.6.3. Real life examples

Gradle's multi-project features are driven by real life use cases. The first example for describing such a use case, consists of two webapplication projects and a parent project that creates a distribution out of them. [19] For the example we use only one build script and do cross project configuration.

Example 42.24. Dependencies - real life example - crossproject configuration

Build layout

    webDist/
      settings.gradle
      build.gradle
      date/
        src/main/java/
          org/gradle/sample/
            DateServlet.java
      hello/
        src/main/java/
          org/gradle/sample/
            HelloServlet.java

Note: The code for this example can be found at `samples/userguide/multiproject/dependencies/webDist` which is in both the binary and source distributions of Gradle.

`settings.gradle`

    include 'date', 'hello'

`build.gradle`

    dependsOnChildren()

    allprojects {
        apply plugin: 'java'
        group = 'org.gradle.sample'
        version = '1.0'
    }

    subprojects {
        apply plugin: 'war'
        repositories {
            mavenCentral()
        }
        dependencies {
            compile "javax.servlet:servlet-api:2.5"
        }
    }

    task explodedDist(dependsOn: assemble) << {
        File explodedDist = mkdir(buildDir, 'explodedDist')
        subprojects.each {project ->
            project.tasks.withType(Jar).each {archiveTask ->
                copy {
                    from archiveTask.archivePath
                    into explodedDist
                }
            }
        }
    }

We have an interesting set of dependencies. Obviously the `date` and `hello` projects have a configuration dependency on `webDist`, as all the build logic for the webapp projects is injected by `webDist`. The execution dependency is in the other direction, as `webDist` depends on the build artifacts of `date` and `hello`. There is even a third dependency. `webDist` has a configuration dependency on `date` and `hello` because it needs to know the `archivePath`. But it asks for this information at execution time. Therefore we have no circular dependency.

Such and other dependency patterns are daily bread in the problem space of multi-project builds. If a build system does not support such patterns, you either can't solve your problem or you need to do ugly hacks which are hard to maintain and massively afflict your productivity as a build master.

There is one more thing to note from the current example. We have used the command `dependsOnChildren()`. It is a convenience method and calls the `dependsOn` method of the parent project for every child project (not every sub project). It declares a `execution` dependency of `webDist` on `date` and `hello`.

Another use case would be a situation where the subprojects have a configuration and execution dependency on the parent project. This is the case when the parent project does configuration injection into its subprojects, and additionally produces something at execution time that is needed by its child projects (e.g. code generation). In this case the parent project would call the `childrenDependOnMe` method to create an execution dependency for the child projects. We might add an example for this in a future version of the user guide.

## 42.7. Project lib dependencies

What if one projects needs the jar produced by another project in its compile path? And not just the jar but also the transitive dependencies of this jar? Obviously this is a very common use case for Java multi-project builds. As already mentioned in Section 36.4.3, “Project dependencies”, Gradle offers project lib dependencies for this.

Example 42.25. Project lib dependencies

Build layout

    java/
      settings.gradle
      build.gradle
      api/
        src/main/java/
          org/gradle/sample/
            api/
              Person.java
            apiImpl/
              PersonImpl.java
      services/personService/
        src/
          main/java/
            org/gradle/sample/services/
              PersonService.java
          test/java/
            org/gradle/sample/services/
              PersonServiceTest.java
      shared/
        src/main/java/
          org/gradle/sample/shared/
            Helper.java

Note: The code for this example can be found at `samples/userguide/multiproject/dependencies/java` which is in both the binary and source distributions of Gradle.

We have the projects `shared`, `api` and`personService`. `personService` has a lib dependency on the other two projects. `api` has a lib dependency on `shared`. [20]

Example 42.26. Project lib dependencies

`settings.gradle`

    include 'api', 'shared', 'services:personService'

`build.gradle`

    subprojects {
        apply plugin: 'java'
        group = 'org.gradle.sample'
        version = '1.0'
        repositories {
            mavenCentral()
        }
        dependencies {
            testCompile "junit:junit:4.8.2"
        }
    }

    project(':api') {
        dependencies {
            compile project(':shared')
        }
    }

    project(':services:personService') {
        dependencies {
            compile project(':shared'), project(':api')
        }
    }

    dependsOnChildren()

All the build logic is in the `build.gradle` of the root project. [21] A lib dependency is a special form of an execution dependency. It causes the other project to be built first and adds the jar with the classes of the other project to the classpath. It also adds the dependencies of the other project to the classpath. So you can enter the `api` directory and trigger a `gradle compile`. First `shared` is built and then `api` is built. Project dependencies enable partial multi-project builds.

If you come from Maven land you might be perfectly happy with this. If you come from Ivy land, you might expect some more fine grained control. Gradle offers this to you:

Example 42.27. Fine grained control over dependencies

`build.gradle`

    subprojects {
        apply plugin: 'java'
        group = 'org.gradle.sample'
        version = '1.0'
    }

    project(':api') {
        configurations {
            spi
        }
        dependencies {
            compile project(':shared')
        }
        task spiJar(type: Jar) {
            baseName = 'api-spi'
            dependsOn classes
            from sourceSets.main.output
            include('org/gradle/sample/api/**')
        }
        artifacts {
            spi spiJar
        }
    }

    project(':services:personService') {
        dependencies {
            compile project(':shared')
            compile project(path: ':api', configuration: 'spi')
            testCompile "junit:junit:4.8.2", project(':api')
        }
    }

The Java plugin adds per default a jar to your project libraries which contains all the classes. In this example we create an additional library containing only the interfaces of the `api` project. We assign this library to a new dependency configuration. For the person service we declare that the project should be compiled only against the `api` interfaces but tested with all classes from `api`.

### 42.7.1. Disabling the build of dependency projects

Sometimes you don't want depended on projects to be built when doing a partial build. To disable the build of the depended on projects you can run gradle with the `-a` option.

## 42.8. Multi-Project Building and Testing

The `build` task of the Java plugin is typically used to compile, test, and perform code style checks (if the CodeQuality plugin is used) of a single project. In multi-project builds you may often want to do all of these tasks across a range of projects. The `buildNeeded` and `buildDependents` tasks can help with this.

Let's use the project structure shown in Example 42.26, “Project lib dependencies”. In this example :services:personservice depends on both :api and :shared. The :api project also depends on :shared.

Assume you are working on a single project, the :api project. You have been making changes, but have not built the entire project since performing a clean. You want to build any necessary supporting jars, but only perform code quality and unit tests on the project you have changed. The `build` task does this.

Example 42.28. Build and Test Single Project

Output of `gradle :api:build`

    > gradle :api:build
    :shared:compileJava
    :shared:processResources
    :shared:classes
    :shared:jar
    :api:compileJava
    :api:processResources
    :api:classes
    :api:jar
    :api:assemble
    :api:compileTestJava
    :api:processTestResources
    :api:testClasses
    :api:test
    :api:check
    :api:build

    BUILD SUCCESSFUL

    Total time: 1 secs

While you are working in a typical development cycle repeatedly building and testing changes to the :api project (knowing that you are only changing files in this one project), you may not want to even suffer the expense of :shared:compile checking to see what has changed in the :shared project. Adding the `-a` option will cause gradle to use cached jars to resolve any project lib dependencies and not try to re-build the depended on projects.

Example 42.29. Partial Build and Test Single Project

Output of `gradle -a :api:build`

    > gradle -a :api:build
    :api:compileJava
    :api:processResources
    :api:classes
    :api:jar
    :api:assemble
    :api:compileTestJava
    :api:processTestResources
    :api:testClasses
    :api:test
    :api:check
    :api:build

    BUILD SUCCESSFUL

    Total time: 1 secs

If you have just gotten the latest version of source from your version control system which included changes in other projects that :api depends on, you might want to not only build all the projects you depend on, but test them as well. The `buildNeeded` task also tests all the projects from the project lib dependencies of the testRuntime configuration.

Example 42.30. Build and Test Depended On Projects

Output of `gradle :api:buildNeeded`

    > gradle :api:buildNeeded
    :shared:compileJava
    :shared:processResources
    :shared:classes
    :shared:jar
    :api:compileJava
    :api:processResources
    :api:classes
    :api:jar
    :api:assemble
    :api:compileTestJava
    :api:processTestResources
    :api:testClasses
    :api:test
    :api:check
    :api:build
    :shared:assemble
    :shared:compileTestJava
    :shared:processTestResources
    :shared:testClasses
    :shared:test
    :shared:check
    :shared:build
    :shared:buildNeeded
    :api:buildNeeded

    BUILD SUCCESSFUL

    Total time: 1 secs

You also might want to refactor some part of the :api project that is used in other projects. If you make these types of changes, it is not sufficient to test just the :api project, you also need to test all projects that depend on the :api project. The `buildDependents` task also tests all the projects that have a project lib dependency (in the testRuntime configuration) on the specified project.

Example 42.31. Build and Test Dependent Projects

Output of `gradle :api:buildDependents`

    > gradle :api:buildDependents
    :shared:compileJava
    :shared:processResources
    :shared:classes
    :shared:jar
    :api:compileJava
    :api:processResources
    :api:classes
    :api:jar
    :api:assemble
    :api:compileTestJava
    :api:processTestResources
    :api:testClasses
    :api:test
    :api:check
    :api:build
    :services:personService:compileJava
    :services:personService:processResources
    :services:personService:classes
    :services:personService:jar
    :services:personService:assemble
    :services:personService:compileTestJava
    :services:personService:processTestResources
    :services:personService:testClasses
    :services:personService:test
    :services:personService:check
    :services:personService:build
    :services:personService:buildDependents
    :api:buildDependents

    BUILD SUCCESSFUL

    Total time: 1 secs

Finally, you may want to build and test everything in all projects. If the root project has declared `dependsOnChildren()` (as this one does), then any task you run against the root project will cause that same named task to be run on all the children. So you can just run `gradle build` to build and test all projects.

## 42.9. Property and method inheritance

Properties and methods declared in a project are inherited to all its subprojects. This is an alternative to configuration injection. But we think that the model of inheritance does not reflect the problem space of multi-project builds very well. In a future edition of this user guide we might write more about this.

Method inheritance might be interesting to use as Gradle's Configuration Injection does not support methods yet (but will in a future release).

You might be wondering why we have implemented a feature we obviously don't like that much. One reason is that it is offered by other tools and we want to have the check mark in a feature comparison :). And we like to offer our users a choice.

## 42.10. Summary

Writing this chapter was pretty exhausting and reading it might have a similar effect. Our final message for this chapter is that multi-project builds with Gradle are usually not difficult. There are six elements you need to remember: `allprojects`, `subprojects`, `dependsOn`, `childrenDependOnMe`, `dependsOnChildren` and project lib dependencies. [22] With those elements, and keeping in mind that Gradle has a distinct configuration and execution phase, you have already a lot of flexibility. But when you enter steep territory Gradle does not become an obstacle and usually accompanies and carries you to the top of the mountain.

[19] The real use case we had, was using http://lucene.apache.org/solr, where you need a separate war for each index your are accessing. That was one reason why we have created a distribution of webapps. The Resin servlet container allows us, to let such a distribution point to a base installation of the servlet container.

[20] `services` is also a project, but we use it just as a container. It has no build script and gets nothing injected by another build script.

[21] We do this here, as it makes the layout a bit easier. We usually put the project specific stuff into the build script of the respective projects.

[22] So we are well in the range of the 7 plus 2 Rule :)