# Programmatically apply a plugin

**URL:** <https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469>\
**Category:** Help/Discuss\
**Tags:** plugins\
**Created:** [January 9, 2020, 10:26am UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469 "2020-01-09T10:26:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [January 9, 2020, 10:26am UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/1 "2020-01-09T10:26:16Z")

</div>

The recently added `pluginManagement` block in `settings.gradle` is a most welcomed feature, however I can’t find a way to conditionally apply a plugin that has been declared in this block.

Say you have a `settings.gradle` file that looks like this

```
pluginManagement {
    repositories {
        gradlePluginPortal()
    }
    plugins {
        id 'com.github.johnrengelman.shadow' version '5.2.0'
    }
}

```

The usage of shadow is just an example, it could be any plugin. Then later in the build file you’d apply this plugin if a particular condition holds true, such as

```
if (something) {
    apply plugin: 'com.github.johnrengelman.shadow'
}

```

Of course this does not work because plugin requests defined in the `pluginManagement` block appear to be fulfilled _ONLY\_IF_ they are coming from the `plugins` block. Unfortunately the `plugins` block is quite restrictive as:

- You’re not allowed to define statements other than `id(...)`.
- Contents on this block must be defined in advance, leaving no room for a meta-plugin to customize.

Is there a way around this problem? What I;'m looking for is to define all required plugins inside the `pluginManagement` block form `settings.gradle`, then apply them to the root project & subprojects depending on particular conditions.

TIA

---

<div class="post-metadata">

**Author:** ![kostasdrakonakis](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/kostasdrakonakis/32/7476_2.png) [@kostasdrakonakis](https://discuss.gradle.org/u/kostasdrakonakis)\
**Post date:** [January 9, 2020, 12:45pm UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/2 "2020-01-09T12:45:02Z")

</div>

You can build your own plugin to do that depending on the conditions you would like. Would that help you?

To make it more understandable I am suggesting to build a standalone plugin, which then will apply all of your desired plugins depending on conditions.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [January 12, 2020, 1:11pm UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/3 "2020-01-12T13:11:13Z")

</div>

Sadly no. It won’t work and here’s why as far as I understand the current mechanism:

1. The `pluginManagerment` block in `settings.gradle` defines which plugins _may_ be resolved in `build.gradle`.
2. Plugins are resolved using a `plugins` block in `build.gradle`.

If the project happens to be a multiproject (which is my case) one can apply the plugins in a subproject by  
a. Using a `plugins` block in the subproject’s build file  
b. Define the plugin with `apply false` in the `plugins` block of the root’s build file, then either use `plugins` or `apply plugin:` in the subproject’s build file.

The secret sauce lies in 2. and b., as it requires defining the plugin request in a `plugins` block, otherwise no plugin resolution occurs. I can’t place do this in a meta-plugin due to 2 reasons:

1. the meta-plugin has no clue which additional plugins may be applied.
2. the plugin resolution mechanism currently requires an explicit `plugins` block to be used, which the meta-plugin doesn’t have access to.

---

<div class="post-metadata">

**Author:** ![jjustinic](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/jjustinic/32/9005_2.png) [@jjustinic](https://discuss.gradle.org/u/jjustinic)\
**Post date:** [January 13, 2020, 7:19am UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/4 "2020-01-13T07:19:38Z")

</div>

The purpose of the `plugins` block in `settings.gradle` is only to define default versions. Only the declaration in a project’s `plugins` block causes the resolution and addition to the buildscript’s classpath (but you can omit the version).

You would need the following to use a `settings.gradle` to specify default versions (noting that the `plugins` block need not be in the same project as the conditional, as long as it’s in the `plugins` block of a parent project. The end result is duplication of the plugins block (but maybe without versions) in the project:

```groovy
// settings.gradle
pluginManagement {
    repositories {
        gradlePluginPortal()
    }
    plugins {
        id 'com.github.johnrengelman.shadow' version '5.2.0'
    }
}

```

```groovy
// build.gradle
plugins {
    id 'com.github.johnrengelman.shadow' apply false
}

if (something) {
    apply plugin: 'com.github.johnrengelman.shadow'
}

```

However, there is also technically nothing that requires you to do anything with the plugins themselves (just the repository if you need something special) in `settings.gradle`. It is equally valid to specify all plugin information in the root project, and then conditionally apply them anywhere else in the build. i.e.:

```groovy
// build.gradle
plugins {
    id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
}

```

```groovy
// subproject/build.gradle
if (something) {
    apply plugin: 'com.github.johnrengelman.shadow'
}

```

There’s also technically no value in caring about the `plugins` block in the meta-plugin case. You can only conditionally apply plugins that are on the classpath. The plugins block puts them on the classpath, but you can decide to not apply them. They’re all going to be on the classpath of the buildscript anyway (and that’s inherited by subprojects), so you might as well just define them all as dependencies in meta-plugin case and then conditionally apply them, not worrying at all about the `plugins` block.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [January 17, 2020, 7:41am UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/5 "2020-01-17T07:41:03Z")

</div>

Yes, except in my case I have a meta-plugin that may or may not apply other plugins based on conditions. This meta-plugin does not know in advance which plugins may be applied, thus the potential plugins are not yet found in the classpath, which is why invoking `apply plugin:` without explicit plugin resolution inside a `plugins` block on a build file is a non starter.

As far as I can find, the `plugins` block found on a build file is processed using APIs that are not reachable by the `Settings` nor `Project` types, that is unless you’re willing to risk using internal APIs, and yet is not that easy. This is what prompted me to ask if there is an alternative.

---

<div class="post-metadata">

**Author:** ![nbn](https://avatars.discourse-cdn.com/v4/letter/n/cc9497/32.png) [@nbn](https://discuss.gradle.org/u/nbn)\
**Post date:** [January 6, 2023, 9:52am UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/6 "2023-01-06T09:52:56Z")

</div>

This is an old question, but I ran into the same problem today.  
Did you ever find a viable solution to this problem?

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [January 12, 2023, 8:54pm UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/7 "2023-01-12T20:54:58Z")

</div>

Which “same problem” do you have?  
There were quite some things spoken about here.  
If you just mean the last comment, then that “meta plugin” would either have the plugins to apply as dependencies, or have them as `compileOnly` dependencies and then require them to be on the classpath already when they should get applied, depending on concrete needs.

---

<div class="post-metadata">

**Author:** ![nbn](https://avatars.discourse-cdn.com/v4/letter/n/cc9497/32.png) [@nbn](https://discuss.gradle.org/u/nbn)\
**Post date:** [January 13, 2023, 2:43pm UTC](https://discuss.gradle.org/t/programmatically-apply-a-plugin/34469/8 "2023-01-13T14:43:37Z")

</div>

I see, it became crystal clear when I read your reply, @Vampire .  
I got confused from the thread and thought I always had to have the plugins defined in the target project, now matter what.

I tried a few experiments with the things and got it all working. Appreciate your response.
