Hans Dockter wrote:

On May 6, 2009, at 11:38 PM, Adam Murdoch wrote:



Hans Dockter wrote:
I have just committed a fix for Gradle-220 (Provide control to the user if and how project dependencies should be rebuild).

With -a or --no-rebuild you can now disable that project dependencies are build at all. Of course this works only if the project dependencies have been build before and are accessible in the ./gradle/internal-repository cache.




Also, when you run with -a, should we still build those artifacts which have not already been built?

I think that would be nice (although I'm wondering a little bit if this could lead to overly smartness).


What's your concern with 'overly smartness'? What do you think could go wrong here?

With gradle -Ajavadoc -Atest you can specify additional tasks that should be run when building project dependencies.

I don't understand why you would want to do this from the command-line. Do you have some use cases?

When we change our lifecycle to make the jar not depend on test any longer, uploading to the internal repository might not trigger a test. You might want to have a special partial build that runs the tests. Or you want to have an additional clean because you want a very reliable partial build. I'm not saying that this is the only way to achieve this. But those are the use cases within the current way of doing things.


These are both valid use cases. However, neither of them really sound like they belong on the command-line. They sound like things that should be declared in the build file (where 'build file' could be a plugin which the build file drags in).

With Gradle-220 I have the following use case: Let's say you want that project-dependencies are build with a clean:

Project A (has a compile dependency on Project B)
gradle -Aclean compile

The problem is that clean is not necessarily executed as the first task when building B. Which of course leads to a failing build. For other tasks (e.g. javadoc) this is not an issue, as it has no side-effects.

I'm wondering what to do here. This also relates to:


I think you should flip the problem around. The -a option works well, I think, because the build describes completely how to build the project, and -a simply takes some stuff out. The problem with -A is that it is trying to add stuff in. It's much more difficult to add things in, which is why we have a DSL and build scripts.

So, a solution to the problem is to change the clean task to always clean the projects which the project depends on. Then, you can simply use -a if you don't want the other projects to be cleaned. And -A and task ordering is not required.

So,

gradle clean libs

will rebuild the current project and all the projects it depends on.

gradle -a clean libs

will rebuild only the current project.

One problem is that the tasks you apply to the current project is most of the time a different set than the task set you need to build the project dependencies. So there is at least the theoretical possibility that a user wants to manipulate only the set of tasks for building the project dependencies. I'm not sure about the practical relevance for that but it does not look extremely exotic. You might argue, whether this should really be solved on the command line.

I will argue that. I always do :)

I would also say that I don't think the user wants to manipulate the set of tasks for the project dependencies. What they actually want to do, is to manipulate the artifacts. That is, they want to be able to say something like: Gradle, for this build, you must use tested JARs for any inputs to another project. Or for this build, you must use rebuilt everything from scratch. Or for this build, build the artifacts as quickly as you can, skipping everything non-essential and not already built. And it's up to Gradle to figure out from that specification which tasks to execute.


What you are proposing is similar to what we did in an early version of Gradle. What we did was to always establish an additional project1.dependsOn project2 for a artifact project dependency (e.g. compile project('project2')). We might reintroduce this, together with the !notation. I need to further think about this. This feature would not be mutually exclusive to the one above. But it might be good enough.

I don't think we should add a project dependency. Instead, we should indirectly clean through the Configuration, just like we do for building the configuration. That is, we currently have a 'how to build this configuration' TaskDependency on Configuration, so we could add an equivalent 'how to destroy this configuration' TaskDependency. Then, the JavaPlugin would do 2 things:

- Register the 'clean' task with the 'master' configuration as the destroy task for all configurations. - Add the 'destroy me' TaskDependency of all configurations to the dependencies of the 'clean' task.


The project dependencies issue will lose some its relevance once Gradle becomes smart in regard to change detection.

We are still left with the more fundamental issue, if there is something missing in our model where an ordered dependsOn set is a bad solution for. I have to think about that.


Do we have some specific use cases other than the 'clean compile' case?

Gut feel says that tasks and the DAG are the wrong abstraction to be trying to express these problems in. Tasks are the 'how' of the world, but almost always people and process are interested in the 'what'. There's 2 areas I think we should layer on top of the task model, to help us solve some of these problems:

* An artifact centric domain model. Artifacts are the most important things in the build domain. By far. Tasks come a distant second. Yet in Gradle, tasks are the most important things. We should flip this around so that artifacts are the most important things and tasks are simply the most *basic* things (the atomic actions of the build). We've started down this path already, with the use of Configuration.getBuildDependencies() and friends, and we're planning to keep going, with things like SourceDirectory and TestSuite, and so on.

That is, we want to end up with a model where the artifact domain objects express the what, and tasks express the how.

* A process model. Often we talk about things like 'the CI build' or the 'release build' or the 'pre-commit build' or the 'staging build'. These are important concepts in the build domain. Yet, there's nothing in Gradle to let you define these things. We should think about adding a first class Build concept.

I think by addressing these missing bits of the model, and making tasks less important, we can come up with some powerful and elegant solutions.


Adam


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

   http://xircles.codehaus.org/manage_email


Reply via email to