Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to run wasm module built from Rust with C++ dependency. Error: Can't resolve 'env' #741

Closed
JanKaul opened this issue Nov 28, 2019 · 9 comments

Comments

@JanKaul
Copy link

JanKaul commented Nov 28, 2019

🐛 Bug description

npm run start fails when running a wasm module that was built from Rust with C++ dependency using wasm-pack. Inspecting the generated wasm module shows that it tries to import (import "env" "double_it" (func $double_it (type $t5))) from a module "env" that it doesn't know ("double_it" is the function in the C++ dependency). The C++ dependency is actually a C file which has been renamed to have a ".cpp" ending. npm run start works with the ".c" file. So maybe the ".cpp" ending triggers different compilation flags that yield the different result. Since both C and C++ compile to wasm I thought there should be no difference in the usage.

A same problem has been initially encountered also for the ".c" file in the comment: #621 (comment). The problem was potentially resolved with a newer clang or Rust update.

Project available here: https://github.com/JanKaul/simple-wasm

🤔 Expected Behavior

npm run start should succeed.

👟 Steps to reproduce

  1. C++ dependency build with cc crate, which determines compiler automatically (I guess clang)
  2. wasm-pack build succeeds
  3. npm install succeeds
  4. npm run strart fails with following error:
ERROR in ../pkg/simple_wasm_bg.wasm
Module not found: Error: Can't resolve 'env' in '/home/user/workspace/rust/simple-wasm/pkg'
 @ ../pkg/simple_wasm_bg.wasm
 @ ../pkg/simple_wasm.js
 @ ./index.js
 @ ./bootstrap.js
ℹ 「wdm」: Failed to compile.

🌍 Your environment

wasm-pack 0.8.1
rustc 1.39.0 (4560ea788 2019-11-04)

clang version 9.0.0-2 (tags/RELEASE_900/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
@SetLinux
Copy link

SetLinux commented Dec 7, 2019

You will have to have a C interface (with extern C) so that you can call wasm functions from and you will have to get a custom malloc that works with wasm

@JanKaul
Copy link
Author

JanKaul commented Dec 13, 2019

Thank you @GreatIndieDeveloper for your reply. But as far as I understand both points should be fine.

Your first point is that I need a C interface. But as far as I understood, the C interface is defined in the file simple-wasm/double-sys/src/lib.rs. So it is there.

And the second point is that I should provide a malloc function. Since I'm not using any includes from the c or c++ standard library, which normally implements malloc, I thought that I don't have to provide that functionality. The code is just a simple function that works on integers, which doesn't require any OS functions.

Did I get your points right? Or did you mean something else?

And shouldn't it have the same problems with the file having a .c ending?

Correct me if I'm wrong.

@JanKaul
Copy link
Author

JanKaul commented Jan 24, 2020

Okay the problem seems to be the fact that c++ uses a different ABI and the symbol for the function has a mangled name, that the rust compiler doesn't know. One has to explicitly tell the rust compiler the mangled function name it has to link. This can be done with the attribute #[link_name = "\u{1}_Z9double_itj"] before the function definition.
If you use bindgen to generate the bindings, it does it automatically for a c++ file.

@TjeuKayim
Copy link

When I compile below C code with the cc crate, the WASM output contains (import "env" "malloc" (func $malloc (type 3))).

#include <stdlib.h>
int* foo(int a) {
    return malloc(a);
}

@JanKaul
Copy link
Author

JanKaul commented Jan 30, 2020

It seems like it cannot find the function malloc to link it into the .wasm file. That's why it uses the import "env". Are you compiling your file as a c++ file? If yes you I guess you should use .cpp_link_stdlib("c++") to link it against the clang standard library or .cpp_link_stdlib("stdc++") to link it against the GNU standard library. I hope it helps.

@TjeuKayim
Copy link

I was not using c++ but want to compile sqlite. I got a Module not found: Error: Can't resolve 'env' just like you. The wasm32-unknown-unknown target has no standard c library, and wasm-pack does not support wasi or emscripten.

@JanKaul JanKaul closed this as completed Feb 7, 2020
@MolotovCherry
Copy link

MolotovCherry commented Apr 9, 2022

I was trying to compile tree-sitter into WASM using the official Rust bindings for it. After a ton of errors during compile due to a bad build command, I manually fixed up the generated build command to make it compile into wasm, although wasm-pack doesn't support target wasm32-unknown-emscripten, so I had to manually compile it and hack together a workable example for the js and npm.

Anyways, I did that, and it comes up with this exact error. I used the default example of the alert() function too.

Seems this must still be a problem. There's nothing wrong with the dependency at all as it is a well known library that works, and compiles fine to Rust on a non-WASM target

@spartucus
Copy link

Hi @TjeuKayim , did you solve the issue?

@TjeuKayim
Copy link

did you solve the issue?

No. If I recall correctly, I ended up not using wasm-pack

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants