On 18/07/2011, at 10:42 AM, Luke Daley wrote: > > On 17/07/2011, at 9:32 AM, Eric Berry wrote: > >> I've run into this issue myself. Right now I'm having our developers >> download the plugin jar file and install it into gradle lib/plugins >> directory. But the buildscript method seems pretty standardized. >> >> I wonder if it could be automated more by adding something like: >> apply plugin: 'company-plugin', fromJar: 'url://to/company-plugin.jar' >> >> I was looking through the source recently, and I was thinking it might be >> possible to add something like this to the DefaultObjectConfigurationAction. >> >> Where it would download the jar to ~/.gradle/cache (or somewhere else), and >> then add a buildscript closure to the project pointing the dependency at the >> downloaded jar file. >> >> Afterwards applying the plugin. >> >> I'm not completely familiar with the Gradle source, but is something like >> this even feasible? If so, I can try and get something working over the next >> week or so and try to submit a patch? > > This thread and the “easy plugin integration” thread are highlighting that > there is a hole here. > > Before working on any implementations or even DSL modifications, I think we > need more thought and exploration of the core problem here. The best way to > do that is probably to explore people's use cases and see what patterns > emerge.
As I see it, the basic problem here is that organisations need to make some build logic available to their teams, in a controlled way. The exact build logic that needs to be shared varies, but generally includes: * Information that the build needs to know about the organisation's infrastructure. For now, this means repository definitions, but might later include things such as resources for distributed build/test or deployment. * Configuration of the standard Gradle plugins, to define the organisation's convention. For example, changing the default source directories. * Making custom plugins available to the build. The idea is that it should be possible to inject this logic from a single place, rather than spreading it out over a bunch of places. I think it is also important that as little boiler-plate as possible is required to inject the logic, and to use the custom plugins. Ideally, you'd use the same dsl to use the custom plugins as you would for the standard Gradle ones. Some possible approaches: You could to inject the logic from the root project. The logic could be packaged up into an external script: apply from: "http://some-server/some-logic/1.2/bootstrap.gradle" This would be able to inject buildscript { } stuff into the build scripts of child projects. But it wouldn't work for external scripts, or the build script of the root project. You could always do: buildscript { apply from: "..." } But this doesn't work for buildSrc projects, which probably need to use the same logic. You'd have to include the above snippet in buildSrc/build.gradle, and keep it in sync with the root project. Finally, it also doesn't help with logic that might be required in the settings.gradle. We really need some point in time before these where we can inject the logic. So, another approach would be to use an init script (*). But this means either installing the init script on every machine which needs to run the build, or checking in the init script and requiring everyone that uses the build (including IDEs via the tooling api) with the appropriate -I flag. These are both non-starters, I think. To address this, we could add some more conventional places where we look for an init script. For example, we could look for $rootDir/init.gradle, and apply it if we find it. The problem with this is that we don't know $rootDir until after we've built buildSrc and executed settings.gradle. So this is no good. I think $cwd/init.gradle is no good, either, as $cwd could be anything. When we're using the wrapper, we do know $rootDir very early in the execution. So, we have some options here. For example, the wrapper could look for, say, $rootDir/init.gradle or $rootDir/gradle/init.gradle, and pass them through to Gradle. The init script could then be checked in, and delegate to an external script: apply from: "http://some-server/some-logic/1.2/bootstrap.gradle" There are a couple of problems with this approach. First, it doesn't work if someone happens to run the build using an installed Gradle distribution, rather than running ./gradlew, which is an easy enough 'mistake' to make. I think we can solve this by making the 'gradle' command wrapper aware. That is, we change the Gradle distribution that you download and install so that it contains just the wrapper. This way, however you invoke Gradle - installed distribution, via the tooling API, or via ./gradlew, you always get the same behaviour. I think this is a good change to make regardless of what we decide to do regarding bootstrap logic. The second downside to the checked-in init script approach is that it is quite awkward to actually develop and change the logic. You have to either embed some logic in the checked-in script which decides whether to use a local development version or the real published version, which is a bad idea if this logic needs to end up in many projects, or you need to publish development versions of the init script to your repository so you can test them. Either way, it's a burden for those who have to maintain and roll out this organisation wide logic. So, another conventional location we could use is either: relative to the target Gradle distribution that the wrapper downloads, or embedded in the distribution itself. Embedding the logic is interesting, in that you can download and install the distribution manually and the logic still works. Another option is to include an optional property in gradle-wrapper.properties which can point to an init script for the wrapper to download and apply. * We'd have to fix the init script mechanism so you can mess with the buildSrc project from the init script. There's a patch from Fred to fix this but it needs a few tweaks before we apply it. -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com
