Gradle Multi-Project Builds TODEPLETE
External
- https://docs.gradle.org/current/userguide/multi_project_builds.html
- https://guides.gradle.org/creating-multi-project-builds/
- https://docs.gradle.org/current/userguide/tutorial_java_projects.html#sec:examples
- https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:multi_project_builds
Internal
Overview
A multi-project build is a build where more than one project is built during a single execution run. Multi-project builds are always represented by a tree of Project instances with a single root. Usually, there is a direct mapping between Project tree elements and directories on the file system where the project configuration and files are maintained, but this behavior is configurable.
A project has a name, and a fully qualified path which uniquely identifies it in the hierarchy.
The project hierarchy is described in the settings.gradle file of the root project. This file is required for multi-project builds. The root project build file can be used to configure as much commonality as possible in the allprojects{...} block, leaving sub-projects to customize only what is specific for them.
A sub-project is a project that is part of a multi-project hierarchy, and it is not the root project. There is a subprojects{...} script block that can be used to provide configuration for sub-projects only. Sub-project may have their own settings.gradle and build.gradle configuration files, though they are not required: the behavior of sub-project can be configured in the root project's configuration files.
The component project and the associated structure of a multi-project build can be displayed with:
gradle projects
It is possible to run any task in any sub-project with the following syntax:
gradle :<sub-project-path>:<task-name>
If you were to spend a lot of time working in one sub-project, changing to that directory and running the build from there is normal. Running a task from that subdirectory will trigger all necessary actions form its dependency projects, thanks to the Gradle task graph implementation.
Multi-Projecte Build Layout
A multi-project build can have a flat or hierarchical layout.
A hierarchical layout allows for multiple level of projects. The path of a sub-project relative to the root project is assumed to match the relative file system path of the directory hosting the sub-project. For example, a ":sub-project1:child2" sub-project is mapped onto a "./sub-project1/child2" directory, relative to the root directory of the project. "project1:child2:subchild3" implies three projects: "project1", "project1:child2" and "project1:child2:subchild3". A hierarchical layout is specified by the include(...) method of the Settings object, invoked in the settings.gradle configuration file.
A flat layout is is specified by the includeFlat(...) method, which takes directory names are argument. These directories need to exist as samplings of the root project directory.
Inter-Project Dependencies
Sub-projects do not automatically expose their artifacts to other sub-projects of the same multi-build project. The dependencies between sub-projects must be declared explicitly in the dependencies{...} script block of the dependent sub-project. For example, if classes that belong to "subproject-B" depend on classes in "subproject-A", then subproject-B build.gradle must contain:
dependencies {
...
implementation project(':subproject-A')
...
}
Selective Project Configuration
Selective project configuration can be achieved via project filtering, by invoking Project's configure(...) method with a predicate closure that selects specific sub-projects, as shown in the example below. The method is executed in the configuration phase, in the order in which it was specified in build.gradle: if other script blocks are declared under the configure(...) method invocation, they will be executed after it, possibly overwriting configuration introduced by configure(...).
configure(subprojects.findAll {it.name == 'subproject-A' || it.name == 'subproject-B'} ) {
println "configuring sub-project $it"
apply plugin : ...
dependencies {
...
}
}