As discussed in Is it documented that Cargo can download and bundle multiple versions of the same crate?, it's possible for Cargo to pull in multiple versions of the same crate for a single program. How do I access both of these versions concurrently?
As of Rust 1.31, you can rename dependencies in Cargo.toml:
[dependencies]
futures_01 = { package = "futures", version = "0.1.0" }
futures_03 = { package = "futures", version = "0.3.0" }
You can choose whatever name you want for the key. The package attribute needs to be the official name of the crate.
Within your code, you can access version 0.1.x using the crate name futures_01, and version 0.3.x via futures_03.
See also:
How to idiomatically alias a crate in Rust 2018?
Why is a trait not implemented for a type that clearly has it implemented?
Related
I'm learning Rust, and I can't seem to use the FromSql trait from the r2d2_postgres crate.
Based on this recommendation, I tried adding the feature in my TOML file:
r2d2_postgres = {version = "0.18", features = ["postgres/with-chrono-0_4"]}
But then Rust tells me:
feature `postgres/with-chrono-0_4` in dependency `r2d2_postgres` is not allowed to contain slashes
If you want to enable features of a transitive dependency, the direct dependency needs to re-export those features from the `[features]` table.
To be able to work with both r2d2 and chrono, an extra dependency on the postgres crate is needed. But the postgres crate must be the same version as the r2d2_postgres::postgress crate in order to work together.
Versions can be compared with the output of cargo tree --duplicates.
At this time of writing, Cargo.toml must contain:
[dependencies]
r2d2_postgres = "0.18"
postgres = {version = "0.19", features = ["with-chrono-0_4"]}
Thank you Caesar.
I am using a library that breaks depending on which other crates I am using. The way around is to downgrade a few dependencies and keep a local version of the library.
It works if I put MyLibraryDep = {version = "*"} in my Cargo.toml. Since Cargo will then fix dependencies automatically, but crates.io doesn't allow for that.
Example:
If using MyLibrary, and LibraryA I have to use MyLibraryDep v0.1.0 in MyLibrary
If using MyLibrary, and LibraryB I have to use MyLibraryDep v0.2.0 in MyLibrary
As specified in the Cargo book, you can use inequality requirements and multiple requirements combined to form a range of valid versions.
MyLibraryDep = {version = ">=0.1.0, <=0.2.0"}
Such a requirement will also allow Cargo to choose the appropriate version and should be allowed by crates.io.
I have a crate foo_sys. In Rust 2015 I used extern crate foo_sys as foo for convenience, but in Rust 2018 extern crate isn't needed anymore and I don't want to use it only for aliasing. When dropping extern crate, I get
error[E0463]: can't find crate for foo
This can be achieved with the rename-dependency Cargo feature, available in Rust 1.31. With this feature, it's possible to provide a package attribute to the dependencies:
The rename-dependency feature allows you to import a dependency with a different name from the source. This can be useful in a few scenarios:
Depending on crates with the same name from different registries.
Depending on multiple versions of a crate.
Avoid needing extern crate foo as bar in Rust source.
Instead of writing
[dependencies]
foo_sys = "0.2"
the package key can be added to the dependency in Cargo.toml:
[dependencies]
foo = { package = "foo_sys", version = "0.2" }
WARNING: Cargo prior to Rust 1.26.0 may download the wrong dependency when using this feature!
The idiomatic solution is to rename the crate in Cargo.toml. See the answer by Tim Diekmann for more information about that.
But if you don't want to use Cargo.toml renaming for some reason, you can still use the old syntax. It's soft-deprecated, but not removed. So this still works:
extern crate foo_sys as foo;
(Playground example)
Cargo.toml:
[package]
name = "proba"
version = "0.1.0"
[lib]
name = "mycoollib"
path = "src/mycoollib.rs"
crate-type = ["cdylib"]
src/mycoollib.rs:
#![no_std]
fn func(v: i32) -> i32 {
v + 10
}
When I try to run cargo build:
error: language item required, but not found: `panic_fmt`
error: language item required, but not found: `eh_personality`
A nightly build is needed to implement panic_fmt and eh_personality, but "Using Rust Without the Standard Library" of the Rust book says that libs can build on stable.
I believe that the documentation is misleading in this case. The problem is in the definition of the word "library".
A Rust library (sometimes known as an rlib) can use #[no_std] and not require definitions for panic_fmt or eh_personality. That's because eventually it will be linked against into a binary that does use the standard library, which defines these symbols.
A native library (either dylib, cdylib, or probably staticlib) has no guarantee of being linked with these symbols / language items, so they must be defined up front.
As you can see, both of these could be called a "library". I think that the book is being a little loose with the terminology, leading to the confusion.
So I am trying to serialize a struct using bincode following these instructions, and I was able to get that to work.
But then I wanted to serialize a struct with an IpAddr enum. Since IpAddr doesn't implement the Encodable trait needed, I downloaded the rustc_serialize crate from git and implemented encodable for IpAddr myself. I then changed my Cargo.toml file to:
[dependencies]
# rustc-serialize = "0.3"
byteorder = "0.3"
bincode = "0.4"
[dependencies.rustc-serialize]
path = "src/rustc-serialize-master"
But now, the same code from the struct I was using doesn't compile saying that
rustc_serialize::serialize::Encodable is not implemented for my struct even though i have #[derive(RustcEncodable)] above the struct.
Even when I get rid of the code I added to the local version of rustc_serialize, I still get that error.
I think it might be due to something being screwed up with the way bincode and a local rustc_serialize interact, but I'm not sure.
Please review the Cargo documentation on overriding dependencies:
To specify overrides, create a .cargo/config file in some ancestor of your project's directory (common places to put it is in the root of your code directory or in your home directory).
Inside that file, put this:
paths = ["/path/to/project/rand"]
Going deeper, you are likely running into issue 22750 - two different versions of a crate interacting leads to unhelpful error messages. When you add rustc-serialize to your dependencies, you aren't replacing the old version, you are adding a new one.
In general, this is a good feature. If my project relies on crates A and B and they both rely on crate Z but with different versions, Rust can handle that just fine. The problem arises when they re-export items from those crates.