Published in


image by pixabay

Clean Dependency Management in Multi Module Android Projects

If you are working on a multi-module Android app and are searching for a clean and scalable way of organizing all the dependencies and build configurations of your project, then this article is for you. We will walk through an approach that organizes build configurations in a common place and takes advantage of Kotlin’s DSL support to enable clear syntax, powerful Kotlin features and smooth navigation within your build files.

Tools that we will use

Nowadays, it would be foolish to not use Gradle as the build automation tool for an Android project. Not only Gradle offers higher performance and customizability than other build tools, but it also comes with a very large library of plugins that make it a very powerful asset.

Indeed, you already likely use a plugin to integrate Gradle with Android Studio. We will also take advantage of the kotlin-dsl plugin to seamlessly write our build logic with Kotlin and add it to the Gradle files.

Structure that we will follow

It is common practice to use a buildSrc directory to encapsulate build logic. Google often uses this approach in their sample architecture projects and Gradle itself includes some tips about this in their documentation.

In a nutshell, logic such as dependency versioning, configuration data, code quality scripts, and other build scripts could be included in the buildSrc directory. The main advantage of using this directory model is that Gradle automatically compiles and test this code and adds it to the classpath of your build script, making it easier to maintain, refactor and test the code.

One important point to note here is that Gradle expects a single buildSrc directory, which has to exist in the project root. If you are still curious, you can read more about how Gradle’s build lifecycle works here.

Create the buildSrc directory

To make it easier, you can follow along the source code while reading the remaining of this article. We will start by creating a buildSrc directory to host our build logic. For illustration purposes, we will include dependency versioning in Dependencies.kt , and configuration data in ConfigurationData.kt. But keep in mind that you can write more sophisticated build scripts in this directory as your project grows.

To create the buildSrc directory simply go to the root directory of your project, click New, then Directory and name it buildSrc.

The image above shows the initial structure your buildSrc directory should have, and the files in orange (1 through 6) are the ones that we will be modifying.

Add the kotlin-dsl plugin

You may have noticed that the .gradle files were changed to include a .kts extension. This is because we wish to use Kotlin in those files, but before we can do that, we must also add the kotlin-dsl gradle plugin. To do that, modify buildSrc‘s build.gradle.kts(ie. file 2) to contain:

If you are unsure about what DSL, it stands for Domain Specific Language, and it is a higher level of abstraction of Kotlin, optimized for a specific problem. You can check out a great example of this straight from the docs.

Add logic to buildSrc

Ok, now our .gradle files understand Kotlin, but we don’t have any data to give them, yet. Change your ConfigurationData.kt to contain actual configuration data, such as:

And add the desired dependencies’ version data to Dependencies.kt:

The format used for Dependencies.kt allows you to organize your dependencies in objects and objects within objects, which can be very helpful as your project grows. Please check the source code for the full version of all files.

Add logic from buildSrc to gradle scripts

Great, we have some build information cleanly written in Kotlin within the buildSrc directory. Thanks to the kotlin-dsl plugin, we can access them from the .gradle files. For that, change your app module’s build.gradle.kts (file 1) to include:

Notice that the configuration data and library’s versions are directly accessible from the gradle script.

Exploring the advantages

This suggested approach to handle build configurations has some noteworthy advantages:

  • It behaves well for multi-module projects. That is, if more than one module depend on the same library, they can easily get the library’s version from the common buildSrc and use in their own build.gradle.kts. Moreover, modules can share other build scripts as well.
  • It supports testable and maintainable build scripts. Remember, buildSrc has Kotlin code, which means you can write your build logic using Kotlin and automatically test it using Gradle.
  • It allows you to take full advantage of your IDE. Go to your app module’s build.gradle.kts (file 1), holding Command (or Ctrl), click on stdlib in implementation(Libs.Kotlin.stdlib). You should navigate right to the definition of stdlib. Other than automated navigation, you can also now enjoy auto-complete suggestions while you write code, just like you already do for regular Kotlin files.

Thank you for reading! Don’t forget to check out the source code, you can always fork it if you wish to use it as base to a project. If you like the content, don’t forget to clap and follow for more!



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Joao Foltran

Joao Foltran

Android Engineer and avid runner