I want to use a C library in my rust-wasi program. but I am having trouble linking external libraries. My Current setup is this.
main.rs
#[link(name = "mylib")]
extern "C" {
pub fn add_one(i: i32) -> i32;
}
pub fn main() {
let res = unsafe { add_one(10) };
println!("I 1: {}", res);
}
https://github.com/codeplea/tinyexpr mylib.cpp
#include "tinyexpr.h"
extern "C" int add_one(int i)
{
te_interp("i 1", 0);
return i 1;
}
build.rs
fn main() {
cc::Build::new()
.archiver("llvm-ar")
.cpp_link_stdlib(None)
.cpp(true)
.flag("--sysroot=/opt/wasi-sysroot/")
.file("mylib.cpp")
.compile("libmylib.a");
}
leading to this error when I try to execute it with wasmtime.
cargo build --target wasm32-wasi --release
wasmtime --dir=. --dir=/tmp target/wasm32-wasi/release/reverser.wasm
Error: failed to run main module `target/wasm32-wasi/release/so.wasm`
Caused by:
0: failed to instantiate "target/wasm32-wasi/release/so.wasm"
1: unknown import: `env::te_interp` has not been defined
I don't have any issues linking to the headers in the sys-root directory. Just with c headers in the same directory
CodePudding user response:
tinyexpr
is not a header-only library, you also need to compile tinyexpr.c
:
cc::Build::new()
.archiver("llvm-ar")
.flag(&sysroot)
.file("tinyexpr.c")
.compile("tinyexpr");
though you don't necessarily need to give it its own library, you could also compile tinyexpr.c
and mylib.cpp
into the same .a
. From what I understand about C/C build processes, that should give you the same result.
If you wanted to be real pretty about it, you'd make a new tinyexpr-sys
crate that contains just tinyexpr.c
(plus a cbindgen
-generated lib.rs
).
Side note: For finding the sysroot, I'd go with something like
let sysroot = var("MYLIB_WASI_SYSROOT")
.or(var("WASI_SYSROOT"))
.ok()
.or_else(|| Some(format!("{}/share/wasi-sysroot", var("WASI_SDK_PATH").ok()?)));
let sysroot = match sysroot {
Some(sysroot) => format!("--sysroot={}", sysroot),
None => {
eprintln!(
"Install wasi-sdk or wasi-libc and specify WASI_SYSROOT path in environment!"
);
exit(1);
}
};
though you could also just expect people to set CFLAGS
/CXXFLAGS
.
Other side notes:
- You might have less of a headache with the rust version of this library
- Related answer