Hans Dockter wrote:

> Hi,
>
> one thing I find inconvenient with Gradle multi-project builds at the
> moment, is that dependent projects are rebuild although it would not
> be necessary.
>
> Let's look at an example:
>
> root
> - commons
> - webservice (has a compile dependency on commons)
>
> Let's look at some use cases
>
> 1.)
> webservice> gradle compile
>
> current:
> does compile, test and uploadLibsInternal on commons
> does compile on webservice
>
> should do: if commons hasn't been touched an existing jar of commons
> should be used. If commons has been touched or no jar does exists, the
> commons-jar should be build, but without being tested.
>
... [show rest of quote]

Part of the problem here is that uploadLibsInternal does not really
depend on test, but we add this as an artificial dependency to overlay a lifecycle over the tasks. Perhaps separating real dependencies (artifact
dependencies?) from lifecycle would help here. Then, Gradle could
consider real dependencies in other projects and ignore lifecycle
dependencies.

> 2.)
> webservice> gradle test
>
> current: like above except that webservice is tested
> should do: If commons hasn't been touched an existing jar of commons
> should be used. If commons has been touched or no jar does exists, the
> commons-jar should be build with being tested.
>

Should commons be tested?

I think this is the same question as to whether commons should be
cleaned or not by 'gradle clean'. Sometimes yes and sometime no.
Sometimes I want the task to be run for the current project and all the projects it depends on. And sometimes I want the task to be run only for
the current project. Running 'gradle test' isn't really expressive
enough - it doesn't declare my intentions.

Right.

One solution is to select one behaviour as the default, and provide some
way to override this from the command-line. A few options:
- Use command-line options to express this, such as: gradle -- recursive test

This is a simple and straight forward way of doing things.

- Use synthetic task names to express this, such as: gradle
recursive-test, where Gradle generates the 'recursive-test' task from
the 'test' task. This could be implemented by a plugin.

This way you could not express that the current project should not be cleaned, but the dependent projects.

- Use task name pattern matching, such as gradle *:test

I would spare us another command option. But we would have to come up with some syntax for 'no-rebuild'. I'm not sure.

Here is an idea for implementing things. After http://jira.codehaus.org/browse/GRADLE-183 is implemented, we have a publish<ConfigurationName>task (I call it the publish task in the rest of the posting). Each project has 0..n of those tasks. Neither the publish task nor the archive tasks will depend on test. I think this publish tasks is nice place for implementing this behavior.

We could offer:

gradle compile -R -no-rebuild // This would disable all the publish tasks of the dependency projects gradle compile -R clean,test // Adds dependsOn for clean and test on the publish tasks of the dependency projects gradle compile // Chooses a default behavior. We can decide which one. I think right now it would make sense to choose 'rebuild without additional stuff'. If our build becomes smarter in avoiding unnecessary stuff, we might add the test task to the default behavior.

A publish task could also come with a property like defaultDependsOnTasks. This would overwrite the default behavior if nothing is specified with the recursive option.

I think for 0.6 we should go with simple tasks names for the recursive option. In a future release we could provide patterns to be more selective, e.g.: gradle compile -R *core*:test (only test project dependencies with a core in there name).

The issue for this is: http://jira.codehaus.org/browse/GRADLE-220

<snip>

- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org




Reply via email to