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

4

61

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)
Leticialetisha answered 24/12, 2014 at 6:40 Comment(0)
W
66

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.

Winograd answered 24/12, 2014 at 9:9 Comment(2)
is it possible to test for feature in "if"? Thanks.Bond
@BulatM. Yes, you can use if cfg!(feature = "customfeature") { ... }Amain
F
14

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

Fresnel answered 9/11, 2022 at 9:46 Comment(1)
Note RUSTFLAGS can only be configured in a root project (cfgs can also be set by build script, howevers).Shf
C
13

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.

Centillion answered 14/9, 2019 at 10:20 Comment(0)
L
1

It is also possible to use a build script if you don't need features per se:

in build.rs:

fn main() {
  println!("cargo::rustc-cfg=foo");
}

in your source code:

fn main() {
  #[cfg(foo)]
  println!("Hello, foo!");
  #[cfg(bar)]
  println!("Hello, bar!");
}

Personally I like this because you need to change it in only one location (you could also use environment variables from build scripts)

see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-cfg for more info.

Larrup answered 1/7 at 11:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.