如何将CFG选项设置为有条件编译



我正在处理一些代码,其中缓冲区由静态大小的数组支持。由于Rust和IT提供的构建工具提供了有条件编译的可能性,因此我可以做这样的事情:

struct Buffer {
    // default case, if none is set
    #[cfg(not(buffersize))]
    buffer: [f32; 16],
    #[cfg(buffersize = "32")]
    buffer: [f32; 32],
    #[cfg(buffersize = "64")]
    buffer: [f32; 64],
}
impl Buffer {
    fn new() -> Buffer {
        Buffer {
            #[cfg(not(buffersize))]
            buffer: [0.0; 16],
            #[cfg(buffersize = "32")]
            buffer: [0.0; 32],
            #[cfg(buffersize = "64")]
            buffer: [0.0; 64],
        }
    }
}

还有另一个使用功能有条件编译代码的问题。我只使用功能,我将不得不结合buffersize和实际值,例如buffersize16。是否可以向货物提供cfg标志,还是我需要将它们直接提供给rustc

您可以设置环境变量RUSTFLAGS或在.cargo/config中设置rustflags变量。
来自环境变异

rustflags - 分隔空间的自定义标志列表,可以传递给所有人 货物执行的编译器调用。与货物相反 rustc,这对于将标志传递给所有编译器实例很有用。

在您的示例中,您可以使用:

RUSTFLAGS='--cfg buffersize="32"' cargo build

我想向我的问题发布更新,作为如何通过构建脚本传递(数字(配置值的附加选项。

假设您的项目内有以下构建脚本:

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
fn main() {
    println!("cargo:rerun-if-env-changed=SIZE");
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest = Path::new(&out_dir).join("consts.rs");
    let mut out_file = File::create(&dest).expect("Cannot create file");
    let size: usize = env!("SIZE").parse().unwrap();
    write!(&out_file, "pub const S : usize = {};", size);
}

它在编译时间读取环境变量,将其解析为usize,并写入仅包含常数的Rust File(consts.rs(。现在,在您的应用程序代码中,您可以包含此文件并将常数用于EG。在堆栈上分配内存:

include!(concat!(env!("OUT_DIR"), "/consts.rs"));
fn main() {
    let array = [0.0f32; S];
    println!("array len= {:?}", array.len());
}

此技巧的缺点是,由于cargo:rerun-if-env-changed=SIZE不会被捕获,因此您必须在环境变量变化时重新编译整个项目(或部分(。这也意味着始终了解此配置选项的知识,但这可以包裹在诸如makefile之类的其他构建脚本中。即使这不是最优雅的选择,也可能是某些情况下的选择。

不过,将此作为宏选项会很不错。

最新更新