"You can't change a configuration which is not in unresolved state!" in trivial multi-project build

Hi,

I’m trying to begin migrating a very complicated multi-project ant build system into Gradle. The first step is to move dependency resolution into gradle, however I am having some issues with understanding how to define dependency configurations in a multi-project environment.

What I want to achieve is to have each subproject containing a build.gradle file, and be able to resolve and download its own dependencies. I will then hand over to the legacy ant script to do the build (for now, at least). I am currently getting the error “You can’t change a configuration which is not in unresolved state!” when I run my simple single project example. This is such a trivial example I am sure that I am somehow misunderstanding how to achieve what I want, but having tried many permutations have had no luck.

I have the following structure:

/build.gradle
/settings.gradle
/subproj/build.gradle

/build.gradle

defaultTasks 'updateLibs'
  allprojects {
 configurations {
  runtime
 }
   repositories {
  mavenCentral()
 }
    task updateLibs {
  copy {
   from configurations.runtime
   into file("lib")
  }
 }
}

/settings.gradle

include 'subproj'

/subproj/build.gradle

dependencies {
 runtime 'com.google.guava:guava:13.0.1'
}

When I run this build I get the following error:

FAILURE: Build failed with an exception.
  * Where:
Build file '/Users/nick/tmp/bld/subproj/build.gradle' line: 2
  * What went wrong:
A problem occurred evaluating project ':subproj'.
> You can't change a configuration which is not in unresolved state!

As far as I can see the configurations are not automatically shared or inherited by projects, as if I remove the configurations declaration from allprojects the build fails, as I would expect, because the task refers to a configuration that is undefined in the subproject. Does this mean that each subproject needs to have a configuration with a unique name, or have I another failure of understanding preventing this from working?

Cheers,

Nick

Hello Nick, your build scripts are just fine, except one little problem.

The problem is your updateLibs task. Your current updateLibs task definition looks like this:

task updateLibs {
        copy {
            from configurations.runtime
            into file("lib")
        }
    }

This task has no action defined, BUT within its configuration closure, you declared a copy operation. This copy operation resolves you’re runtime configuration during the configuration phase. After that resolving, you cannot add further dependencies to a configuration as the error message you got already told you. To understand the differences of configuration and execution phase have a look at the usergude, that explains this in more detail: http://gradle.org/docs/current/userguide/userguide_single.html#sec:configuration_and_execution_phase

To fix your problem, I can see two options:

OPTION #1: Move the copy operation in a doLast block:

task updateLibs {
    doLast{
        copy {
            from configurations.runtime
            into file("lib")
        }
}

OPTION #2: Refactor your updateLibs task to be a Copy task:

task updateLibs(type:Copy) {
    from configurations.runtime
    into file("lib")
}

I strongly recommend you option2 as it has some other advantages like the build-in up-to-date check.

hope that helped,

cheers, René