Rust依赖特性传递失效:底层C库未获正确CMake配置
解决方案
1. 改用环境变量检测特性(替代cfg!宏)
在wrapper的build.rs中,不要依赖cfg!宏检测特性,转而读取Cargo为build脚本专门设置的CARGO_FEATURE_*环境变量——无论特性是直接指定还是通过上层依赖传递,Cargo都会正确设置这些变量,可靠性更高。
修改后的build.rs示例:
use std::env; use cmake::Config; fn main() { let mut cmake_config = Config::new("path/to/your_c_lib"); // 配置FEATURE1开关 if env::var_os("CARGO_FEATURE_FEATURE1").is_some() { cmake_config.define("FEATURE1", "ON"); } else { cmake_config.define("FEATURE1", "OFF"); } // 配置FEATURE2开关 if env::var_os("CARGO_FEATURE_FEATURE2").is_some() { cmake_config.define("FEATURE2", "ON"); } else { cmake_config.define("FEATURE2", "OFF"); } // 构建C库 let _ = cmake_config.build(); // 确保特性变化时重新运行build.rs println!("cargo:rerun-if-env-changed=CARGO_FEATURE_FEATURE1"); println!("cargo:rerun-if-env-changed=CARGO_FEATURE_FEATURE2"); // 可选:C库源码变化时触发重新构建 println!("cargo:rerun-if-changed=path/to/your_c_lib"); }
2. 确认顶层库的依赖特性配置
在顶层纯Rust库的Cargo.toml中,明确指定wrapper依赖的特性:
[dependencies] wrapper = { path = "../wrapper", features = ["feature1"] }
如果需要通过命令行动态指定特性,运行顶层库构建时执行:
cargo build --features=wrapper/feature1
注意:如果wrapper的特性绑定了默认依赖,不要随意设置default-features = false,避免特性失效。
3. 清理构建缓存(解决CMake缓存残留问题)
如果之前的构建缓存导致CMake未重新生成配置,手动清理构建目录:
# 清理wrapper的target目录 rm -rf wrapper/target # 或者清理顶层库的target目录 rm -rf rustlib/target
之后重新构建,确保CMake使用新的特性配置生成构建文件。
为什么原来的cfg!宏不生效?
cfg!宏在build.rs中检测的是build.rs自身编译时的特性,而非wrapper crate的特性。虽然多数场景下两者一致,但当特性通过上层依赖传递时,Cargo可能不会将特性传递给build.rs的编译过程,或者缓存机制导致cfg!无法正确感知特性变化。而CARGO_FEATURE_*环境变量是Cargo专门为build脚本设置的,直接对应wrapper crate启用的特性,因此更可靠。
内容的提问来源于stack exchange,提问作者user422005
相关产品推荐
相关产品推荐

