wasmer/
lib.rs

1#![doc(
2    html_logo_url = "https://github.com/wasmerio.png?size=200",
3    html_favicon_url = "https://wasmer.io/images/icons/favicon-32x32.png"
4)]
5#![deny(
6    missing_docs,
7    trivial_numeric_casts,
8    unused_extern_crates,
9    rustdoc::broken_intra_doc_links
10)]
11#![warn(unused_import_braces)]
12#![allow(
13    clippy::new_without_default,
14    ambiguous_wide_pointer_comparisons,
15    unreachable_patterns,
16    unused
17)]
18#![warn(
19    clippy::float_arithmetic,
20    clippy::mut_mut,
21    clippy::nonminimal_bool,
22    clippy::map_unwrap_or,
23    clippy::print_stdout,
24    clippy::unicode_not_nfc,
25    clippy::use_self
26)]
27
28//! [`Wasmer`](https://wasmer.io/) is the most popular
29//! [WebAssembly](https://webassembly.org/) runtime for Rust. It supports
30//! JIT (Just In Time) and AOT (Ahead Of Time) compilation as well as
31//! pluggable compilers suited to your needs and interpreters.
32//!
33//! It's designed to be safe and secure, and runnable in any kind of environment.
34//!
35//! # Usage
36//!
37//! Here is a small example of using Wasmer to run a WebAssembly module
38//! written with its WAT format (textual format):
39//!
40//! ```rust
41//! use wasmer::{Store, Module, Instance, Value, imports};
42//!
43//! fn main() -> anyhow::Result<()> {
44//!     let module_wat = r#"
45//!     (module
46//!       (type $t0 (func (param i32) (result i32)))
47//!       (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
48//!         local.get $p0
49//!         i32.const 1
50//!         i32.add))
51//!     "#;
52//!
53//!     let mut store = Store::default();
54//!     let module = Module::new(&store, &module_wat)?;
55//!     // The module doesn't import anything, so we create an empty import object.
56//!     let import_object = imports! {};
57//!     let instance = Instance::new(&mut store, &module, &import_object)?;
58//!
59//!     let add_one = instance.exports.get_function("add_one")?;
60//!     let result = add_one.call(&mut store, &[Value::I32(42)])?;
61//!     assert_eq!(result[0], Value::I32(43));
62//!
63//!     Ok(())
64//! }
65//! ```
66//!
67//! [Discover the full collection of examples](https://github.com/wasmerio/wasmer/tree/main/examples).
68//!
69//! # Overview of the Features
70//!
71//! Wasmer is not only fast, but also designed to be *highly customizable*:
72//!
73//! * **Pluggable compilers** — A compiler is used by the engine to
74//!   transform WebAssembly into executable code:
75//!   * [`wasmer-compiler-singlepass`](https://docs.rs/wasmer-compiler-singlepass/) provides a fast compilation-time
76//!     but an unoptimized runtime speed,
77//!   * [`wasmer-compiler-cranelift`](https://docs.rs/wasmer-compiler-cranelift/) provides the right balance between
78//!     compilation-time and runtime performance, useful for development,
79//!   * [`wasmer-compiler-llvm`](https://docs.rs/wasmer-compiler-llvm/) provides a deeply optimized executable
80//!     code with the fastest runtime speed, ideal for production.
81//!
82//! * **Other runtimes** - Wasmer supports [`v8`].
83//!
84//! * **Headless mode** — Once a WebAssembly module has been compiled, it
85//!   is possible to serialize it in a file for example, and later execute
86//!   it with Wasmer with headless mode turned on. Headless Wasmer has no
87//!   compiler, which makes it more portable and faster to load. It's
88//!   ideal for constrained environments.
89//!
90//! * **Cross-compilation** — Most compilers support cross-compilation. It
91//!   means it possible to pre-compile a WebAssembly module targeting a
92//!   different architecture or platform and serialize it, to then run it
93//!   on the targeted architecture and platform later.
94//!
95//! * **Run Wasmer in a JavaScript environment** — With the `js` Cargo
96//!   feature, it is possible to compile a Rust program using Wasmer to
97//!   WebAssembly. In this context, the resulting WebAssembly module will
98//!   expect to run in a JavaScript environment, like a browser, Node.js,
99//!   Deno and so on. In this specific scenario, there is no engines or
100//!   compilers available, it's the one available in the JavaScript
101//!   environment that will be used.
102//!
103//! Wasmer ships by default with the Cranelift compiler as its great for
104//! development purposes.  However, we strongly encourage to use the LLVM
105//! compiler in production as it performs about 50% faster, achieving
106//! near-native speeds.
107//!
108//! Note: if one wants to use multiple compilers at the same time, it's
109//! also possible! One will need to import them directly via each of the
110//! compiler crates.
111//!
112//! # Table of Contents
113//!
114//! - [WebAssembly Primitives](#webassembly-primitives)
115//!   - [Externs](#externs)
116//!     - [Functions](#functions)
117//!     - [Memories](#memories)
118//!     - [Globals](#globals)
119//!     - [Tables](#tables)
120//! - [Project Layout](#project-layout)
121//!   - [Engines](#engines)
122//!   - [Compilers](#compilers)
123//! - [Cargo Features](#cargo-features)
124//! - [Using Wasmer in a JavaScript environment](#using-wasmer-in-a-javascript-environment)
125//!
126//!
127//! # WebAssembly Primitives
128//!
129//! In order to make use of the power of the `wasmer` API, it's important
130//! to understand the primitives around which the API is built.
131//!
132//! Wasm only deals with a small number of core data types, these data
133//! types can be found in the [`Value`] type.
134//!
135//! In addition to the core Wasm types, the core types of the API are
136//! referred to as "externs".
137//!
138//! ## Externs
139//!
140//! An [`Extern`] is a type that can be imported or exported from a Wasm
141//! module.
142//!
143//! To import an extern, simply give it a namespace and a name with the
144//! [`imports!`] macro:
145//!
146//! ```
147//! # use wasmer::{imports, Function, FunctionEnv, FunctionEnvMut, Memory, MemoryType, Store, Imports};
148//! # fn imports_example(mut store: &mut Store) -> Imports {
149//! let memory = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap();
150//! imports! {
151//!     "env" => {
152//!          "my_function" => Function::new_typed(&mut store, || println!("Hello")),
153//!          "memory" => memory,
154//!     }
155//! }
156//! # }
157//! ```
158//!
159//! And to access an exported extern, see the [`Exports`] API, accessible
160//! from any instance via `instance.exports`:
161//!
162//! ```
163//! # use wasmer::{imports, Instance, FunctionEnv, Memory, TypedFunction, Store};
164//! # fn exports_example(mut env: FunctionEnv<()>, mut store: &mut Store, instance: &Instance) -> anyhow::Result<()> {
165//! let memory = instance.exports.get_memory("memory")?;
166//! let memory: &Memory = instance.exports.get("some_other_memory")?;
167//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut store, "add")?;
168//! let result = add.call(&mut store, 5, 37)?;
169//! assert_eq!(result, 42);
170//! # Ok(())
171//! # }
172//! ```
173//!
174//! These are the primary types that the `wasmer` API uses.
175//!
176//! ### Functions
177//!
178//! There are 2 types of functions in `wasmer`:
179//! 1. Wasm functions,
180//! 2. Host functions.
181//!
182//! A Wasm function is a function defined in a WebAssembly module that can
183//! only perform computation without side effects and call other functions.
184//!
185//! Wasm functions take 0 or more arguments and return 0 or more results.
186//! Wasm functions can only deal with the primitive types defined in
187//! [`Value`].
188//!
189//! A Host function is any function implemented on the host, in this case in
190//! Rust.
191//!
192//! Thus WebAssembly modules by themselves cannot do anything but computation
193//! on the core types in [`Value`]. In order to make them more useful we
194//! give them access to the outside world with [`imports!`].
195//!
196//! If you're looking for a sandboxed, POSIX-like environment to execute Wasm
197//! in, check out the [`wasmer-wasix`] crate for our implementation of WASI,
198//! the WebAssembly System Interface, and WASIX, the Extended version of WASI.
199//!
200//! In the `wasmer` API we support functions which take their arguments and
201//! return their results dynamically, [`Function`], and functions which
202//! take their arguments and return their results statically, [`TypedFunction`].
203//!
204//! ### Memories
205//!
206//! Memories store data.
207//!
208//! In most Wasm programs, nearly all data will live in a [`Memory`].
209//!
210//! This data can be shared between the host and guest to allow for more
211//! interesting programs.
212//!
213//! ### Globals
214//!
215//! A [`Global`] is a type that may be either mutable or immutable, and
216//! contains one of the core Wasm types defined in [`Value`].
217//!
218//! ### Tables
219//!
220//! A [`Table`] is an indexed list of items.
221//!
222//! # Project Layout
223//!
224//! The Wasmer project is divided into a number of crates, below is a dependency
225//! graph with transitive dependencies removed.
226//!
227//! <div>
228//! <img src="https://raw.githubusercontent.com/wasmerio/wasmer/master/docs/deps_dedup.svg" />
229//! </div>
230//!
231//! While this crate is the top level API, we also publish crates built
232//! on top of this API that you may be interested in using, including:
233//!
234//! - [`wasmer-cache`] for caching compiled Wasm modules,
235//! - [`wasmer-wasix`] for running Wasm modules compiled to the WASI ABI.
236//!
237//! The Wasmer project has two major abstractions:
238//! 1. [Engine][wasmer-compiler],
239//! 2. [Compilers][wasmer-compiler].
240//!
241//! These two abstractions have multiple options that can be enabled
242//! with features.
243//!
244//! ## Engine
245//!
246//! The engine is a system that uses a compiler to make a WebAssembly
247//! module executable.
248//!
249//! ## Runtimes
250//!
251//! A runtime is a system that handles the details of making a Wasm module executable. We support
252//! multiple kinds of runtimes: compilers, which generate native machine code for each Wasm
253//! function and interpreter, in which no native machine code is generated and can be used on
254//! platforms where JIT compilation is not allowed, such as iOS.
255//!
256//! # Cargo Features
257//!
258//! 1. `sys`
259#![cfg_attr(feature = "sys", doc = "(enabled),")]
260#![cfg_attr(not(feature = "sys"), doc = "(disabled),")]
261//!    where `wasmer` will be compiled to a native executable
262//!    which provides compilers, engines, a full VM etc.
263//!    By default, the `singlepass` and `cranelift` backends are enabled.
264//!
265//! 2. `v8`
266#![cfg_attr(feature = "v8", doc = "(enabled),")]
267#![cfg_attr(not(feature = "v8"), doc = "(disabled),")]
268//!   where `wasmer` will be compiled to a native executable
269//!   where the `v8` runtime is used for execution.
270//!
271//! 3. `js`
272#![cfg_attr(feature = "js", doc = "(enabled),")]
273#![cfg_attr(not(feature = "js"), doc = "(disabled),")]
274//!    where `wasmer` will be compiled to WebAssembly to run in a
275//!    JavaScript host (see [Using Wasmer in a JavaScript
276//!    environment](#using-wasmer-in-a-javascript-environment)).
277//!
278#![cfg_attr(
279    feature = "sys",
280    doc = "## Features for the `sys` feature group (enabled)"
281)]
282#![cfg_attr(
283    not(feature = "sys"),
284    doc = "## Features for the `sys` feature group (disabled)"
285)]
286//!
287//! The default features can be enabled with the `sys-default` feature.
288//!
289//! The features for the `sys` feature group can be broken down into 2
290//! kinds: features that enable new functionality and features that
291//! set defaults.
292//!
293//! The features that enable new functionality are:
294//! - `cranelift`
295#![cfg_attr(feature = "cranelift", doc = "(enabled),")]
296#![cfg_attr(not(feature = "cranelift"), doc = "(disabled),")]
297//!   enables Wasmer's [`Cranelift` compiler](https://docs.rs/wasmer-compiler-cranelift),
298//! - `llvm`
299#![cfg_attr(feature = "llvm", doc = "(enabled),")]
300#![cfg_attr(not(feature = "llvm"), doc = "(disabled),")]
301//!   enables Wasmer's [`LLVM` compiler](https://docs.rs/wasmer-compiler-llvm),
302//! - `singlepass`
303#![cfg_attr(feature = "singlepass", doc = "(enabled),")]
304#![cfg_attr(not(feature = "singlepass"), doc = "(disabled),")]
305//!   enables Wasmer's [`Singlepass` compiler](https://docs.rs/wasmer-compiler-singlepass),
306//! - `wat`
307#![cfg_attr(feature = "wat", doc = "(enabled),")]
308#![cfg_attr(not(feature = "wat"), doc = "(disabled),")]
309//!   enables `wasmer` to parse the WebAssembly text format,
310//! - `compilation`
311#![cfg_attr(feature = "compiler", doc = "(enabled),")]
312#![cfg_attr(not(feature = "compiler"), doc = "(disabled),")]
313//!   enables compilation with the wasmer engine.
314//!
315//! Notice that the `sys` and `v8` features are composable together,
316//! so a single build of Wasmer using `llvm`, `cranelift`, `singlepass`, and `v8`
317//! (or any combination of them) is possible.
318//!
319#![cfg_attr(
320    feature = "js",
321    doc = "## Features for the `js` feature group (enabled)"
322)]
323#![cfg_attr(
324    not(feature = "js"),
325    doc = "## Features for the `js` feature group (disabled)"
326)]
327//!
328//! The default features can be enabled with the `js-default` feature.
329//!
330//! Here are the detailed list of features:
331//!
332//! - `wasm-types-polyfill`
333#![cfg_attr(feature = "wasm-types-polyfill", doc = "(enabled),")]
334#![cfg_attr(not(feature = "wasm-types-polyfill"), doc = "(disabled),")]
335//!   parses the Wasm file, allowing to do type reflection of the
336//!   inner Wasm types. It adds 100kb to the Wasm bundle (28kb
337//!   gzipped). It is possible to disable it and to use
338//!   `Module::set_type_hints` manually instead for a lightweight
339//!   alternative. This is needed until the [Wasm JS introspection API
340//!   proposal](https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md)
341//!   is adopted by browsers,
342//! - `wat`
343#![cfg_attr(feature = "wat", doc = "(enabled),")]
344#![cfg_attr(not(feature = "wat"), doc = "(disabled),")]
345//!  allows to read a Wasm file in its text format. This feature is
346//!  normally used only in development environments. It will add
347//!  around 650kb to the Wasm bundle (120Kb gzipped).
348//!
349//! # Using Wasmer in a JavaScript environment
350//!
351//! Imagine a Rust program that uses this `wasmer` crate to execute a
352//! WebAssembly module. It is possible to compile this Rust program to
353//! WebAssembly by turning on the `js` Cargo feature of this `wasmer`
354//! crate.
355//!
356//! Here is a small example illustrating such a Rust program, and how
357//! to compile it with [`wasm-pack`] and [`wasm-bindgen`]:
358//!
359//! ```ignore
360//! use wasm_bindgen::prelude::*;
361//! use wasmer::{imports, Instance, Module, Store, Value};
362//!
363//! #[wasm_bindgen]
364//! pub extern fn do_add_one_in_wasmer() -> i32 {
365//!     let module_wat = r#"
366//!     (module
367//!       (type $t0 (func (param i32) (result i32)))
368//!       (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
369//!         local.get $p0
370//!         i32.const 1
371//!         i32.add))
372//!     "#;
373//!     let mut store = Store::default();
374//!     let module = Module::new(&store, &module_wat).unwrap();
375//!     // The module doesn't import anything, so we create an empty import object.
376//!     let import_object = imports! {};
377//!     let instance = Instance::new(&mut store, &module, &import_object).unwrap();
378//!
379//!     let add_one = instance.exports.get_function("add_one").unwrap();
380//!     let result = add_one.call(&mut store, &[Value::I32(42)]).unwrap();
381//!     assert_eq!(result[0], Value::I32(43));
382//!
383//!     result[0].unwrap_i32()
384//! }
385//! ```
386//!
387//! Note that it's the same code as above with the former example. The
388//! API is the same!
389//!
390//! Then, compile with `wasm-pack build`. Take care of using the `js`
391//! or `js-default` Cargo features.
392//!
393//! [wasm]: https://webassembly.org/
394//! [wasmer-examples]: https://github.com/wasmerio/wasmer/tree/main/examples
395//! [`wasmer-cache`]: https://docs.rs/wasmer-cache/
396//! [wasmer-compiler]: https://docs.rs/wasmer-compiler/
397//! [`wasmer-compiler-singlepass`]: https://docs.rs/wasmer-compiler-singlepass/
398//! [`wasmer-compiler-llvm`]: https://docs.rs/wasmer-compiler-llvm/
399//! [`wasmer-compiler-cranelift`]: https://docs.rs/wasmer-compiler-cranelift/
400//! [`wasmer-wasix`]: https://docs.rs/wasmer-wasix/
401//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack/
402//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
403//! [`v8`]: https://v8.dev/
404
405macro_rules! cfg_compiler {
406    ($($item:item)*) => {
407        $(
408            #[cfg(any(
409                feature = "cranelift",
410                feature = "singlepass",
411                feature = "llvm",
412                feature = "js",
413                feature = "v8",
414                feature = "headless"
415            ))]
416            $item
417        )*
418    };
419}
420
421#[cfg(not(any(
422    feature = "singlepass",
423    feature = "cranelift",
424    feature = "llvm",
425    feature = "v8",
426    feature = "js",
427    feature = "headless",
428)))]
429compile_error!(
430    "wasmer requires enabling at least one backend feature: `singlepass`, `cranelift`, `llvm`, `v8`, `js` or `headless`."
431);
432
433#[cfg(all(
434    feature = "sys",
435    not(any(
436        feature = "singlepass",
437        feature = "cranelift",
438        feature = "llvm",
439        feature = "headless"
440    ))
441))]
442compile_error!(
443    "the `sys` feature requires enabling at least one compiler backend: `singlepass`, `cranelift`, `llvm`, or `headless`."
444);
445
446cfg_compiler! {
447    mod utils;
448    pub use utils::*;
449    pub use entities::memory::{MemoryView, location::MemoryLocation};
450    mod error;
451    pub use error::*;
452    pub use entities::*;
453    mod backend;
454    pub use backend::*;
455    mod vm;
456}
457
458// TODO: cannot be placed into cfg_compiler due to: error: `inner` is ambiguous
459#[cfg(any(
460    feature = "cranelift",
461    feature = "singlepass",
462    feature = "llvm",
463    feature = "js",
464    feature = "v8",
465    feature = "headless",
466))]
467mod entities;
468
469pub use wasmer_types::{
470    Bytes, CompileError, DeserializeError, ExportIndex, ExportType, ExternType, FrameInfo,
471    FunctionType, GlobalInit, GlobalType, ImportType, LocalFunctionIndex, MemoryError, MemoryStyle,
472    MemoryType, ModuleInfo, Mutability, OnCalledAction, Pages, ParseCpuFeatureError,
473    SerializeError, TableStyle, TableType, TagKind, TagType, Type, ValueType, WASM_MAX_PAGES,
474    WASM_MIN_PAGES, WASM_PAGE_SIZE, WasmError, WasmResult, is_wasm,
475};
476
477#[cfg(feature = "wasmparser")]
478pub use wasmparser;
479
480#[cfg(feature = "wat")]
481pub use wat::parse_bytes as wat2wasm;
482
483pub use wasmer_derive::ValueType;
484
485#[cfg(any(
486    all(
487        feature = "sys-default",
488        any(feature = "js-default", feature = "v8-default")
489    ),
490    all(
491        feature = "js-default",
492        any(feature = "sys-default", feature = "v8-default")
493    ),
494    all(
495        feature = "v8-default",
496        any(feature = "sys-default", feature = "js-default")
497    ),
498))]
499compile_error!("Multiple *-default features selected. Please, pick one only!");