// Copyright 2020 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
[[declaring_dependencies_between_subprojects]]
= Declaring Dependencies between Subprojects

[[sec:project_jar_dependencies]]
== Project dependencies

What if one project needs the jar produced by another project on its compile classpath? What if it also requires the transitive dependencies of the other project?
Obviously this is a very common use case for Java multi-project builds.
As mentioned in <<declaring_dependencies.adoc#sub:project_dependencies,Project dependencies>>, Gradle offers project dependencies for this.

.Project dependencies
====
[.multi-language-sample]
=====
.Project layout
[source, groovy]
----
.
├── buildSrc
│   ...
├── api
│   ├── src
│   │   └──...
│   └── build.gradle
├── services
│   └── person-service
│       ├── src
│       │   └──...
│       └── build.gradle
├── shared
│   ├── src
│   │   └──...
│   └── build.gradle
└── settings.gradle
----
=====
[.multi-language-sample]
=====
.Project layout
[source, kotlin]
----
.
├── buildSrc
│   ...
├── api
│   ├── src
│   │   └──...
│   └── build.gradle.kts
├── services
│   └── person-service
│       ├── src
│       │   └──...
│       └── build.gradle.kts
├── shared
│   ├── src
│   │   └──...
│   └── build.gradle.kts
└── settings.gradle.kts
----
=====
====

We have the projects `shared`, `api` and `person-service`.
The `person-service` project has a dependency on the other two projects.
The `api` project has a dependency on the `shared` project.
It has no build script and gets nothing injected by another build script.
We use the `:` separator to define a project path.
Consult the DSL documentation of link:{groovyDslPath}++/org.gradle.api.initialization.Settings.html#org.gradle.api.initialization.Settings:include(java.lang.String[])++[Settings.include(java.lang.String[\])] for more information about defining project paths.

[[javadependencies_2]]
====
include::sample[dir="snippets/multiproject/dependencies-java/groovy",files="settings.gradle[];buildSrc/src/main/groovy/myproject.java-conventions.gradle[];api/build.gradle[];shared/build.gradle[];services/person-service/build.gradle[]"]
include::sample[dir="snippets/multiproject/dependencies-java/kotlin",files="settings.gradle.kts[];buildSrc/src/main/kotlin/myproject.java-conventions.gradle.kts[];api/build.gradle.kts[];shared/build.gradle.kts[];services/person-service/build.gradle.kts[]"]
====

Shared build logic is extracted into a _convention plugin_ that is applied in the subprojects' build scripts that also define project dependencies.
A project 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.
You can trigger a `gradle :api:compile`. First the `shared` project is built and then the `api` project is built.
Project dependencies enable partial multi-project builds.


[[sec:depending_on_output_of_another_project]]
== Depending on artifacts produced by another project

<<#sec:project_jar_dependencies,Project dependencies>> model dependencies between modules.
Effectively, you are saying that you depend on the main output of another project. In a Java-based project that's usually a JAR file.

Sometimes you may want to depend on an output produced by another task.
In turn, you'll want to make sure that the task is executed beforehand to produce that very output.
Declaring a task dependency from one project to another is a poor way to model this kind of relationship and introduces unnecessary coupling.
The recommended way to model such a dependency is to produce the output, mark it as an "outgoing" artifact or add it to the output of the `main` source set which you can depend on in the consuming project.

Let's say you are working in a multi-project build with the two subprojects `producer` and `consumer`.
The subproject `producer` defines a task named `buildInfo` that generates a properties file containing build information e.g. the project version.
You can then map the task provider to its output file and Gradle will automatically establish a task dependency.

.Task generating a property file containing build information
====
include::sample[dir="snippets/multiproject/dependencies-outgoingArtifact/groovy/producer",files="build.gradle[]"]
include::sample[dir="snippets/multiproject/dependencies-outgoingArtifact/kotlin/producer",files="build.gradle.kts[]"]
.buildSrc/src/main/java/BuildInfo.java
[source, java]
----
include::{snippetsPath}/multiproject/dependencies-outgoingArtifact/groovy/buildSrc/src/main/java/BuildInfo.java[tags=task]
----
====

The consuming project is supposed to be able to read the properties file at runtime.
Declaring a project dependency on the producing project takes care of creating the properties beforehand and making it available to the runtime classpath.

.Declaring a project dependency on the project producing the properties file
====
include::sample[dir="snippets/multiproject/dependencies-outgoingArtifact/groovy/consumer",files="build.gradle[tags=producer-project-dependency]"]
include::sample[dir="snippets/multiproject/dependencies-outgoingArtifact/kotlin/consumer",files="build.gradle.kts[tags=producer-project-dependency]"]
====

In the example above, the consumer now declares a dependency on the outputs of the `producer` project.



Depending on the main output artifact from another project is only one example.
Gradle has one of the most powerful <<core_dependency_management#sec:dependency-mgmt-in-gradle,dependency management engines>> that allows you to share arbitrary artifacts between projects and let Gradle build them on demand.
For more details see the section on <<cross_project_publications#cross_project_publications,sharing outputs between projects>>.
