Cargo and native library version conflicts

Hey,

Hit an interesting situation today. A conflict when cargo tries to resolve a native library dependency ... of some of my dependencies.

In this case ring.

From everything I've been able to find out it seems like an unresolvable situation, unless the dependencies update their dependencies or one forks, updates (if possible) and then uses that.

It potentially gets even tricker if the dependency is deeper down the tree.

Are there other ways to resolve this that I'm missing?

can you describe what is the configuration of your build environment and/or how exactly the libraries conflicts?

The environment is a MBP M2, Rust 1.70.0.

When cargo build runs and starts pulling and sorting out the dependencies it errors out saying:

.....
error: failed to select a version for `ring`.
......
Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary.
.....

I believe one comes from mongodb -> rustls -> ring
and the other one from another library that directly uses an older version of ring

I think I somewhat understand why this is a problem, but I'm curious how this is expected to be handled in the ecosystem in general.

yeah, cargo is complaining the links attributes, so the conflict is not in the native/ffi libraries, but actually within the crates dependency graph. as you already figured out, eventually the solution would require some of the dependency crates to update their dependencies.

but temporarily, maybe you can workaround this if you can find some older versions of some of the dependencies which are compatible, but I would suggest against it for crypto libraries if possible.

another common workaround is to add patched local copies of certain dependencies before the upstream crates get updated.

cargo tree would show the dependencies in a tree view so you can see what versions are actually in conflict.

Generally the solution is to either upgrade/downgrade some dependencies such that their transitive dependencies' versions become compatible or patch one of them to use a non-incompatible dependency. Unfortunately I cannot tell you which one to upgrade/downgrade to which version because you haven't posted the full error message, which includes which crates are causing the problem.

1 Like

I tried using some of the advice here, but no luck so far.

❯ cargo add mongodb
    Updating `<repository>` index
      Adding mongodb v2.6.0 to dependencies.
             Features:
             + serde_bytes
             + tokio-runtime
             - async-std
             - async-std-resolver
             - async-std-runtime
             - aws-auth
             - azure-kms
             - bson-chrono-0_4
             - bson-serde_with
             - bson-uuid-0_8
             - bson-uuid-1
             - flate2
             - gcp-kms
             - in-use-encryption-unstable
             - log
             - mongocrypt
             - num_cpus
             - openssl
             - openssl-probe
             - openssl-tls
             - rayon
             - reqwest
             - snap
             - snappy-compression
             - sync
             - tokio-openssl
             - tokio-sync
             - tracing
             - tracing-unstable
             - zlib-compression
             - zstd
             - zstd-compression
    Updating `<repository>` index
error: failed to select a version for `ring`.
    ... required by package `webpki v0.22.0 (registry `<repository>`)`
    ... which satisfies dependency `webpki = "^0.22"` of package `tokio-rustls v0.23.2 (registry `<repository>`)`
    ... which satisfies dependency `tokio-rustls = "^0.23.2"` of package `mongodb v2.6.0 (registry `<repository>`)`
    ... which satisfies dependency `mongodb = "^2.6.0"` of package `<project> v0.1.0 (/<project>)`
versions that meet the requirements `^0.16.19` are: 0.16.20, 0.16.19

the package `ring` links to the native library `ring-asm`, but it conflicts with a previous package which links to `ring-asm` as well:
package `ring v0.16.20`
    ... which satisfies dependency `ring = "^0.16.5"` (locked to 0.16.20) of package `jsonwebtoken v8.3.0`
    ... which satisfies dependency `jsonwebtoken = "^8.3.0"` (locked to 8.3.0) of package `<internal-lib> v0.1.2 (registry `<repository>`)`
    ... which satisfies dependency `<internal-lib> = "^0.1.2"` (locked to 0.1.2) of package `<project> v0.1.0 (/<project>)`
Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='ring' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.

failed to select a version for `ring` which could resolve this conflict
[patch.<repo>]
ring = "=0.16.20"

Trying to build, we get to the next one:

