Why duplicate plugins in top-level build scripts

In many Android projects, I notice this in the root build.gradle file:

plugins {
    // this is necessary to avoid the plugins to be loaded multiple times
    // in each subproject's classloader
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.androidLibrary) apply false
    alias(libs.plugins.jetbrainsCompose) apply false
    alias(libs.plugins.compose.compiler) apply false
    alias(libs.plugins.kotlinMultiplatform) apply false
    alias(libs.plugins.kotlinParcelize) apply false
    alias(libs.plugins.kotlinSerialization) apply false
    alias(libs.plugins.buildConfig) apply false
    alias(libs.plugins.detekt) apply false
}

• I couldn’t find explanation for this anywhere. Why are we doing this? Is it not enough to specify the plugin to apply only in the subprojects that actually use it?
• The code comment seems confusing, and feels like Gradle’s implementation details leaking. Is this really the recommended practice? I couldn’t find it explained anywhere in the docs.
• The settings script (settings.gradle[.kts]) also has the “plugins {}” top-level block. Is it somehow related to this?

I will greatly appreciate a clear explanation. Thank you in advance.

It usually doesn’t make sense to add all plugins like that, but for some plugins it is necessary indeed.
If for example a plugin uses a shared build service to communicate between tasks in different projects in the build, it wouldn’t work without that or something similar, because as the comment correctly states, the plugin classes would then be taken from the classloaders of the subprojects’ build script classpath and thus be different classes. By putting it to the root project build script like that, or by putting the same instead in the settings script top-level plugins block, or by adding it to the buildscript classpath of the root project or settings script manually, or by adding it as dependencies in buildSrc, all that puts it to a classloader that is higher in the hierarchy and a common parent of all projects’ build script classloaders, so the classes are then used from there.

1 Like

Thank you Björn, I really appreciate your response.

I have to admit though, that it’s still really confusing (and that it’s Gradle’s/plugin’s implementation details leaking). Is there maybe a piece of Gradle docs that explains it in more detail?

There is at least none I’m aware of.