How to tell what "features" are available per crate? - rust

Is there a standard way to determine what features are available for a given crate?
I'm trying to read Postgres timezones, and this says to use the crate postgres = "0.17.0-alpha.1" crate's with-time or with-chrono features.
When I try this in my Cargo.toml:
[dependencies]
postgres = { version = "0.17.0-alpha.1", features = ["with-time"] }
I get this error:
error: failed to select a version for `postgres`.
... required by package `mypackage v0.1.0 (/Users/me/repos/mypackage)`
versions that meet the requirements `^0.17.0-alpha.1` are: 0.17.0, 0.17.0-alpha.2, 0.17.0-alpha.1
the package `mypackage` depends on `postgres`, with features: `with-time` but `postgres` does not have these features.
Furthermore, the crate page for postgres 0.17.0 says nothing about these features, so I don't even know if they're supposed to be supported or not.
It seems like there would be something on docs.rs about it?

Crates uploaded to crates.io (and thus to docs.rs) will show what feature flags exist. crates.io issue #465 suggests placing the feature list on the crate's page as well.
Beyond that, the only guaranteed way to see what features are available is to look at the Cargo.toml for the crate. This generally means that you need to navigate to the project's repository, find the correct file for the version you are interested in, and read it.
You are primarily looking for the [features] section, but also for any dependencies that are marked as optional = true, as optional dependencies count as an implicit feature flag.
Unfortunately, there's no requirement that the crate author puts any documentation about what each feature flag does. Good crates will document their feature flags in one or more locations:
As comments in Cargo.toml
Their README
Their documentation
See also:
How do you enable a Rust "crate feature"?
For the postgres crate, we can start at crates.io, then click "repository" to go to the repository. We then find the right tag (postgres-v0.17.0), then read the Cargo.toml:
[features]
with-bit-vec-0_6 = ["tokio-postgres/with-bit-vec-0_6"]
with-chrono-0_4 = ["tokio-postgres/with-chrono-0_4"]
with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"]
with-geo-types-0_4 = ["tokio-postgres/with-geo-types-0_4"]
with-serde_json-1 = ["tokio-postgres/with-serde_json-1"]
with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"]

You can use the cargo-feature crate to view and manage your dependencies' features:
> cargo install cargo-feature --locked
> cargo feature postgres
Avaliable features for `postgres`
array-impls = ["tokio-postgres/array-impls"]
with-bit-vec-0_6 = ["tokio-postgres/with-bit-vec-0_6"]
with-chrono-0_4 = ["tokio-postgres/with-chrono-0_4"]
with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"]
with-eui48-1 = ["tokio-postgres/with-eui48-1"]
with-geo-types-0_6 = ["tokio-postgres/with-geo-types-0_6"]
with-geo-types-0_7 = ["tokio-postgres/with-geo-types-0_7"]
with-serde_json-1 = ["tokio-postgres/with-serde_json-1"]
with-smol_str-01 = ["tokio-postgres/with-smol_str-01"]
with-time-0_2 = ["tokio-postgres/with-time-0_2"]
with-time-0_3 = ["tokio-postgres/with-time-0_3"]
with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"]
with-uuid-1 = ["tokio-postgres/with-uuid-1"]
Note: this only works if the crate is already in Cargo.toml as a dependency.
The list of features are also displayed when using cargo add:
> cargo add postgres
Updating crates.io index
Adding postgres v0.19.4 to dependencies.
Features:
- array-impls
- with-bit-vec-0_6
- with-chrono-0_4
- with-eui48-0_4
- with-eui48-1
- with-geo-types-0_6
- with-geo-types-0_7
- with-serde_json-1
- with-smol_str-01
- with-time-0_2
- with-time-0_3
- with-uuid-0_8
- with-uuid-1

It seems like there would be something on docs.rs about it?
Other people thought so too! This was added to docs.rs in late 2020. You can view the list of features from the crate's documentation by navigating to "Feature flags" on the top bar:
You still won't see the list of features of postgres 0.17.0 though since old documentation isn't regenerated when new functionality is added to the site, but any recently published versions will have it available.
Note: this is only available on docs.rs and not generated when running cargo doc.

