On 02/07/2011, at 1:19 AM, Merlyn Albery-Speyer wrote:
> Hi all,
>
> I'd like to make it easier for third party plugins to be integrated into
> Gradle builds. Right now plugins either need to insist on an internet
> connection in order to apply a script, or the contents of that script needs
> to be inlined. "apply plugin: 'xxx'" is so much cleaner than bulky build
> script dependencies configurations with funky GitHub Ivy resolvers. Getting
> plugins added to maven central is enough of an obstacle that no-one does it.
> So, these are the motivating pain points for me.
>
> This is the kind of DSL change I'm considering:
>
> apply plugin: 'pluginname', githubid: 'githubid', version: '1.0'
>
> The key here being that as a side-effect of the apply that it adds an
> IvyResolver that will resolve to a URL pattern like this:
> "http://cloud.github.com/downloads/[organisation]/[module]/[module]-[revision].[ext]"
> But only for an exact match on the dependency: organisation "githubid",
> module "pluginname", and version "1.0". The other side effect of course being
> an implicit: "buildscript { dependencies { classpath
> 'githubid:pluginname:1.0' } }".
> What do you think? Would this be in line with the plans for Gradle?
Pretty much, but with some tweaks.
I think there are 2 really good ideas here:
* A convenience, and convention, for resolving dependencies from github.
* Inlining the dependency declaration for a plugin into the apply statement, so
you don't need the buildscript { } boilerplate.
I think we should separate the two, so that they can be used independently of
each other (and, of course, together).
I can see how you might want to resolve any type of dependencies from github,
not just plugins. In fact, doing this turns github into an interesting
alternative to maven central for the distribution of binaries, with much more
control for the binary author. This suggests to me a new type of repository in
the DSL:
repositories {
github()
}
I can also see how you might want to resolve a plugin from any repository, not
just github. Being able to inline the dependency declaration into the apply
statement is something we've discussed before. The plan is to have the apply
statement handle dependency coordinates. You would be able to do any of the
following:
1. apply group: 'mygroup', name: 'myplugin-project', version: '1.0', plugin:
'myplugin'
2. apply group: 'mygroup', plugin: 'myplugin', version: '1.0'
3. apply plugin: 'myplugin'
Option 1. would resolve 'mygroup:myplugin-project:1.0' using
buildscript.repositories, then scan the resolved artifacts (but probably not
their dependencies) for a plugin with id 'myplugin', which it would then load
and apply.
Option 2. would use the plugin id as the dependency project name, and resolve
'mygroup:myplugin:1.0' using buildscript.repositories.
Option 3. would work as it currently does now. That is, it scans the build
script classpath for a plugin with id 'myplugin'
What this means is that instead of:
buildscript {
repositories { someRepo() }
dependencies { classpath 'mygroup:myplugin:1.0' }
}
apply plugin: 'myplugin'
You would do:
buildscript {
repositories { someRepo() }
}
apply group: 'mygroup', plugin: 'myplugin', version: '1.0'
We could simplify this further by using project.repositories instead of
project.buildscript.repositories for resolution, or by having
project.buildscript.repositories default to project.repositories:
repositories { github() }
apply group: 'mygroup', plugin: 'myplugin', version: '1.0'.
There is (at least) one complication to this approach. At the moment, a plugin
can contribute static types to a build script classpath. That is, when I
declare some dependencies in buildscript { dependencies { classpath ... }}},
then the types packaged in these jars are visible in my build script. This
means, for example, I can use the task types to declare task instances:
task someCustom(type: SomeCustomTaskType)
I think it will be extremely difficult to get this to work with arbitrary apply
statements scattered throughout the build script. The main problem is that in
order to figure out the script classpath, you need to first execute the script.
Some possible solutions:
1. Only allow apply statements at fixed locations in the script, so we can do
some AST analysis to figure out what the classpath should be.
2. Don't try to solve the problem. I think we want to move the DSL in this
direction anyway, where the DSL uses properties and factory methods to declare
things, rather than using static types.
I'd be tempted to go with option 2, plus the associated bits and pieces to make
it easy to handle not having access to plugin types in the script.
--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com