On 16/04/2013, at 8:39 PM, Luke Daley <luke.da...@gradleware.com> wrote:
> > On 15/04/2013, at 8:47 PM, Adam Murdoch <adam.murd...@gradleware.com> wrote: > >> >> On 15/04/2013, at 7:02 PM, Luke Daley <luke.da...@gradleware.com> wrote: >> >>> >>> On 14/04/2013, at 2:51 AM, Daz DeBoer <darrell.deb...@gradleware.com> wrote: >>> >>>> On 13 April 2013 17:11, Peter Niederwieser <pnied...@gmail.com> wrote: >>>>> Daz DeBoer-2 wrote >>>>>> The problem is that this equivalence doesn't translate to the parallel >>>>>> world. I guess we don't currently have a nice way to describe the >>>>>> 'contract' that you're expecting to be honoured >>>>> >>>>> I'm not sure if we are on the same page already. What I'm saying is that >>>>> we >>>>> should change the behavior of `--parallel` to honor the contract I >>>>> mentioned. How we do that is secondary (for now). >>>> >>>> While I agree this makes sense for: >>>> "gradle --parallel clean build " >>>> >>>> it's not so clear that it works for: >>>> "gradle --parallel :a:build :b:build" >>>> Do you really want to wait for 'a' to finish building before starting >>>> to build 'b'? >>> >>> It's more important that `clean build` does the right thing than it is that >>> `a:build b:build` is as fast as possible. So, without other mechanisms then >>> it has to work this way for my money. >>> >>> Given that we are starting to add the capability to be very explicit about >>> task orderings though it is indeed not that simple. >>> >>>> So I'm not sure about making this an explicit contract. I'm not 100% >>>> against, but I don't think it's a given either. >>>> I think we first need to define exactly what the contract means, ie: >>>> "gradle clean build" constructs an anonymous build-type with >>>> parameters "clean, build" (where build-type is a well-defined >>>> construct). >>> >>> I'm not sure what anonymous build types would give you. Every Gradle >>> invocation is effectively an "anonymous build type" in terms of what we >>> have been describing as build types. >>> >>> >>> The options as I seem them are: >>> >>> 1. task order at invocation time implies a temporary should run after >>> relationship >>> 2. task order at invocation time implies no relationship between tasks and >>> the necessary relationships must be described elsewhere >>> >>> >>> To me #2 is definitely better as the more information we have about the >>> task graph in a mineable way the more interesting things we can do with >>> this information in other contexts. The problem for me though is that we >>> might be a ways away from having the capability to do #2. This means we >>> have to live with the current unsafe behaviour until that time. Given that >>> parallel execution is an incubating feature, I guess living with the >>> current unsafe behaviour is not so bad. >> >> This pretty much sums up my thoughts as well. >> >> With must-run-after, we can pretty much express what we need for the command >> line: `clean` really must run before `build`. There's no should there. > > Just to be clear, you're saying that the command line order shouldn't express > any relationship and the relationships should be expressed in a persistent > fashion in the configuration of the build? > > So running `./gradlew build clean` would still clean everything before > building? Not really, just that they should be interleaved as much as possible, but safely. The result should be the same as running `gradle build` and then `gradle clean`. So `gradle clean build` should delete a thing before it tries to build the thing, but can interleave building one thing and deleting some other thing, and `gradle build clean` should build a thing before it tries to delete it, but can interleave building one thing and deleting some other thing. It should be something about the definition of 'clean' and something about the definition of 'build' that determines how to interleave them. Specifically, the fact that they do work on an overlapping set of files (or more generally, an overlapping set of resources). Forcing everything to be cleaned first and then built second is very much a workaround. It doesn't solve the problem in a general way, only when you happen to run things from the command-line, in a certain order (there's a quality user interface). It also breaks parallel execution for other use cases that don't have this problem, such as gradle proj1:build proj2:build. However, it's one that's been present for a very long time, it's relatively easy to workaround the workaround (eg define a task that dependsOn proj1:build and proj2:build), and we can implement it more cheaply. So, pragmatically speaking, it's certainly an option. At this stage, we're not going to do anything about this. We'll let it soak for a while and collect up some use cases. -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com Join us at the Gradle Summit 2013, June 13th and 14th in Santa Clara, CA: http://www.gradlesummit.com