Joe Roskopf
Joe's Android Blog

Follow

Joe's Android Blog

Follow
Custom Gradle File Names In Modules

Custom Gradle File Names In Modules

Joe Roskopf's photo
Joe Roskopf
·Apr 11, 2023·

3 min read

If you're working on an Android project with multiple modules, you're probably familiar with the default build.gradle(.kts) file name for new modules. If you open the Now In Android project and search for build.gradle.kts, every module inside of the project will appear. This can often be a confusing situation to be in because you then have to start to fuzzy search to get the exact build file you want. The problem also compounds as your project grows in size.

However, what if you want to use a different name for the build.gradle.kts file, such as the name of the module? In this post, we'll show you how to write a custom Gradle function inside your settings.gradle.kts that allows you to do just that.

To get started, you'll need to create a new Gradle function inside settings.gradle.kts. Here is the function we will be adding:

fun includeModule(name: String) {
    settings.include(name)
    // `configureModuleWithProject` is yet to be defined
    configureModuleWithProject(name, project(name))
}

This function takes in one parameter, the name of the module. Using the Now In Android project as a reference again, there are two modules we will be focusing on: :feature:interests and :feature:topic

With our new function, we can include these modules inside of our settings.gradle.kts via:

includeModule(":feature:topic")
includeModule(":feature:interests")

Now, onwards to define the crux of our custom function, configureFileWithProject. This method will offer a lot of flexibility to fit within a multitude of Android projects, so the first thing we will want to do is break up the module name into its subsequent parts (which we're defining as logical modules/folders). We are doing this because we ultimately want to support multiple levels of nesting within our module structure. So for example, if we have :features:home:feed as a module name, we want to support naming the build files within this module either features-feed.gradle.kts or home-feed.gradle.kts (or just feed.gradle.kts) while still supporting leaving the file as build.gradle.kts too.

We then need to check for each of the supported file names existing. From our earlier example of :features:home:feed, we will need to:

  1. check if feed.gradle.kts exists

  2. If not, check if home-feed.gradle.kts exists

  3. If not, check if features-feed.gradle.kts exists

With all of that being said, here is the implementation of configureModuleWithProject :

fun configureModuleWithProject(
    moduleName: String,
    projectDescriptor: ProjectDescriptor,
) {
    projectDescriptor.apply {
        val name = moduleName.substringAfterLast(":")

        /**
         * Breakup the module name into its logical parts
         */
        val thirdToLastModuleIndex = lastOrdinalIndexOf(moduleName, ':', 3)
        val secondToLastModuleIndex = lastOrdinalIndexOf(moduleName, ':', 2)
        val lastModuleIndex = lastOrdinalIndexOf(moduleName, ':', 1)
        val directParentModule = moduleName.substring(secondToLastModuleIndex, lastModuleIndex).trim(':')
        val thirdLevelParentModule = moduleName.substring(thirdToLastModuleIndex, lastModuleIndex).trim(':').replace(":","-")

        // in the example :features:home:feed - check for just `feed.gradle.kts` first
        buildFileName = "$name.gradle.kts"

        if (!buildFile.exists()) {
            // if that does not exist, check for `home-feed.gradle.kts`
            buildFileName = "$directParentModule-$name.gradle.kts"
        }

        if (!buildFile.exists()) {
            // if that does not exist, check for `features-feed.gradle.kts`
            buildFileName = "$thirdLevelParentModule-$name.gradle.kts"
        }

        if (!buildFile.exists()) {
            // if that does not exist, check for the default `build.gradle.kts`
            buildFileName = "build.gradle.kts"
        }

        if (!buildFile.exists()) {
            // if none of the above exist, throw an exception
            throw GradleException("Build file: build.gradle, $name.gradle.kts, $directParentModule-$name.gradle.kts, or $thirdLevelParentModule-$name.gradle.kts does not exist. Cannot include module: $name")
        }
    }
}

Results

After adding our custom function to the Now In Android project, we can now see that the modules :features:interests and :feature:topic have its build file named interests.gradle.kts and :feature-topic.gradle.kts, which is less confusing to maintain in the long run.

In summary, if you want to use a different name for your build.gradle(.kts) files in your Android project, you can create a custom Gradle function that allows you to do just that.

 
Share this