skip to content

How do you run a task that lives in an included build from the command line in a Gradle composite build?

level: juniorimportance: must knowfreq 55%

answer

  1. `:buildName:task` prefix
  2. build name = dir name unless overridden
  3. name set in includeBuild { name = ... }
  4. no special CLI flag
  5. root `build` skips included builds

basics

~10 s

Prefix the task path with the included build's name: ./gradlew :includedBuildName:some:task. The leading segment is the build name (its directory name unless overridden), not a project in the root build.

solid answer

~40 s

A composite build wires another standalone Gradle build into the main build via `includeBuild`. To invoke a task that physically lives inside that included build from the CLI, you address it with the included build's **name** as the first path segment: `./gradlew :my-lib:build` or `./gradlew :my-lib:sub:test`. The build name defaults to the included build's root directory name but can be set with `includeBuild('../my-lib') { name = 'lib' }`. This differs from ordinary project paths in the same build, which start with `:` and reference subprojects of the *current* build. Note that only the **root** of the composite (the build doing the including) exposes this addressing; you generally run from there. Use `./gradlew :build --include-build` is not needed — inclusion is configured in `settings.gradle(.kts)`.

code

bash · 8 lines
bash
# settings.gradle.kts of root build contains:
#   includeBuild("../my-lib") { name = "lib" }

# run a task in the included build 'lib'
./gradlew :lib:build

# run a task in a subproject of the included build
./gradlew :lib:core:test

go deeper

for a junior

Recall the :buildName:task syntax and that the name defaults to the directory name.

for a middle

Explain that included builds keep their own project tree and that root build does not cascade into them.

for a senior

Contrast build-name addressing with ordinary project paths and explain on-demand execution of included-build tasks.

for a principal

Discuss how this addressing underpins develop-together workflows and how naming/conventions keep large composites navigable.

## What an included build is A **composite build** is a build that includes other, otherwise-independent Gradle builds. You configure it in `settings.gradle(.kts)` of the *including* (root) build: ```kotlin // settings.gradle.kts includeBuild("../my-lib") ``` Each included build is a complete Gradle build with its own `settings.gradle(.kts)`, its own subprojects, and its own task graph. It is **not** flattened into the root build's project tree — it keeps its own identity. ## Build name vs. project path Every build in a composite has a **name**. By default the name is the included build's root directory name (`my-lib` above). You can override it: ```kotlin includeBuild("../my-lib") { name = "lib" } ``` Within a single build, task paths are `:subproject:task` (a leading `:` is the build's root project). In a **composite**, you reach into an included build by prefixing with that build's name: ``` :<buildName>:<subproject-path>:<task> ``` So `:lib:build` runs the `build` task of the root project of the included build named `lib`, and `:lib:core:test` runs `test` in its `core` subproject. ## Running it From the root build directory: ```bash ./gradlew :lib:build ./gradlew :lib:core:test ``` There is no extra CLI flag — the inclusion is already declared in settings, so Gradle resolves the leading segment as a build name. If you omit the build prefix (`./gradlew build`), Gradle runs the task only in the **root** build (and its subprojects), *not* in included builds — included-build tasks are run on demand, when addressed or when something depends on them. ## Why this matters Composite builds let you develop a library and its consumer together without publishing to a repository. Being able to address the library's tasks (`:lib:publishToMavenLocal`, `:lib:test`) directly from the consumer's command line is the everyday workflow.

  • What determines the build name used in the task path?
    By default it is the included build's root directory name. You can override it in the `includeBuild(...) { name = "..." }` configuration block in settings.
  • If you run `./gradlew build` at the root, do included builds' `build` tasks run?
    No. Included-build tasks only execute when explicitly addressed (`:lib:build`) or when a root-build task depends on them. A bare `build` runs only the root build and its subprojects.

saying these in an interview costs you the question

  • Thinking the leading segment is a subproject of the root build rather than a separate build's name.
  • Believing `./gradlew build` automatically runs all included builds' equivalent tasks.

context