<commit_before>// Copyright 2017 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.

[[multi_project_builds]]
= Authoring 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.

A multi-project build in gradle consists of one root project, and one or more subprojects that may also have subprojects.

[[sec:sharing_configuration_between_subprojects]]
== Sharing configuration between subprojects

Usually subprojects in a multi-project build share some common traits.
For example, a project might consist of several subprojects containing _code_ written in a particular programming language as well as a subproject
dedicated for _documentation_.
There may be further traits that the _code_ subprojects share, such as certain code quality rules that we want to apply to all of them.
At the same time the subprojects that share one common trait may serve different purposes - they may produce different _artifact types_, for example:

 - _public libraries_ - libraries that are published to some repository
 - _internal libraries_ - libraries on which other subprojects depend internally within the project
 - _command line applications_ - applications with specific packaging requirements
 - _web services_ - applications with specific packaging requirements that are different from above
 - etc

Some other _code_ subprojects may be dedicated for _testing purposes_ and so on.

The traits above identify a subproject's _type_.
Or in other words, a subproject's _type_ tells us what traits the project has.

Gradle's recommended way of organizing build logic is its plugin system.
A plugin should define the _type_ of a subproject.
In fact, Gradle core plugins are modeled in the same way - for example `java` plugin configures a generic `java` project,
while `java-library` plugin internally applies the `java` plugin and configures aspects specific to a generic Java library.

Similarly, we can compose custom build logic by applying and configuring both core and external plugins and create custom plugins
that define new project _types_.
For each of the example traits from the beginning of this section, we can write a plugin that encapsulates
the logic common to the project of a given _type_.

Have a look at the link:{samplesPath}/sample_convention_plugins.html[sample that demonstrates a multi-project build that models the build logic using convention plugins].

Another, more complex and real-world example of a multi-project build that composes build logic using convention plugins
is the build of the link:https://github.com/gradle/gradle[Gradle Build Tool] itself.

[[sec:convention_plugins_vs_cross_configuration]]
=== Convention plugins versus cross project configuration

While cross-cutting aspects of subprojects can be configured using <<#sec:cross_project_configuration,cross project configuration>> as well,
doing so will make it harder to understand the logic of a particular subproject in the long term.
With cross configuration, build logic gets injected into a subproject and this is not evident from looking at the subproject's
build script.
In the long run cross configuration usually grows complex with more and more conditional logic being added.

There are two most common uses of cross-configuration that can be better modelled using convention plugins:

- Applying plugins or other configuration to subprojects of certain type.
Often the cross-configuration section will do `if subproject is of type X, then configure Y`.
This is equivalent to applying `X-conventions` plugin directly to a subproject.
- Extracting information from subprojects of certain type.
This use case can be modelled using <<cross_project_publications.adoc#sec:simple-sharing-artifacts-between-projects,outgoing configuration variants>>.

[[sec:cross_project_configuration]]
== Cross project configuration

While each subproject could configure itself in complete isolation of the other subprojects, it is common that subprojects share common traits.
It is then usually preferable to share configurations among projects, so the same configuration affects several subprojects.

Let's start with a very simple multi-project build.
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.


[[sec:configuration_and_execution]]
=== Configuration and execution

<<build_lifecycle.adoc#sec:build_phases,Build phases>> describes the phases of every Gradle build. Let's zoom into the configuration and execution phases of a multi-project build. Configuration here means executing the `build.gradle` (or `build.gradle.kts`) file of a project, which implies e.g. downloading all plugins that were declared using '```apply plugin```' or a `plugins` block. By default, the configuration of all projects happens before any task is executed. This means that when a single task, from a single project is requested, _all_ projects of multi-project build are configured first. The reason every project needs to be configured is to support the flexibility of accessing and changing any part of the Gradle project model.


[[sec:configuration_on_demand]]
==== Configuration on demand

The _Configuration injection_ feature and access to the complete project model are possible because every project is configured before the execution phase. Yet, this approach may not be the most efficient in a very large multi-project build. There are Gradle builds with a hierarchy of hundreds of subprojects. The configuration time of huge multi-project builds may become noticeable. Scalability is an important requirement for Gradle. Hence, starting from version 1.4 a new incubating 'configuration on demand' mode is introduced.

Configuration on demand mode attempts to configure only projects that are relevant for requested tasks, i.e. it only executes the `build.gradle[.kts]` file of projects that are participating in the build. This way, the configuration time of a large multi-project build can be reduced. In the long term, this mode will become the default mode, possibly the only mode for Gradle build execution. The configuration on demand feature is incubating so not every build is guaranteed to work correctly. The feature should work very well for multi-project builds that have <<#sec:decoupled_projects,decoupled projects>>. In “configuration on demand” mode, projects are configured as follows:

* The root project is always configured. This way the typical common configuration is supported (allprojects or subprojects script blocks).
* The project in the directory where the build is executed is also configured, but only when Gradle is executed without any tasks. This way the default tasks behave correctly when projects are configured on demand.<commit_msg>Reword intro to cross-project configuration section<commit_after>// Copyright 2017 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.

[[multi_project_builds]]
= Authoring 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.

