### Start local development server with npm run start Source: https://github.com/dylibso/chicory/blob/main/docs/README.md Starts a local development server and opens a browser window. Changes are reflected live without restarting. ```bash $ npm run start ``` -------------------------------- ### Download test Wasm module with curl Source: https://github.com/dylibso/chicory/blob/main/docs/docs/index.md Download the test Wasm module used in the quick start guide. The module computes factorial and is saved as factorial.wasm. ```bash curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/iterfact.wat.wasm > factorial.wasm ``` -------------------------------- ### Install dependencies with npm install Source: https://github.com/dylibso/chicory/blob/main/docs/README.md Run this command in the project root to install all required npm packages for the Docusaurus site. ```bash $ npm install ``` -------------------------------- ### Download example.wasm with curl Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2023-12-25-chicory-first.md Downloads a pre-built WebAssembly module from the example repository to use for testing the upload endpoint. ```bash curl \-sL https://raw.githubusercontent.com/andreaTP/first-chicory-blog/main/dynamic-loading/example.wasm \--output example.wasm ``` -------------------------------- ### Instantiate WasiPreview1 with default options Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/wasi.md Downloads the hello-wasi.wasm example and instantiates a WasiPreview1 instance with default options. The module runs automatically upon instantiation because WASI command modules implicitly call _start. ```bash curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/hello-wasi.wat.wasm > hello-wasi.wasm ``` ```java import com.dylibso.chicory.log.SystemLogger; import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.runtime.Store; import java.io.File; var logger = new SystemLogger(); // let's just use the default options for now var options = WasiOptions.builder().build(); // create our instance of wasip1 var wasi = WasiPreview1.builder().withOptions(options).build(); // create the module and connect the host functions var store = new Store().addFunction(wasi.toHostFunctions()); // instantiate and execute the main entry point store.instantiate("hello-wasi", Parser.parse(new File("hello-wasi.wasm"))); ``` -------------------------------- ### Configure stdin, stdout, and stderr with WasiOptions Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/wasi.md Downloads the greet-wasi.wasm example and demonstrates how to provide custom stdin, stdout, and stderr streams via WasiOptions. The module reads from stdin and writes the greeting to stdout; the assertions verify the captured output. ```bash curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/greet-wasi.rs.wasm > greet-wasi.wasm ``` ```java // Let's create a fake stdin stream with the bytes "Chicory" var fakeStdin = new ByteArrayInputStream("Chicory".getBytes()); // We will create two output streams to capture stdout and stderr var fakeStdout = new ByteArrayOutputStream(); var fakeStderr = new ByteArrayOutputStream(); // now pass those to our wasi options builder var wasiOpts = WasiOptions.builder().withStdout(fakeStdout).withStderr(fakeStderr).withStdin(fakeStdin).build(); var wasi = WasiPreview1.builder().withOptions(wasiOpts).build(); // greet-wasi is a rust program that greets the string passed in stdin var store = new Store().addFunction(wasi.toHostFunctions()); // instantiating will execute the module if it's a WASI command-pattern module store.instantiate("hello-wasi", Parser.parse(new File("greet-wasi.wasm"))); // check that we output the greeting assert(fakeStdout.toString().equals("Hello, Chicory!")); // there should be no bytes in stderr! assert(fakeStderr.toString().equals("")); ``` -------------------------------- ### Run spec tests with Maven Source: https://github.com/dylibso/chicory/blob/main/AGENT.md Commands to run the full spec test suite for the interpreter, compiler, and WASI modules. Install first to generate test classes, then run surefire tests. The one-shot install also runs tests. ```bash # Full spec test suite (interpreter) — install first to generate test classes, then run mvn install -pl runtime-tests -am -DskipTests mvn surefire:test -pl runtime-tests # Or in one shot (install runs tests too) mvn install -pl runtime-tests -am # Compiler spec tests mvn surefire:test -pl compiler-tests # WASI spec tests mvn surefire:test -pl wasi-tests ``` -------------------------------- ### Use wat2wasm to parse WebAssembly text format Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/tools.md Java example showing how to use Wat2Wasm to convert a WebAssembly text module to binary, then instantiate and call an exported function. The example imports from either com.dylibso.chicory.wabt or com.dylibso.chicory.tools.wasm. ```java import com.dylibso.chicory.wabt.Wat2Wasm; // or import com.dylibso.chicory.tools.wasm.Wat2Wasm; var wasm = Wat2Wasm.parse( "(module (func (export \"add\") (param $x i32) (param $y i32) (result i32)" + " (i32.add (local.get $x) (local.get $y))))"); var moduleInstance = Instance.builder(Parser.parse(wasm)).build(); var addFunction = moduleInstance.export("add"); var result = addFunction.apply(1, 41)[0]; System.out.println(result); ``` -------------------------------- ### Generated signature for @Buffer example Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2024-11-08-chicory-1.0.0-M1.md Equivalent signature of the generated host function for the @Buffer example, showing the translated parameters. ```text public long[] path_filestat_set_times( long fd // ValueType.I32 long lookup_flags // ValueType.I32 long raw_path_ptr // ValueType.I32 => string pointer long raw_path_size // ValueType.I32 => string length long access_time // ValueType.I64 long modified_time // ValueType.I64 long fst_flags // ValueType.I32 ) ``` -------------------------------- ### Run the Docker container Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2023-12-25-chicory-first.md Use this command to run the Chicory getting-started Docker image. It starts a container with port 8080 mapped and runs interactively, allowing you to test the server with the provided curl commands. ```bash docker run -i --rm -p 8080:8080 chicory/getting-started ``` -------------------------------- ### Key Maven build commands Source: https://github.com/dylibso/chicory/blob/main/AGENT.md Common Maven commands for building, testing, and formatting the project. Use `mvn clean install` for a full build, `-Dquickly` to skip tests and checks, `-DskipTests` to skip tests only, `-Ddev` to disable linters and enforcers, and `spotless:apply` to autoformat code before committing. ```bash # Full build with all tests mvn clean install # Quick install, skip all tests and checks mvn -Dquickly # Skip tests only mvn install -DskipTests # Disable linters and enforcers during development mvn -Ddev # Autoformat code (required before committing) mvn spotless:apply ``` -------------------------------- ### Configure InterpreterFallback.FAIL Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/runtime-compiler.md Modify the previous example to use InterpreterFallback.FAIL to throw an exception if any function is too large to compile. ```java import com.dylibso.chicory.compiler.MachineFactoryCompiler; import com.dylibso.chicory.compiler.InterpreterFallback; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.WasmModule; var module = Parser.parse(new File("your.wasm")); var instance = Instance.builder(module). withMachineFactory( MachineFactoryCompiler.builder(module) .withInterpreterFallback(InterpreterFallback.FAIL) .compile() ). build(); ``` -------------------------------- ### Build and instantiate the module Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/memory.md Parses the wasm file and builds an Instance, then gets the exported count_vowels function. ```java import com.dylibso.chicory.runtime.ExportFunction; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasm.Parser; Instance instance = Instance.builder(Parser.parse(new File("./count_vowels.wasm"))).build(); ExportFunction countVowels = instance.export("count_vowels"); ``` -------------------------------- ### Building and testing a single module Source: https://github.com/dylibso/chicory/blob/main/AGENT.md Commands to build and test a specific module. After changing code, run `mvn install` on the module and its dependencies so downstream modules see the changes. Use `-DskipTests` to propagate artifacts without running tests. ```bash # Build runtime and everything it depends on, skip tests mvn install -pl runtime -am -DskipTests # Run only runtime unit tests (after install) mvn test -pl runtime # Build everything up to wasm-tools mvn install -pl wasm-tools -am -DskipTests ``` -------------------------------- ### Dockerfile.native-scratch: Build and run a native Quarkus image with musl Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2023-12-25-chicory-first.md Multi-stage Dockerfile to build a native Quarkus application with musl libc and run it in a scratch image. The build stage installs make, gcc, and musl, compiles zlib, and runs the Maven native build with the flags --static and --libc=musl. The final stage copies the native runner to /application and exposes port 8080. ```docker FROM quay.io/quarkus/ubi-quarkus-graalvmce-builder-image:jdk-21 AS build USER root RUN microdnf install make gcc RUN mkdir /musl && \ curl \-L \-o musl.tar.gz https://more.musl.cc/11.2.1/x86\_64-linux-musl/x86\_64-linux-musl-native.tgz && \ tar \-xvzf musl.tar.gz \-C /musl \--strip-components 1 && \ curl \-L \-o zlib.tar.gz https://www.zlib.net/zlib-1.3.tar.gz && \ mkdir zlib && tar \-xvzf zlib.tar.gz \-C zlib \--strip-components 1 && \ cd zlib && ./configure \--static \--prefix=/musl && \ make && make install && \ cd .. && rm \-rf zlib && rm \-f zlib.tar.gz && rm \-f musl.tar.gz ENV PATH="/musl/bin:${PATH}" USER quarkus WORKDIR /code COPY . . RUN ./mvnw package \-Dnative \-DskipTests \-Dquarkus.native.additional-build-args="--static","--libc=musl" *\#\# Stage 2 : create the final image* FROM scratch COPY \--from\=build /code/target/\*-runner /application EXPOSE 8080 ENTRYPOINT [ "/application" ] ``` -------------------------------- ### Using the Store to register host functions and instantiate modules Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2024-11-08-chicory-1.0.0-M1.md Demonstrates the new Store utility: create a store, add a host function, parse a module, and instantiate it with a name. ```java // instantiate the store var store = new Store(); // registers a host function in the store store.addFunction(myFunction); // create a named `instance` with name `logger` var module = Parser.parse(new File("logger.wasm")); var instance = store.instantiate("logger", module); ``` -------------------------------- ### Get exported function handle Source: https://github.com/dylibso/chicory/blob/main/docs/docs/index.md Get a handle to the exported function 'iterFact' from the instance. Use Instance#export(String) to obtain an ExportFunction. ```java ExportFunction iterFact = instance.export("iterFact"); ``` -------------------------------- ### Instantiate the module with a Store Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/host-functions.md Creates a Store, registers the host function, and instantiates the logger module. Then it calls the exported logIt function, which should print 'Hello, World!' 10 times. ```java import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.runtime.ImportValues; import com.dylibso.chicory.runtime.Store; // instantiate the store var store = new Store(); // registers `console.log` in the store store.addFunction(func); var instance = store.instantiate("logger", Parser.parse(new File("./logger.wasm"))); var logIt = instance.export("logIt"); logIt.apply(); // should print "Hello, World!" 10 times ``` -------------------------------- ### Build static site with npm run build Source: https://github.com/dylibso/chicory/blob/main/docs/README.md Generates static content into the build directory, which can be served by any static hosting service. ```bash $ npm run build ``` -------------------------------- ### Lower-level equivalent of store.instantiate Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/linking.md Shows the equivalent lower-level sequence for store.instantiate("logger", ...). It converts store imports, parses the module, builds an instance with those imports, and registers it. The shorthand form is recommended in most cases. ```java var imports = store.toImportValues(); var m = Parser.parse(new File("./logger.wasm")); var instance = Instance.builder(m).withImportValues(imports).build(); store.register("logger", instance); ``` -------------------------------- ### Get alloc and dealloc exports Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/memory.md Retrieves the alloc and dealloc exported functions from the instance for memory management. ```java ExportFunction alloc = instance.export("alloc"); ExportFunction dealloc = instance.export("dealloc"); ``` -------------------------------- ### Build the container image with docker build Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2023-12-25-chicory-first.md Builds the native container image using the Dockerfile.native-scratch file and tags it as chicory/getting-started. ```bash docker build -f src/main/docker/Dockerfile.native-scratch -t chicory/getting-started . ``` -------------------------------- ### Instantiate module with SimdInterpreterMachine Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/simd.md Use SimdInterpreterMachine::new as the machine factory when building the instance to enable SIMD support. Requires Java 21+ and interpreter mode. ```java import com.dylibso.chicory.simd.SimdInterpreterMachine; var module = Parser.parse(new File("your.wasm")); var instance = Instance.builder(module).withMachineFactory(SimdInterpreterMachine::new).build(); ``` -------------------------------- ### Execute with ExecutorService timeout Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/cpu.md Uses an ExecutorService to run the function and get the result with a 100-millisecond timeout, catching TimeoutException. ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; ExecutorService service = Executors.newSingleThreadExecutor(); var future = service.submit(() -> function.apply()); try { future.get(100, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { // handle the failure } ``` -------------------------------- ### Set command-line arguments with WasiOptions.builder().withArguments() Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/wasi.md Provides command-line arguments to pass to the WASI module. Example usage is shown for CLI with a system. ```java var wasi = WasiOptions.builder().withArguments(List.of("executable-name", "--more", "--options")).build(); ``` -------------------------------- ### Parse and build an Instance Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2024-11-08-chicory-1.0.0-M1.md Shows the new API for parsing a WebAssembly module and building an instance from it. ```java var module = Parser.parse("path/to/your.wasm"); var instance = Instance.builder(module).build(); ``` -------------------------------- ### Use Chicory dependency without version Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/bom.md After importing the BOM, you can declare any Chicory dependency without specifying the version. This example shows the runtime artifact. ```xml com.dylibso.chicory runtime ``` -------------------------------- ### Describe chicory-compiler-maven-plugin with mvn help:describe Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/build-time-compiler.md Use this Maven command to display the full parameter list and description of the chicory-compiler-maven-plugin. The output includes the plugin's implementation class, bound phase, and all available parameters with their defaults and required status. ```bash mvn help:describe -DgroupId=com.dylibso.chicory -DartifactId=chicory-compiler-maven-plugin -Dversion=999-SNAPSHOT -Ddetail ``` -------------------------------- ### Register a console.log host function with Store Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/linking.md Shows how to create a HostFunction for console.log and register it with a Store. The function reads a string from instance memory and prints it. Requires imports for Parser, Instance, HostFunction, Store, ValType, and FunctionType. ```java import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.runtime.HostFunction; import com.dylibso.chicory.runtime.Store; import com.dylibso.chicory.wasm.types.ValType; import com.dylibso.chicory.wasm.types.FunctionType; var func = new HostFunction( "console", "log", FunctionType.of( List.of(ValType.I32, ValType.I32), List.of() ), (Instance instance, long... args) -> { // decompiled is: console_log(13, 0); var len = (int) args[0]; var offset = (int) args[1]; var message = instance.memory().readString(offset, len); println(message); return null; }); // instantiate the store var store = new Store(); // registers `console.log` in the store store.addFunction(func); ``` -------------------------------- ### Maven plugin configuration for chicory-compiler-maven-plugin Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/build-time-compiler.md Example Maven plugin configuration that compiles a Wasm binary (add.wasm) into a generated class (org.acme.wasm.Add). The wasmFile and name parameters are required. ```xml com.dylibso.chicory chicory-compiler-maven-plugin compiler-gen compile src/main/resources/add.wasm org.acme.wasm.Add ``` -------------------------------- ### Instantiate a module with AotMachine Source: https://github.com/dylibso/chicory/blob/main/docs/blog/2024-11-08-chicory-1.0.0-M1.md Opt in to the Ahead-of-Time backend by providing an AotMachine factory to the Instance builder. This translates the module into Java bytecode on-the-fly and in-memory, typically evaluating faster and consuming less memory. ```java var module = Parser.parse("path/to/your.wasm"); var instance = Instance.builder(module) .withMachineFactory(AotMachine::new) .build(); ``` -------------------------------- ### Build and instantiate infinite-loop module Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/cpu.md Parses the infinite-loop.wasm file and builds an Instance, then exports the 'run' function. ```java import com.dylibso.chicory.runtime.ExportFunction; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasm.Parser; Instance instance = Instance.builder(Parser.parse(new File("./infinite-loop.wasm"))).build(); ExportFunction function = instance.export("run"); ``` -------------------------------- ### Invoke Wasm function and print result Source: https://github.com/dylibso/chicory/blob/main/docs/docs/index.md Invoke the exported function with apply(). Map Java types to raw longs; the result is an array because Wasm functions can return multiple values. This example takes the first value and prints it. ```java var result = iterFact.apply(5)[0]; System.out.println("Result: " + result); // should print 120 (5!) ``` -------------------------------- ### Use disk operations with Jimfs Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/wasi.md Configured a virtual file system using Google's Jimfs. Copies a local directory and then uses that directory in WASI options. Recommended for the disk support. ```java import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; try (FileSystem fs = Jimfs.newFileSystem(Configuration.unix().toBuilder().setAttributeViews("unix").build())) { Path source = Path.of("my-source"); Path target = fs.getPath("my-source"); com.dylibso.chicory.wasi.Files.copyDirectory(source, target); var wasi = WasiOptions.builder().withDirectory(target.toString(), target).build(); // ... } ``` -------------------------------- ### Parse selective sections with ParserListener Source: https://github.com/dylibso/chicory/blob/main/wasm/README.md Uses the ParserListener interface and parse() method to parse only specified sections. Call includeSection(int sectionId) for each section to include; otherwise all sections are parsed. The example includes custom sections and throws an exception if other sections are received. ```java import com.dylibso.chicory.wasm.ParserListener; import com.dylibso.chicory.wasm.types.CustomSection; import com.dylibso.chicory.wasm.types.SectionId; var parser = new Parser(); // include the custom sections, don't call this to receive all sections parser.includeSection(SectionId.CUSTOM); // parser.includeSection(SectionId.CODE); // call for each section you want String result = ""; // implement the listener ParserListener listener = section -> { if (section.sectionId() == SectionId.CUSTOM) { var customSection = (CustomSection) section; var name = customSection.name(); result += name + "\n"; System.out.println("Got custom section with name: " + name); } else { throw new RuntimeException("Should not have received section with id: " + section.sectionId()); } }; // call parse() var is = ClassLoader.getSystemClassLoader().getResourceAsStream("compiled/count_vowels.rs.wasm"); parser.parse(is, listener); ``` -------------------------------- ### Run a single reproducer with environment variables Source: https://github.com/dylibso/chicory/blob/main/fuzz/README.md Set CHICORY_FUZZ_SEED and CHICORY_FUZZ_TYPES environment variables, then run the SingleReproTest#singleReproducer test. ```bash export CHICORY_FUZZ_SEED=path/to/seed.txt export CHICORY_FUZZ_TYPES=numeric,table mvn -B verify -pl fuzz -DskipTests=false -Dtest="SingleReproTest#singleReproducer" ``` -------------------------------- ### Enable runtime compiler with CompilerMachine::new Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/runtime-compiler.md Configure the instance to use CompilerMachine::new as the machine factory instead of the default InterpreterMachine. ```java import com.dylibso.chicory.compiler.MachineFactoryCompiler; import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.WasmModule; var module = Parser.parse(new File("your.wasm")); var instance = Instance.builder(module). withMachineFactory(MachineFactoryCompiler::compile). build(); ``` -------------------------------- ### Build and run fuzz tests with Maven Source: https://github.com/dylibso/chicory/blob/main/fuzz/README.md Build the project first, then run fuzz tests with default 10 iterations per instruction type. Optionally set a custom iteration count with -Dfuzz.test.iterations. ```bash # Build everything first mvn -B install -DskipTests -Dquickly # Run fuzz tests with default 10 iterations per instruction type mvn -B verify -pl fuzz -DskipTests=false # Run with custom iteration count mvn -B verify -pl fuzz -DskipTests=false -Dfuzz.test.iterations=50 ``` -------------------------------- ### Output of mvn help:describe for chicory:compile Source: https://github.com/dylibso/chicory/blob/main/docs/docs/usage/build-time-compiler.md This is the output of the `mvn help:describe` command for the `chicory:compile` goal. It lists the plugin's description, implementation class, bound phase, and all available parameters with their defaults and required status. ```text chicory:compile Description: This plugin generates an invokable library from the compiled Wasm Implementation: com.dylibso.chicory.build.time.maven.ChicoryCompilerGenMojo Language: java Bound to phase: generate-sources Available parameters: interpretedFunctions The indexes of functions that should be interpreted, separated by commas interpreterFallback (Default: FAIL) Required: true the action to take if the compiler needs to use the interpreter because a function is too big moduleInterface Fully qualified name of the user's class for which to generate _ModuleExports and _ModuleImports wrapper classes. When set, eliminates the need for @WasmModuleInterface annotation and the annotation processor. name Required: true the base name to be used for the generated classes targetClassFolder (Default: ${project.build.directory}/generated-resources/chicory-compiler) Required: true the target folder to generate classes targetSourceFolder (Default: ${project.build.directory}/generated-sources/chicory-compiler) Required: true the target source folder to generate the Machine implementation targetWasmFolder (Default: ${project.build.directory}/generated-resources/chicory-compiler) Required: true the target wasm folder to generate the stripped meta wasm module wasmFile Required: true the wasm module to be used ``` -------------------------------- ### Compile guest module with compile.sh Source: https://github.com/dylibso/chicory/blob/main/wasm-corpus/README.md Commands to compile a specific guest module folder (e.g., rust) on the host machine using the compile.sh script, assuming WASI_SDK_PATH is set for compiling C. ```bash cd wasm-corpus/src/main/resources # example ./compile.sh rust ```