Conan: Conan not picking latest version when in conflict

Created on 4 Nov 2017  路  9Comments  路  Source: conan-io/conan

Suppose I have multiple projects A,B,C and D which depends each other on following versions.

B(v0.1) depends on A(v0.1)
C(v0.1) depends on A(v0.2)
D(v0.1) depends on B(v0.1) and C(v0.1)

And I have exported packages like this,

PackageA/0.1@demo/demo
PackageA/0.2@demo/demo
PackageB/0.1@demo/demo
PackageC/0.1@demo/demo

And when I try to create package D, I get the following warning.

WARN: Conflict in PackageC/0.1@demo/demo
    Requirement PackageA/0.2@demo/demo conflicts with already defined PackageA/0.1@demo/demo
    Keeping PackageA/0.1@demo/demo
    To change it, override it in your base requirements

Which is understandable considering that two different versions of PackageA is referenced.

But my question is why conan has picked version 0.1 instead of picking 0.2? Shouldn't the latest version needs to be picked here?

I'm using conan version 0.28.1.

question

All 9 comments

Choosing one or the other is quite arbitrary, given that you are in a version conflict. The build can error both if you go for the latest or for the previous version. The -werror command line option allows to raise an error instead of warning (just thinking, probably we want to make this the default, what do you think @lasote?).

The criteria used for conan is the requirements declared first have priority. The graph computation is depth-first, so the requirements that you declare first will be the ones that define the upstream dependencies to use.

Hi, Thanks for the quick reply.
Is there a way to guarantee all downstream projects gets the latest version of PackageA? In practice, PackageA is the Boost library. I would like to propagate Boost library release updates to downstream with smallest changes as possible.

It seems like I have following options,

  • Make sure that PackageA dependency is in a left most leaf in dependency graph.
  • Create a new release version in all packages that depends on PackageA.

First option would require a careful maintenance of the dependency graph, and the second will require to bump releases in downstream exponentially.

Any thoughts?

There are several ways to do this:

  • You can use rquirements overriding. The consumer always has control. So if the project defines a requirement to the Boost version you want, that is the version that will be used upstream, irrespective of the one declared in the upstream packages. This is standard procedure to resolve version conflicts. It can also override user/channel

  • You might try to use version ranges in packages like depending on Boost/[>1.60]@user/channel, so they will upgrade automatically when new versions are out (if using --update, or cleaning the cache). Beware of binary compatibility, you might want to learn about the package_id() method: http://docs.conan.io/en/latest/howtos/define_abi_compatibility.html

  • You can try to use package-creator definition of latest. So with conan alias you can define a Boost/latest@user/channel that points to the latest published version (or the one you want to consider latest for your team)

About the -werror is not the first time I think about it and probably should be an error by default. You never read the warning.

It seems like I could get it working using version ranges. Thanks!

Hello, about the versioning using semver, what if I have:

B(v0.1.0) depends on A/[>=0.1.0)]
C(v0.1.0) depends on A/[~0.1.0]
D(v0.1.0) depends on B(v0.1.0) and C(v0.1.0)

and I have packages:

PackageA/0.1.0@demo/demo
PackageA/0.2.0@demo/demo
PackageB/0.1.0@demo/demo
PackageC/0.1.0@demo/demo

With Conan 1.0 (I have Conan 1.1.0), this throws a conflict error because PackageB resolves to A(v0.2.0) and PackageA to A(v0.1.0). Shouldn't PackageB resolve to A(v0.1.0) since we have greater or equal to A(v0.1.0)?

Conan version resolution is greedy, it doesn't compute interval intersections or try to solve the joint compatibility problem (which is an NP problem).

The reason for this is that the conan dependency graphs are not unique. They can change with every configuration of input (settings, options). And the configuration can be different in different branches of the dependency graph, this makes this computation extremelly challenging and slow, not to say unfeasible.

So the computation is greedy, first B depends on A>0.1.0, which is resolved to A/0.2.0, and when the other branch via C evaluates, it finds a conflict.

To solve it, add a dependency to A/[~0.1.0] from D and the conflict should be resolved.

I've been experiencing this as well in a setup similar.

A depends on B and C.
B has a requirement D/[>=0.1,<0.4]@test/test
C has a requirement D/[>=0.3,<0.6]@test/test
D has no requirements.

Here, B and C overlap in a requirement for D v0.3. Conan instead produces the error described above. This is really misleading and is not intuitive. I shouldn't have to modify or pin A to any version of D, especially if A is supposed to be agnostic of what its dependencies are doing.

Hi @Lnk2past

The reasons are explained above, conan is not computing the SAT problem that joint compatibility of dependencies ranges define, which is an NP problem, because of the added complexity of exploding combinatorics of dependency graphs over the possible binary configurations. It is not that B has a requirement on D.1, but it could have that requirement if it is a static library, and require a different version D.2 if it is not. That makes the problem extremely difficult to solve, specially if it has to be solved in finite time. Instead of waiting for many minutes for a solution to come, failing quickly and letting the user define which version they want upstream works very well in practice.
Thanks for the feedback!

Was this page helpful?
0 / 5 - 0 ratings