13

Is it possible to make the list of default features platform dependent in your Cargo.toml? I'd like to use features to select platform-dependent dependencies.

I'd imagine something like this:

[features]
# on Unix
default = ["feature-a"]
# not on Unix
default = ["feature-b"]

feature-a = ["dep-a"]
feature-b = ["dep-b"]

[dependencies]
dep-a = { version = "*", optional = true }
dep-b = { version = "*", optional = true }

I've tried:

  • Using [target.'cfg(unix)'.features] does not work, it is ignored:

    [target.'cfg(unix)'.features]
    default = ["feature-a"]
    # -- snip --
    
  • Using a build.rs script to enable features based on cfg conditions only partially works. Dependency resolution is done before running build.rs, so this won't import optional dependencies for features enabled in it. This example won't import dep-a:

    fn main() {
        #[cfg(unix)]
        println!("cargo:rustc-cfg=feature=\"feature-a\"");
        // -- snip --
    }
    

Can this be achieved within Rust itself, without external scripts?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Tim Visée
  • 2,988
  • 4
  • 45
  • 55
  • 3
    Probably a duplicate of [How to enable crate features per-platform in Cargo.toml?](https://stackoverflow.com/q/56908077/155423) – Shepmaster May 03 '21 at 17:45

2 Answers2

1

winit's workaround for this is to just have the features do nothing on the platforms where they're not supported. e.g. the x11 and wayland features do nothing on the platforms where they're not supported.

In order for this to be a bit cleaner, they use the cfg_aliases crate to make new cfg flags: https://docs.rs/cfg_aliases/latest/cfg_aliases/

How winit uses it for x11/wayland: https://github.com/rust-windowing/winit/blob/fbea75d31f4025825e9bf88b99d7c92e4eb79273/build.rs#L47

bobbaluba
  • 3,584
  • 2
  • 31
  • 45
0

You can specify different features under each cfg. There is no support of cfg for root section features. So you can reach your goal but in a different way.

You can have different dependencies with different set of features.

For example:

[target.'cfg( target_os = "android" )'.dependencies]
some_dep = { version = "0.3.0", features = [ "feature1" ] }

[target.'cfg( target_os = "ios" )'.dependencies]
some_dep = { version = "0.3.0", features = [ "feature2" ] }

Official documentation.

Kos
  • 1,547
  • 14
  • 23
  • 4
    This does not achieve the same as having a different set of `default` features on different platforms. – Tim Visée Dec 12 '21 at 19:14
  • Is not? You can specify different `features` under each `cfg`. There is no support of `cfg` for section `features`. So you can reach your goal but in a different way. – Kos Dec 13 '21 at 07:02
  • Section [Platform specific dependencies](https://doc.rust-lang.org/cargo/guide/dependencies.html) of The Cargo Book explains how to use different features of dependencies depending on a platform. In 2022 there is no way to make default depending on a platform. But you can reach the same goal with help of explained in the section technique. – Kos Dec 13 '21 at 07:10
  • 7
    This does not achieve the same goal. With this approach the end user has no way of managing used features using `--no-default-features` and `--features`. That's why I explicitly stated to make the `default` set platform dependent, rather than selecting dependency features based on the current platform. – Tim Visée Dec 13 '21 at 15:04