prezi / gradle

A powerful build system for the JVM
www.gradle.org
0 stars 0 forks source link

Replacing a transitive project dependency with an external dependency #13

Closed lptr closed 9 years ago

lptr commented 9 years ago

When replacing a transitive project dependency with an external dependency, you still get the transitive dependency built, because the direct dependency still depends on the project, and not on the replacement. While this can be argued to be the correct behavior, it might also be pretty confusing if this is not your intention.

Question: do we want to do something about this?

Example:

Take the following three Java projects and their configurations (-> means "depends on", => means configuration extends other configuration):

project(":impl") {
    dependencies {
        compile project(":api")
    }
}

project(":test") {
    dependencies {
        compile project(":impl")
    }
}

The :test project's compile configuration dependency chain looks like this:

:test:compile -> :impl:default => :impl:compile -> :api:default => :api:compile

From the :impl project's point of view the world looks like this:

:impl:compile -> :api:default => :api:compile

Now, in :test:compile, replace the :api project dependency with an external dependency. But do NOT replace it in :impl.

project(":test") {
    configurations.compile.resolutionStrategy.eachDependency { details ->
        if (details.requested.name == "api") {
            details.useTarget "org.utils:api:1.5"
        }
    }
}

So now :test sees things like this:

:test:compile -> :impl:default => :impl:compile -> "org.utils:api:1.5:default"

...while for:impl things remain unchanged:

:impl:compile -> :api:default => :api:compile

When you run :impl:jar, you get :api:jar executed as well, because of the Jar artifact on :api:compile.

:impl:jar -> :impl:compile -> :api:default => :api:compile

But what should happen when you run :test:jar? I'd expect :api:jar not to run, because we just replaced the :api project dependency with an external dependency:

:test:jar -> :test:compile -> :impl:default => :impl:compile -> "org.utils:api:1.5:default"

However, when we build the task graph, we calculate :impl:jar's dependencies from the :impl:compile configuration, and not from :test:compile. So we end up still running :api:jar. Only we won't use the Jar produced that way in the :test project, but we'd use the external dependency.

lptr commented 9 years ago

Discussed with @bigdaz. It's okay to leave it like this, better than trying to do something clever that the user might not intend to do.