This, and if it works, I copy the string over to the other Cargo.tomls when I get around to it. The present world with multi-repo is nothing to marvel at.
If the goal is to keep versions of common dependencies in sync, then I'd rather let dependencies refer to each other:
[dependencies]
foo = "^3.14"
bar = "^2.71"
baz = { same_as = ["foo", "bar"] }
- This will make the crate use the same version of
baz
thatfoo
andbar
use. - If
foo
andbaz
use different-but-compatible version requirements - e.g.foo
needs>=0.2.3
whilebar
needs>=0.2.4
- it'll just have them both use a version they both accept. - If
foo
andbar
require incompatible versions ofbaz
- cargo should fail with an appropriate error message.
That is discussed earlier. For more information on the idea, see 3516-public-private-dependencies - The Rust RFC Book.
That only helps make sure that baz uses the same version requirement/range as foo
and bar
but does not ensure that foo
, bar
, and baz
use the same precise versions some external source which is the request in this issue.
Where one has such stringent compatibility requirements, I've just exported the inner dependency crate from the foo
or bar
crates to use directly. For example, ghostflow_gitlab
offers APIs around the gitlab
crate and, because the version is hard to specify properly as a ghostflow_gitlab
consumer, instead ghostflow_gitlab::gitlab
is used.
just exported the inner dependency crate
As an interim, I've considered re-exporting our dependencies to a "pinning" crate. This might actually help the developer experience since all of our main dependencies would just complete off of same pinning::foo
pattern.
When using a polyrepo pattern for services, each new service requires us to add multiple dependencies to the Cargo.toml. Even if the version resolution was delegated out, the dependency names don't complete off of a common list. Using a type name the first time frequently requires adding the type in three places if not using the fully qualified name. Even after we switch to a private registry for other reasons, having the list of our frequent direct dependencies in a consolidated form would still add value in the form of completion for frequent direct dependencies.
Our common crate, which is rather monorepo style, embodies this kind of solution already. If a crate only uses the re-exported common interfaces, we can often alleviate the need to list the dependency or maintain version parity at all.
To combat fat binaries, I bet I would have to add some features. Our common crate does this. With a shared target (configured by .cargo/config.toml), all projects can share targets fairly easily, so re-using builds has been achieve a while ago. I haven't thought though the lockfile implications of re-export as a workaround.
If you aren't actually using the code, it is extremely unlikely to be present in the final binary. Otherwise everyone would get a full copy of the stdlib for every binary.