❯ cargo build
warning: unused manifest key: target.aarch64-apple-darwin.rustflags
warning: unused manifest key: target.x86_64-apple-darwin.rustflags
warning: unused manifest key: target.x86_64-pc-windows-gnu.rustflags
warning: unused manifest key: target.x86_64-pc-windows-msvc.rustflags
warning: unused manifest key: target.x86_64-unknown-linux-gnu.rustflags
error: failed to select a version for `wasm-bindgen-shared`.
    ... required by package `wasm-bindgen-macro-support v0.2.68`
    ... which satisfies dependency `wasm-bindgen-macro-support = "=0.2.68"` (locked to 0.2.68) of package `wasm-bindgen-macro v0.2.68`
    ... which satisfies dependency `wasm-bindgen-macro = "=0.2.68"` (locked to 0.2.68) of package `wasm-bindgen v0.2.68`
    ... which satisfies dependency `wasm-bindgen = "^0.2"` (locked to 0.2.68) of package `chrono v0.4.20`
    ... which satisfies dependency `chrono = "^0.4.19"` (locked to 0.4.20) of package `reqwest-retry v0.1.5`
    ... which satisfies dependency `reqwest-retry = "^0.1.5"` (locked to 0.1.5) of package `<service> v0.1.0 (/<project>)`
versions that meet the requirements `=0.2.68` (locked to 0.2.68) are: 0.2.68

the package `wasm-bindgen-shared` links to the native library `wasm_bindgen`, but it conflicts with a previous package which links to `wasm_bindgen` as well:
package `wasm-bindgen-shared v0.2.68 (registry `<repository>`)`
    ... which satisfies dependency `wasm-bindgen-shared = "=0.2.68"` of package `wasm-bindgen-macro-support v0.2.68 (registry `<repository>`)`
    ... which satisfies dependency `wasm-bindgen-macro-support = "=0.2.68"` (locked to 0.2.68) of package `wasm-bindgen-macro v0.2.68 (registry `<repository>`)`
    ... which satisfies dependency `wasm-bindgen-macro = "=0.2.68"` (locked to 0.2.68) of package `wasm-bindgen v0.2.68 (registry `<repository>`)`
    ... which satisfies dependency `wasm-bindgen = "^0.2"` (locked to 0.2.68) of package `chrono v0.4.20 (registry `<repository>`)`
    ... which satisfies dependency `chrono = "^0.4.7"` (locked to 0.4.20) of package `mongodb v2.6.0 (registry `<repository>`)`
    ... which satisfies dependency `mongodb = "^2.6.0"` (locked to 2.6.0) of package `<service> v0.1.0 (/<project>)`
Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the links ='wasm-bindgen-shared' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.

Trying to pin this one:

[patch.<repository>]
ring = "=0.16.20"
wasm-bindgen-shared = "=0.2.68" #=0.2.40 has the same result

The pinning seems to have some adverse effects when compiling the dependencies:

error[E0308]: mismatched types
   --> /<projet-path>/webpki-0.22.0/src/trust_anchor.rs:95:22
    |
95  |                 skip(tbs, der::Tag::Sequence)?; // signature.
    |                 ---- ^^^ expected `Reader<'_>`, found `untrusted::Reader<'_>`
    |                 |
    |                 arguments to this function are incorrect
    |



    error[E0308]: mismatched types
   --> /<projet-path>/webpki-0.22.0/src/trust_anchor.rs:96:22
    |
96  |                 skip(tbs, der::Tag::Sequence)?; // issuer.
    |                 ---- ^^^ expected `Reader<'_>`, found `untrusted::Reader<'_>`
    |                 |
    |                 arguments to this function are incorrect

Worth noting the wasm-bindgen-shared issue only pops up when I try to patch ring. No mongodb dependency and no ring issues, everything else resolves and compiles fine.

Resolved the problem.

It was the custom registry and how it is set up. (The behavior is to be investigated.)

Thanks for the responses; this exercise was definitely educational! :saluting_face:

The only question I'm left with is:

Now that I've seen this type of problem, does it happen often? And when it happens, does it get this hairy, or did this instance spiral into a rabbit hole of horrors due to the custom registry messing with the packages?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.