如何设置 cfg 选项以有条件地编译?
How to set cfg options to compile conditionally?
我正在编写一些代码,其中缓冲区由静态大小的数组支持。由于 Rust 和它提供的构建工具提供了条件编译的可能性,我可以这样做:
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],
}
}
}
有another question使用特性有条件地编译代码。单独使用功能,我将不得不结合 buffersize
和实际值,例如buffersize16
。是否可以向 Cargo 提供 cfg
标志,或者我需要直接向 rustc
提供它们吗?
您可以在.cargo/config
中设置环境变量RUSTFLAGS
或设置rustflags
变量。
来自 environment-variables
RUSTFLAGS — A space-separated list of custom flags to pass to all
compiler invocations that Cargo performs. In contrast with cargo
rustc, this is useful for passing a flag to all compiler instances.
在您的示例中,您可以使用:
RUSTFLAGS='--cfg buffersize="32"' cargo build
我想post更新我的问题,作为关于如何在编译时传递(数字)配置值的附加选项,这可以通过构建脚本实现。
假设您的项目中有以下构建脚本:
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 文件 (consts.rs
)。现在,在您的应用程序代码中,您可以包含此文件并将常量用于例如。在堆栈上分配内存:
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。即使这不是最优雅的选择方式,在某些情况下也可能是一种选择。
不过,最好将其作为宏选项。
我正在编写一些代码,其中缓冲区由静态大小的数组支持。由于 Rust 和它提供的构建工具提供了条件编译的可能性,我可以这样做:
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],
}
}
}
有another question使用特性有条件地编译代码。单独使用功能,我将不得不结合 buffersize
和实际值,例如buffersize16
。是否可以向 Cargo 提供 cfg
标志,或者我需要直接向 rustc
提供它们吗?
您可以在.cargo/config
中设置环境变量RUSTFLAGS
或设置rustflags
变量。
来自 environment-variables
RUSTFLAGS — A space-separated list of custom flags to pass to all compiler invocations that Cargo performs. In contrast with cargo rustc, this is useful for passing a flag to all compiler instances.
在您的示例中,您可以使用:
RUSTFLAGS='--cfg buffersize="32"' cargo build
我想post更新我的问题,作为关于如何在编译时传递(数字)配置值的附加选项,这可以通过构建脚本实现。
假设您的项目中有以下构建脚本:
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 文件 (consts.rs
)。现在,在您的应用程序代码中,您可以包含此文件并将常量用于例如。在堆栈上分配内存:
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。即使这不是最优雅的选择方式,在某些情况下也可能是一种选择。
不过,最好将其作为宏选项。