about summary refs log tree commit diff
path: root/src/tools/wasm-component-ld/README.md
blob: b51de9a9dce2f57452f155c7ef436e6ef08254b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# `wasm-component-ld`

This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate.
That crate is itself a thin wrapper around two pieces:

* `wasm-ld` - the LLVM-based linker distributed as part of LLD and packaged in
  Rust as `rust-lld`.
* [`wit-component`] - a Rust crate for creating a [WebAssembly Component] from a
  core wasm module.

This linker is used for Rust's `wasm32-wasip2` target to natively output a
component instead of a core WebAssembly module, unlike other WebAssembly
targets. If you're confused about any of this here's an FAQ-style explanation of
what's going on here:

* **What's a component?** - It's a proposal to the WebAssembly standard
  primarily developed at this time by out-of-browser use cases of WebAssembly.
  You can find high-level documentation [here][component docs].

* **What's WASIp2?** - Not to be confused with WASIp1, WASIp0,
  `wasi_snapshot_preview1`, or `wasi_unstable`, it's a version of WASI. Released
  in January 2024 it's the first version of WASI defined in terms of the
  component model.

* **Why does this need its own linker?** - like any target that Rust has the
  `wasm32-wasip2` target needs a linker. What makes this different from other
  WebAssembly targets is that WASIp2 is defined at the component level, not core
  WebAssembly level. This means that filesystem functions take a `string`
  instead of `i32 i32`, for example. This means that the raw output of LLVM and
  `wasm-ld`, a core WebAssembly module, is not suitable.

* **Isn't writing a linker really hard?** - Generally, yes, but this linker
  works by first asking `wasm-ld` to do all the hard work. It invokes `wasm-ld`
  and then uses the output core WebAssembly module to create a component.

* **How do you create a component from a core module?** - this is the purpose of
  the [`wit-component`] crate, notably the `ComponentEncoder` type. This uses
  component type information embedded in the core module and a general set of
  conventions/guidelines with what the core module imports/exports. A component
  is then hooked up to codify all of these conventions in a component itself.

* **Why not require users to run `wit-component` themselves?** - while possible
  it adds friction to the usage `wasm32-wasip2` target. More importantly though
  the "module only" output of the `wasm32-wasip2` target is not ready right now.
  The standard library still imports from `wasi_snapshot_preview1` and it will
  take time to migrate all usage to WASIp2.

* **What exactly does this linker do?** - the `wasm-component-ld` has the same
  CLI interface and flags as `wasm-ld`, plus some more that are
  component-specific. These flags are used to forward most flags to `wasm-ld` to
  produce a core wasm module. After the core wasm module is produced the
  `wit-component` crate will read custom sections in the final binary which
  contain component type information. After merging all this type information
  together a component is produced which wraps the core module.

If you've got any other questions about this linker or its operation don't
hesitate to reach out to the maintainers of the `wasm32-wasip2` target.

[`wasm-component-ld`]: https://crates.io/crates/wasm-component-ld
[`wit-component`]: https://crates.io/crates/wit-component
[WebAssembly Component]: https://github.com/webassembly/component-model
[component docs]: https://component-model.bytecodealliance.org/