# Multi-Project Builds

version 8.4

While some small projects and monolithic applications may contain a single build file and source tree, it is often more common for a project to have been split into smaller, interdependent modules. The word "interdependent" is vital in this case as you typically want to link the many modules together through a single build.

Gradle supports this scenario through multi-project builds.

## Multi-Project structure

A Gradle multi-project build should have a root project with multiple subprojects.

The directory structure should look as follows:

    ├── .gradle
    │   └── ⋮
    ├── gradle
    │   └── wrapper
    ├── gradlew
    ├── gradlew.bat
    ├── settings.gradle.kts  (1)
    ├── subproject-one
    │   └── build.gradle.kts (2)
    └── subproject-two
        └── build.gradle.kts (2)

1 | The `settings.gradle.kts` file should include all subprojects.
2 | Each subproject should have its own `build.gradle.kts` file.

## Multi-Project standards

The Gradle community has two standards for multi-project build structures:

- Multi-Project Builds using buildSrc - where `buildSrc` is a subproject-like directory at the Gradle project root, which contains all the build logic.

- Composite Builds - a build that includes other builds where `build-logic` is a build directory at the Gradle project root, which contains all the build logic.

## Project path

A project path has the following pattern: it starts with an optional colon, which denotes the root project. The root project, `:`, is the only project in a path that is not specified by its name.

The rest of a project path is a colon-separated sequence of project names, where the next project is a subproject of the previous project such as `:subproject`.

You can see the project paths when running `gradle projects` shown below.

Project paths usually reflect the filesystem layout, but there are exceptions. Most notably for composite builds.

See how to declare dependencies between subprojects using `include` and how to create composite builds with `includeBuild`.

## Identifying project structure

You can use the `gradle projects` command to identify the project structure.

As an example, let’s use a multi-project build with the following structure:

    > gradle -q projects

    ------------------------------------------------------------
    Root project 'multiproject'
    ------------------------------------------------------------

    Root project 'multiproject'
    +--- Project ':api'
    +--- Project ':services'
    |    +--- Project ':services:shared'
    |    \--- Project ':services:webservice'
    \--- Project ':shared'

    To see a list of the tasks of a project, run gradle <project-path>:tasks
    For example, try running gradle :api:tasks

From a user’s perspective, multi-project builds are collections of tasks you can run. The difference is that you may want to control which project’s tasks get executed.

The following sections will cover your two options for executing tasks in a multi-project build.

## Executing tasks by name

The command `gradle test` will execute the `test` task in any subprojects relative to the current working directory that have that task.

If you run the command from the root project directory, you will run `test` in api, shared, services:shared and services:webservice.

If you run the command from the services project directory, you will only execute the task in services:shared and services:webservice.

The basic rule behind Gradle’s behavior is to execute all tasks down the hierarchy with this name. And complain if there is no such task found in any of the subprojects traversed.

| Some task selectors, like `help` or `dependencies`, will only run the task on the project they are invoked on and not on all the subprojects to reduce the amount of information printed on the screen.

Gradle looks down the hierarchy, starting with the current directory, for tasks with the given name and executes them.

One thing is essential 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 directory, 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.

When using the Gradle wrapper, executing a task for a specific subproject by running Gradle from the subproject’s directory doesn’t work well because you have to specify the path to the wrapper script if you’re not in the project root. For example, if you want to run the `build` task for the webservice subproject, and you’re in the webservice subproject directory, you must run `../../gradlew build`.

The following section shows how this can be achieved directly from the project’s root directory.

## Executing tasks by fully qualified name

You can use a task’s fully qualified name to execute a specific task in a particular subproject. For example: `gradle :services:webservice:build` will run the `build` task of the webservice subproject.

The fully qualified name of a task is its project path plus the task name.

This approach works for any task, so if you want to know what tasks are in a particular subproject, use the `tasks` task, e.g. `gradle :services:webservice:tasks`.

Regardless of which technique you use to execute tasks, Gradle will build any subprojects that the target depends on. You don’t have to worry about the inter-project dependencies.

## 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 various projects. The `buildNeeded` and `buildDependents` tasks can help with this.

In this example, the `:services:person-service` project depends on both the `:api` and `:shared` projects. The `:api` project also depends on the `:shared` project.

Assuming you are working on a single project, the `:api` project, and 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 parts of the project you have changed.

The `build` task does this:

Output of `gradle :api:build`

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

    BUILD SUCCESSFUL in 0s

If you have just gotten the latest version of the source from your version control system, which included changes in other projects that `:api` depends on, you might want to build all the projects you depend on AND test them too.

The `buildNeeded` task builds AND tests all the projects from the project dependencies of the testRuntime configuration:

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

    BUILD SUCCESSFUL in 0s

You may want to refactor some part of the `:api` project that is used in other projects. If you make these changes, testing only the `:api` project is not sufficient. You must test all projects that depend on the `:api` project.

The `buildDependents` task tests ALL the projects that have a project dependency (in the testRuntime configuration) on the specified project:

    > gradle :api:buildDependents
    > Task :shared:compileJava
    > Task :shared:processResources
    > Task :shared:classes
    > Task :shared:jar
    > Task :api:compileJava
    > Task :api:processResources
    > Task :api:classes
    > Task :api:jar
    > Task :api:assemble
    > Task :api:compileTestJava
    > Task :api:processTestResources
    > Task :api:testClasses
    > Task :api:test
    > Task :api:check
    > Task :api:build
    > Task :services:person-service:compileJava
    > Task :services:person-service:processResources
    > Task :services:person-service:classes
    > Task :services:person-service:jar
    > Task :services:person-service:assemble
    > Task :services:person-service:compileTestJava
    > Task :services:person-service:processTestResources
    > Task :services:person-service:testClasses
    > Task :services:person-service:test
    > Task :services:person-service:check
    > Task :services:person-service:build
    > Task :services:person-service:buildDependents
    > Task :api:buildDependents

    BUILD SUCCESSFUL in 0s

Finally, you can build and test everything in all projects. Any task you run in the root project folder will cause that same-named task to be run on all the children.

You can run `gradle build` to build and test ALL projects.