How to activate an optional dependency? - rust

Cargo.toml:
[features]
parallel = ["rayon"]
[dependencies.rayon]
version = "1.5"
optional = true
lib.rs:
#[cfg(feature = "parallel")]
pub mod par;
Rust Analyzer:
code is inactive due to #[cfg] directives: feature = "parallel" is disabled
How to enable the optional dependency?

You can set the Rust Analyzer configuration option rust-analyzer.cargo.features to an array containing a list of features that you want RA to consider active.
You can also set rust-analyzer.cargo.allFeatures to true, in order to enable all features in the project.
Methods for setting these vary according to the IDE you are using - for example, if using VS Code, you can set it via the "Extension Settings" for Rust Analyzer.
This assumes you are asking how to activate the features within Rust Analyzer - to activate them when building or running from Cargo, just use the --features option.
See: Rust Analyzer Manual

All non-default features need to be specified when running. So run with:
# Option 1
cargo run --features parallel
# Option 2
cargo run --all-features
Check cargo run --help for more help.

Related

How can I run cargo check/test individually on each feature of my Cargo.toml?

Cargo features allow conditional compilation, so the final build will have just specific groups of features which can be filtered by the final user.
Now depending on the complexity of a library crate, you may end with several features forming a dependency tree, something like:
[features]
banana = []
avocado = []
pineapple = ["avocado"]
orange = ["pineapple", "banana"]
It's natural that, beyond cargo check|test --all-features, I will want to run cargo check|test --features banana on each one of the individual features, to ensure they can live on their own. Currently I'm doing this with a crude shell script, manually fed with the features. If I add a new feature and I forget to add it to the script, I'm in trouble.
FEATS=(banana avocado pineapple orange)
for FEAT in "${FEATS[#]}" ; do
echo "$FEAT..."
cargo check --features "$FEAT"
#cargo test --features "$FEAT"
done
So, is there any automated way to run cargo check|test --features banana on each feature, one by one, then report the warnings/errors which have been found?
I recently found taiki-e/cargo-hack which claims to handle this problem. I haven't tried it myself.
cargo-hack is basically wrapper of cargo that propagates subcommand and most of the passed flags to cargo, but provides additional flags and changes the behavior of some existing flags.
--each-feature
Perform for each feature which includes default features and --no-default-features of the package.
This is useful to check that each feature is working properly.
There is the cargo-all-features crate that provides commands for using all combination of features, not only individual features:
> cargo install cargo-all-features --locked
With it installed, you can run the following cargo commands to check, test, and build:
> cargo check-all-features
> cargo test-all-features
> cargo build-all-features
Further customizations (like skipping features or combinations) can be set by configuring the [package.metadata.cargo-all-features] section in your Cargo.toml.

How can I enable --gc-targets in my Cargo.toml?

According to the archival notice in wasm-gc,
The wasm-pack (and wasm-bindgen) project will already run [--gc-targets] by default for you, so there's no need to run it again.
How do we specify this in Cargo.toml explictly?
Rustc passes arguments with
-C, --codegen OPT[=VALUE]
Set a codegen option
The codegen option you want link-arg so you'd use it like -C link-arg=--gc-targets you can set that up in your Cargo.toml with,
[[bin]]
rustflags = [
"-C", "link-arg=--gc-targets",
]
Alternatively, you can now set this up directly with the new experimental extra-link-arg option in Cargo.

How to run cargo with features flag