The feature-set of a dependency can be retrieved programmatically via the cargo-metadata crate:
use cargo_metadata::MetadataCommand;
fn main() {
let metadata = MetadataCommand::new()
.exec()
.expect("failed to get metadata");
let dependency = metadata.packages
.iter()
.find(|package| package.name == "postgres")
.expect("failed to find dependency");
println!("{:#?}", dependency.features);
}
{
"with-time-0_3": [
"tokio-postgres/with-time-0_3",
],
"with-smol_str-01": [
"tokio-postgres/with-smol_str-01",
],
"with-chrono-0_4": [
"tokio-postgres/with-chrono-0_4",
],
"with-uuid-0_8": [
"tokio-postgres/with-uuid-0_8",
],
"with-uuid-1": [
"tokio-postgres/with-uuid-1",
],
"array-impls": [
"tokio-postgres/array-impls",
],
"with-eui48-1": [
"tokio-postgres/with-eui48-1",
],
"with-bit-vec-0_6": [
"tokio-postgres/with-bit-vec-0_6",
],
"with-geo-types-0_6": [
"tokio-postgres/with-geo-types-0_6",
],
"with-geo-types-0_7": [
"tokio-postgres/with-geo-types-0_7",
],
"with-eui48-0_4": [
"tokio-postgres/with-eui48-0_4",
],
"with-serde_json-1": [
"tokio-postgres/with-serde_json-1",
],
"with-time-0_2": [
"tokio-postgres/with-time-0_2",
],
}
This is how other tools like cargo add and cargo feature provide dependency and feature information.

Related

how to list crate features? [duplicate]

