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