On 23/10/2010, at 2:05 AM, chris wrote:
>
> Hi,
>
> I'm try to do a multi-project build, and to keep my sanity I'm checking the
> dependencies on a configuration I have. The problem is when I do this, it
> appears to alter the list of files attached to this later on!
>
> So I have this kind of thing:
>
> rootProject build.gradle:
>
> subprojects
> {
> apply plugin: 'java'
>
> configurations {
> configServerTier // server tier jars
> configServer { // server-tier, test jars, libraries
> extendsFrom configServerTier, configTest
> }
> }
>
> // etc...
>
> afterEvaluate { project ->
>
> if (project.hasProperty('specialProject'))
> {
> // if following is commented, I get all my dependency libraries
> for the configServer configuration, otherwise I just get project artifacts!
> WHY?
> println "configServer: " +
> project.configurations.configServer.files.collect { it.name }
>
> task testJar (type: Jar, dependsOn:
> subprojects.configurations.configServer) {
> into('test') {
> from configurations.configServer
> from configurations.configServer.allArtifactFiles
> }
> }
> }
> }
> }
>
>
> subproject :core build.gradle:
>
> configurations {
> compile { extendsFrom configServer }
> }
> dependencies {
> compile project(':util')
> configServer 'ecs:ecs:1.4.2'
> configServer 'com.thoughtworks.xstream:xstream:1.3'
> }
>
>
> subproject :anotherProject (depends on above core project) build.gradle:
>
> specialProject = true
> dependencies {
> // depend on all other projects
> rootProject.standardProjects(exclude:this.project).each {
> configServer project(path: it.path, configuration: 'configServer')
> }
> compile project(path: ':core')
> }
>
>
> When the println is commented I get the ecs and xstream jars in my Jar as
> well as artifacts through the serverConfig configuration. When the println
> is executed, all I get is the artifacts - no ecs or xstream.
>
> What's going on? Why would a println affect the configuration?
There's two things going on here.
First, when a configuration is resolved (for example, when iterating over its
files) the result is cached and the same set of files is always returned.
Second, the afterEvaluate { } closure of a project is executed immediately
after the build script for the project is executed, but not necessarily after
the other build scripts which affect the project have been executed.
In your example, the build script for :anotherProject executes first. When its
afterEvaluate { } closure executes, the build scripts for :core and :util
projects have not been executed. The println causes the configuration to be
resolved and the result cached. And since :core's build script has not been
executed, the dependencies for ecs and xstream have not been added.
You're supposed to get an exception when you modify a configuration in some way
after it's been resolved, but you've run into a situation where it's broken:
http://jira.codehaus.org/browse/GRADLE-1120
Configuration ordering is a bit of a problem at the moment, and can lead to
some really confusing behaviour. We want to make some changes to improve this.
One part of the solution will be to have things fail when you try to configure
something which has already been 'executed'. Adding dependencies to a
configuration after it has been resolved is an example of this. Or adding
dependencies to a task after the graph has been built. Or changing a task
property after the task has executed. And so on.
Another part will be to provide better ways to declare what your code needs.
For example, your println really only works once the configServer configuration
has been fully configured. So we might offer a whenConfigured { } method on the
Gradle domain objects, so you can do something like:
configurations.configServer.whenConfigured { println ... }
Or perhaps you might be able to say that the afterEvaluate { } closure
dependsOn the configServer configuration.
The final part is to have Gradle take care of more (or all) of the ordering for
you. For example, Gradle can figure out that that the whenConfigured { }
closure above must be deferred until after the :core and :utils projects have
been configured, because of the transitive project dependencies in the
configServer configuration.
--
Adam Murdoch
Gradle Developer
http://www.gradle.org
CTO, Gradle Inc. - Gradle Training, Support, Consulting
http://www.gradle.biz