// 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 on 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#plugin_reference,Gradle core plugins>> are modeled in the same way - for example, the <<java_plugin#java_plugin,Java Plugin>> configures a generic `java` project,
while <<java_library_plugin#java_library_plugin,Java Library Plugin>> internally applies the <<java_plugin#java_plugin,Java Plugin>> and configures aspects specific to a Java library in addition.
Similarly, the <<application_plugin#application_plugin,Application Plugin>> applies and configures the <<java_plugin#java_plugin,Java Plugin>> and the <<distribution_plugin#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]]
== Cross project configuration

Another, discouraged, way to share build logic between subproject is _cross project configuration_ via the `subprojects {}` and `allprojects {}` DSL constructs.
With cross configuration, build logic can be injected into a subproject and this is not obvious when looking at the subproject's
build script, making it harder to understand the logic of a particular subproject.
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>>.
