How to express "optional strict" dependencies in an ivy-compatible way?

Hi all,

I’ve already posted this quetsion on the ivy-users mailing list, and had one response, that my proposed solution is a reasonable one. I just wanted to ask this here to see if i get any more good ideas.

I’m looking for a way to enforce a particular kind of check on versions in a transitive dependency graph. I have an idea for how to do it, but I’d like to hear opinions on whether there’s a better way, whether it’s the wrong thing to be doing in the first place, etc.

Context

We have multiple teams building, publishing and using multiple in-house and third-party dependencies, mostly non-Java.

These teams are using two (soon three) different custom tools built on top of Ivy; one based on Gradle (1.4), one completely custom. Among many other things, these tools download dependencies as ZIP files (which might contain, say, header files), then unzip them to a cache, and put a symlink to there from the workspace of the module being built.

Requirement

Some of the dependencies have runtime binary-compatibility issues, meaning that all dependencies on those modules must be using the same version. However, not all builds want to use all (or any) of these libraries. And some of the problem libraries are very large, so teams don’t want to have to pull down the files for those libraries, to save time and space. Ideally they don’t want to have to symlinks to them in their workspace at all, for clarity.

So, we want a way to be able to express the constraint that if some module M has problem module P in its dependency graph (possibly multiple times), it must have a specific version P:1.5; but it doesn’t have to have a dependency on P.

We don’t want to always take the latest version, and we don’t want to force conflicts to resolve to a specific version. Some of the problem modules are C-style static libraries, already compiled in to the modules which use them, so anything other than strict conflict resolution would only be misleading. (Suppose I’m building module M, which depends on module A:2.0, which itself depends on P:1.1. I want M to have this “optional dependency” on P:1.5. If I “use latest” and the dependency is resolved to P:1.5, that doesn’t change the fact that A:2.0 has code from P:1.1 compiled into it.)

And, we want to solve this problem using only features of Ivy which are supported by Gradle 1.4.

Proposed solution

For each problem module P, give it a configuration called, say, “marker”, which has no artifacts.

Configurations of M (all of them?) declare a dependency on only the “marker” configuration of P.

Strict conflict resolution is used.

The tools are modified (if required) so that, if there are no artifacts at all for a resolved module’s configurations, they won’t create a symlink for that module in the workspace.

— So, how does that sound?