添加opencascade依赖后,Rust编译WebAssembly缺失algorithm头文件报错
问题:Rust + Webpack编译Wasm时添加opencascade依赖后cxx crate编译失败
添加opencascade = "0.2.0"依赖后执行npm run build(对应webpack脚本)时,cxx crate编译报错提示找不到<algorithm>头文件,移除该依赖则编译正常。cargo update执行成功,尝试过配置build.rs指定C++头文件路径但未解决。
Cargo.toml配置
[package] name = "wasm-demo" version = "0.1.0" authors = ["Ravi"] edition = "2018" [env] LIBC_INCLUDE_DIR = { value = "/usr/include/c++/11", force = true, relative = false } build = "build.rs" [lib] crate-type = ["cdylib"] [dependencies] console_error_panic_hook = "=0.1.5" js-sys = "0.3.19" lazy_static = "1.3.0" nalgebra = "0.18.0" opencascade = "0.2.0" wasm-bindgen = "0.2.44" [dependencies.web-sys] version = "0.3.4" features = [ 'Document', 'Element', 'EventTarget', 'HtmlCanvasElement', 'MouseEvent', 'WebGlBuffer', 'WebGlProgram', 'WebGlRenderingContext', 'WebGlShader', 'WebGlUniformLocation', 'Window', ]
编译错误信息
[INFO]: 🌀 Compiling to Wasm... warning: unused manifest key: env Blocking waiting for file lock on package cache Compiling cxx v1.0.122 Compiling wasm-demo v0.1.0 (/home/xxx/learning/wasm) The following warnings were emitted during compilation: warning: cxx@1.0.122: In file included from /home/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cxx-1.0.122/src/cxx.cc:1: warning: cxx@1.0.122: /home/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cxx-1.0.122/src/../include/cxx.h:2:10: fatal error: 'algorithm' file not found warning: cxx@1.0.122: #include <algorithm> warning: cxx@1.0.122: ^~~~~~~~~~~ warning: cxx@1.0.122: 1 error generated. error: failed to run custom build command for `cxx v1.0.122` Caused by: process didn't exit successfully: `/home/xxx/learning/wasm/target/debug/build/cxx-9e222f77eeee6661/build-script-build` (exit status: 1) --- stdout TARGET = Some("wasm32-unknown-unknown") OPT_LEVEL = Some("0") HOST = Some("x86_64-unknown-linux-gnu") cargo:rerun-if-env-changed=CXX_wasm32-unknown-unknown CXX_wasm32-unknown-unknown = None cargo:rerun-if-env-changed=CXX_wasm32_unknown_unknown CXX_wasm32_unknown_unknown = None cargo:rerun-if-env-changed=TARGET_CXX TARGET_CXX = None cargo:rerun-if-env-changed=CXX CXX = None cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT cargo:rerun-if-env-changed=CRATE_CC_NO_DEFAULTS CRATE_CC_NO_DEFAULTS = None DEBUG = Some("true") cargo:rerun-if-env-changed=CXXFLAGS_wasm32-unknown-unknown CXXFLAGS_wasm32-unknown-unknown = None cargo:rerun-if-env-changed=CXXFLAGS_wasm32_unknown_unknown CXXFLAGS_wasm32_unknown_unknown = None cargo:rerun-if-env-changed=TARGET_CXXFLAGS TARGET_CXXFLAGS = None cargo:rerun-if-env-changed=CXXFLAGS CXXFLAGS = None cargo:warning=In file included from /home/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cxx-1.0.122/src/cxx.cc:1: cargo:warning=/home/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cxx-1.0.122/src/../include/cxx.h:2:10: fatal error: 'algorithm' file not found cargo:warning=#include <algorithm> cargo:warning= ^~~~~~~~~~~ cargo:warning=1 error generated. --- stderr error occurred: Command "clang" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "--target=wasm32-unknown-unknown" "-std=c++11" "-Wall" "-Wextra" "-o" "/home/xxx/learning/wasm/target/wasm32-unknown-unknown/debug/build/cxx-6e717868d7b84106/out/a01d5fedadde4775-cxx.o" "-c" "/home/xxx/.cargo/registry/src/index.crates.io-6f17d22bba15001f/cxx-1.0.122/src/cxx.cc" with args clang did not execute successfully (status code exit status: 1).
build.rs代码
// use std::process::Command; // fn main() { // // Set the include paths for the required C++ headers // let include_paths = ["/usr/include/c++/11" ]; // // Compile the Rust libraries with the required C++ headers // let mut cmd = Command::new("cargo"); // cmd.arg("build") // .args(&include_paths.iter().flat_map(|path| vec!["--extra-include-dir", path]).collect::<Vec<&str>>()); // let output = cmd.output().expect("failed to execute cargo build"); // if !output.status.success() { // panic!("failed to compile Rust libraries:\n{}", String::from_utf8_lossy(&output.stderr)); // } // } fn main() { println!("cargo:rustc-link-search=native=/usr/include/c++/11"); println!("cargo::rustc-env=LIBC_INCLUDE_DIR=/usr/include/c++/11"); println!("cargo::rustc-env=LIBCXX_INCLUDE_DIR=/usr/include/c++/11"); println!("cargo::rustc-env=GLIBC_INCLUDE_DIR=/usr/include/c++/11"); } // use cc::Build; // fn main() { // cc::Build::new() // .include("/usr/include/c++/11") // .flag("-g"); // } // use std::process::Command; // fn main() { // // Set the include path for the standard C++ headers // let output = Command::new("g++") // .arg("-c") // .arg("-I/usr/include/c++/11") // .output() // .expect("failed to execute process"); // if !output.status.success() { // panic!("failed to compile C++ code:\n{}", String::from_utf8_lossy(&output.stderr)); // } // // Link the compiled object file // println!("cargo:rustc-link-lib=static=cpp_code"); // }
解决方法
1. 安装Wasm专用的C++工具链
编译wasm32-unknown-unknown目标时,主机系统的/usr/include/c++/11是针对x86架构的,无法被Wasm目标的clang识别。推荐使用Emscripten工具链,它自带完整的Wasm C++运行环境:
# 克隆并安装Emscripten git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh
2. 指定C++编译器环境变量
在执行npm run build前,设置环境变量让cargo使用Emscripten的编译器:
export CXX=em++ export CXXFLAGS="-stdlib=libc++"
3. 修复build.rs配置
原build.rs存在语法错误(cargo::rustc-env多打了一个冒号),且未正确传递包含路径给cxx构建脚本。替换为以下代码:
use cc::Build; fn main() { // 获取Emscripten的系统头文件路径 let emscripten_sysroot = std::env::var("EMSDK").unwrap_or_default() + "/upstream/emscripten/cache/sysroot/include"; Build::new() .include(emscripten_sysroot) .flag("-std=c++11") .flag("--target=wasm32-unknown-unknown") .compile("dummy"); // 编译空目标以触发cc配置生效 // 让cxx crate感知环境变量变化 println!("cargo:rerun-if-env-changed=CXX"); println!("cargo:rerun-if-env-changed=CXXFLAGS"); }
4. 清理Cargo.toml无效配置
删除Cargo.toml中无效的[env]段(编译提示unused manifest key: env):
# 删除以下内容 [env] LIBC_INCLUDE_DIR = { value = "/usr/include/c++/11", force = true, relative = false }
内容的提问来源于stack exchange,提问作者Ravi Belkhindi
相关产品推荐
相关产品推荐

