<commit_before>// 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.
[[sharing_build_logic_between_subprojects]]
= Sharing Build Logic between Subprojects

[[sec:convention_plugins]]
== Convention Plugins

Usually subprojects in a multi-project build share some common traits.
For example, several subprojects may contain _code_ in a particular programming language while another subproject may be
dedicated for _documentation_.
Code quality rules apply to all of the _code_ subprojects but not the _documentation_ subproject.
At the same time, the subprojects that share one common trait may serve different purposes - they may produce different _artifact types_ that further differentiate them, 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 to use its plugin system.
A plugin should define the _type_ of a subproject.
In fact, <<plugin_reference#,Gradle core plugins>> are modeled in the same way - for example <<java_plugin#,java plugin>> configures a generic `java` project,
while <<java_library_plugin#,java-library plugin>> internally applies the <<java_plugin#,java plugin>> and configures aspects specific to a generic Java library.
Similarly, the <<application_plugin#,application plugin>> applies and configures the <<java_plugin#,java plugin>> and the <<distribution_plugin#,distribution plugin>>.

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

We recommend putting source code and tests for the convention plugins in the special `buildSrc` directory in the root directory of the project.
For more information about `buildSrc`, consult <<organizing_gradle_projects.adoc#sec:build_sources,Using buildSrc to organize build logic>>.

Have a look at the link:../samples/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.
With cross configuration, build logic can be injected into a subproject and this is not obvious when looking at the subproject's
build script.
In the long run, cross configuration usually grows complex with more and more conditional logic and a higher maintenance burden.
Cross configuration can also introduce <<sec:decoupled_projects,configuration-time coupling between projects>>, which can prevent optimizations like
<<sec:configuration_on_demand,configuration-on-demand>> from working properly.

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 a 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:convention_plugins,sharing build logic between subprojects via convention plugins>> is cross project configuration.
This is a powerful feature, but one that should be used with caution.
Before we dive into the details, do check if your <<sec:convention_plugins_vs_cross_configuration,use case can be solved using convention plugins instead>>.

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.<commit_msg>Fix documentation links between pages<commit_after>// 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.
[[sharing_build_logic_between_subprojects]]
= Sharing Build Logic between Subprojects

[[sec:convention_plugins]]
== Convention Plugins

Usually subprojects in a multi-project build share some common traits.
For example, several subprojects may contain _code_ in a particular programming language while another subproject may be
dedicated for _documentation_.
Code quality rules apply to all of the _code_ subprojects but not the _documentation_ subproject.
At the same time, the subprojects that share one common trait may serve different purposes - they may produce different _artifact types_ that further differentiate them, 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 to use its plugin system.
A plugin should define the _type_ of a subproject.
In fact, <<plugin_reference#,Gradle core plugins>> are modeled in the same way - for example <<java_plugin#,java plugin>> configures a generic `java` project,
while <<java_library_plugin#,java-library plugin>> internally applies the <<java_plugin#,java plugin>> and configures aspects specific to a generic Java library.
Similarly, the <<application_plugin#,application plugin>> applies and configures the <<java_plugin#,java plugin>> and the <<distribution_plugin#,distribution plugin>>.

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

We recommend putting source code and tests for the convention plugins in the special `buildSrc` directory in the root directory of the project.
For more information about `buildSrc`, consult <<organizing_gradle_projects.adoc#sec:build_sources,Using buildSrc to organize build logic>>.

Have a look at the link:../samples/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.
With cross configuration, build logic can be injected into a subproject and this is not obvious when looking at the subproject's
build script.
In the long run, cross configuration usually grows complex with more and more conditional logic and a higher maintenance burden.
Cross configuration can also introduce <<multi_project_configuration_and_execution#sec:decoupled_projects,configuration-time coupling between projects>>, which can prevent optimizations like
<<multi_project_configuration_and_execution#sec:configuration_on_demand,configuration-on-demand>> from working properly.

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 a 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:convention_plugins,sharing build logic between subprojects via convention plugins>> is cross project configuration.
This is a powerful feature, but one that should be used with caution.
Before we dive into the details, do check if your <<sec:convention_plugins_vs_cross_configuration,use case can be solved using convention plugins instead>>.

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.
{'fraction_non_alphanumeric': 0.05126831011075384, 'fraction_numerical': 0.0014290818149339049, 'mean_word_length': 5.409273039496279, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 59, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7156546', 'n_tokens_mistral': 2598, 'n_tokens_neox': 2483, 'n_words': 1419}