Access to buildscript from Settings object

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Access to buildscript from Settings object

Spencer Allain
In attempts to make a Settings plugin it seems there is no access to the buildscript for adding repositories and things to the classpath in order to apply an additional Settings plugin or do other fun stuff.

I have something that works as an apply: script, but I really would like to make it a versioned settings plugin so there is not a need to hit the network on every build invocation to check that the versioned script is "current".

Even looking at internal objects, it doesn't seem to be readily possible to adjust the settings classpath for applying plugins.

There is a huge amount of boilerplate in the Settings script that I have now, that applies a Settings plugin and configures several project repositories and plugin applications.

In short, the current script does the below steps:
[1] Configure buildscript and classpath for settings to apply the other Settings plugin
[2] Bring class names into scope to avoid missing property 'com' for package com.something.plugin.PluginClass
[3] Apply the other Settings plugin
[4] Configure buildscript and classpath for all projects to easily apply other plugins
[5] Apply some plugins directly to the rootProject before any other plugins will be applied

I can make all the steps work in a proper plugin except for Step 1.

Step 2 at the moment requires the exact classname and direct imports of the Plugin classes, so it's not ideal, but I haven't found a way to dynamically work from a Class object, but I'm sure there must be one.  Step 2 shouldn't be required, but somehow the plugin-by-id stuff isn't initialized at this point.


buildscript {
  repositories {
    maven { url 'http://some-repo' }
  }
  dependencies {
    classpath aSettingsPluginArtifactNotation
    classpath aRootProjectPluginArtifactNotation
    classpath bRootProjectPluginArtifactNotation
  }
}

// NOTE: Cannot apply plugins by name at this point, that magic happens later, so have to
//       explicitly import plugin classes for apply purposes to settings and rootProject
//       to ensure they happen before any other plugins take effect
import settings.plugin.PluginClass
import project.plugin.PluginClass
import project.plugin.PluginClass2

settings.apply(plugin: settings.plugin.PluginClass)

gradle.projectsLoaded { afterProjectsLoadedGradle ->
  afterProjectsLoadedGradle.rootProject.allprojects {
    buildscript {
      repositories {
        maven { url 'url1' }
        maven { url 'url2' }
        maven { url 'url2' }
      }
    dependencies {
      classpath artifactNotation1
      classpath artifactNotation2
      classpath artifactNotation3
      classpath artifactNotation4
    }
  }

  afterProjectsLoadedGradle.rootProject {
    apply plugin: project.plugin.PluginClass
    apply plugin: project.plugin.PluginClass2
  }
}

Maybe this isn't the best solution, but there are issues with attempting to build our own custom distribution of gradle with init scripts.

Again, the current solution works, but a proper plugin feels more correct, and the network call for the apply from: url is a performance hit every single time a build is run.

Thoughts?

-Spencer
Reply | Threaded
Open this post in threaded view
|

Re: Access to buildscript from Settings object

Luke Daley-2

On 30 Jan 2014, at 9:50 am, Spencer Allain <[hidden email]> wrote:

> In attempts to make a Settings plugin it seems there is no access to the buildscript for adding repositories and things to the classpath in order to apply an additional Settings plugin or do other fun stuff.

Chicken and egg problem here: classpath has to be resolved to add plugins, so you can't alter the classpath to add more plugins from a plugin.

What's other “fun stuff”?

>
> I have something that works as an apply: script, but I really would like to make it a versioned settings plugin so there is not a need to hit the network on every build invocation to check that the versioned script is "current".
>
> Even looking at internal objects, it doesn't seem to be readily possible to adjust the settings classpath for applying plugins.
>
> There is a huge amount of boilerplate in the Settings script that I have now, that applies a Settings plugin and


> configures several project repositories and plugin applications.

Why don't you do this from the plugin?

>
> In short, the current script does the below steps:
> [1] Configure buildscript and classpath for settings to apply the other Settings plugin
> [2] Bring class names into scope to avoid missing property 'com' for package com.something.plugin.PluginClass
> [3] Apply the other Settings plugin
> [4] Configure buildscript and classpath for all projects to easily apply other plugins
> [5] Apply some plugins directly to the rootProject before any other plugins will be applied
>
> I can make all the steps work in a proper plugin except for Step 1.

Right, this doesn't work for reason mentioned above.

>
> Step 2 at the moment requires the exact classname and direct imports of the Plugin classes, so it's not ideal, but I haven't found a way to dynamically work from a Class object, but I'm sure there must be one.  Step 2 shouldn't be required, but somehow the plugin-by-id stuff isn't initialized at this point.
>
>
> buildscript {
>   repositories {
>     maven { url 'http://some-repo' }
>   }
>   dependencies {
>     classpath aSettingsPluginArtifactNotation
>     classpath aRootProjectPluginArtifactNotation
>     classpath bRootProjectPluginArtifactNotation
>   }
> }
>
> // NOTE: Cannot apply plugins by name at this point, that magic happens later, so have to
> //       explicitly import plugin classes for apply purposes to settings and rootProject
> //       to ensure they happen before any other plugins take effect
> import settings.plugin.PluginClass
> import project.plugin.PluginClass
> import project.plugin.PluginClass2
>
> settings.apply(plugin: settings.plugin.PluginClass)
>
> gradle.projectsLoaded { afterProjectsLoadedGradle ->
>   afterProjectsLoadedGradle.rootProject.allprojects {
>     buildscript {
>       repositories {
>         maven { url 'url1' }
>         maven { url 'url2' }
>         maven { url 'url2' }
>       }
>     dependencies {
>       classpath artifactNotation1
>       classpath artifactNotation2
>       classpath artifactNotation3
>       classpath artifactNotation4
>     }
>   }
>
>   afterProjectsLoadedGradle.rootProject {
>     apply plugin: project.plugin.PluginClass
>     apply plugin: project.plugin.PluginClass2
>   }
> }
>
> Maybe this isn't the best solution, but there are issues with attempting to build our own custom distribution of gradle with init scripts.
>
> Again, the current solution works, but a proper plugin feels more correct, and the network call for the apply from: url is a performance hit every single time a build is run.

This awkwardness is a variation of http://issues.gradle.org/browse/GRADLE-2407.

There's a missing lifecycle event: after project buildscript classpath has been resolved, but before evaluation proper starts. You'd ideally use that same hook here.

So in short, what you have now is the best you can currently do.

(btw: this post would have been better suited for the forums)

--
Luke Daley
Principal Engineer, Gradleware
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email