On May 9, 2009, at 2:26 AM, Adam Murdoch wrote:
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).
Do you mean with plugin in this case, something like a configuration
script (possibly belonging to a certain profile)?
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 about 0.6? As long as we don't have a domain language for that,
the specification is to use for example -A to manipulate the
configuration.buildArtifacts task dependency :)
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.
I like this very much. And with -a (or the future ! notation) I would
prevent that the clean gets applied to the other projects.
I just remebered that 10 months ago we did already talk about this :)
http://markmail.org/message/7jr37jyyxl7p56bv
And now we have a good solution.
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?
I don't have another one although the pattern behind this is not
exotic. I have Marc whether he wants to tell us his real world use
case (http://jira.codehaus.org/browse/GRADLE-427). Anyway, I don't
think this is an urgent issue.
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'.
A good example for this is source directory vs. compile.
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.
Definitely.
That is, we want to end up with a model where the artifact domain
objects express the what, and tasks express the how.
Right.
* 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.
This is a very interesting idea.
- Hans
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
--
Hans Dockter
Gradle Project lead
http://www.gradle.org
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email