Ohohohoh Gradle. Making Android software turns this into a form of Stockholm syndrome, where you just get used to it. (And as some colleagues go, even pretend to like it. That is, until the next time it does something utterly stupid.) I have spent half a day trying to get a set of tasks to run depending on files that were changed since the original commit that started the git branch. This ought to be simple. Get all the files changed since the start, figure out their modules, figure out modules that have a dependency on those, run the tests only on those modules!

In Gradle-insanity land, you'll need a whole plugin for that. That you have to register in the buildScript.classpath closure. Wait, is it also in the plugins block of the root file ? But maybe also the modules themselves, as an apply. Or is it a plugin block too ? Oh wait, you're using buildSrc ? Well that's a whole other problem. Don't forget you need a basic .properties file in META-INF that just gives out the plugin's name so it can discover it through reflection instead of having a proper API to do so.

You would think the Kotlin scripts instead would fix it, but oh no. Not content with adding a solid 10 seconds every time gradle builds your model (which it rebuilds... Kind of when it feels like it), half of the pretended benefits of it simply do not exist. Almost all the documentation online is for the Groovy scripts, which is, obviously, incompatible with the .kts scripts. And I'm not just talking about syntax, no! Entire APIs are different. Setting a flag like `enabled = true` in groovy ? Have fun, we've added an isEnabled instead, because why not. Registering tasks? Wait, hold on, we've added new solutions in Kotlin! The existing APIs weren't batshit insane already, so let's abuse kotlin delegation. Kotlin's `by lazy {}` is nice and simple, why do we not make your write `val taskName by creating { }` ? And through some horrible logic, the name of your variable is what is exposed to Gradle. Or abusing the same thing for you to read things from a .properties file, because what is more clear than `val isFlagEnabled by project` ? Isn't it obvious that it's going to read a .properties file ? Not the values given through the -P flag when building though, because that would actually make sense. But wait! Let the gradle website explain to you the logic of lazy registered tasks. Why do you need these, you ask? Because Gradle is so absolutely terrible that having a large amount of tasks means they all get created when your daemon starts. Or when it performs anything.

Oh, right, you need a daemon because why would you not need to eat 1GB of RAM just to not have horrible startup times for a build tool? Load all the tasks, at all the times! Add a development flavor to all your modules ? lol you've just doubled your amount of tasks.

Let's add to this of course the absolute insanity that are the Android build tools. Making those work in a Makefile would be hell. aapt2, dexing... An absolute abomination of an amalgamation of bad tools (lol aapt2 silently ignoring your vector drawable overrides because it doesn't like the android:fillType attribute.) and horrible performance (aapt2 taking over a minute to process files on a medium sized project, or kapt (but that's a Kotlin problem) being awful in terms of performance.) All this to output a glorified .zip in the end. Or whatever new format's Google drug addled minds have invented to lock you in further to the Play Store and to make you give them your signing keys.

I am not a fan of Gradle. Or Android's build tools.