How can I override a constant via a compiler option?

后端 未结 2 664
挽巷
挽巷 2020-12-01 23:52

Is it possible to define a constant in source code that can be overridden by a compiler flag? That is, something like setting a #define value in the C preproces

相关标签:
2条回答
  • 2020-12-02 00:30

    No, you can't define constants (read: const bindings) with a compiler flag. But you can use the env! macro for something similar. It reads some environment variable at compile time.

    const MAX_DIMENSIONS_RAW: &'static str = env!("MAX_DIMENSIONS");
    

    Sadly, this returns a string and not an integer. Furthermore we can't yet call arbitrary functions (like parse) at compile time to calculate a constant. You could use lazy_static to achieve something similar:

    lazy_static! {
        static ref MAX_DIMENSIONS: usize = MAX_DIMENSIONS_RAW.parse().unwrap();
    }
    

    Of course you should add proper error handling. If your user doesn't need to define the environment variable, you can use option_env!.

    With this approach, you can pass the setting at build time:

    $ MAX_DIMENSIONS=1000 cargo build
    
    0 讨论(0)
  • 2020-12-02 00:42

    Building on Lukas Kalbertodt's answer, you can get the environment variable as a constant number with some extra indirection, namely by using a build script.

    build.rs

    use std::{env, fs::File, io::Write, path::Path};
    
    fn main() {
        let out_dir = env::var("OUT_DIR").expect("No out dir");
        let dest_path = Path::new(&out_dir).join("constants.rs");
        let mut f = File::create(&dest_path).expect("Could not create file");
    
        let max_dimensions = option_env!("MAX_DIMENSIONS");
        let max_dimensions = max_dimensions
            .map_or(Ok(10_000), str::parse)
            .expect("Could not parse MAX_DIMENSIONS");
    
        write!(&mut f, "const MAX_DIMENSIONS: usize = {};", max_dimensions)
            .expect("Could not write file");
        println!("cargo:rerun-if-env-changed=MAX_DIMENSIONS");
    }
    

    main.rs

    include!(concat!(env!("OUT_DIR"), "/constants.rs"));
    
    fn main() {
        println!("The value is {} ({})", MAX_DIMENSIONS, MAX_DIMENSIONS + 1);
    }
    
    $ cargo run
    The value is 10000 (10001)
    
    $ MAX_DIMENSIONS=17 cargo run
    The value is 17 (18)
    
    $ MAX_DIMENSIONS=1 cargo run
    The value is 1 (2)
    
    0 讨论(0)
提交回复
热议问题