Sitemap

πŸ› οΈ How to Use Composite Builds in Gradle to Work Locally with Shared Modules πŸ€–

4 min readApr 12, 2025

--

In modern projects that use Gradle β€” whether Android, KMP, Kotlin backend, or others β€” it’s common to centralize business logic in an external library πŸ“š published to remote repositories like GitHub Packages or Maven Central . However, during development, constantly publishing changes can be slow and inefficient.

An ideal alternative βœ… is to use Gradle’s Composite Builds. This allows you to reference the source code of an external project directly, without the need to publish it ☁️.

In this article πŸ“, you’ll learn how to configure βš™οΈ an Android project (used as an example) to locally include a shared module using Composite Builds πŸ”—. That way, you’ll replace a published dependency with the module’s actual source code πŸ“„.

πŸ“ Project Structure

Let’s assume your folder structure looks like this:

/my-project/ πŸ“‚
β”œβ”€β”€ test-android/ # Main Android project πŸ“±
β”œβ”€β”€ sharedlibrary/ # Shared project (KMP or Android Library) 🧩
β”‚ └── shared-library/ # Shared module 🧠

πŸ“š Create Android Library or KMP project (For this example)

Let’s create an Android library project from scratch, which will serve as a practical example to demonstrate how to integrate local libraries into Android projects. This project will contain a string constant that we will use in a small Android application project.

Within the shared-library module, add the following code:

object TestData {
const val value = "External value from shared-library"
}

πŸ“±Create Android Project

Now, we proceed to create a simple Android project (Empty Activity) where we will add the following configurations:

Within the build.gradle.kts of the :app module, add a reference dependency:

implementation("com.example.shared:shared-library")

βš™οΈ Configure settings.gradle.kts in the Android Project

The next step is to configure the settings.gradle.kts file to integrate our local library. Add the following includeBuild block to reference the sharedlibrary project and define a dependency substitution:

includeBuild("../sharedlibrary") {
dependencySubstitution {
substitute(module("com.example.shared:shared-library"))
.using(project(":shared-library"))
}
}

🧐 What does this block do?

  • includeBuild("../sharedlibrary"): Tells Gradle to include the external sharedlibrary project as a Composite Build.
  • dependencySubstitution: Defines a rule to substitute the published dependency (com.example.shared:shared-library) with the local module :shared-library.

Make sure the module name (:shared-library) exactly matches the one declared in the settings.gradle.kts file of the sharedlibrary project.

βœ… Runtime Verification

To confirm that our Android project is indeed using the local version of the shared library, we referenced the TestData object that was previously defined in the shared-library.

In MainActivity, we simply used it like this:

Text(
text = TestData.value
)

When running the app, the following message is displayed:

External value from shared-library

This confirms that the local changes in the library are being picked up by the Android project, proving that the Gradle Composite Build setup is working as expected.

From now on, any changes you make in shared-library will be instantly visible in test-android without the need to publish the library.

Another way to confirm that the settings have been applied correctly is by checking the Project View tool in Android Studio (or IntelliJ IDEA), where the sharedlibrary project should now appear as a referenced module.

πŸ” Important Note About Local Changes

Android Studio may show changes from the shared library (e.g., Android Chart Library) as if they were part of your main Android project, even though they belong to a separate module. This can create confusion, especially when reviewing changes before committing.

To get a more accurate and project-specific view of what has really changed, you can use Git in the terminal:

βœ… View all modified or untracked files

git ls-files -m -o --exclude-standard

πŸ“Š Count how many files have changes

git ls-files -m -o --exclude-standard | wc -l

πŸ’‘ Run these commands inside each project (test-android and sharedlibrary) to see exactly which files were modified. This will help you avoid the misleading perception of changes caused by how Android Studio aggregates changes across builds.

πŸ’‘ Extra Tip: Use a Git Tool Outside of Android Studio

When working with Composite Builds, tools like GitKraken, Fork, Sourcetree, or even the terminal are better alternatives for reviewing and managing Git changes. These tools offer a clearer, project-specific diff view, avoiding the false positives that can appear in the built-in VCS (Version Control System) of Android Studio or IntelliJ IDEA.

This ensures that only actual changes from your current working directory are committed β€” not the ones mistakenly shown as modified due to how composite builds are linked in the IDE.

🧠 Conclusion

Using Composite Builds with dependency substitution boosts your development workflow ⚑. It allows you to work with local changes in shared modules instantly, without needing to publish intermediate versions πŸ“¦. This speeds up iteration and testing across multiple modules in real-time, improving productivity πŸš€.

For clearer change tracking, consider using Git tools like GitKraken, Fork, Sourcetree, or even the terminal πŸ’» to avoid confusion caused by IDE-specific Git handling.

In short, Composite Builds in Gradle are a powerful and efficient solution for managing shared dependencies in modern projects.

--

--

Jorge Luis Castro Medina
Jorge Luis Castro Medina

Written by Jorge Luis Castro Medina

I'm a Software Engineer passionate about mobile technologies, and I like everything related to software design and architecture

Responses (1)