Gradle versions catalog integration
Tags: android, gradle, kotlin
Published: 2022-01-28 18:57:05

This post is a continuation from another, I'd advise reading that prior to tucking it this. You can find it [here](https://dev.to/charlietap/upgrading-to-gradles-modern-plugin-configuration-5h40)

## A versions what?
---

Gradles versions catalog is new feature in modern versions of Gradle that allows you to centralise your projects dependencies, plugins and their respective versions into a single location. (though its possible to have more than one).

If you've worked with projects that have more than one module, you'll know the pain of trying to keep all of your dependencies in alignment across all of the modules. The solution prior to the versions catalog introduction, was to create files inside the special Gradle buildSrc folder which could then be referenced in your build.gradle files. Whilst there's nothing terribly wrong with this approach, Gradle advocates for the versions catalog, and it has some additional benefits which you can leverage in certain conditions.

For example, imagine you work in a large team, on a big project, and you have several repositories which are essentially modules for the same application. Rather than having different catalogs in each repository, you could publish the catalog to a repository like Maven and consume it in each repository, ensuring that even separate repos have their dependencies aligned. You can read more about this [here](https://docs.gradle.org/current/userguide/platforms.html#sec:version-catalog-plugin)

## Okay enough spiel, lets see it what it looks like
---

The catalog is written in a config language called toml, I've put a cut down implementation below just to showcase the sections.


#### **`build.gradle`**
```toml
[versions]

compileSdk = "31"
minSdk = "23"
targetSdk = "31"

appVersionCode = "1"
appVersionName = "1.0"
applicationId = "com.x.y"

kotlin = "1.5.31"
android-build-tools-plugin = "7.1.0"

hilt-core = "2.40.5"
hilt-integrations = "1.0.0"

[plugins]

plugin-kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
plugin-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
plugin-android = { id = "com.android.application", version.ref = "android-build-tools-plugin" }
plugin-android-lib = { id = "com.android.library", version.ref = "android-build-tools-plugin" }

[libraries]

hilt-core = { module = "com.google.dagger:hilt-android", version.ref = "hilt-core"}
hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt-core"}
hilt-integrations-work = { module = "androidx.hilt:hilt-work", version.ref = "hilt-integrations"}
hilt-integrations-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hilt-integrations"}
hilt-integrations-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hilt-compose"}


[bundles]

hilt-deps = [ "hilt-core", "hilt-integrations-work", "hilt-integrations-compose" ]
hilt-compilers = [ "hilt-compiler", "hilt-integrations-compiler" ]

```


## Thats... different

---

It is, but at a high level its very simple, there's four sections:

1. A section for declaring versions
2. A section for declaring plugins
3. A section for declaring libraries 
4. A section for declaring bundles (basically a logical grouping of libraries)

You place this file in your projects top level gradle folder and you should be ready to use it.

## How to reference the different sections

---


###For plugins

You can reference them when loading them into the classpath as discussed in the prior article.

That looks like this:

#### **`build.gradle`**
```groovy
plugins {
    alias(libs.plugins.plugin.kotlin.android) apply false
}
```
Remember the apply false, you don't want to apply it here, it needs to be applied in each module you need it in respectively.

Applying inside the module using the alias notation requires Gradle 7.4 which is currently at rc-01, if you're willing to upgrade early you can do this.

#### **`app/build.gradle`**
```groovy
plugins {
    alias(libs.plugins.plugin.android) 
}
```
The default is to apply, thus when not putting apply at all it will apply the plugin on that module.

If you are not in a position to upgrade and for Gradle versions < 7.4, you can do this:

#### **`app/build.gradle`**
```groovy
plugins {
    id "org.jetbrains.kotlin.android"
}
```

###For versions

Individual versions can be referenced in your build.gradle files, it allows you to do things like this:

#### **`app/build.gradle`**
```groovy 
android {

    compileSdkVersion libs.versions.compileSdk.get() as Integer

    defaultConfig {
        applicationId libs.versions.applicationId.get()
        minSdkVersion libs.versions.minSdk.get() as Integer
        targetSdkVersion libs.versions.targetSdk.get() as Integer
        versionName libs.versions.appVersionName.get()
        versionCode libs.versions.appVersionCode.get() as Integer
    }
...
```

###For libraries

For libraries its equally simple

#### **`app/build.gradle`**
```groovy
dependencies {
    implementation libs.material
}
```
###For bundles

Bundles provide a great way to group related dependencies and save you some line space, similarly to bundles they can be implemented like so:

#### **`app/build.gradle`**
```groovy
dependencies {
    implementation libs.bundles.hilt.deps
    kapt libs.bundles.hilt.compilers
}
```

## Fin

Next up I'll be looking at tidying up Gradle files using precompiled Gradle script plugins..