Skip to main content

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