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


(nick) #1

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


(René Groeschke) #2

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é