Is there a standard way to determine what features are available for a given crate?
I'm trying to read Postgres timezones, and this says to use the crate postgres = "0.17.0-alpha.1" crate's with-time or with-chrono features.
When I try this in my Cargo.toml:
[dependencies]
postgres = { version = "0.17.0-alpha.1", features = ["with-time"] }
I get this error:
error: failed to select a version for `postgres`.
... required by package `mypackage v0.1.0 (/Users/me/repos/mypackage)`
versions that meet the requirements `^0.17.0-alpha.1` are: 0.17.0, 0.17.0-alpha.2, 0.17.0-alpha.1
the package `mypackage` depends on `postgres`, with features: `with-time` but `postgres` does not have these features.
Furthermore, the crate page for postgres 0.17.0 says nothing about these features, so I don't even know if they're supposed to be supported or not.
It seems like there would be something on docs.rs about it?
Crates uploaded to crates.io (and thus to docs.rs) will show what feature flags exist. crates.io issue #465 suggests placing the feature list on the crate's page as well.
Beyond that, the only guaranteed way to see what features are available is to look at the Cargo.toml for the crate. This generally means that you need to navigate to the project's repository, find the correct file for the version you are interested in, and read it.
You are primarily looking for the [features] section, but also for any dependencies that are marked as optional = true, as optional dependencies count as an implicit feature flag.
Unfortunately, there's no requirement that the crate author puts any documentation about what each feature flag does. Good crates will document their feature flags in one or more locations:
As comments in Cargo.toml
Their README
Their documentation
See also:
How do you enable a Rust "crate feature"?
For the postgres crate, we can start at crates.io, then click "repository" to go to the repository. We then find the right tag (postgres-v0.17.0), then read the Cargo.toml:
[features]
with-bit-vec-0_6 = ["tokio-postgres/with-bit-vec-0_6"]
with-chrono-0_4 = ["tokio-postgres/with-chrono-0_4"]
with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"]
with-geo-types-0_4 = ["tokio-postgres/with-geo-types-0_4"]
with-serde_json-1 = ["tokio-postgres/with-serde_json-1"]
with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"]
You can use the cargo-feature crate to view and manage your dependencies' features:
> cargo install cargo-feature --locked
> cargo feature postgres
Avaliable features for `postgres`
array-impls = ["tokio-postgres/array-impls"]
with-bit-vec-0_6 = ["tokio-postgres/with-bit-vec-0_6"]
with-chrono-0_4 = ["tokio-postgres/with-chrono-0_4"]
with-eui48-0_4 = ["tokio-postgres/with-eui48-0_4"]
with-eui48-1 = ["tokio-postgres/with-eui48-1"]
with-geo-types-0_6 = ["tokio-postgres/with-geo-types-0_6"]
with-geo-types-0_7 = ["tokio-postgres/with-geo-types-0_7"]
with-serde_json-1 = ["tokio-postgres/with-serde_json-1"]
with-smol_str-01 = ["tokio-postgres/with-smol_str-01"]
with-time-0_2 = ["tokio-postgres/with-time-0_2"]
with-time-0_3 = ["tokio-postgres/with-time-0_3"]
with-uuid-0_8 = ["tokio-postgres/with-uuid-0_8"]
with-uuid-1 = ["tokio-postgres/with-uuid-1"]
Note: this only works if the crate is already in Cargo.toml as a dependency.
The list of features are also displayed when using cargo add:
> cargo add postgres
Updating crates.io index
Adding postgres v0.19.4 to dependencies.
Features:
- array-impls
- with-bit-vec-0_6
- with-chrono-0_4
- with-eui48-0_4
- with-eui48-1
- with-geo-types-0_6
- with-geo-types-0_7
- with-serde_json-1
- with-smol_str-01
- with-time-0_2
- with-time-0_3
- with-uuid-0_8
- with-uuid-1
It seems like there would be something on docs.rs about it?
Other people thought so too! This was added to docs.rs in late 2020. You can view the list of features from the crate's documentation by navigating to "Feature flags" on the top bar:
You still won't see the list of features of postgres 0.17.0 though since old documentation isn't regenerated when new functionality is added to the site, but any recently published versions will have it available.
Note: this is only available on docs.rs and not generated when running cargo doc.
The feature-set of a dependency can be retrieved programmatically via the cargo-metadata crate:
use cargo_metadata::MetadataCommand;
fn main() {
let metadata = MetadataCommand::new()
.exec()
.expect("failed to get metadata");
let dependency = metadata.packages
.iter()
.find(|package| package.name == "postgres")
.expect("failed to find dependency");
println!("{:#?}", dependency.features);
}
{
"with-time-0_3": [
"tokio-postgres/with-time-0_3",
],
"with-smol_str-01": [
"tokio-postgres/with-smol_str-01",
],
"with-chrono-0_4": [
"tokio-postgres/with-chrono-0_4",
],
"with-uuid-0_8": [
"tokio-postgres/with-uuid-0_8",
],
"with-uuid-1": [
"tokio-postgres/with-uuid-1",
],
"array-impls": [
"tokio-postgres/array-impls",
],
"with-eui48-1": [
"tokio-postgres/with-eui48-1",
],
"with-bit-vec-0_6": [
"tokio-postgres/with-bit-vec-0_6",
],
"with-geo-types-0_6": [
"tokio-postgres/with-geo-types-0_6",
],
"with-geo-types-0_7": [
"tokio-postgres/with-geo-types-0_7",
],
"with-eui48-0_4": [
"tokio-postgres/with-eui48-0_4",
],
"with-serde_json-1": [
"tokio-postgres/with-serde_json-1",
],
"with-time-0_2": [
"tokio-postgres/with-time-0_2",
],
}
This is how other tools like cargo add and cargo feature provide dependency and feature information.

use of undeclared crate or module in rust [duplicate]

If I define a dependency like foo = { version = "1.0.0", optional = true },
will it be available when I do "cargo run"? Can I check if it is enabled in the code?
if cfg!(feature = "foo") {}
Doesn't seem to be working, like the feature is missing all the time.
Moving answer to 60258216 here:
Optional dependencies do double as features: https://stackoverflow.com/a/39759592/8182118
They will not be enabled by default unless they're listed in the default feature, though you can enable the feature using cargo run --features foo.
For clarity and forward compatibility you may want to create an actual feature which enables the dependency though, that way if you need to "fluff up" the feature in the future and that requires new optional dependencies it's much easier.
In the code, both #[cfg] and cfg! should work depending whether you want to check for it at compile-time or runtime.
It's not hard to test either:
[package]
name = "testx"
version = "0.1.0"
edition = "2018"
[features]
default = ["boolinator"]
magic = ["boolinator"]
empty = []
[dependencies]
boolinator = { version = "*", optional = true }
and a main.rs of:
fn main() {
# macro and attributes would work the same here
if cfg!(feature = "boolinator") {
println!("Hello, bool!");
} else {
println!("Hello, world!");
}
}
you get
$ cargo run -q
Hello, bool!
$ cargo run -q --no-default-features
Hello, world!
$ cargo run -q --no-default-features --features boolinator
Hello, bool!
$ cargo run -q --no-default-features --features magic
Hello, bool!
$ cargo run -q --no-default-features --features empty
Hello, world!
See also https://github.com/rust-lang/edition-guide/issues/96

