Cargo native link conflict issue caused by source replacement

Hi folks, I encountered a problem when using a private registry "proxy" as source replacement of crates-io in our company.

When a package contains native link:
The same package from crates-io and from the registry source that replaces creates-io are treated as different packages and lead to the conflict error.
(Although the crates-io has been replaced and the download is never from crates-io )

The error is like:

Error details
error: failed to select a version for `wasm-bindgen-shared`.
    ... required by package `wasm-bindgen-macro-support v0.2.40`
    ... which satisfies dependency `wasm-bindgen-macro-support = "=0.2.40"` of package `wasm-bindgen-macro v0.2.40`
    ... which satisfies dependency `wasm-bindgen-macro = "=0.2.40"` of package `wasm-bindgen v0.2.40`
    ... which satisfies dependency `wasm-bindgen = "^0.2.23"` of package `js-sys v0.3.0`
    ... which satisfies dependency `js-sys = "^0.3"` of package `chrono v0.4.20`
    ... which satisfies dependency `chrono_0_4 = "^0.4.20"` of package `serde_with v3.3.0`
    ... which satisfies dependency `serde_with = "^3.3.0"` of package `testdeps v0.1.0 (/Users/wzhang1/workspace/rsworkspace/testdeps)`
versions that meet the requirements `=0.2.40` are: 0.2.40

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.81 (registry `test-mirror`)`
    ... which satisfies dependency `wasm-bindgen-shared = "=0.2.81"` of package `wasm-bindgen-macro-support v0.2.81 (registry `test-mirror`)`
    ... which satisfies dependency `wasm-bindgen-macro-support = "=0.2.81"` of package `wasm-bindgen-macro v0.2.81 (registry `test-mirror`)`
    ... which satisfies dependency `wasm-bindgen-macro = "=0.2.81"` of package `wasm-bindgen v0.2.81 (registry `test-mirror`)`
    ... which satisfies dependency `wasm-bindgen = "^0.2"` of package `chrono v0.4.21 (registry `test-mirror`)`
    ... which satisfies dependency `chrono = "^0.4.21"` of package `testdeps v0.1.0 (/Users/wzhang1/workspace/rsworkspace/testdeps)`
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"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links.

failed to select a version for `wasm-bindgen-shared` which could resolve this conflict

The issue can be reproduced in:

Assuming you have .cargo/config.toml

source replacement
[source.crates-io]
replace-with = "test-mirror"

[registries]
[registries.test-mirror]
index = "<......>"

The example of cargo.tom is like

[package]
name = "demo-conflict"
version = "0.1.0"
edition = "2021"

[dependencies]
serde_with = { version = "3.3.0"}
wasm-bindgen = {version = "0.2", registry = "test-mirror"}
chrono = { version = "0.4.21", registry = "test-mirror"}

I would like to hear your thoughts about this issue.
And I was attempting to some fix /cargo/pull/14713 Where I explicitly preserve the replaced source info for a package so that the later resolve step can handle the info.

Alternatively, the fix might be done to: change the conflict check

I think this is expected. Registry replacing is only meant for exact mirrors. The lockfile will still refer to the original registry and cargo expects that the checksum matched between the original and replaced registry. Try omitting the registry = "test-mirror" key for all crates that you mirrored from crates.io and only use it for crates that are only published to the company registry and not to crates.io.

The .cargo/config.toml has the replacement section

[source.crates-io]
replace-with = "test-mirror"

[registries]
[registries.test-mirror]
....

Which means the packages would be always downloaded from the test-mirror if not explicitly specified or specified as crates-io.
Therefore I have been expecting the resolve process can make decision based on all this information.


Try omitting the registry = "test-mirror" key for all crates

Yes, it works if all the crates do the same. The issue in our company is that we have multiple crates owned by different teams. They don't always have consistent pattern.
It is always need additional fix when some team use registry = "test-mirror" and some does not use.

Dependency resolution completely ignores registry replacement afaik to ensure that it doesn't affect the lockfile. Only the crate and registry download code takes it into account. I'm not sure if you are even supposed to use a single registry for a crates.io mirror and your own packages in the first place.

We have two registries. One for the crates.io mirror and one for our own internal code.

The registries:

[registries]
[registries.crates-io-mirror]
index = "sparse+ https:...artifactory/api/cargo/cargo-mirror/index/"

[registries.internal]
index = "sparse+https ... rtifactory/api/cargo/internal/index/"

The replacement is only for the

[source.crates-io]
replace-with = "crates-io-mirror"

Dependency resolution completely ignores registry replacement afaik to ensure that it doesn't affect the lockfile.

yes, the current cargo try to achieve that.
I tried some change to fix the issue but it affects the lock file.

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.