loading...

Better dependency management in Android Studio 3.5 with Gradle buildSrcVersions

jmfayard profile image Jean-Michel Fayard πŸ‡«πŸ‡·πŸ‡©πŸ‡ͺπŸ‡¬πŸ‡§πŸ‡ͺπŸ‡ΈπŸ‡¨πŸ‡΄ Updated on ・4 min read

Android Studio 3.5 is released! Have you updated yet? Go to https://developer.android.com/studio, I will wait.

Personally, I'm most excited not by any new feature but by a bugfix which makes relevant again for android developers my open-source project for managing dependencies.

GitHub logo jmfayard / refreshVersions

Life is too short to google for dependencies and versions

refreshVersions

End the dependency hell in minutes.

refreshVersions latest release on Gradle plugin portal dependencies plugin latest release on Gradle plugin portal Kotlinlang Slack Code Triage GitHub

What

The refreshVersions plugin targets all kinds of Gradle projects, including the following:

  • Kotlin Multiplatform

  • Android

  • Kotlin/JS, Kotlin/JVM, Kotlin/Native

  • Java

The refreshVersions Gradle plugin brings the following benefits:

  1. Centralizes dependencies versions (very useful in multi-module projects)

  2. Shows available updates in seconds

  3. Allows applying the available updates with minimal effort

Why (the problem this project solves)

Gradle multi-module projects are on the rise because of how it enforces code decoupling which is a good thing for maintenance and inevitable changes.

Unfortunately, that means the number of build files (build.gradle[.kts]) are multiplied which makes upgrading the dependencies versions where significantly more tedious as you now need to open, edit and check more files.

Also, some library vendors like Google are publishing artifacts with different versions (AndroidX, Google Play Services and Firebase, just to name a few). AndroidX for example has about 70…

This project was born out of a growing disgust for this dark corner of Android Studio:

πŸ™€ Gradle project sync failed. [Try again] πŸ™€

"Try Again" is kind of misnomer here.

Android Studio support for editing the Gradle files was bad 😿

Android Studio is in general a magnificent IDE, and integration with Gradle is an essential component of it. So you would expect to have great tooling support for editing your build files.

Instead, this error message is the exact moment where it all breaks down. Instead of Try Again, the wording should be more something like: "You have some error, somewhere, and you are on your own to fix it. Good luck, and tell me when you think you are done.".

The developer experience becomes more like something you would expect from the JavaScript world. You copy/paste some stuff from some website, hopefully at the right place (which is non-trivial!). Hoping for the best, you run it and a cryptic error message is thrown. Rince and repeat.

Why is the tooling so bad? Pretty much the same reasons that in the javascript world: we are doing lots of meta-programming stuff (with Gradle plugins) using a dynamic language (Groovy).

Gradle has the right long-term plan to overcome this problem: write less Groovy and more Kotlin.

But while Kotlin is probably the future, Groovy is the present. And we need some incremental progress to help us here and now with our existing builds.

The Gradle "buildSrc" module 😼

With Android Studio 3.5, the Gradle "buildSrc" module comes to the rescue.

The "buildSrc" is a Gradle module where you can write Kotlin code like usual (with full tooling support). That code is then be available to all your build files - not your final application. Crucially IntelliJ IDEA and Android Studio have good support for calling it from build.gradle

You can put all the things there that are a bit complicated or should be reused, and keep your build.gradle files nice and tidy.

The main use-case I had in mind was to replace those Groovy libraries.gradle files we used to write:

That's quite straightforward but... do I have to write all this code manually?

Laziness is one of the three great virtues of a programmer, so I wrote a plugin which asks Gradle which dependencies my project is using and let the KotlinPoet generate those files.

Gradle buildSrcVersions 😸

Install the plugin by editing your root build.gradle(.kts) file like this:

The plugin adds a task to your build, also called :buildSrcVersions.

Run it like this:

Sync your Gradle build.

You can now start to replace your magic strings with the properties available in Libs.kt

Finally the IDE tooling we deserve:

  • auto-completion
  • jumping to definition
  • ...

