|
1 | 1 | --- |
2 | 2 | layout: docs-experimental |
3 | 3 | toc_group: wasm |
4 | | -link_title: WebAssembly Reference |
| 4 | +link_title: GraalWasm |
5 | 5 | permalink: /reference-manual/wasm/ |
6 | 6 | --- |
7 | 7 |
|
8 | | -# GraalVM Implementation of WebAssembly |
| 8 | +# GraalWasm |
9 | 9 |
|
10 | | -GraalVM can run programs compiled to WebAssembly. |
11 | | -It can interpret and compile WebAssembly code in the binary format or embed it into other programs. |
12 | | -The support for WebAssembly is in the early stages of its development. |
| 10 | +GraalWasm is an open source WebAssembly runtime. |
| 11 | +It runs WebAssembly programs in the binary format and can be used to embed and leverage WebAssembly modules in Java applications. |
| 12 | +GraalWasm is under active development and is tracking a number of WebAssembly extensions. |
13 | 13 |
|
14 | | -## Getting Started |
| 14 | +## Running WebAssembly Embedded in Java |
15 | 15 |
|
16 | | -The GraalVM WebAssembly runtime (known as Wasm) is available as a standalone distribution. |
17 | | -You can download a standalone based on Oracle GraalVM or GraalVM Community Edition. |
| 16 | +Compiled WebAssembly binary code can be accessed programmatically with [GraalVM SDK Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html), which allows embedding WebAssembly into user applications. |
18 | 17 |
|
19 | | -1. Download the Wasm 24.0 standalone for your operating system: |
20 | | - - Native standalone |
21 | | - * [Linux x64](https://gds.oracle.com/download/wasm/archive/graalwasm-24.0.1-linux-amd64.tar.gz) |
22 | | - * [Linux AArch64](https://gds.oracle.com/download/wasm/archive/graalwasm-24.0.1-linux-aarch64.tar.gz) |
23 | | - * [macOS x64](https://gds.oracle.com/download/wasm/archive/graalwasm-24.0.1-macos-amd64.tar.gz) |
24 | | - * [macOS AArch64](https://gds.oracle.com/download/wasm/archive/graalwasm-24.0.1-macos-aarch64.tar.gz) |
25 | | - * [Windows x64](https://gds.oracle.com/download/wasm/archive/graalwasm-24.0.1-windows-amd64.zip) |
26 | | - - JVM standalone |
27 | | - * [Linux x64](https://gds.oracle.com/download/wasm/archive/graalwasm-jvm-24.0.1-linux-amd64.tar.gz) |
28 | | - * [Linux AArch64](https://gds.oracle.com/download/wasm/archive/graalwasm-jvm-24.0.1-linux-aarch64.tar.gz) |
29 | | - * [macOS x64](https://gds.oracle.com/download/wasm/archive/graalwasm-jvm-24.0.1-macos-amd64.tar.gz) |
30 | | - * [macOS AArch64](https://gds.oracle.com/download/wasm/archive/graalwasm-jvm-24.0.1-macos-aarch64.tar.gz) |
31 | | - * [Windows x64](https://gds.oracle.com/download/wasm/archive/graalwasm-jvm-24.0.1-windows-amd64.zip) |
| 18 | +The example below demonstrates how to compile a C function to WebAssembly and run it embedded in a Java application. |
| 19 | +To run the demo, you need the following: |
| 20 | +- [GraalVM JDK](https://www.graalvm.org/downloads/) |
| 21 | +- [Emscripten compiler frontend](https://emscripten.org/docs/tools_reference/emcc.html) |
| 22 | +- [Maven](https://maven.apache.org/) |
32 | 23 |
|
33 | | -2. Unzip the archive: |
| 24 | +### Demo Part |
34 | 25 |
|
35 | | - > Note: If you are using macOS Catalina and later you may need to remove the quarantine attribute: |
36 | | - ```shell |
37 | | - sudo xattr -r -d com.apple.quarantine <archive>.tar.gz |
38 | | - ``` |
39 | | - |
40 | | - Extact: |
41 | | - ```shell |
42 | | - tar -xzf <archive>.tar.gz |
43 | | - ``` |
44 | | - |
45 | | -3. A standalone comes with a JVM in addition to its native launcher. Check the version to see GraalVM WebAssembly runtime is active: |
46 | | - ```bash |
47 | | - ./path/to/bin/wasm --version |
48 | | - ``` |
49 | | - |
50 | | -## Running WebAssembly Programs |
| 26 | +1. Put the following C program in a file named _floyd.c_: |
| 27 | + ```c |
| 28 | + #include <stdio.h> |
51 | 29 |
|
52 | | -You can run a program written in the language that compiles to WebAssembly on GraalVM. |
53 | | -For example, put the following C program in a file named _floyd.c_: |
54 | | -```c |
55 | | -#include <stdio.h> |
56 | | -
|
57 | | -int main() { |
58 | | - int number = 1; |
59 | | - int rows = 10; |
60 | | - for (int i = 1; i <= rows; i++) { |
61 | | - for (int j = 1; j <= i; j++) { |
62 | | - printf("%d ", number); |
63 | | - ++number; |
| 30 | + void floyd() { |
| 31 | + int number = 1; |
| 32 | + int rows = 10; |
| 33 | + for (int i = 1; i <= rows; i++) { |
| 34 | + for (int j = 1; j <= i; j++) { |
| 35 | + printf("%d ", number); |
| 36 | + ++number; |
| 37 | + } |
| 38 | + printf(".\n"); |
| 39 | + } |
64 | 40 | } |
65 | | - printf(".\n"); |
66 | | - } |
67 | | - return 0; |
68 | | -} |
69 | | -``` |
70 | | - |
71 | | -Compile it using the most recent [Emscripten compiler frontend](https://emscripten.org/docs/tools_reference/emcc.html) version. It should produce a standalone _floyd.wasm_ file in the current working directory: |
72 | | -```shell |
73 | | -emcc -o floyd.wasm floyd.c |
74 | | -``` |
75 | 41 |
|
76 | | -Then you can run the compiled WebAssembly binary on GraalVM as follows: |
77 | | -```shell |
78 | | -wasm --Builtins=wasi_snapshot_preview1 floyd.wasm |
79 | | -``` |
80 | | - |
81 | | -In this example, the flag `--Builtins` specifies builtin modules that the [Emscripten toolchain](https://emscripten.org/index.html) requires. |
82 | | - |
83 | | -## Embedding WebAssembly Programs |
84 | | - |
85 | | -The compiled WebAssembly binary code can be accessed programmatically with [GraalVM Polyglot API](https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/package-summary.html), which allows embedding GraalVM WebAssembly into user programs. Here is a simple example of how to call WebAssembly code from a Java application: |
| 42 | + int main() { |
| 43 | + floyd(); |
| 44 | + return 0; |
| 45 | + } |
| 46 | + ``` |
| 47 | + Note that `floyd` is defined as a separate function and can be exported. |
86 | 48 |
|
87 | | -```java |
88 | | -import org.graalvm.polyglot.*; |
89 | | -import org.graalvm.polyglot.io.ByteSequence; |
90 | | -//Load the WASM contents into a byte array |
91 | | -byte[] binary = readBytes("example.wasm"); |
92 | | -Context.Builder contextBuilder = Context.newBuilder("wasm"); |
93 | | -Source.Builder sourceBuilder = Source.newBuilder("wasm", ByteSequence.create(binary), "example"); |
94 | | -Source source = sourceBuilder.build(); |
95 | | -Context context = contextBuilder.build(); |
| 49 | +2. Compile the C code using the most recent version of the [Emscripten compiler frontend](https://emscripten.org/docs/tools_reference/emcc.html): |
| 50 | + ```bash |
| 51 | + emcc --no-entry -s EXPORTED_FUNCTIONS=_floyd -o floyd.wasm floyd.c |
| 52 | + ``` |
| 53 | + > The exported functions must be prefixed by `_`. If you reference that function in, for example, the Java code, the exported name should not contain the underscore. |
| 54 | + |
| 55 | + It produces a standalone file _floyd.wasm_ in the current working directory. |
| 56 | + |
| 57 | +3. Add dependencies. The GraalVM SDK Polyglot API is not available by default, but can be easily added as a Maven dependency to your Java project. |
| 58 | +The GraalWasm artifact should be on the Java module or classpath too. Add the following set of dependencies to the project configuration file (_pom.xml_ in case of Maven). |
| 59 | + |
| 60 | + - To enable the GraalVM polyglot runtime: |
| 61 | + ```xml |
| 62 | + <dependency> |
| 63 | + <groupId>org.graalvm.polyglot</groupId> |
| 64 | + <artifactId>polyglot</artifactId> |
| 65 | + <version>${graalvm.polyglot.version}</version> |
| 66 | + </dependency> |
| 67 | + ``` |
| 68 | + - To enable Wasm: |
| 69 | + ```xml |
| 70 | + <dependency> |
| 71 | + <groupId>org.graalvm.polyglot</groupId> |
| 72 | + <artifactId>wasm</artifactId> |
| 73 | + <version>${graalvm.polyglot.version}</version> |
| 74 | + <type>pom</type> |
| 75 | + </dependency> |
| 76 | + ``` |
| 77 | + |
| 78 | +4. Now you can embed this WebAssembly function in a Java application, for example: |
| 79 | + |
| 80 | + ```java |
| 81 | + import org.graalvm.polyglot.*; |
| 82 | + import org.graalvm.polyglot.io.ByteSequence; |
| 83 | +
|
| 84 | + // Load the WebAssembly contents into a byte array |
| 85 | + byte[] binary = Files.readAllBytes(Path.of("path", "to", "wasm", "file", "floyd.wasm")); |
| 86 | +
|
| 87 | + // Setup context |
| 88 | + Context.Builder contextBuilder = Context.newBuilder("wasm").option("wasm.Builtins", "wasi_snapshot_preview1"); |
| 89 | + Source.Builder sourceBuilder = Source.newBuilder("wasm", ByteSequence.create(binary), "example"); |
| 90 | + Source source = sourceBuilder.build(); |
| 91 | + Context context = contextBuilder.build(); |
| 92 | +
|
| 93 | + // Evaluate the WebAssembly module |
| 94 | + context.eval(source); |
| 95 | +
|
| 96 | + // Execute the floyd function |
| 97 | + context.getBindings("wasm").getMember("example").getMember("_initialize").executeVoid(); |
| 98 | + Value mainFunction =context.getBindings("wasm").getMember("example").getMember("floyd"); |
| 99 | + mainFunction.execute(); |
| 100 | + context.close(); |
| 101 | + ``` |
96 | 102 |
|
97 | | -context.eval(source); |
| 103 | +5. Compile and run this Java application with Maven as usual. |
98 | 104 |
|
99 | | -Value mainFunction = context.getBindings("wasm").getMember("main").getMember("_start"); |
100 | | -mainFunction.execute(); |
101 | | -``` |
| 105 | +### Related Documentation |
102 | 106 |
|
103 | | -For more polyglot examples, visit the [Embedding Languages](../embedding/embed-languages.md) guide. |
| 107 | +- [Embedding Languages documentation](../embedding/embed-languages.md) |
| 108 | +- [GraalWasm](https://github.com/oracle/graal/tree/master/wasm) |
0 commit comments