How to bootstrapp buildscript classpath - Cannot change configuration ':classpath' after it has been resolved

Hi,

I have a plugin I call “myplugin” which configures standard items for projects such as ivy-configure configurations, publications, and repositories. This is necessary since my organization has a rather large setup needed to interface with tools such as artifactory. This setup contains ordered “chained” repositories that are hit in a specific order among other things. Without this plugin approach a lot of standard setup code would be duplicated across independent projects.

I would like to do the following:

  1. bootstrap the buildscript loading of myplugin

  2. apply myplugin

  3. setup the rest of the projects buildscript dependencies (these may pull from our organizations artifactory)

I am encountering a problem in that once the classpath buildscript configuration is used (which it is in my bootstrap to pull down this plugin) it can no longer be modified. I am looking for a way around this.

buildscript {
 repositories {
  ivy {
   name "myplugin-bootstrap"
   url "http://<myplugin literal repository path to jar>"
   layout "pattern", { artifact "[artifact]-[revision].[ext]" }
  }
 }
 dependencies {
  classpath group: 'myorg', name: 'myplugin', version: "myversion"
 }
}
  // Apply standard configurations
apply plugin: 'myplugin'
  // Now that we have loaded our standard configurations procede with the rest of the script.
buildscript.repositories { addAll project.repositories }
  buildscript.dependencies {
        // These items need to use the custom project repository configurations set up in myplugin
        // Gradle complains that ':classpath' has already been resolved
 classpath group: 'group1', name: 'name1', version: 'version1', configuration: 'config1'
 classpath group: 'group2', name: 'name2', version: 'version2', configuration: 'config2'
        // etc.
}

I’ve looked at init.d scripts but it does not appear that these can be set on the project level. I would like all scripts to be self contained in source control gradle projects so users (and automated build boxes) don’t have to go do manual gradle configurations.

Is there a way to do what I want to do here?

It should be good enough to have the remaining repositories/dependencies in myplugin-bootstrap’s ivy.xml or pom.xml.

I don’t follow. The plugin is generic whereas each independent project has different additional buildscript dependencies.

Not sure what you are trying to do here, but the build script class path cannot be extended dynamically.

The plugin sets up project.repositories. The buildscript needs to use these project repositories. In order to do this the classpath must of first been resolved so the plugin can be used and applied. However, once the plugin is applied part of it’s purpose is defeated since no additional buildscript dependencies can be added. It’s a chicken and egg problem.

If this doesn’t work I need to duplicate the project repositories in the buildscript repositories block.

It should be possible to apply a plugin inside the build script block, although it’s not very common. Instead of declaring multiple repositories, you could perhaps use a single virtual Artifactory repository.

When attempting to apply the plugin from within the buildscript it always says “Plugin with id ‘myplugin’ not found.” no matter where I attempt to apply it.

The repositories contain more than just artifactory. For example, there are also repos configured to hit the local filesystem.

When attempting to apply the plugin from within the buildscript it always says “Plugin with id ‘myplugin’ not found.” no matter where I attempt to apply it.

The repositories contain more than just artifactory. For example, there are also repos configured to hit the local filesystem.

This will only work for a script plugin, built-in plugin, or plugin that ships with a custom Gradle distribution (if at all). My general feeling is that you may have to live with some duplication, or rethink the bigger picture of how your build works.

The buildscript classloader appears to automatically grab all libraries in the gradle lib directory. Is there a way for me to modify the classloader to pull another file? I could easily write a standalone bootstrapper jar to obtain the file and then have the buildscript classloader automatically pull in the jar without going through the publishing system and resolving the classpath prematurely.

List urls = org.gradle.internal.classloader.ClasspathUtil.getClasspath(getClassLoader());

for (URL url : urls) {

println "CP1 " + url;

}

And yes I am aware that such a “hack” would not be officially supported and could break in future gradle versions.

Standard class loaders don’t support adding Jars dynamically. You could try to call the protected ‘URLClassLoader#addURL’ method (which Groovy allows you to do), but it’s a huge hack and not something I would recommend.

I need the same, something like maven parent plugin, which will setup me all the things.

Maybe for me will be enough static import like Peter mention in first replay. But how to do this?

Now I have two module project, where one module is gradle plugin and second is sample app. I have no deployed pom.xml yet.

But I hope, that will be possible to add allprojects.repositories from the plugin