Multiple versions of OpenSSL compile issue

I'm running into an issue where there is an unexpected choice being made when resolving decencies on a crate of mine.

I am using mongo-rust-driver and it depends on which in turn depends on mongoc-sys. In mongoc-sys's "openssl-sys = "> 0.7.0". The rest of my project needs ~0.7. I even have this is my Cargo.toml:

openssl = "0.7.14"
openssl-sys = "0.7.17"

Looking at this I would think "Oh well, it will just use 0.7.14 because that meets the '> 0.7.0' requirement," but I would be wrong. For some reason I get the error message:

error: native library openssl is being linked to by more than one version of the same package, but it can only be linked once; try updating or pinning your dependencies to ensure that this package only shows up once

openssl-sys v0.7.17
openssl-sys v0.9.1

When I run cargo-graph I see mongoc is the only crate that is using openssl-sys v0.9.1. What can I do to tell cargo to use 0.7.17 for mongoc?

What is mongoc? I don't see it on crates.io.

@steveklabnik I'm sorry. The full name was mongoc-sys https://crates.io/crates/mongoc-sys

I found the issue. In their Cargo.toml file they declare: openssl-sys = "> 0.7.0"

Looks like cargo just ignore this and gives them the newest library version. I'm going to open a bug with cargo and the mongoc-sys library.

  1. https://github.com/thijsc/mongo-rust-driver/blob/master/mongoc-sys/Cargo.toml#L16

Why would that be "ignored"? 9.0 > 0.7.

They should have been using just 0.7.0, which is ^0.7.0, for sure.

Do you mean “0.9 > 0.7”? I can see there could be an expectation that cargo performs libsolv-style dependency resolution, instead of greedily picking the highest possible version at the first time a dependency is encountered. I don't know if cargo actually does this—some other package managers implement dependency handling this way.

Java module managers (or even just class loaders) enforce similar restrictions on native libraries (i.e., loading of dynamic shared objects).

The bigger question in this context is whether the run-time dynamic linker should try support this usage scenario, loading different versions of the same shared object into the same process. There already is dlmopen, but it may not be sufficiently sophisticated, and glibc's current implementation is rather buggy and only there to supported its implementation of audit modules.

I did, yeah.

Cargo will try to attempt to unify versions, but only if they're "compatible" ones. Since any 0.y version is incompatible with any other number of y, cargo will instead choose to include both. So like, if this was ^1.1.0 and > 1.0, you'd get a single 1.2 (or whatever) for both. But if you had ^1.1.10 and > 2.0, then you'd end up with two versions again. Does that make sense?

2 Likes

It does, thanks.