On 04/02/2013, at 11:07 PM, Adam Murdoch <[email protected]> wrote:
> > On 04/02/2013, at 8:48 PM, Luke Daley wrote: > >> >> On 03/02/2013, at 8:05 PM, Adam Murdoch <[email protected]> wrote: >> >>> >>> On 03/02/2013, at 9:50 AM, Adam Murdoch wrote: >>> >>>> Hi, >>>> >>>> Something I'd like to try to achieve as part of the work to introduce >>>> multiple outputs for JVM based projects, is to create fewer task instances >>>> at configuration time. There are 2 main parts to this: >>>> >>>> 1. Don't create tasks that will never be required. For example, if there >>>> is no src/main/resources directory, and nothing generates it, then don't >>>> create a processResources task. >>>> 2. Don't create tasks that are not required for the current build. For >>>> example, if I'm generating the javadoc, don't create the test task or any >>>> of its dependencies. >>>> >>>> Ignore for the moment how we might do this. Let's just say its possible to >>>> infer both #1 and #2. >>>> >>>> Let's also say that if such as task is directly referenced in the build >>>> logic, then it's "required". For example, if I execute >>>> `myTask.dependsOn(processResources)` in my build script, then >>>> processResources is required and must be created. Possibly also for the >>>> command-line, so that if I run `gradle processResources`, then it is >>>> required. >>>> >>>> The question is whether we consider it backwards compatible or not that we >>>> don't create certain tasks that used to always be created. >>>> >>>> At first glance, it looks not too bad. The tasks don't do anything and >>>> nothing references them from code, so it's fine to leave them out. There >>>> are a few important benefits to doing this: >>>> >>>> - There's less work to do at configuration time. >>>> - There's less heap required to maintain the model through the whole build. >>>> - We wouldn't log the execution of tasks that don't do anything. For >>>> example, if there is no test source, you wouldn't see 'testClasses', >>>> 'compileTestJava', 'processTestResources' etc. >>>> - It pushes the decoupling of 'what' and 'how', which means the 'how' can >>>> vary across different executions of the same build. For example, when >>>> generated source must be downloaded when building on one platform but can >>>> be generated when building on some other platform. Or when I'm running the >>>> tests against a distribution built by CI. >>>> >>>> Unfortunately, there are a few places where the tasks leak out and are not >>>> referenced by name or path: >>>> >>>> - Via the events on TaskContainer, such as tasks.all { } or >>>> tasks.whenAdded { } >>>> - Iterating over the various collections of tasks, such as >>>> project.getTasks(name), or tasks.withType(type). >>>> - Via the execution events, such as gradle.taskGraph.beforeTask { } >>>> >>>> Strictly speaking, we'd still be following the contract for these things. >>>> In practice, though, I think there's an implicit contract that says that >>>> we must continue to create all possible tasks. >>>> >>>> Some options: >>>> >>>> 1. Don't create the tasks, and simply document this as a potential >>>> breaking change (or, more likely, as series of changes). >>>> 2. Create alternatives to the above leakage points, but with stronger >>>> contracts. If you use one of the above, then we always create every >>>> possible task. >>>> 3. Toggle the strategy based on whether you're using the Gradle 2.0 >>>> configuration model or not. >>> >>> 4. Provide this as a general capability, so that the new language plugins >>> (and other new/incubating plugins) can take advantage of it. The old >>> language plugins would extend the new plugins and simply mark their tasks >>> as always required. Later deprecate and remove the old language plugins. >>> 5. As for #4, but instead of removing the old plugins, change them in >>> Gradle 2.0 so that they no longer mark the tasks as required. >> >> #4 seems compelling. This seems like it could become a watershed moment, for >> better/worse. We could build new plugins from the ground up that embrace the >> new dependency management (incl. publishing) worlds and make them available >> in parallel. However, I'm not sure about this. It's appealing because it >> will decrease the time to market for new features and generally make our >> lives easier (I think) > > One thing that might not be so apparent about #4 is that it will make plugin > author's lives easier. In particular, part of the work would be to tighten up > some rules about when things can be considered 'configured' and provide some > infrastructure that takes advantage of this. This would mean that most plugin > implementations won't need to worry about laziness, but only if we guarantee > that the plugin will only ever run against the new inference model. > > Another implication of this work would be better warning and error messages > when you attempt to configure something that has already been 'used' and the > configuration will have no effect. This will be the case whether it's a > per-plugin or a per-build-invocation decision whether to use the new stuff or > not. Not sure if this is an argument for #3 or #4, actually. > >> , I'm not sure it's the most user friendly. > > Just to explore this a bit more: What do you think would make it less user > friendly, compared to, say, option #3? There's a certain unpleasant taste to having parallel modes. It makes gradual migration for users harder and can have the appearance of indecisiveness and/or thrashing. Though you're right, this is not much different to #3 in this regard. The --configure-on-demand parallel mode is a little different to me in that it doesn't require anything new (i.e. new API mechanisms) but just restricts what you can do, then you opt in. I can't see this working out the same way. >> At the moment I'm leaning towards #2 and #3. That is, >> >> 1. Improve the API over time to provide equivalent functionality that is >> compatible with this inferencing >> 2. Move the existing plugins over to this API >> 3. Pre Gradle 2.0, opt-in to the new behaviour >> >> This is the longer, more difficult road, but safer and more user friendly I >> think. -- Luke Daley Principal Engineer, Gradleware http://gradleware.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email
