Dependencies links resolver conflict?

Hi there,

I'm pretty newbie on Rust and playing with dependencies in a workspace project, and stuck with conflict resolution.
In my workspace I have 2 packages :

  • one with
[dependencies]
plotters = "0.3.4"
  • the second with
[dependencies]
three-d = "0.14.0"

It is resulting in a dependency graph conflict

    Updating crates.io index
error: failed to select a version for `yeslogic-fontconfig-sys`.
    ... required by package `font-kit v0.11.0`
    ... which satisfies dependency `font-kit = "^0.11.0"` of package `plotters v0.3.4`
    ... which satisfies dependency `plotters = "^0.3.4"` of package `debug-ui v0.1.0 (D:\project\debug-ui)`
versions that meet the requirements `^3.0.0` are: 3.2.0, 3.1.0, 3.0.1, 3.0.0

the package `yeslogic-fontconfig-sys` links to the native library `fontconfig`, but it conflicts with a previous package which links to `fontconfig` as well:
package `servo-fontconfig-sys v5.1.0`
    ... which satisfies dependency `servo-fontconfig-sys = "^5.1.0"` of package `servo-fontconfig v0.5.1`
    ... which satisfies dependency `servo-fontconfig = "^0.5.1"` of package `crossfont v0.5.0`
    ... which satisfies dependency `crossfont = "^0.5.0"` of package `sctk-adwaita v0.4.1`
    ... which satisfies dependency `sctk-adwaita = "^0.4.1"` of package `winit v0.27.1`
    ... which satisfies dependency `winit = "^0.27.1"` of package `glutin v0.29.0`
    ... which satisfies dependency `glutin = "^0.29"` of package `three-d v0.14.0`
    ... which satisfies dependency `three-d = "^0.14.0"` of package `ui v0.1.0 (D:\project\ui)`
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 ='yeslogic-fontconfig-sys' value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.

By looking at both crates

I see that yeslogic-fontconfig-sys uses cargo links to refers to its other package named 'fontconfig'.

# yeslogic/fontconfig Cargo.toml
[package]
name = "fontconfig"
# yeslogic/fontconfig-sys Cargo.toml
links = "fontconfig"

From my undersanding it is conflicting with servo/rust-fontconfig using in its toml the lib tag ?

#  servo/rust-fontconfig Cargo.toml
[package]
name = "servo-fontconfig"
[lib]
name = "fontconfig"

If so I'm not sure about the best way to solve this :thinking:
Is there a trick / tip to make them live together in my project ?

Thanks in advance for your help :slight_smile:

It is not possible to put both crates into the same workspace, because workspaces are designed to share one Cargo.lock file. Quoting the Cargo Book wrt the links field:

Primarily, Cargo requires that there is at most one package per links value. In other words, it is forbidden to have two packages link to the same native library. This helps prevent duplicate symbols between crates.

This appears to be a variant of workspaces: overzealous native library dependency conflicting · Issue #7880 · rust-lang/cargo (github.com). I.e., even though Cargo should be able to determine that the dependency trees for each crate are entirely unrelated, the shared lock file causes a flattening of dependencies that makes the resolution impossible.

The easiest solution is putting these two crates into separate repositories.


ninja edit: You can workaround this issue by adding one of the two crates to the workspace.exclude array. You lose some benefits of the workspace by doing this, but retain the ability to keep both crates in the same repo. The excluded crate will have its own lock file and target subdirectory, and you'll have to run cargo from within the excluded directory separately to the rest of the workspace.

This is not a great workaround, but it's a thing you can do.

1 Like

I have tried this one, as it is an ok traid-off in my dev context, but in the end I will surely want to use both of my crates as [dependencies] of a parent package. In this case I encounter the same error :thinking:
Which is not really surprising me for the reasons you have given

Cargo requires that there is at most one package per links value

[package]
name = "project-parent"
[dependencies]
ui = { path="../ui"}
debug-ui = { path = "../debug-ui"}

I am not sure how to work this one out, I have tried something like that (in a single workspace context)

[workspace]
members = ["ui", "debug-ui"]
exclude = ["debug-ui"]

I put it in members to reuse crates in incoming packages, and put specifically debug-ui in exclude (arbitrarily) in order to apply your hint, but still got the same error.

Can you eventually provide an example ?
Sorry if I'm stuck on something trivial :sweat_smile:

This is where you will not be able to make any progress. Your best bet might be to patch either crossfont to use yeslogic-fontconfig-sys or patch font-kit to use servo-fontconfig. In other words, break the requirement of multiple crates linking to the same library.


No, it would be like this, but it isn't what you want.

[workspace]
members = ["ui"]
exclude = ["debug-ui"]

I saw that coming :smile: but I perfered to ask first for a workaround, thank you for your replies !
I think I can report this topic as an issue for both crates to see where this ends.

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.