From 9691719f4d157dc75053bf3cef418a1711b8b3e0 Mon Sep 17 00:00:00 2001 From: Andrea Peruffo Date: Fri, 18 Oct 2024 18:24:50 +0100 Subject: [PATCH] Remove pages in docs from the readme --- README.md | 339 +----------------------------------------------------- 1 file changed, 1 insertion(+), 338 deletions(-) diff --git a/README.md b/README.md index 616916fcd..443ee22d2 100644 --- a/README.md +++ b/README.md @@ -16,332 +16,7 @@ simplicity and safety in mind. See the [development section](#development) for a ## Getting Started (as a user) -### Install Dependency - -To use the runtime, you need to add the `com.dylibso.chicory:runtime` dependency -to your dependency management system. - -#### Maven - -```xml - - com.dylibso.chicory - runtime - 0.0.12 - -``` - -#### Gradle - -```groovy -implementation 'com.dylibso.chicory:runtime:0.0.12' -``` - -### Install the CLI (experimental) - -The Chicory CLI is available for download on Maven at the link: - -``` -https://repo1.maven.org/maven2/com/dylibso/chicory/cli//cli-.sh -``` - -you can download the latest version and use it locally with few lines: - -```bash -export VERSION=$(wget -q -O - https://api.github.com/repos/dylibso/chicory/tags --header "Accept: application/json" | jq -r '.[0].name') -wget -O chicory https://repo1.maven.org/maven2/com/dylibso/chicory/cli/${VERSION}/cli-${VERSION}.sh -chmod a+x chicory -./chicory -``` - - - - - -### Loading and Instantiating Code - -First your Wasm module must be loaded from disk and then "instantiated". Let's [download a test module](https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/iterfact.wat.wasm) . -This module contains some code to compute factorial: - -Download from the link or with curl: - -```bash -curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/iterfact.wat.wasm > factorial.wasm -``` - - - -Now let's load this module and instantiate it: - -```java -import com.dylibso.chicory.runtime.ExportFunction; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.Module; -import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.runtime.Instance; -import java.io.File; - -// point this to your path on disk -Module module = Parser.parse(new File("./factorial.wasm")); -Instance instance = Instance.builder(module).build(); -``` - -You can think of the `module` as the inert code and the `instance` as a virtual machine -loaded with the code and ready to execute. - -### Invoking an Export Function - -Wasm modules, like all code modules, can export functions to the outside -world. This module exports a function called `"iterFact"`. We can get a handle to this function using `Instance#export(String)`: - -```java -ExportFunction iterFact = instance.export("iterFact"); -``` - -iterFact can be invoked with the `apply()` method. We must map any java types to a wasm type and do the reverse -when we want to go back to Java. This export function takes an `i32` argument. We can use a method like `Value#asInt()` -on the return value to get back the Java integer: - -```java -long result = iterFact.apply(5)[0]; -System.out.println("Result: " + result); // should print 120 (5!) -``` - - - -> *Note*: Functions in Wasm can have multiple returns but here we're just taking the first returned value. - -### Memory and Complex Types - -Wasm only understands basic integer and float primitives. So passing more complex types across the boundary involves -passing pointers. To read, write, or allocate memory in a module, Chicory gives you the `Memory` class. Let's look at an -example where we have a module `count_vowels.wasm`, written in rust, that takes a string input and counts the number of vowels -in the string: - -```bash -curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/count_vowels.rs.wasm > count_vowels.wasm -``` - - - -Build and instantiate this module: - -```java -Instance instance = Instance.builder(Parser.parse(new File("./count_vowels.wasm"))).build(); -ExportFunction countVowels = instance.export("count_vowels"); -``` - -To pass it a string, we first need to put the string in the module's memory. To make this easier and safe, -the module gives us some extra exports to allow us to allocate and deallocate memory: - -```java -ExportFunction alloc = instance.export("alloc"); -ExportFunction dealloc = instance.export("dealloc"); -``` - -Let's allocate Wasm memory for a string and put in the instance's memory. We can do this with `Memory#put`: - -```java -import com.dylibso.chicory.runtime.Memory; -Memory memory = instance.memory(); -String message = "Hello, World!"; -int len = message.getBytes().length; -// allocate {len} bytes of memory, this returns a pointer to that memory -int ptr = (int) alloc.apply(len)[0]; -// We can now write the message to the module's memory: -memory.writeString(ptr, message); -``` - -Now we can call `countVowels` with this pointer to the string. It will do it's job and return the count. We will -call `dealloc` to free that memory in the module. Though the module could do this itself if you want: - -```java -var result = countVowels.apply(ptr, len)[0]; -dealloc.apply(ptr, len); -assert(3L == result); // 3 vowels in Hello, World! -``` - - - -### Host Functions - -On its own, Wasm can't do anything but compute. It cannot affect the outside world. This might seem like a weakness -but it's actually Wasm's greatest strength. By default, programs are sandboxed and have no capabilities. If you want a program -to have capabilities, you must provide them. This puts you in the seat of the operating system. A module can -ask for a capability by listing an "import" function in it's bytecode format. You can fulfill this import with a host -function written in Java. Regardless of the language of the module, it can call this Java function when it needs. -If it helps, you can think of host functions like syscalls or a languages standard library but you decide what they -are and how they behave and it's written in Java. - -Let's download another example module to demonstrate this: - -```bash -curl https://raw.githubusercontent.com/dylibso/chicory/main/wasm-corpus/src/main/resources/compiled/host-function.wat.wasm > logger.wasm -``` - - - -This module expects us to fulfil an import with the name `console.log` which will allow the module to log to the stdout. -Let's write that host function: - - - - -```java -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.wasm.types.ValueType; -var func = new HostFunction( - "console", - "log", - (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; - }, - List.of(ValueType.I32, ValueType.I32), - List.of()); -``` - -Again we're dealing with pointers here. The module calls `console.log` with the length of the string -and the pointer (offset) in its memory. We again use the `Memory` class but this time we're pulling a string -*out* of memory. We can then print that to stdout on behalf of our Wasm program. - -Note that the HostFunction needs 3 things: - -1. A lambda to call when the Wasm module invokes the import -2. The namespace and function name of the import (in our case it's console and log respectively) -3. The Wasm type signature (this function takes 2 i32s as arguments and returns nothing) - -Now we just need to pass this host function in during our instantiation phase: - -```java -import com.dylibso.chicory.runtime.ExternalValues; -var hostFunctions = new ExternalValues(new HostFunction[] {func}); -var instance = Instance.builder(Parser.parse(new File("./logger.wasm"))).withExternalValues(hostFunctions).build(); -var logIt = instance.export("logIt"); -logIt.apply(); -// should print "Hello, World!" 10 times -``` - - - -### Store and Instantiating Multiple Modules - -A [Store][spec] is an intermediate-level abstraction that collects Wasm function, global, memory, and table instances -as named entities. - -It simplifies creating instances when there are a lot of interdependencies, by collecting all the - -In the simplest case, it allows to register single host functions, globals, memories and tables: - -```java -import com.dylibso.chicory.runtime.Store; - -// instantiate the store -var store = new Store(); -// registers `console.log` in the store (see the previous section for the definition of `func`) -store.addFunction(func); -``` - -However, the store also automatically exposes the exports of a module to the other instances that are registered. - -```java -// registers the `instance` created earlier (see the previous section) with the name `logger` -store.register("logger", instance); -// now the exported function `logIt` can be imported by other modules as `logger.logIt` -``` - -There is also a shorthand method to instantiate a module and register the resulting instance: - -```java -var logger2 = store.instantiate("logger2", Parser.parse(new File("./logger.wasm"))); -``` - -This is equivalent to: - -```java -var external = store.toExternalValues(); -var m = Parser.parse(new File("./logger.wasm")); -var instance = Instance.builder(m).withExternalValues(external).build(); -store.register("logger2", instance); -``` - -Notice that registering two instances with the same name results in overwriting the -functions, globals, memories, tables with matching names. In this case, the new `logger2.logIt` function -overwrote the old `logger2.logIt` function. - -The current `Store` is a mutable object, not meant to be shared (it is not thread-safe). - -A `Store` _does not_ resolve interdependencies between modules in itself: if your set of modules -have interdependencies, you will have to instantiate and register them in the right order. - -[spec]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#store%E2%91%A0 +To get started visit the [official documentation](https://chicory.dev/docs/). ## Development @@ -446,15 +121,3 @@ Basic steps: * `./scripts/compile-resources.sh` will recompile and regenerate the `resources/compiled` folders NOTE: The `install` target relies on the `wabt` library to compile the test suite. This is not currently released for ARM (e.g. new Macs with Apple Silicon). However, `wabt` is available from Homebrew, so `brew install wabt` before running `mvn clean install` should work. - -#### logging - -For maximum compatibility and to avoid external dependencies we use, by default, the JDK Platform Logging (JEP 264). -You can configure it by providing a `logging.properties` using the `java.util.logging.config.file` property and [here](https://docs.oracle.com/cd/E57471_01/bigData.100/data_processing_bdd/src/rdp_logging_config.html) you can find the possible configurations. - -For more advanced configuration scenarios we encourage you to provide an alternative, compatible, adapter: - -- [slf4j](https://www.slf4j.org/manual.html#jep264) -- [log4j2](https://logging.apache.org/log4j/2.x/log4j-jpl.html) - -It's also possible to provide a custom `com.dylibso.chicory.log.Logger` implementation if JDK Platform Logging is not available or doesn't fit.