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!");