Declaring Dependencies between Subprojects
What if one project needs the artifact produced by another project on its compile classpath?

What if it also requires the transitive dependencies of the other project?
This is a common use case for multi-project builds. Gradle offers project dependencies for this.
Depending on another project
A typical multi-project build has the following layout:
.
├── buildSrc
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── api
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle.kts
└── settings.gradle.kts
.
├── buildSrc
│ ├── src
│ │ └──...
│ └── build.gradle
├── api
│ ├── src
│ │ └──...
│ └── build.gradle
├── services
│ └── person-service
│ ├── src
│ │ └──...
│ └── build.gradle
├── shared
│ ├── src
│ │ └──...
│ └── build.gradle
└── settings.gradle
In this example, there are three projects called shared
, api
, and person-service
:
-
The
person-service
project depends on the other two projects,shared
andapi
. -
The
api
project depends on theshared
project. -
Shared build logic used by
shared
,api
, andperson-service
is provided bybuildSrc
.
We use the :
separator to define a project path such as services:person-service
or :shared
.
Consult the DSL documentation of Settings.include(java.lang.String[]) for more information about defining project paths.
Shared build logic is extracted into a convention plugin in buildSrc
that is applied in the subprojects' build scripts that also define project dependencies:
rootProject.name = "dependencies-java"
include("api", "shared", "services:person-service")
plugins {
id("java")
}
group = "com.example"
version = "1.0"
repositories {
mavenCentral()
}
dependencies {
testImplementation("junit:junit:4.13")
}
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
plugins {
id("myproject.java-conventions")
}
dependencies {
implementation(project(":shared"))
}
plugins {
id("myproject.java-conventions")
}
plugins {
id("myproject.java-conventions")
}
dependencies {
implementation(project(":shared"))
implementation(project(":api"))
}
rootProject.name = 'dependencies-java'
include 'api', 'shared', 'services:person-service'
plugins {
id 'java'
}
group = 'com.example'
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
testImplementation "junit:junit:4.13"
}
plugins {
id 'groovy-gradle-plugin'
}
plugins {
id 'myproject.java-conventions'
}
dependencies {
implementation project(':shared')
}
plugins {
id 'myproject.java-conventions'
}
plugins {
id 'myproject.java-conventions'
}
dependencies {
implementation project(':shared')
implementation project(':api')
}
A project dependency affects execution order. It causes the other project to be built first and adds the output with the classes of the other project to the classpath. It also adds the dependencies of the other project to the classpath.
If you execute gradle :api:compile
, first the shared
project is built, and then the api
project is built.
Project dependencies enable partial multi-project builds. |
Depending on artifacts produced by another project
Project dependencies model dependencies between subprojects (modules).
Effectively, a project depends on the main output of another project. In a Java-based project, it’s usually a JAR file.
Sometimes, you may want to depend on an output produced by another task. As such, you want to ensure the task is executed first in order to produce that output. Declaring a task dependency from one project to another is a poor way to model this relationship and introduces unnecessary coupling.
The recommended way to model such a dependency is to produce the output and mark it as an "outgoing" artifact. Gradle’s dependency management engine allows you to share arbitrary artifacts between projects and build them on demand. Consult the Sharing outputs between projects section to learn more.