-
Notifications
You must be signed in to change notification settings - Fork 78
Add initial documentation for C tooling #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kate-goldenring
merged 6 commits into
bytecodealliance:main
from
seanisom:feature-c-tooling
Aug 27, 2024
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
d2b48d2
Add initial documentation for C tooling
seanisom 80b08a6
Merge branch 'main' into feature-c-tooling
seanisom b99ffa8
Update component-model/src/language-support/c.md
seanisom 4964bff
Update component-model/src/language-support/c.md
seanisom b7b734c
Update component-model/src/language-support/c.md
seanisom 73828f6
Feedback on documentation
seanisom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| ## C/C++ Tooling | ||
|
|
||
| ### Building a Component with `wit-bindgen` and `wasm-tools` | ||
|
|
||
| [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen) is a tool to generate guest language bindings from a given `.wit` file. Although it is less integrated into language toolchains than other tools such as `cargo-component`, it can currently generate source-level bindings for `Rust`, `C`, `Java (TeaVM)`, and `TinyGo`, with the ability for more language generators to be added in the future. | ||
|
|
||
| `wit-bindgen` can be used to generate C applications that can be compiled directly to Wasm modules using `clang` with a `wasm32-wasi` target. | ||
|
|
||
| First, install the CLI for [`wit-bindgen`](https://github.com/bytecodealliance/wit-bindgen#cli-installation), [`wasm-tools`](https://github.com/bytecodealliance/wasm-tools), and the [`WASI SDK`](https://github.com/webassembly/wasi-sdk). | ||
|
|
||
| The WASI SDK will install a local version of `clang` configured with a wasi-sysroot. Follow [these instructions](https://github.com/WebAssembly/wasi-sdk#use) to configure it for use. Note that you can also use your installed system or emscripten `clang` by building with `--target=wasm32-wasi` but you will need some artifacts from WASI SDK to enable and link that build target (more information is available in WASI SDK's docs). | ||
|
|
||
| Start by generating a C skeleton from `wit-bindgen` using the [sample `add.wit` file](../../examples/example-host/add.wit): | ||
| ```sh | ||
| >wit-bindgen c add.wit | ||
| Generating "example.c" | ||
| Generating "example.h" | ||
| Generating "example_component_type.o" | ||
| ``` | ||
|
|
||
| This has generated several files - an `example.h` (based on the name of your `world`) with the prototype of the `add` function - `int32_t example_add(int32_t x, int32_t y);`, as well as some generated code in `example.c` that interfaces with the component model ABI to call your function. Additionally, `example_component_type.o` contains object code referenced in `example.c` from an `extern` that must be linked via clang. | ||
|
|
||
| Next, create an `add.c` that implements your function defined in `example.h`: | ||
| ```c | ||
| #include "example.h" | ||
|
|
||
| int32_t example_add(int32_t x, int32_t y) | ||
| { | ||
| return x + y; | ||
| } | ||
| ``` | ||
|
|
||
| Now, you can compile the function into a Wasm module via clang: | ||
| ```sh | ||
| clang add.c example.c example_component_type.o -o add-core.wasm -mexec-model=reactor | ||
| ``` | ||
|
|
||
| Next, you need to transform the module into a component. For this example, you can use `wasm-tools component new`: | ||
| ```sh | ||
| wasm-tools component new ./add-core.wasm -o add-component.wasm | ||
| ``` | ||
|
|
||
| Do note this will fail if your code references any WASI APIs that must be imported. This requires an additional step as the WASI SDK still references `wasi_snapshot_preview1` APIs that are not compatible directly with components. | ||
|
|
||
| For example, modifying the above to reference `printf()` would compile: | ||
| ```c | ||
| #include "example.h" | ||
| #include <stdio.h> | ||
|
|
||
| int32_t example_add(int32_t x, int32_t y) | ||
| { | ||
| int32_t result = x + y; | ||
| printf("%d", result); | ||
| return result; | ||
| } | ||
| ``` | ||
|
|
||
| However, the module would fail to transform to a component: | ||
| ```sh | ||
| >wasm-tools component new ./add-core.wasm -o add-component.wasm | ||
| error: failed to encode a component from module | ||
|
|
||
| Caused by: | ||
| 0: module requires an import interface named `wasi_snapshot_preview1` | ||
| ``` | ||
|
|
||
| Install the appropriate reactor adapter module [as documented here](https://github.com/bytecodealliance/wit-bindgen#creating-components-wasi) - you can either get the linked release of `wasi_snapshot_preview1.reactor.wasm` and rename it to `wasi_snapshot_preview1.wasm`, or build it directly from source in `wasmtime` following the [instructions here](https://github.com/bytecodealliance/wasmtime/tree/main/crates/wasi-preview1-component-adapter) (make sure you `git submodule update --init` first). | ||
|
|
||
| Now, you can adapt preview1 to preview2 to build a component: | ||
| ```sh | ||
| wasm-tools component new add-core.wasm --adapt wasi_snapshot_preview1.wasm -o add-component.wasm | ||
| ``` | ||
|
|
||
| Finally, you can inspect the embedded wit to see your component (including any WASI imports if necessary): | ||
| ```sh | ||
| >wasm-tools component wit add-component.wasm | ||
| package root:component | ||
|
|
||
| world root { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My output does not have any of the WASI imports: package root:component
world root {
export add: func(x: s32, y: s32) -> s32
}however, if i add |
||
| import wasi:clocks/wall-clock | ||
| import wasi:io/streams | ||
| import wasi:filesystem/types | ||
| import wasi:filesystem/preopens | ||
| import wasi:cli/stdin | ||
| import wasi:cli/stdout | ||
| import wasi:cli/stderr | ||
| import wasi:cli/terminal-input | ||
| import wasi:cli/terminal-output | ||
| import wasi:cli/terminal-stdin | ||
| import wasi:cli/terminal-stdout | ||
| import wasi:cli/terminal-stderr | ||
|
|
||
| export add: func(x: s32, y: s32) -> s32 | ||
| } | ||
| ``` | ||
|
|
||
|
|
||
| ### Running a Component from C/C++ Applications | ||
|
|
||
seanisom marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| It is not yet possible to run a Component using the `wasmtime` `c-api` - [see this issue](https://github.com/bytecodealliance/wasmtime/issues/6987). The c-api is preferred to trying to directly use the Rust crate in C++. | ||
|
|
||
| However, C/C++ language guest components can be composed with components written in any other language and run by their toolchains, or even composed with a C language command component and run via the `wasmtime` CLI or any other host. | ||
|
|
||
| See the [Rust Tooling guide](rust.md#running-a-component-from-rust-appliacations) for instructions on how to run this component from the Rust `example-host`. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The adapter may have evolved in Wasmtime 13 as I am able to successfully create a component when adding
printand the adapter automatically imports the wasi worlds