I'm trying to learn rust by writing CLI but i can't do cargo run with features passed and i don't understand why. I read docs / stack and i still don't see why this is happening. It feels like it should work this way https://doc.rust-lang.org/cargo/commands/cargo-run.html
I'm trying to run this code
https://github.com/clap-rs/clap/blob/master/examples/17_yaml.rs
with command cargo run --features=yaml or cargo run --features yaml. I tried many combinations, none of them worked.
My Cargo.toml looks like that:
[dependencies.clap]
version = "*"
default-features = false
features = ["yaml"]
When i run i have error:
:!cargo run --features=yaml
error: Package `fun v0.1.0 (/Users/XXX/Projekty/rust/fun)` does not have these fe
atures: `yaml`
shell returned 101
What am i doing wrong?
Their code expects you to have cloned the clap repository, changed into its directory, and then run cargo run --features yaml --example 17_yaml from there. You can read more about how the cargo examples feature works here.
If you’re planning on copying their code, as noted in that example code, you have to remove this conditional compilation attribute:
// Note: If you're using clap as a dependency and don't have a feature for your users called
// "yaml", you'll need to remove the #[cfg(feature = "yaml")] conditional compilation attribute
#[cfg(feature = "yaml")]
fn main() {
Otherwise it will load this other main implementation and emit that error:
#[cfg(not(feature = "yaml"))]
fn main() {
// As stated above, if clap is not compiled with the YAML feature, it is disabled.
println!("YAML feature is disabled.");
println!("Pass --features yaml to cargo when trying this example.");
}
You don’t actually need to pass --features on the command line unless you are running their example within their crate as described above. You should also remove this whole function if you’re copying their code! It is only relevant when run as an example.

Conditional compilation for 'nightly' vs 'stable' Rust or compiler version

I am using some Rust unstable features, but I still want to be able to compile a reduced version of my library with stable Rust. I am happy to only include those unstable features when the compiler supports them, and exclude them when they are not supported.
I thought it would be easy to achieve this goal using conditional compilation like #[cfg(rust_version = "nightly")], but it seems like 'stable' vs 'nightly' are not cfg options.
How do you guys perform conditional compilation based on 'stable' vs 'nightly', or based on the compiler version?
I recommend creating a feature for your nightly-only code that is disabled by default, for example
Cargo.toml
[features]
default = []
nightly-features = []
Since the nightly-features feature is not default, compilation with the stable toolchain works out of the box. You can use attributes #[cfg(feature = "nightly-features")] and #[cfg(not(feature = "nightly-features"))] to include or exclude code from nightly-specialized versions. This method has the added benefit of allowing testing of the nightly features independently of the compiler (i.e. answer the question: did the compiler break my code, or does code enabled by nightly-features contain bugs?).
Despite the risks, I want to enable nightly features automatically
Use build scripts, sometimes called build.rs in addition to the nightly feature described above. (note: the following should NEVER be used in a library, otherwise switching compilers could become a breaking change. prefer the solution explained above)
build.rs (goes in package root)
use std::env;
fn main() {
let rust_toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap();
if rust_toolchain.starts_with("stable") {
// do nothing
} else if rust_toolchain.starts_with("nightly") {
//enable the 'nightly-features' feature flag
println!("cargo:rustc-cfg=feature=\"nightly-features\"");
} else {
panic!("Unexpected value for rustc toolchain")
}
}
this build script checks the toolchain environment variable set by rustup (some rust installations do not use rustup) and enables the nightly feature flag if the compiler is nightly.
src/main.rs
fn main() {
#[cfg(feature = "nightly-features")]
println!("Hello, nightly!");
#[cfg(not(feature = "nightly-features"))]
println!("Hello, stable!");
}
now, running
➜ cargo +stable run
Hello, stable!
➜ cargo +nightly run
Hello, nightly!
Is it possible to turn this feature off when build.rs turns it on?
As far as I can tell, no. Running cargo +nightly run --no-default-features leaves the feature on, due to how cargo passes flags to rustc. A programmer could create a specific environmental variable that build.rs checks for to skip the automatic version detection, but that is more complicated than the alternative with no build script - cargo build --features=nightly-features
Crate alternative
Instead of the proposed solution, you can use the rustversion crate, which works in a very similar way (but parses the output of rustc --version).
fn main() {
#[rustversion(nightly)]
println!("Hello, nightly!");
#[rustversion::not(nightly)]
println!("Hello, stable! (or beta)");
}

How do I use conditional compilation with `cfg` and Cargo?

I want to conditionally compile my source code using cfg with Cargo,
after Googling for a while,
it seems that the solution is to use cargo --features.
http://doc.crates.io/manifest.html
I tried adding a few
#[cfg(feature = "foo")]
in the source code and
cargo build --features foo
, but it says
Package `xxx v0.0.1 (file:///C:/yyy/xxx)` does not have these features: `foo`
How can I let cargo identify the features? Do I have to add something in Cargo.toml?
Here's the version of rustc and cargo I am using:
C:\>rustc --version
rustc 0.13.0-nightly (42deaa5e4 2014-12-16 17:51:23 +0000)
C:\>cargo --version
cargo 0.0.1-pre-nightly (5af754d 2014-12-18 01:50:48 +0000)
You have to introduce the existing features in your Cargo.toml.
I was able to conditionally compile by doing the following:
In Cargo.toml, create a features section and introduce a certain feature name:
[features]
customfeature = [] # feature has no explicit dependencies
If you want your feature to have specific dependencies check the examples in the documentation.
In your code, use #[cfg(feature="customfeature")]
Run cargo build --features customfeature
Since your steps 2 & 3 seem to be fine, there must probably be a problem with your Cargo.toml.
As stated in other answers, you can use features for this. I would like to add that features do not only allow you to conditionally compile parts of your code but also to conditionally include dependencies that may be part of that code. Consider the following snippets:
You can activate the conditional code using a feature flag as already described in other anwsers:
cargo build --features customfeature
You need to mark your conditional code to exist only when your customfeature is enabled:
#[cfg(feature = "customfeature")]
fn my_func() {
my_optional_dependency::do_something();
}
// This includes dependencies only when customfeature is enabled
#[cfg(feature = "customfeature")]
extern crate my_optional_dependency;
....
#[cfg(feature = "customfeature")]
use my_optional_dependency::*;
....
Your Cargo.toml needs to have the following sections:
[dependencies.my_optional_dependency]
version = "1.2.3"
optional = true
[features]
customfeature = ["my_optional_dependency"]
This allows you to activate certain parts of your code along with their dependencies only if a feature is enabled.
Alternatively, you could create a cargo configuration file in your project, by creating a .cargo subdir in your project main folder, adding in it a config.toml file,
then inserting this section in .cargo/config.toml:
[build]
rustflags = "--cfg my_cfg_flag"
This will make cargo call rustc with flags --cfg my_cfg_flag
See here for details:
https://doc.rust-lang.org/cargo/reference/config.html

Resources