Rust in two different projects but same Cargo.toml. The other project is giving me an issue of dependency issue

Rust in two different projects but same Cargo.toml. The other project is giving me an issue of dependency issue while the other one is building fine. Both are compiling and in the same rust nightly build.
Am I missing anything?
Below is the error that I am seeing when I do `cargo build
error: failed to select a version for the requirement `pbkdf2 = "^0.2.0"`
candidate versions found which didn't match: 0.9.0, 0.8.0, 0.7.5, ...
required by package `mongodb v0.3.12`
... which satisfies dependency `mongodb = "^0.3.12"` of package `r2d2-mongodb v0.2.2`
... which satisfies dependency `r2d2-mongodb = "^0.2.2"` of package
Here's my cargo.toml
[dependencies]
anyhow = "1.0.34"
chrono = { version = "0.4.19", features = ["serde"] }
dotenv = "0.15.0"
jsonwebtoken = "7.2.0"
r2d2 = "0.8.9"
r2d2-mongodb = "0.2.2"
rand = "0.7.3"
rocket = "0.4.8"
rocket_contrib = { version = "0.4.8", features = ["helmet", "uuid"] }
rust-argon2 = "0.8.2"
serde = { version = "1.0.117", features = ["derive"] }
uuid = { version = "0.8.1", features = ["serde", "v4"] }
log = "0.4"
log4rs = "0.8"
[dev-dependencies]
lazy_static = "1.4.0"
serde_json = "1.0.59"
My rustc version
rustc 1.56.0-nightly (29ef6cf16 2021-08-31)
failed to select a version for the requirement `pbkdf2 = "^0.2.0"`
A transitive dependency is looking for a pbkdf2 0.2.x dependency. However, all versions of pbkdf2 prior to 0.3.0 have been yanked from crates.io. I haven't found a specific reason why, it could be due to a security vulnerability or other error on the authors' part, wherein they've decided these versions shouldn't be used.
The likely reason you get the error in one project and not the other is because one has a Cargo.lock file that has already selected a pbkdf2 0.2 version. Yanking doesn't prevent a version's use, only prevents new crates from depending on it.
The fix is to copy the Cargo.lock from the working project to the other.

How can I force rustqlite to be built as statically linked when using sqlcipher?

I'm using rustqlite and am trying to configure it to use sqlcipher via a Cargo feature. In the usual case, rustqlite has a bundled feature to include the sqlite source. When changing to sqlcipher, the source isn't bundled anymore.
Locally I was able to install sqlcipher and compile my project (installed via brew install sqlcipher on Mac).
The resulting binary dynamically links to the local sqlcipher installation so I can no longer distribute the binary to customers
How I can I embed the library libsqlcipher.0.dylib into the binary? Customers can't be expected to install sqlcipher on their own.
For reference, looking at the linked libraries for a dummy project:
/tmp/try-sqlite/cipher$ otool -L target/release/cipher
target/release/cipher:
/usr/local/opt/sqlcipher/lib/libsqlcipher.0.dylib (compatibility version 9.0.0, current version 9.6.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
My project is simple:
Cargo.toml
[package]
name = "cipher"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[dependencies.rusqlite]
version = "0.24.2"
features = ["sqlcipher"]
main.rs
use rusqlite::{params, Connection, Result, NO_PARAMS};
use std::thread::sleep;
#[derive(Debug)]
struct Person {
id: i32,
name: String,
data: Option<Vec<u8>>,
}
fn main() -> Result<()> {
let conn = Connection::open("/tmp/enc2.db")?;
conn.execute("PRAGMA KEY='passphrase'", NO_PARAMS);
conn.execute(
"CREATE TABLE IF NOT EXISTS person (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
data BLOB
)",
NO_PARAMS,
)?;
let me = Person {
id: 0,
name: "Steven".to_string(),
data: None,
};
conn.execute(
"INSERT INTO person (name, data) VALUES (?1, ?2)",
params![me.name, me.data],
)?;
let mut stmt = conn.prepare("SELECT id, name, data FROM person")?;
let person_iter = stmt.query_map(NO_PARAMS, |row| {
Ok(Person {
id: row.get(0)?,
name: row.get(1)?,
data: row.get(2)?,
})
})?;
for person in person_iter {
println!("Found person {:?}", person.unwrap());
}
Ok(())
}
EDIT
I have a partial solution to static linking (not tested robustly yet) by exporting
SQLCIPHER_STATIC=1
otool -L /private/tmp/try-sqlite/cypher/target/debug/cypher
/private/tmp/try-sqlite/cypher/target/debug/cypher:
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/local/opt/openssl#1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
Open issues
how to auto-export this environment variable (through toml config / build.rs - still working on that)
developer ergonomics - how to ensure that sqlcipher is installed on a dev machine (through build.rs / toml dev etc. config)
ensure that CI will run with SQLCIPHER_STATIC=1 (and have it installed)
It looks like this is currently not possible with the version published on crates.io.
But there is an open Pull Request that you can probably use for that.
First clone the working branch locally and then use it as a patch in your Cargo.toml like that:
[dependencies]
rusqlite = { version = "0.24.2", features = ["bundled-sqlcipher"] }
[patch.crates-io]
rusqlite = { path = "../path/to/your_patch" }
Note that I did not test this and because the feature only exists in the patch it might be that you need to include the feature branch like that:
[dependencies]
rusqlite = { path = "../path/to/your_patch", features = ["bundled-sqlcipher"] }
A word of Warning: As stated in the PR it is not clear if zetetic (the vendor of sqlcipher) is fine with that, so you should be cautious when you use this (especially in a commercial product).
Edit
This Issue / Comment is also relevant.

My Cargo.toml is displaying some red lines with error couldn't compile serde_derive

I try to build a project using rust-lang recently (this is my first rust project, and my boss is supporting me to use a new technology in my company). But, I suddenly get some red lines on my Cargo.toml :
could not compile `serde_derive`.
error: could not compile `async-trait`.
To learn more, run the command again with --verbose.
error: could not compile `rand_chacha`.
To learn more, run the command again with --verbose.
error: could not compile `proc-macro-hack`.
To learn more, run the command again with --verbose.
error: could not compile `diesel_derives`.
To learn more, run the command again with --verbose.
I run a command Cargo Run and my project is running well, but these red lines prevent me to tracking an error on my other code in my project (So if there is an error in code, it won't display as there are still exists some errors in another file, it is Cargo.toml)
I am using cargo 1.43.0-nightly (bda50510d 2020-03-02), rustc 1.43.0-nightly (c20d7eecb 2020-03-11), and vs code 1.43 version.
This is my Cargo.toml :
[package]
name = "app_base"
version = "0.1.0"
authors = ["yonathan"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = "0.4.3"
rocket_codegen = "0.4.3"
rocket_contrib = "0.4.3"
rocket_http = "0.4.3"
cookie = "0.11.2"
rocket-json-response = "0.5.10"
diesel = { version = "1.4.3", features = ["postgres"] }
dotenv = "0.15.0"
postgres = { version = "0.17.2", features = ["with-chrono-0_4"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
json-gettext = "3.1.7"
debug-helper = "0.3.8"
serializers = "0.2.3"
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
chrono = "0.4"
As this is an RLS (rust language server) bug [which is closed apparently, see here], a temporary alternative can be using the rust-analyzer extension [website here].
To install the extension, you can launch VSCode, click on the Extensions tab on the left and search for rust-analyzer in the Marketplace.
Please note that as mentioned on the website [as of 04/01/2020], this project is still in ALPHA, which means it may be prone to breakages.

Resources