But the more important half of what the plugin do is looking automatically for you what are the newer versions available for all your dependencies!

😻 Search for dependencies updates

Upgrade dependencies tend to be tedious. But it is really important to manage them properly. Here are some reasons:

  • Few projects have versioned documentation: master/README.md is their documentation. This means you can waste time trying out snippets that do not work in the version you are using.
  • When you open an issue, you will often be asked: Can you reproduce this problem in the latest version?
  • On the other hand, you don't want to break your app because there was a breaking change and you didn't bother to read the CHANGELOG documenting it.

This plugin inherits from ben-manes/gradle-versions-plugin the feature to automatically determine which dependencies have updates.

When you decide you want to update some dependencies, run the plugin again:

The file Versions.kt is regenerated with a comment indicating which new version is available.

At that point, your build is exactly the same. Commit.

Don’t waste your time finding out manually what is the exact latest stable version available. Instead, spend it deciding whether you want or not to update the version. The format is optimized to update with one DELETE key:

Press DELETE to update

This screencast shows this in action:

Once you are done:

  • Sync your Gradle build
  • Run your unit tests and otherwise verify that it works.
  • Commit.

Show me an example! 😽

I submitted a pull-request to dev.to's Android app

Dependencies management with Gradle buildSrcVersions #44

Description

Hello, I refactored the Gradle build to use my plugin buildSrcVersions to manage dependencies.

The files {Libs,Versions}.kt have been generated with the command $ ./gradlew buildSrcVersions

See https://github.com/jmfayard/buildSrcVersions

See this article https://dev.to/jmfayard/better-dependency-management-in-android-studio-3-5-with-gradle-buildsrcversions-34e9

Next Steps

Currently the versions in the dependencies are exactly the same as on master.

If you wish to update Kotlin, edit Versions.kt

If you want to update Gradle, run $ ./gradlew wrapper

New in Android Studio 3.5 πŸ†• ?

Let me backtrack a bit: the buildSrc is technically not a new thing. Gradle made it available a number of years ago and is widely used in JVM/IntelliJ projects. But it may well be new to you: the IDE integration that makes it a game changer launched in Android Studio 3.2. Without enough publicity. And then it got broken immediately after in Android Studio 3.3 and 3.4 with bug #123032843.

So you are excused if you missed the news, and now is a good time to give it a try.

As a conclusion, I will share my favorite reaction after first posting this story:

References πŸ“š

Github

GitHub logo jmfayard / refreshVersions

Life is too short to google for dependencies and versions

refreshVersions

End the dependency hell in minutes.

refreshVersions latest release on Gradle plugin portal dependencies plugin latest release on Gradle plugin portal Kotlinlang Slack Code Triage GitHub

What

The refreshVersions plugin targets all kinds of Gradle projects, including the following:

  • Kotlin Multiplatform

  • Android

  • Kotlin/JS, Kotlin/JVM, Kotlin/Native

  • Java

The refreshVersions Gradle plugin brings the following benefits:

  1. Centralizes dependencies versions (very useful in multi-module projects)

  2. Shows available updates in seconds

  3. Allows applying the available updates with minimal effort

Why (the problem this project solves)

Gradle multi-module projects are on the rise because of how it enforces code decoupling which is a good thing for maintenance and inevitable changes.

Unfortunately, that means the number of build files (build.gradle[.kts]) are multiplied which makes upgrading the dependencies versions where significantly more tedious as you now need to open, edit and check more files.

Also, some library vendors like Google are publishing artifacts with different versions (AndroidX, Google Play Services and Firebase, just to name a few). AndroidX for example has about 70…

Discussion

markdown guide
 

Cool trick! I think it's good to know that when you update a version, this will change the classpath generated by buildSrc which will cause most if not all main build tasks to re-execute. This can be highly counter-productive in larger projects.

 

Which is one of the reason why I just released another solution based on generating dependencies and plug-in versions inside gradle.properties
Have a look here
github.com/jmfayard/buildSrcVersio...