Multi-Project Builds in Gradle
Introduction
Large codebases split into modules—shared libraries, APIs, and apps. Gradle links them in settings.gradle and wires dependencies with project(':module'). One ./gradlew build at the root compiles everything in the right order. This chapter builds a common + app layout and compares it to Maven multi-module projects.
Prerequisites
Layout
demo-monorepo/
settings.gradle
build.gradle # optional root config
common/
build.gradle
src/main/java/...
app/
build.gradle
src/main/java/...settings.gradle
rootProject.name = 'demo-monorepo'
include 'common', 'app'Gradle expects folders common/ and app/ with build.gradle each.
Root build.gradle (Shared Defaults)
subprojects { } runs for common and app. The root project itself may have no sources.
common Library Module
common/build.gradle:
plugins {
id 'java-library'
}
dependencies {
api 'com.google.code.gson:gson:2.11.0'
}common/src/main/java/com/example/common/Greeting.java:
package com.example.common;
public final class Greeting {
private Greeting() {}
public static String hello(String name) {
return "Hello, " + name;
}
}java-library + api exposes Gson to consumers if they use types from Gson in public API (here only strings—implementation would also work).
app Application Module
app/build.gradle:
plugins {
id 'application'
}
dependencies {
implementation project(':common')
}
application {
mainClass = 'com.example.app.Main'
}app/src/main/java/com/example/app/Main.java:
package com.example.app;
import com.example.common.Greeting;
public class Main {
public static void main(String[] args) {
System.out.println(Greeting.hello("Gradle"));
}
}Build and Run from Root
./gradlew build
./gradlew :app:runTask path syntax: :project:task (:app:run, :common:test).
List all projects:
./gradlew projectsProject Dependency Direction
app ──implementation──> commonNever create cycles (common must not depend on app). Gradle fails the build on circular project references.
Maven Comparison
| Maven | Gradle |
|---|---|
<modules> in parent POM | include in settings.gradle |
<parent> inheritance | subprojects / allprojects blocks |
| Inter-module dep | <dependency><artifactId>common</artifactId></dependency> |
| Build from root | mvn install |
Version Catalog in Monorepos
Place gradle/libs.versions.toml at root; subprojects use libs.gson—keeps versions consistent (see dependency chapter).
Mini Example: Task Only on One Module
// app/build.gradle
tasks.register('showMain') {
doLast {
println "Main class: " + application.mainClass.get()
}
}./gradlew :app:showMainFAQ
Root project has no src/?
Normal—root aggregates configuration; modules hold code.
Project with path ':common' not found?
Check include 'common' and folder name spelling.
Publish one module only?
./gradlew :common:publishToMavenLocal with maven-publish on that subproject.
IDEA import?
Open the root folder containing settings.gradle—IDEA loads all modules.