pluginManagement and Precompiled script plugins

Hi, I have a set of precompiled script plugins in a separate project (not under buildSrc). These plugins are applied to rootProject. But, it fails to resolve the plugin defined inside pluginManagement

An exception occurred applying plugin request [id: 'convention-plugin']
> Failed to apply plugin 'convention-plugin'.
   > org.gradle.api.plugins.UnknownPluginException: Plugin with id 'com.android.library' not found.

Folder structure

PrecompiledPlugins/
   src/main/groovy/convention-plugin.gradle
RootProject
   settings.gradle
   build.gradle
   app/build.gradle

RootProject/settings.gradle

pluginManagement {
    includeBuild "../PrecompiledPlugins"

    repositories {
        gradlePluginPortal()
        google()
    }

    apply from: "$commonDir/dependencies.gradle"

    plugins {
        id 'com.android.library' version "$versions.androidGradlePlugin" apply false
        ...
    }
}

PrecompiledPlugins/src/main/groovy/convention-plugin.gradle

plugins {
    id 'com.android.library'
}

When I apply convention-plugin

RootProject/app/build.gradle

plugins {
    id 'convention-plugin'
}

It fails with the aforementioned exception

An exception occurred applying plugin request [id: 'convention-plugin']
> Failed to apply plugin 'convention-plugin'.
   > org.gradle.api.plugins.UnknownPluginException: Plugin with id 'com.android.library' not found.

After I add a plugins { } block to RootProject/build.gradle, it works fine

RootProject/build.gradle

plugins {
    id 'com.android.library' apply false
}

I would like to avoid applying the plugin twice, in settings.gradle and RootProject/build.gradle. Is this possible?

Edit

I also tried to add pluginManagement block to PrecompiledPlugins/settings,gradle, without luck.

Looking at the generated source code for precompiled script plugins, apparently it delegates applying the script to to target project after applying some of its own code. Thus, I would expect the target project to use pluginManagement to resolve the plugin. Perhaps this call is happening too early?

try {
            Class<? extends BasicScript> pluginsBlockClass = Class.forName("cp_precompiled_...").asSubclass(BasicScript.class);
            BasicScript pluginsBlockScript = pluginsBlockClass.getDeclaredConstructor().newInstance();
            pluginsBlockScript.setScriptSource(scriptSource(pluginsBlockClass));
            pluginsBlockScript.init(target, target.getServices());
            pluginsBlockScript.run();

           target.getPluginManager().apply("com.android.library");

Gradle version: 7.6.1

The plugins { ... } block within pluginManagement { ... } never applies anything anywhere, nor adds anything to any classpath. It only defines default versions if those plugins are used somewhere in the same build without version, hence the apply false actually is useless.

Your build that build the convention plugin should have a dependency declared on the Android plugin instead. As your convention plugin is meant to apply the plugin, it is a dependency of that plugin.

If you really want to apply “whatever version is present”, you have to make one version present, which is what you did by adding it in the build script of the root project.

Btw. I’d like to recommend using a version catalog instead of script plugins for centralizing version declarations for several reasons. :slight_smile:

Thanks for your explanation! That clarifies things.

I use a version catalog, but it’s not supported in pluginManagement block, AFAIK. Cédric Champeau's blog: Frequently asked questions about version catalogs

Now that I have precompiled script plugins, I can simplify my settings.gradle files and use the version catalog there.

I use a version catalog,

:ok_hand:

but it’s not supported in pluginManagement block, AFAIK

Yes, you are correct, version catalog cannot be used in pluginManagement block as it is too soon and they do not exist yet.
But if you have the plugins in the version catalog, you shouldn’t define default version for them in the pluginManagement block anyway, so don’t need the information from the version catalog there, no matter whether you have precompiled script plugins or not. :slight_smile:

1 Like