A multi-project build in gradle consists of one root project, and one or more subprojects that may also have subprojects.

[[sec:sharing_configuration_between_subprojects]]
== Sharing configuration between subprojects

Usually subprojects in a multi-project build share some common traits.
For example, a project might consist of several subprojects containing _code_ written in a particular programming language as well as a subproject
dedicated for _documentation_.
There may be further traits that the _code_ subprojects share, such as certain code quality rules that we want to apply to all of them.
At the same time the subprojects that share one common trait may serve different purposes - they may produce different _artifact types_, for example:

 - _public libraries_ - libraries that are published to some repository
 - _internal libraries_ - libraries on which other subprojects depend internally within the project
 - _command line applications_ - applications with specific packaging requirements
 - _web services_ - applications with specific packaging requirements that are different from above
 - etc

Some other _code_ subprojects may be dedicated for _testing purposes_ and so on.

The traits above identify a subproject's _type_.
Or in other words, a subproject's _type_ tells us what traits the project has.

Gradle's recommended way of organizing build logic is its plugin system.
A plugin should define the _type_ of a subproject.
In fact, Gradle core plugins are modeled in the same way - for example `java` plugin configures a generic `java` project,
while `java-library` plugin internally applies the `java` plugin and configures aspects specific to a generic Java library.

Similarly, we can compose custom build logic by applying and configuring both core and external plugins and create custom plugins
that define new project _types_.
For each of the example traits from the beginning of this section, we can write a plugin that encapsulates
the logic common to the project of a given _type_.

Have a look at the link:{samplesPath}/sample_convention_plugins.html[sample that demonstrates a multi-project build that models the build logic using convention plugins].

Another, more complex and real-world example of a multi-project build that composes build logic using convention plugins
is the build of the link:https://github.com/gradle/gradle[Gradle Build Tool] itself.

[[sec:convention_plugins_vs_cross_configuration]]
=== Convention plugins versus cross project configuration

While cross-cutting aspects of subprojects can be configured using <<#sec:cross_project_configuration,cross project configuration>> as well,
doing so will make it harder to understand the logic of a particular subproject in the long term.
With cross configuration, build logic gets injected into a subproject and this is not evident from looking at the subproject's
build script.
In the long run cross configuration usually grows complex with more and more conditional logic being added.

There are two most common uses of cross-configuration that can be better modelled using convention plugins:

- Applying plugins or other configuration to subprojects of certain type.
Often the cross-configuration section will do `if subproject is of type X, then configure Y`.
This is equivalent to applying `X-conventions` plugin directly to a subproject.
- Extracting information from subprojects of certain type.
This use case can be modelled using <<cross_project_publications.adoc#sec:simple-sharing-artifacts-between-projects,outgoing configuration variants>>.

[[sec:cross_project_configuration]]
== Cross project configuration

An alternative to <<#sec:sharing_configuration_between_subprojects,sharing build logic between subprojects via convention plugins>> is cross project configuration.

Let's start with a very simple multi-project build.
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.


[[sec:configuration_and_execution]]
=== Configuration and execution

<<build_lifecycle.adoc#sec:build_phases,Build phases>> describes the phases of every Gradle build. Let's zoom into the configuration and execution phases of a multi-project build. Configuration here means executing the `build.gradle` (or `build.gradle.kts`) file of a project, which implies e.g. downloading all plugins that were declared using '```apply plugin```' or a `plugins` block. By default, the configuration of all projects happens before any task is executed. This means that when a single task, from a single project is requested, _all_ projects of multi-project build are configured first. The reason every project needs to be configured is to support the flexibility of accessing and changing any part of the Gradle project model.


[[sec:configuration_on_demand]]
==== Configuration on demand

The _Configuration injection_ feature and access to the complete project model are possible because every project is configured before the execution phase. Yet, this approach may not be the most efficient in a very large multi-project build. There are Gradle builds with a hierarchy of hundreds of subprojects. The configuration time of huge multi-project builds may become noticeable. Scalability is an important requirement for Gradle. Hence, starting from version 1.4 a new incubating 'configuration on demand' mode is introduced.

Configuration on demand mode attempts to configure only projects that are relevant for requested tasks, i.e. it only executes the `build.gradle[.kts]` file of projects that are participating in the build. This way, the configuration time of a large multi-project build can be reduced. In the long term, this mode will become the default mode, possibly the only mode for Gradle build execution. The configuration on demand feature is incubating so not every build is guaranteed to work correctly. The feature should work very well for multi-project builds that have <<#sec:decoupled_projects,decoupled projects>>. In “configuration on demand” mode, projects are configured as follows:

* The root project is always configured. This way the typical common configuration is supported (allprojects or subprojects script blocks).
* The project in the directory where the build is executed is also configured, but only when Gradle is executed without any tasks. This way the default tasks behave correctly when projects are configured on demand.
{'fraction_non_alphanumeric': 0.04367909788737178, 'fraction_numerical': 0.0013586033557502887, 'mean_word_length': 4.996741344195519, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7663247', 'n_tokens_mistral': 3310, 'n_tokens_neox': 3189, 'n_words': 2027}