Compiling your Project

MicroEJ supports Managed C through WebAssembly, meaning your Managed C or C++ code must be compiled to WebAssembly first.

The supported toolchain for this process is WASI SDK.

Installing the Toolchain

Download the WASI SDK version 25 and extract it at the location of your choice on your machine. This location will be referred to as [path_to_wasi_sdk] in the rest of this documentation.

Compiling a Simple C File

Assuming you have a file named my_app.c located in the src/main/c folder, follow these steps:

  • Open your terminal and navigate to your project root directory.

  • Execute the following command:

    [path_to_wasi_sdk]/bin/clang -mcpu=mvp -O3 -c -o src/main/resources/my_app.o src/main/c/my_app.c
    

The compilation option -mcpu=mvp ensures that the output adheres to the WebAssembly MVP specification. For a detailed explanation of the compiler options, please consult the official documentation for clang.

Linking a Wasm Module

Once the C files are compiled into object files (.o files), the next step is to link them together to produce a Wasm module (.wasm file). Use clang as the linker driver to generate the final .wasm module. It automatically calls wasm-ld, the Wasm linker.

The following options are recommended to ensure the produced .wasm binary is compatible with MICROEJ VEE:

For example, if you have the object file src/main/resources/my_app.o that defines a main entry point, the following command will generate a Wasm module including this entry point along with all transitive dependencies from the WASI Libc. Any unresolved symbols in the object file are expected to be provided by the Java host.

[path_to_wasi_sdk]/bin/clang -Wl,--stack-first -z stack-size=4096 -Wl,--allow-undefined -o src/main/resources/my_app.wasm src/main/resources/my_app.o

When your object file defines a main function, the linker automatically exports a function named _start. This function performs initialization tasks before invoking the user-defined main. You must bind the _start function — not main — to a Java method.

Additionally, any other functions that should be callable from the Java Application must be explicitly exported using the -Wl,--export=[function_name] linker option (this does not apply to main, which is invoked internally by _start).

Note

For convenience, you can store the list of exported functions in an options file. Create a file named exports.txt containing:

--export=foo
--export=bar

You can then reference this file in the command line using the -Wl,@exports.txt option.

If your module is composed of multiple C files, make sure to append all the object files to the command line. The resulting file, my_app.wasm, will be a linked Wasm module containing all functions, globals, and constants defined across those object files.

This Wasm module can then be bound to a Java class for integration with your application. You may also need to Configure the Linear Memory Size.

For an in-depth understanding of the linker options, please refer to the official documentation for wasm-ld.

Compiling C++ Code

The WASI SDK also includes a C++ compiler, clang++, which you can use to compile and link C++ code using similar options.

# To compile:
[path_to_wasi_sdk]/bin/clang++ [...] -fno-exceptions -c -o my_app.o my_app.cc
# To link:
[path_to_wasi_sdk]/bin/clang++ [...] -fno-exceptions -o my_app.wasm my_app.o

Note

C++ exceptions are not supported, so you’ll need to build your C++ code with the -fno-exceptions flag.

Building Without The Standard Library

The -Wl,--no-entry -nostdlib options prevent the compiler and linker from automatically linking with the standard system libraries (such as libc in C or the C++ Standard Library), and omit embedding the startup code responsible for initializing the runtime environment. This configuration is particularly useful for building Wasm modules that embed only their own code, with all external dependencies defined by the Java host.

Strip the Debug info sections

When building a Wasm module from C or C++ source code, enabling debug information (for example, by compiling with the -g flag) instructs the compiler to embed additional metadata into the generated .wasm file.

These debug sections usually contain symbol tables, source file references, and line number information that are useful for debugging purposes, such as producing stack traces. However, including this data increases the size of the final application.

To reduce the size of the resulting application file, you can strip the debug information from the .wasm binary before using it. There are two recommended methods:

# Using LLVM tools
llvm-strip --strip-debug yourfile.wasm

# Using Binaryen
wasm-opt yourfile.wasm -o output.wasm --strip-debug