Cargo工作区中OpenVINO库运行时冲突问题求助
解决Cargo工作区中OpenVINO链接冲突的方案
问题根源
Linux系统下动态库加载会按链接搜索路径的顺序查找,engine crate将旧版OpenVINO的路径加入全局链接搜索后,engine_rs运行时会优先加载该旧库,导致版本检测失败。
具体解决方案
1. 提升系统库的链接优先级
修改engine_rs的build.rs,将系统库路径设置为优先搜索,确保engine_rs先找到新版OpenVINO:
#[cfg(all(target_os = "linux", target_arch = "x86_64"))] fn linux_x86_64_main() { // 使用before参数让/usr/lib在搜索路径最前面 println!("cargo:rustc-link-search=native,before=/usr/lib"); println!("cargo:rustc-link-lib=openvino_c"); println!("cargo:rustc-link-lib=openvino"); println!("cargo:rustc-link-lib=tbb"); println!("cargo:rustc-link-lib=opencv_core"); println!("cargo:rustc-link-lib=opencv_dnn"); println!("cargo:rustc-link-lib=opencv_imgproc"); println!("cargo:rustc-link-lib=opencv_imgcodecs"); }
同时确保engine的build.rs中未设置全局LD_LIBRARY_PATH环境变量。
2. 手动加载旧版OpenVINO(推荐)
让engine不通过自动链接加载旧库,而是用dlopen手动指定路径加载,彻底隔离两个版本:
- 修改
engine的build.rs,移除旧OpenVINO的全局链接配置:#[cfg(all(target_os = "linux", target_arch = "x86_64"))] fn linux_x86_64_main() { let cpp_engine = cmake::Config::new("./engine") .no_build_target(true) .build(); println!("cargo:warning=engine output:{}", cpp_engine.display()); println!("cargo:rustc-link-search={}/build", cpp_engine.display()); println!("cargo:rustc-link-lib=engine"); // 移除旧OpenVINO的全局链接配置 // println!("cargo:rustc-link-search=native=fid_engine/engine/external/openvino/lib"); // println!("cargo:rustc-link-lib=dylib=openvino"); // println!("cargo:rustc-link-lib=dylib=tbb"); println!("cargo:rerun-if-changed=engine/CMakeLists.txt"); } - 在
engine的Rust代码中,手动加载旧版OpenVINO并获取函数指针:use libc::{c_void, dlopen, dlsym, RTLD_NOW, RTLD_LOCAL}; use std::ffi::CString; use std::path::PathBuf; // 根据你的C++函数签名定义对应类型 type YourEngineFunc = unsafe extern "C" fn() -> i32; unsafe fn load_old_openvino() -> YourEngineFunc { // 构建旧OpenVINO库的绝对路径 let lib_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("engine/external/openvino/lib/libopenvino.so"); let lib_path_c = CString::new(lib_path.to_str().unwrap()).unwrap(); // RTLD_LOCAL确保库符号不会暴露给全局 let lib_handle = dlopen(lib_path_c.as_ptr(), RTLD_NOW | RTLD_LOCAL); if lib_handle.is_null() { panic!("加载旧版OpenVINO失败: {}", std::io::Error::last_os_error()); } // 获取C++函数的符号(替换为你的函数名) let func_c = CString::new("your_engine_function").unwrap(); let func_ptr = dlsym(lib_handle, func_c.as_ptr()) as *mut c_void; if func_ptr.is_null() { panic!("在旧版OpenVINO中找不到目标函数"); } std::mem::transmute(func_ptr) } - 调用时使用手动加载的函数指针,避免旧库影响
engine_rs的新版库加载。
3. 重命名旧版OpenVINO库
如果手动加载太复杂,可通过重命名旧库避免名字冲突:
- 将
engine/external/openvino/lib/libopenvino.so重命名为libopenvino_old.so(同时调整对应版本的符号链接,如libopenvino.so.2022.1)。 - 修改
engine的C++代码链接配置,将openvino改为openvino_old。 - 更新
engine的build.rs:println!("cargo:rustc-link-search=native=fid_engine/engine/external/openvino/lib"); println!("cargo:rustc-link-lib=dylib=openvino_old"); // 修改库名 println!("cargo:rustc-link-lib=dylib=tbb");
4. 静态链接旧版OpenVINO
如果旧版OpenVINO提供静态库,可让engine静态链接,避免动态库冲突:
- 修改
engine的CMakeLists.txt,启用静态链接选项(如设置BUILD_SHARED_LIBS=OFF,或指定静态库路径)。 - 更新
engine的build.rs,链接静态版本的OpenVINO和TBB:println!("cargo:rustc-link-search=native=fid_engine/engine/external/openvino/lib"); println!("cargo:rustc-link-lib=static=openvino"); // 改为静态链接 println!("cargo:rustc-link-lib=static=tbb");
内容的提问来源于stack exchange,提问作者Fabrício Dematte
相关产品推荐
相关产品推荐

