How to declare dependencies in Cargo without cascading effects

Say I have a crate A that depends on zstd = ^0.6 (only used internally) and a crate B that depends on A and zstd = ^0.6 (also only used internally).

Crate B uses ^0.6 because it matches A (smaller binary, etc.).

A confirms that it is compatible with ^0.9 and would like to offer support also for this in their next release (e.g. 0.9 is faster than 0.6).

How should A proceed?

  1. change ^0.6 to ^0.9.
  2. change ^0.6 to >=0.6,<0.10

From the Python ecosystem, we generally favor 2. because it offers downstream consumers the flexibility to choose how they wanna do it. However, Python does not allow 2 packages with different versions.

Option 1. seems the preferred option in Cargo, but my impression is that we "force" everyone to follow suit or increase the binary size (the same way B was "forced" to use ^0.6 in the first place).

Is there a practice here?

I normally just update the requirement in my crate's Cargo.toml file and let the dependency update whenever they want. For 99% of use cases you honestly don't care about binary size (and the increase will be marginal anyway, so you'd barely notice if cargo compiled both v0.6 and v0.9 of the dependency.

Running cargo outdated and cargo update every now and then also helps tidy up these sorts of duplicated versions because it lets you upgrade all your dependencies to the latest version.

The only situations I can think of where you might care are...

  1. Your platform has limited memory and you need to squeeze out every last kb from your binary
  2. The resulting binary ends up massive (e.g. hundreds of MB)
  3. Compiling both versions of the dependency has a non-trivial effect on build times (e.g. wasmer or tokio)
  4. When you need to pass objects defined in v0.6 of zstd to something that expects the v0.9 version
2 Likes

Isn't the binary size a concern in wasm?

I also get a feeling that it is also a concern when building Python wheels with pyo3, which affects download speed, CI time, etc.

Is there a downside of bracketing the dependencies in cargo (besides not being common).

The biggest downside I can see to relaxing restrictions is that those versions may not actually be semver compatible and your users run into compilation issues because the resolver chose to use a particular version.

2 Likes

Option 1 is the Cargo way.

Run cargo tree -d and then bug dependency authors to upgrade their deps too.

2 Likes