cargo icon indicating copy to clipboard operation
cargo copied to clipboard

feature to env var mapping is not unique

Open durka opened this issue 8 years ago • 7 comments

Build scripts receive information about activated features as environment variables CARGO_FEATURE_$name, where $name is the feature name uppercased and with dashes converted to underscores.

However, feature names are allowed to contain underscores, so this transformation can create collisions. Example:

  • Cargo.toml
    [package]
    name = "tester"
    version = "0.1.0"
    
    build = "build.rs"
    
    [features]
    foo-bar = []
    foo_bar = []
    
  • build.rs
    use std::env;
    
    fn main() {
        for (k, v) in env::vars() {
            if k.starts_with("CARGO_FEATURE") {
                println!("{} => {}", k, v);
            }
        }
        panic!(); // so cargo prints the output
    }
    
  • cargo build --features "foo_bar foo-bar"
    --- stdout
    CARGO_FEATURE_FOO_BAR => 1
    
    --- stderr
    thread 'main' panicked at 'explicit panic', build.rs:9
    note: Run with `RUST_BACKTRACE=1` for a backtrace.
    

durka avatar Feb 14 '17 21:02 durka

Out of curiosity, was this causing a problem in practice? We could perhaps set both in the case of a - name, but it may also just be best to not recommend naming features as such.

alexcrichton avatar Feb 15 '17 15:02 alexcrichton

It's definitely an edge case and I highly doubt it's come up in practice, I was writing a build script helper crate that looks at those env vars and I realized that you can't quite map the var back to a feature name (since you don't know whether to replace the underscores). One thing we could do is repeat the feature name as the value of the env var, so instead of setting CARGO_FEATURE_FOO_BAR=1 it would be CARGO_FEATURE_FOO_BAR=foo-bar.

durka avatar Feb 15 '17 15:02 durka

Yeah that's true and we could handle the case you mentioned in theory by listing everything to the right as well. Should be backwards compatible as well!

alexcrichton avatar Feb 15 '17 18:02 alexcrichton

Technically not backcompat :( I found one crate1 relying on the value being "1" though they could probably be convinced to change it since it's not documented to be any specific value. Another option is defining yet another env var e.g. CARGO_FEATURES="foo-bar foo_bar". Or ignoring this edge case :)

On Wed, Feb 15, 2017 at 1:26 PM, Alex Crichton [email protected] wrote:

Yeah that's true and we could handle the case you mentioned in theory by listing everything to the right as well. Should be backwards compatible as well!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rust-lang/cargo/issues/3702#issuecomment-280095480, or mute the thread https://github.com/notifications/unsubscribe-auth/AAC3n1H8LOyMsrg0aqFcEhr-9uSYSU66ks5rc0NrgaJpZM4MBCFU .

durka avatar Feb 15 '17 18:02 durka

Do we care to support the use case foreman has? Being able to map back from env var to feature name?

If yes, we should decide on which solution to use. If not, we should close this feature request.

dwijnand avatar Feb 13 '19 09:02 dwijnand

The case where I would find this helpful is I have tests that compile/run examples and need to pass along feature flags. Maintaining that manually is easy to mess up.

epage avatar Oct 11 '23 21:10 epage

I have a build script that runs cargo_metadata::MetadataCommand, and would like to forward the same features that the crate enabled. Because of this lossy conversion, the best I can do is gather a list of all the env_vars that start with CARGO_FEATURE_, and try to programmatically match them to the features in the crate (requiring an extra cargo metadata invocation).

Given the backwards-compat issue listed here, I wonder if maybe this could be solved with a new env var that lists all the features? Something like CARGO_CFG_TARGET_FEATURE but for cargo features. Maybe add a CARGO_FEATURES?

wmmc88 avatar Apr 11 '24 02:04 wmmc88