Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable linking libc in emscripten

I'm curious if it's possible to have emscripten build a binary without libc.

If I have simple.c:

int add1(int x) {
    return x + 1;
}

And I don't want to include any of libc, is that possible?

My best attempt so far has been:

emcc simple.c -s NO_FILESYSTEM=1 -s DISABLE_EXCEPTION_CATCHING=1 -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE='[]' -s LIBRARY_DEPS_TO_AUTOEXPORT='[]' -s EXPORTED_FUNCTIONS='["add1"]' -s USE_SDL=0 -o simple.js -nostdlib

But the generated output still includes symbols for malloc, string conversion routines, and so on.

I'm also interested in the same process for generating webassembly; that is, my real goal is generating a webassembly module that contains only a single function. Is this possible with emscripten?

like image 298
James Gilles Avatar asked Jan 14 '17 19:01

James Gilles


People also ask

Can Emscripten compile itself?

Emscripten compiles to WebAssembly by default, but you can also compile to JS for older browsers.

What is EMCC compiler?

The Emscripten Compiler Frontend ( emcc ) is used to call the Emscripten compiler from the command line. It is effectively a drop-in replacement for a standard compiler like gcc or clang.

What is Binaryen?

Binaryen is a compiler and toolchain infrastructure library for WebAssembly, written in C++. It aims to make compiling to WebAssembly easy, fast, and effective: Easy: Binaryen has a simple C API in a single header, and can also be used from JavaScript.


4 Answers

Emscripten is not currently well-suited for this use case. Object files are bitcode, and anytime linking is used, it wants to include some libraries and JS module code.

For WebAssembly, it is possible to use clang from upstream LLVM trunk along with the s2wasm tool from Binaryen. Clang (optionally in conjunction with LLVM's llc tool) can generate a .s assembly file which s2wasm can convert into wast (WebAssembly's text format). This file can be converted to wasm binary using Binaryen's wasm-as tool or the wast2wasm tool from WABT. This pipeline will turn any undefined references to functions from the C file into wasm imports, which you'll need to manually hook up to JavaScript functions. There are a few examples of this floating around on the Internet (I found some by googling "webassembly clang s2wasm"). Note also that s2wasm does the linker's job of laying out the wasm linear memory, and it has several options that you'll want to be aware of; see its help output and its sources, e.g. the tool and linker code.

like image 67
Derek Avatar answered Jan 03 '23 07:01

Derek


You can use the option -s ONLY_MY_CODE=1 to get a file containing only your compiled code.

See the possible options you can pass to emscripten.

like image 26
A.Perrot Avatar answered Jan 03 '23 07:01

A.Perrot


You have 2 options to build standalone wasm module. Via emsdk or via llvm. Note, that now emsdk generates code via asm.js backend, and does not support natively some i64 operations like multiplication.

emsdk

emcc your_module.c -v -O3 -s WASM=1 -s SIDE_MODULE=1 -o your_module.wasm

native llvm + binaryen

Note, now you need latest llvm from trunk, compiled with wasm support.

clang -emit-llvm --target=wasm32 -O3 -c -o your_module.bc your_module.c
llc -asm-verbose=false -o your_module.s your_module.bc
s2wasm --emscripten-glue your_module.s > your_module.wast
wasm-opt -O3 your_module.wast -o your_module.wasm
like image 30
Vitaly Avatar answered Jan 03 '23 07:01

Vitaly


See WebAssembly Standalone, there is also a link to examples in this page.

emcc simple.c -Os -s WASM=1 -s SIDE_MODULE=1 -o simple.wasm

To run it in html/js you must provide an imports object with imports.env={memoryBase, tableBase, memory, table}. But if you convert wasm file by wabt to wat format you can strip the import section because you don't need neither memory nor table then compile it back to wasm. Here is an exemple

like image 42
Mihai Manole Avatar answered Jan 03 '23 05:01

Mihai Manole