More often that not, projects end up in one of these situations:
- Many random
*.gradle(.kts)scripts that not everyone understands.
- Very complicated
buildSrcdirectory that houses much of the build logic.
The first two can cause a lot of trouble down the line because you either end up with a lot of code duplication as developers tend to copy/paste these scripts when creating new modules, or you end up with massive configuration blocks that needlessly apply most of your build logic to every module. The third option is a bit better in terms of code duplication, but
buildSrc is not great because it invalidates build cache every time you make changes to anything inside it, effectively causing a clean build with every change.
These plugins are additive and composable, and try to only accomplish a single responsibility. Modules can then pick and choose the configurations they need.
Some really good examples from the codebase that show how this is all tied together are the following:
AndroidLibraryConventionPlugin applies the
org.jetbrains.kotlin.androidplugins, uses the
KotlinAndroid.ktto configure things like your
kotlinOptions, and the
configureFlavors()function from the
Flavor.ktfile to configure project flavors.
AndroidFeatureConventionPlugin applies the same plugins from above plus
org.jetbrains.kotlin.kapt because all features modules in NiA use libraries like Hilt which require KAPT for code generation. It also adds a lot of common
dependencies like the
:core modules and some libraries.
AndroidLibraryComposeConventionPlugin uses the
configureAndroidCompose() function to configure Compose to work in any module it’s applied to.
The result is your feature modules’ build scrips mostly end up looking like this, which is how they should. No duplication or unnecessary scripts that are hard to understand down the line. Just the things that your module needs.
You can immediately see what it means for these plugins to be additive and composable. Want a module that doesn’t use Compose? Just apply the first two plugins. Want to use Compose? Just add the third one. A good example of this in NiA is the
build.gradle.kts script in the
:feature-author module, which you can see here.
Those of you with a keen eye may have noticed that the plugin ids are different from their file names, that’s because when you register your custom plugins to be exposed to the rest of your project, they’re given an id and implementation. This can be seen here.
This article was originally published on proandroiddev.com on July 27, 2022