Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modifying project classpath from init script should either work or fail #8173

Open
Vampire opened this issue Jan 7, 2019 · 9 comments
Open

Comments

@Vampire
Copy link
Contributor

Vampire commented Jan 7, 2019

I tried to use the following init script:

rootProject {
    buildscript {
        repositories {
            gradlePluginPortal()
        }

        dependencies {
            classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
        }
    }

    apply plugin: 'com.github.ben-manes.versions'
}

The effect it has is Plugin with id 'com.github.ben-manes.versions' not found..
I guess that at the time the closure is applied to the root project it is too late to add to its classpath.

It would be nice if this would either work (or maybe with some other method that can add dependencies to the classpath) or if it would at least error out.
Well, it errors out, but I mean with "you cannot do this here" or something more meaningful, I think you know what I'm talking about. :-)

@ljacomet
Copy link
Member

ljacomet commented Jan 7, 2019

I agree that there should be a clearer error message. I need to dig a it to understand why you can access a buildscript scope there and why it does not error out, as it should do that when not the first instruction in a build file.

I believe the right way to achieve what you want is:

import com.github.benmanes.gradle.versions.VersionsPlugin

initscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
    }
}


rootProject {
    apply {
        plugin(VersionsPlugin)
    }
}

That is you add the plugin to the init script classpath and then apply it using its class and not its id.

@Vampire
Copy link
Contributor Author

Vampire commented Jan 7, 2019

Yes, the following indeed works as expected, thanks:

import com.github.benmanes.gradle.versions.VersionsPlugin

initscript {
    repositories {
        gradlePluginPortal()
    }

    dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
    }
}

rootProject {
    apply plugin: VersionsPlugin
}

I didn't think that adding to the initscript classpath and then applying to the project would work.
Unlike with script plugins (apply from one script plugin and do tasks.withType from another script plugin), it even works to do tasks.withType in the real script that the init plugin applies this to, nice.

@ldaley
Copy link
Member

ldaley commented Jan 9, 2019

it even works to do tasks.withType in the real script that the init plugin applies this to, nice.

I'm surprised this works.

When you do rootProject.buildscript… you are adding to that project's build script classpath. Then you were trying to access that class in the init script and it fails.

When you do initscript {} you are adding to the init scripts classpath, which is why you can then see the class in that script.

Why I'm skeptical that this is actually working for you is that the init scripts classpath is not a parent of the build scripts. I can't think of any way in which you the task types coming from this JAR loaded in the init script would be the same as any referenced statically from the build script.

@eskatos
Copy link
Member

eskatos commented Jan 10, 2019

@Vampire from my testing the following fails:

// my.init.gradle
import com.github.benmanes.gradle.versions.VersionsPlugin

initscript {
    repositories {
        gradlePluginPortal()
    }

    dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
    }
}

rootProject {
    apply plugin: VersionsPlugin
}
// build.gradle
tasks.withType(DependencyUpdatesTask) {
    checkForGradleUpdate = true
}

fails with:

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/paul/src/local/gradle/gradle-8173/build.gradle' line: 7

* What went wrong:
A problem occurred evaluating root project 'gradle-8173'.
> Could not get unknown property 'DependencyUpdatesTask' for root project 'gradle-8173' of type org.gradle.api.Project.

could you share a reproducer demonstrating "it even works to do tasks.withType in the real script that the init plugin applies this to, nice"?

@ljacomet
Copy link
Member

For reference, the reason it fails is described in #4078

@Vampire
Copy link
Contributor Author

Vampire commented Jan 10, 2019

@ldaley

When you do rootProject.buildscript… you are adding to that project's build script classpath. Then you were trying to access that class in the init script and it fails.

Even when applying via its id, not its class object?
If I would have tried with the class object I would have considered this.
But if that would be the case, this of course would explain why it does not work but also does not throw any exception.

But are you sure it is this way?
When I just do the rootProject { buildscript { ... part in the init script and then try to apply the plugin by ID or access the class object in the real build script, it fails, even in afterEvaluate, so it seems the classes are not added to the buildscript classpath.

Why I'm skeptical that this is actually working for you is that the init scripts classpath is not a parent of the build scripts. I can't think of any way in which you the task types coming from this JAR loaded in the init script would be the same as any referenced statically from the build script.

I wondered the same after I understood those quirks a bit better in that other ticket where it was about script plugins. But it indeed works, just try it, I just retried to make sure.

In the init script

initscript {
    repositories {
        gradlePluginPortal()
    }

    dependencies {
        classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
    }
}

rootProject {
    apply plugin: com.github.benmanes.gradle.versions.VersionsPlugin
}

Then doing in the real build script just tasks.withType(com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask) { println it } of course complains with Could not get unknown property 'com' as it was not added to the classpath of that script, but with

plugins {
    id 'com.github.ben-manes.versions' version '0.20.0' apply false
}
tasks.withType(com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask) { println it }

the task is printed.

@Vampire
Copy link
Contributor Author

Vampire commented Jan 10, 2019

@eskatos the reproducer is in my last comment, didn't see yours before I sent it.
Why it does not work for you is because you don't import the class and then it would complain about com not found, until you add the plugin to the classpath.

@ljacomet ljacomet added the @jvm label Feb 17, 2020
@stale
Copy link

stale bot commented Feb 17, 2021

This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. If you're interested in how we try to keep the backlog in a healthy state, please read our blog post on how we refine our backlog. If you feel this is something you could contribute, please have a look at our Contributor Guide. Thank you for your contribution.

@stale stale bot added the stale label Feb 17, 2021
@Vampire
Copy link
Contributor Author

Vampire commented Feb 17, 2021

This is still relevant in 6.8.2.

Actually I made another experiment that surprisingly worked, so it seems you can add to the class path using the original post code, because this works:
my.init.gradle:

rootProject {
    buildscript {
        repositories {
            gradlePluginPortal()
        }

        dependencies {
            classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
        }
    }
}

build.gradle.kts:

apply(plugin = "com.github.ben-manes.versions")

while having the apply in the init script like in the original post still fails with the same error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants