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

Building a wasm library without needing to define a main() #332

Open
arvid-norlander opened this issue Jul 3, 2023 · 8 comments
Open

Building a wasm library without needing to define a main() #332

arvid-norlander opened this issue Jul 3, 2023 · 8 comments
Assignees

Comments

@arvid-norlander
Copy link
Contributor

I'm new to wasm, so I may be misunderstanding things. I'm using the wasi-sdk.cmake file to build a library that I will load as a plugin into a native program using WAMR.

However, in order to get a .wasm file out (and not a .a file) I need to use add_executable(mylib.wasm src/test.cpp) in cmake, which complains about missing the main entrypoint. I could of course provide a dummy, but that seems pointless.

  • If I use add_library(mylib.wasm src/test.cpp) I get a .a archive instead.
  • If I use add_library(mylib.wasm SHARED src/test.cpp) I get:
    clang-16: error: argument unused during compilation: '-shared' [-Werror,-Wunused-command-line-argument]
    
    (and it tries to create mylib.wasm.so which is not what I want, I think?)
    If I do allow errors (which is against the policy at my workplace), it still claims to need a main:
    wasm-ld: error: /opt/wasi-sdk/bin/../share/wasi-sysroot/lib/wasm32-wasi/libc.a(__main_void.o): undefined symbol: main
    

What is the proper way to create a plugin style library using wasi-sdk (using cmake)? I will be calling functions from the host, I do not need a main as far as I know (I wouldn't need this in a native loadable library for sure).

@arvid-norlander arvid-norlander changed the title Building a wasm library Building a wasm library without needing to define a main() Jul 3, 2023
@lum1n0us
Copy link
Contributor

lum1n0us commented Sep 4, 2023

maybe using exec-model.

target_link_options(reactor
  PRIVATE
    -mexec-model=reactor
)

@arvid-norlander
Copy link
Contributor Author

Yes, that worked in the end (discovered a few weeks ago, but forgot to update this bug report). Perhaps the documentation should be a bit better though, especially for people who are new to WASM (it was not at all clear to me that "reactor" had anything to do with "library")

@sbc100
Copy link
Member

sbc100 commented Sep 6, 2023

The problem is that the term "library" in a build system normally means just a part of a program (either as a static or dynamic library). What a reactor is is a full (statically linked) program without a main function. There was no existing term for that so WASI invented the term "reactor". I believe in future versions that term will actually be dropped, but that is the history of the term.

If what you really want is a dynamically loaded library (which is how most plugin systems are built) then WASI doesn't currently support that, but there are efforts to port/standardize the dynamic linking system used by emscripten, so it maybe be possible in the future.

One way to tell if you need to use DSOs if that if your plugins share memory with each other or with some "main" program or with other shared libraries. With "reactors" each module has own complete copy of libc, along with all its global data, which makes calling across the program boundaries more like an RPC to completely separate program.

@arvid-norlander
Copy link
Contributor Author

One way to tell if you need to use DSOs if that if your plugins share memory with each other or with some "main" program or with other shared libraries. With "reactors" each module has own complete copy of libc, along with all its global data, which makes calling across the program boundaries more like an RPC to completely separate program.

My plugins are completely separate, though sharing libc (and thus reducing memory usage) would be nice.

@lum1n0us
Copy link
Contributor

lum1n0us commented Sep 7, 2023

It seems there are different ways, please correct me if I was wrong @sbc100

  • add an embedded as a bridge between libc-module-instance and plugin-main-module-instance. It is a shared-nothing model. both libc-module-instance and plugin-main-module-instance have their own linear memory. Embedded should copy/transfer data between two memories(RPC). libc-module-instance like a service to respond requests from variant plugins. there will be only one libc-module-instances in the system.

  • another one likes shared-everything model. Treat libc as a separate module instance and let every plugin-main-module-instance import libc-module-instance. Every plugin-main-module-instance has its owned libc-module-instance. And two instances share a linear-memory. Since both plugin-main and libc are in language C or C++, it is able to share data layout in this case

@sbc100
Copy link
Member

sbc100 commented Sep 7, 2023

It seems there are different ways, please correct me if I was wrong @sbc100

  • add an embedded as a bridge between libc-module-instance and plugin-main-module-instance. It is a shared-nothing model. both libc-module-instance and plugin-main-module-instance have their own linear memory. Embedded should copy/transfer data between two memories(RPC). libc-module-instance like a service to respond requests from variant plugins. there will be only one libc-module-instances in the system.
  • another one likes shared-everything model. Treat libc as a separate module instance and let every plugin-main-module-instance import libc-module-instance. Every plugin-main-module-instance has its owned libc-module-instance. And two instances share a linear-memory. Since both plugin-main and libc are in language C or C++, it is able to share data layout in this case

Basically yes. Note that wasi-sdk does not currently support shared-everything linking or any kind of runtime linking. The only implementation that I know of today is in emscripten.

In the emscripten model the main module includes libc and the side module(s) import all the libc symbols from the main module: https://emscripten.org/docs/compiling/Dynamic-Linking.html

@arvid-norlander
Copy link
Contributor Author

In the emscripten model the main module includes libc and the side module(s) import all the libc symbols from the main module: https://emscripten.org/docs/compiling/Dynamic-Linking.html

Reading this, it doesn't look like emscripten supports this model for it's WASI support? Only in the web case? Or at least WASI not not explicitly mentioned on that page.

@sbc100
Copy link
Member

sbc100 commented Sep 8, 2023

In the emscripten model the main module includes libc and the side module(s) import all the libc symbols from the main module: https://emscripten.org/docs/compiling/Dynamic-Linking.html

Reading this, it doesn't look like emscripten supports this model for it's WASI support? Only in the web case? Or at least WASI not not explicitly mentioned on that page.

Yes, that is correct.

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

4 participants