How to static link c lib to wasm?

i have a creat with c lib:

and i hope static link the c code the the wasm.
the build script are in Makefile(build-wasm):

gcc -c -o number.o ./src/vendor/number.c
ar rcs libnumber.a number.o

# static 选项没有生效, 生成的wasm还是要import对应的函数
rustc -L native=. -l static=number --target wasm32-unknown-unknown ./src/main.rs -o a.out.wasm

but the a.out.wasm still need import the c function (number_add_mod).

how to static link c lib to wasm?

thx

Do you have a C to WASM cross-compiler? C compiled for your native CPU (which is what gcc does by default) cannot be run in the WASM VM, so even if you link it, it won't work.

the c compiler is clang llvm9, it can output wasm file. but the c function need import from env object.

It doesn't matter that clang supports WASM if you don't use it. If you don't explicitly tell clang to make WASM file, it won't. Your number.o is probably native machine-dependent code that doesn't work with WASM.

You have to add --target=wasm32 to compiler invocation, otherwise you're getting x86 or similar.

Try compiling with the cc crate which handles target settings automatically. gcc itself does not.

2 Likes

i got it. for macos:

  1. brew install llvm
  2. /usr/local/opt/llvm/bin/clang --target=wasm32 ...
  3. /usr/local/opt/llvm/bin/llvm-ar rcs libnumber.a number.o
  4. rustc -L . -l number --target wasm32-unknown-unknown ./src/main.rs -o a.out.wasm

or use cargo with cc creat. build.rs:

fn main() {
	let host = std::env::var("HOST").unwrap();
	let target = std::env::var("TARGET").unwrap();

	if target.contains("wasm32") {
		if host.contains("darwin") {
			// brew install llvm
			std::env::set_var("CC", "/usr/local/opt/llvm/bin/clang");
			std::env::set_var("AR", "/usr/local/opt/llvm/bin/llvm-ar");
		}
	}

	cc::Build::new()
		.include("src/vendor")
		.file("src/vendor/number.c")
		.flag("-Ofast")
		.compile("number")
}

thx @kornel :+1:

2 Likes

That's quite cool, I had similar issue and thought it is not possible at all, thanks for a hint.

BTW, I also just saw post about C2Rust transpiler, thought it might be a way too, though your solution seems better... https://immunant.com/blog/2020/01/quake3/