mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 13:48:26 +00:00
495 lines
18 KiB
Rust
495 lines
18 KiB
Rust
#![doc(
|
|
html_logo_url = "https://github.com/wasmerio.png?size=200",
|
|
html_favicon_url = "https://wasmer.io/images/icons/favicon-32x32.png"
|
|
)]
|
|
#![deny(
|
|
missing_docs,
|
|
trivial_numeric_casts,
|
|
unused_extern_crates,
|
|
rustdoc::broken_intra_doc_links
|
|
)]
|
|
#![warn(unused_import_braces)]
|
|
#![cfg_attr(
|
|
feature = "cargo-clippy",
|
|
allow(clippy::new_without_default, clippy::vtable_address_comparisons)
|
|
)]
|
|
#![cfg_attr(
|
|
feature = "cargo-clippy",
|
|
warn(
|
|
clippy::float_arithmetic,
|
|
clippy::mut_mut,
|
|
clippy::nonminimal_bool,
|
|
clippy::map_unwrap_or,
|
|
clippy::print_stdout,
|
|
clippy::unicode_not_nfc,
|
|
clippy::use_self
|
|
)
|
|
)]
|
|
#![allow(deprecated_cfg_attr_crate_type_name)]
|
|
#![cfg_attr(feature = "js", crate_type = "cdylib")]
|
|
|
|
//! [`Wasmer`](https://wasmer.io/) is the most popular
|
|
//! [WebAssembly](https://webassembly.org/) runtime for Rust. It supports
|
|
//! JIT (Just In Time) and AOT (Ahead Of Time) compilation as well as
|
|
//! pluggable compilers suited to your needs.
|
|
//!
|
|
//! It's designed to be safe and secure, and runnable in any kind of environment.
|
|
//!
|
|
//! # Usage
|
|
//!
|
|
//! Here is a small example of using Wasmer to run a WebAssembly module
|
|
//! written with its WAT format (textual format):
|
|
//!
|
|
//! ```rust
|
|
//! use wasmer::{Store, Module, Instance, Value, imports};
|
|
//!
|
|
//! fn main() -> anyhow::Result<()> {
|
|
//! let module_wat = r#"
|
|
//! (module
|
|
//! (type $t0 (func (param i32) (result i32)))
|
|
//! (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
|
|
//! get_local $p0
|
|
//! i32.const 1
|
|
//! i32.add))
|
|
//! "#;
|
|
//!
|
|
//! let mut store = Store::default();
|
|
//! let module = Module::new(&store, &module_wat)?;
|
|
//! // The module doesn't import anything, so we create an empty import object.
|
|
//! let import_object = imports! {};
|
|
//! let instance = Instance::new(&mut store, &module, &import_object)?;
|
|
//!
|
|
//! let add_one = instance.exports.get_function("add_one")?;
|
|
//! let result = add_one.call(&mut store, &[Value::I32(42)])?;
|
|
//! assert_eq!(result[0], Value::I32(43));
|
|
//!
|
|
//! Ok(())
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! [Discover the full collection of examples](https://github.com/wasmerio/wasmer/tree/master/examples).
|
|
//!
|
|
//! # Overview of the Features
|
|
//!
|
|
//! Wasmer is not only fast, but also designed to be *highly customizable*:
|
|
//!
|
|
//! * **Pluggable compilers** — A compiler is used by the engine to
|
|
//! transform WebAssembly into executable code:
|
|
//! * [`wasmer-compiler-singlepass`] provides a fast compilation-time
|
|
//! but an unoptimized runtime speed,
|
|
//! * [`wasmer-compiler-cranelift`] provides the right balance between
|
|
//! compilation-time and runtime performance, useful for development,
|
|
//! * [`wasmer-compiler-llvm`] provides a deeply optimized executable
|
|
//! code with the fastest runtime speed, ideal for production.
|
|
//!
|
|
//! * **Headless mode** — Once a WebAssembly module has been compiled, it
|
|
//! is possible to serialize it in a file for example, and later execute
|
|
//! it with Wasmer with headless mode turned on. Headless Wasmer has no
|
|
//! compiler, which makes it more portable and faster to load. It's
|
|
//! ideal for constrainted environments.
|
|
//!
|
|
//! * **Cross-compilation** — Most compilers support cross-compilation. It
|
|
//! means it possible to pre-compile a WebAssembly module targetting a
|
|
//! different architecture or platform and serialize it, to then run it
|
|
//! on the targetted architecture and platform later.
|
|
//!
|
|
//! * **Run Wasmer in a JavaScript environment** — With the `js` Cargo
|
|
//! feature, it is possible to compile a Rust program using Wasmer to
|
|
//! WebAssembly. In this context, the resulting WebAssembly module will
|
|
//! expect to run in a JavaScript environment, like a browser, Node.js,
|
|
//! Deno and so on. In this specific scenario, there is no engines or
|
|
//! compilers available, it's the one available in the JavaScript
|
|
//! environment that will be used.
|
|
//!
|
|
//! Wasmer ships by default with the Cranelift compiler as its great for
|
|
//! development purposes. However, we strongly encourage to use the LLVM
|
|
//! compiler in production as it performs about 50% faster, achieving
|
|
//! near-native speeds.
|
|
//!
|
|
//! Note: if one wants to use multiple compilers at the same time, it's
|
|
//! also possible! One will need to import them directly via each of the
|
|
//! compiler crates.
|
|
//!
|
|
//! # Table of Contents
|
|
//!
|
|
//! - [WebAssembly Primitives](#webassembly-primitives)
|
|
//! - [Externs](#externs)
|
|
//! - [Functions](#functions)
|
|
//! - [Memories](#memories)
|
|
//! - [Globals](#globals)
|
|
//! - [Tables](#tables)
|
|
//! - [Project Layout](#project-layout)
|
|
//! - [Engines](#engines)
|
|
//! - [Compilers](#compilers)
|
|
//! - [Cargo Features](#cargo-features)
|
|
//! - [Using Wasmer in a JavaScript environment](#using-wasmer-in-a-javascript-environment)
|
|
//!
|
|
//!
|
|
//! # WebAssembly Primitives
|
|
//!
|
|
//! In order to make use of the power of the `wasmer` API, it's important
|
|
//! to understand the primitives around which the API is built.
|
|
//!
|
|
//! Wasm only deals with a small number of core data types, these data
|
|
//! types can be found in the [`Value`] type.
|
|
//!
|
|
//! In addition to the core Wasm types, the core types of the API are
|
|
//! referred to as "externs".
|
|
//!
|
|
//! ## Externs
|
|
//!
|
|
//! An [`Extern`] is a type that can be imported or exported from a Wasm
|
|
//! module.
|
|
//!
|
|
//! To import an extern, simply give it a namespace and a name with the
|
|
//! [`imports!`] macro:
|
|
//!
|
|
//! ```
|
|
//! # use wasmer::{imports, Function, FunctionEnv, FunctionEnvMut, Memory, MemoryType, Store, Imports};
|
|
//! # fn imports_example(mut store: &mut Store) -> Imports {
|
|
//! let memory = Memory::new(&mut store, MemoryType::new(1, None, false)).unwrap();
|
|
//! imports! {
|
|
//! "env" => {
|
|
//! "my_function" => Function::new_typed(&mut store, || println!("Hello")),
|
|
//! "memory" => memory,
|
|
//! }
|
|
//! }
|
|
//! # }
|
|
//! ```
|
|
//!
|
|
//! And to access an exported extern, see the [`Exports`] API, accessible
|
|
//! from any instance via `instance.exports`:
|
|
//!
|
|
//! ```
|
|
//! # use wasmer::{imports, Instance, FunctionEnv, Memory, TypedFunction, Store};
|
|
//! # fn exports_example(mut env: FunctionEnv<()>, mut store: &mut Store, instance: &Instance) -> anyhow::Result<()> {
|
|
//! let memory = instance.exports.get_memory("memory")?;
|
|
//! let memory: &Memory = instance.exports.get("some_other_memory")?;
|
|
//! let add: TypedFunction<(i32, i32), i32> = instance.exports.get_typed_function(&mut store, "add")?;
|
|
//! let result = add.call(&mut store, 5, 37)?;
|
|
//! assert_eq!(result, 42);
|
|
//! # Ok(())
|
|
//! # }
|
|
//! ```
|
|
//!
|
|
//! These are the primary types that the `wasmer` API uses.
|
|
//!
|
|
//! ### Functions
|
|
//!
|
|
//! There are 2 types of functions in `wasmer`:
|
|
//! 1. Wasm functions,
|
|
//! 2. Host functions.
|
|
//!
|
|
//! A Wasm function is a function defined in a WebAssembly module that can
|
|
//! only perform computation without side effects and call other functions.
|
|
//!
|
|
//! Wasm functions take 0 or more arguments and return 0 or more results.
|
|
//! Wasm functions can only deal with the primitive types defined in
|
|
//! [`Value`].
|
|
//!
|
|
//! A Host function is any function implemented on the host, in this case in
|
|
//! Rust.
|
|
//!
|
|
//! Thus WebAssembly modules by themselves cannot do anything but computation
|
|
//! on the core types in [`Value`]. In order to make them more useful we
|
|
//! give them access to the outside world with [`imports!`].
|
|
//!
|
|
//! If you're looking for a sandboxed, POSIX-like environment to execute Wasm
|
|
//! in, check out the [`wasmer-wasix`] crate for our implementation of WASI,
|
|
//! the WebAssembly System Interface, and WASIX, the Extended version of WASI.
|
|
//!
|
|
//! In the `wasmer` API we support functions which take their arguments and
|
|
//! return their results dynamically, [`Function`], and functions which
|
|
//! take their arguments and return their results statically, [`TypedFunction`].
|
|
//!
|
|
//! ### Memories
|
|
//!
|
|
//! Memories store data.
|
|
//!
|
|
//! In most Wasm programs, nearly all data will live in a [`Memory`].
|
|
//!
|
|
//! This data can be shared between the host and guest to allow for more
|
|
//! interesting programs.
|
|
//!
|
|
//! ### Globals
|
|
//!
|
|
//! A [`Global`] is a type that may be either mutable or immutable, and
|
|
//! contains one of the core Wasm types defined in [`Value`].
|
|
//!
|
|
//! ### Tables
|
|
//!
|
|
//! A [`Table`] is an indexed list of items.
|
|
//!
|
|
//! # Project Layout
|
|
//!
|
|
//! The Wasmer project is divided into a number of crates, below is a dependency
|
|
//! graph with transitive dependencies removed.
|
|
//!
|
|
//! <div>
|
|
//! <img src="https://raw.githubusercontent.com/wasmerio/wasmer/master/docs/deps_dedup.svg" />
|
|
//! </div>
|
|
//!
|
|
//! While this crate is the top level API, we also publish crates built
|
|
//! on top of this API that you may be interested in using, including:
|
|
//!
|
|
//! - [`wasmer-cache`] for caching compiled Wasm modules,
|
|
//! - [`wasmer-emscripten`] for running Wasm modules compiled to the
|
|
//! Emscripten ABI,
|
|
//! - [`wasmer-wasix`] for running Wasm modules compiled to the WASI ABI.
|
|
//!
|
|
//! The Wasmer project has two major abstractions:
|
|
//! 1. [Engine][wasmer-compiler],
|
|
//! 2. [Compilers][wasmer-compiler].
|
|
//!
|
|
//! These two abstractions have multiple options that can be enabled
|
|
//! with features.
|
|
//!
|
|
//! ## Engine
|
|
//!
|
|
//! The engine is a system that uses a compiler to make a WebAssembly
|
|
//! module executable.
|
|
//!
|
|
//! ## Compilers
|
|
//!
|
|
//! A compiler is a system that handles the details of making a Wasm
|
|
//! module executable. For example, by generating native machine code
|
|
//! for each Wasm function.
|
|
//!
|
|
//! # Cargo Features
|
|
//!
|
|
//! This crate comes in 2 flavors:
|
|
//!
|
|
//! 1. `sys`
|
|
#![cfg_attr(feature = "sys", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "sys"), doc = "(disabled),")]
|
|
//! where `wasmer` will be compiled to a native executable
|
|
//! which provides compilers, engines, a full VM etc.
|
|
//! 2. `js`
|
|
#![cfg_attr(feature = "js", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "js"), doc = "(disabled),")]
|
|
//! where `wasmer` will be compiled to WebAssembly to run in a
|
|
//! JavaScript host (see [Using Wasmer in a JavaScript
|
|
//! environment](#using-wasmer-in-a-javascript-environment)).
|
|
//!
|
|
//! Consequently, we can group the features by the `sys` or `js`
|
|
//! features.
|
|
//!
|
|
#![cfg_attr(
|
|
feature = "sys",
|
|
doc = "## Features for the `sys` feature group (enabled)"
|
|
)]
|
|
#![cfg_attr(
|
|
not(feature = "sys"),
|
|
doc = "## Features for the `sys` feature group (disabled)"
|
|
)]
|
|
//!
|
|
//! The default features can be enabled with the `sys-default` feature.
|
|
//!
|
|
//! The features for the `sys` feature group can be broken down into 2
|
|
//! kinds: features that enable new functionality and features that
|
|
//! set defaults.
|
|
//!
|
|
//! The features that enable new functionality are:
|
|
//! - `cranelift`
|
|
#![cfg_attr(feature = "cranelift", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "cranelift"), doc = "(disabled),")]
|
|
//! enables Wasmer's [Cranelift compiler][wasmer-compiler-cranelift],
|
|
//! - `llvm`
|
|
#![cfg_attr(feature = "llvm", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "llvm"), doc = "(disabled),")]
|
|
//! enables Wasmer's [LLVM compiler][wasmer-compiler-lvm],
|
|
//! - `singlepass`
|
|
#![cfg_attr(feature = "singlepass", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "singlepass"), doc = "(disabled),")]
|
|
//! enables Wasmer's [Singlepass compiler][wasmer-compiler-singlepass],
|
|
//! - `wat`
|
|
#![cfg_attr(feature = "wat", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "wat"), doc = "(disabled),")]
|
|
//! enables `wasmer` to parse the WebAssembly text format,
|
|
//! - `compilation`
|
|
#![cfg_attr(feature = "compiler", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "compiler"), doc = "(disabled),")]
|
|
//! enables compilation with the wasmer engine.
|
|
//!
|
|
#![cfg_attr(
|
|
feature = "js",
|
|
doc = "## Features for the `js` feature group (enabled)"
|
|
)]
|
|
#![cfg_attr(
|
|
not(feature = "js"),
|
|
doc = "## Features for the `js` feature group (disabled)"
|
|
)]
|
|
//!
|
|
//! The default features can be enabled with the `js-default` feature.
|
|
//!
|
|
//! Here are the detailed list of features:
|
|
//!
|
|
//! - `wasm-types-polyfill`
|
|
#![cfg_attr(feature = "wasm-types-polyfill", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "wasm-types-polyfill"), doc = "(disabled),")]
|
|
//! parses the Wasm file, allowing to do type reflection of the
|
|
//! inner Wasm types. It adds 100kb to the Wasm bundle (28kb
|
|
//! gzipped). It is possible to disable it and to use
|
|
//! `Module::set_type_hints` manually instead for a lightweight
|
|
//! alternative. This is needed until the [Wasm JS introspection API
|
|
//! proposal](https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md)
|
|
//! is adopted by browsers,
|
|
//! - `wat`
|
|
#![cfg_attr(feature = "wat", doc = "(enabled),")]
|
|
#![cfg_attr(not(feature = "wat"), doc = "(disabled),")]
|
|
//! allows to read a Wasm file in its text format. This feature is
|
|
//! normally used only in development environments. It will add
|
|
//! around 650kb to the Wasm bundle (120Kb gzipped).
|
|
//!
|
|
//! # Using Wasmer in a JavaScript environment
|
|
//!
|
|
//! Imagine a Rust program that uses this `wasmer` crate to execute a
|
|
//! WebAssembly module. It is possible to compile this Rust progam to
|
|
//! WebAssembly by turning on the `js` Cargo feature of this `wasmer`
|
|
//! crate.
|
|
//!
|
|
//! Here is a small example illustrating such a Rust program, and how
|
|
//! to compile it with [`wasm-pack`] and [`wasm-bindgen`]:
|
|
//!
|
|
//! ```ignore
|
|
//! use wasm_bindgen::prelude::*;
|
|
//! use wasmer::{imports, Instance, Module, Store, Value};
|
|
//!
|
|
//! #[wasm_bindgen]
|
|
//! pub extern fn do_add_one_in_wasmer() -> i32 {
|
|
//! let module_wat = r#"
|
|
//! (module
|
|
//! (type $t0 (func (param i32) (result i32)))
|
|
//! (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
|
|
//! get_local $p0
|
|
//! i32.const 1
|
|
//! i32.add))
|
|
//! "#;
|
|
//! let mut store = Store::default();
|
|
//! let module = Module::new(&store, &module_wat).unwrap();
|
|
//! // The module doesn't import anything, so we create an empty import object.
|
|
//! let import_object = imports! {};
|
|
//! let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
|
//!
|
|
//! let add_one = instance.exports.get_function("add_one").unwrap();
|
|
//! let result = add_one.call(&mut store, &[Value::I32(42)]).unwrap();
|
|
//! assert_eq!(result[0], Value::I32(43));
|
|
//!
|
|
//! result[0].unwrap_i32()
|
|
//! }
|
|
//! ```
|
|
//!
|
|
//! Note that it's the same code as above with the former example. The
|
|
//! API is the same!
|
|
//!
|
|
//! Then, compile with `wasm-pack build`. Take care of using the `js`
|
|
//! or `js-default` Cargo features.
|
|
//!
|
|
//! [wasm]: https://webassembly.org/
|
|
//! [wasmer-examples]: https://github.com/wasmerio/wasmer/tree/master/examples
|
|
//! [`wasmer-cache`]: https://docs.rs/wasmer-cache/
|
|
//! [wasmer-compiler]: https://docs.rs/wasmer-compiler/
|
|
//! [`wasmer-emscripten`]: https://docs.rs/wasmer-emscripten/
|
|
//! [`wasmer-compiler-singlepass`]: https://docs.rs/wasmer-compiler-singlepass/
|
|
//! [`wasmer-compiler-llvm`]: https://docs.rs/wasmer-compiler-llvm/
|
|
//! [`wasmer-compiler-cranelift`]: https://docs.rs/wasmer-compiler-cranelift/
|
|
//! [`wasmer-wasix`]: https://docs.rs/wasmer-wasix/
|
|
//! [`wasm-pack`]: https://github.com/rustwasm/wasm-pack/
|
|
//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
|
|
|
|
#[cfg(all(not(feature = "sys"), not(feature = "js")))]
|
|
compile_error!("At least the `sys` or the `js` feature must be enabled. Please, pick one.");
|
|
|
|
#[cfg(all(feature = "sys", feature = "js"))]
|
|
compile_error!(
|
|
"Cannot have both `sys` and `js` features enabled at the same time. Please, pick one."
|
|
);
|
|
|
|
#[cfg(all(feature = "sys", target_arch = "wasm32"))]
|
|
compile_error!("The `sys` feature must be enabled only for non-`wasm32` target.");
|
|
|
|
#[cfg(all(feature = "js", not(target_arch = "wasm32")))]
|
|
compile_error!(
|
|
"The `js` feature must be enabled only for the `wasm32` target (either `wasm32-unknown-unknown` or `wasm32-wasi`)."
|
|
);
|
|
|
|
mod access;
|
|
mod engine;
|
|
mod errors;
|
|
mod exports;
|
|
mod extern_ref;
|
|
mod externals;
|
|
mod function_env;
|
|
mod imports;
|
|
mod instance;
|
|
mod into_bytes;
|
|
mod mem_access;
|
|
mod module;
|
|
mod native_type;
|
|
mod ptr;
|
|
mod store;
|
|
mod typed_function;
|
|
mod value;
|
|
pub mod vm;
|
|
|
|
#[cfg(feature = "sys")]
|
|
mod sys;
|
|
|
|
#[cfg(feature = "sys")]
|
|
pub use sys::*;
|
|
|
|
#[cfg(feature = "js")]
|
|
mod js;
|
|
|
|
#[cfg(feature = "js")]
|
|
pub use js::*;
|
|
|
|
pub use crate::externals::{Extern, Function, Global, HostFunction, Memory, MemoryView, Table};
|
|
pub use access::WasmSliceAccess;
|
|
pub use engine::{AsEngineRef, Engine};
|
|
pub use errors::{InstantiationError, LinkError, RuntimeError};
|
|
pub use exports::{ExportError, Exportable, Exports, ExportsIterator};
|
|
pub use extern_ref::ExternRef;
|
|
pub use function_env::{FunctionEnv, FunctionEnvMut};
|
|
pub use imports::Imports;
|
|
pub use instance::Instance;
|
|
pub use into_bytes::IntoBytes;
|
|
pub use mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
|
pub use module::{IoCompileError, Module};
|
|
pub use native_type::{FromToNativeWasmType, NativeWasmTypeInto, WasmTypeList};
|
|
pub use ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64};
|
|
pub use store::{AsStoreMut, AsStoreRef, OnCalledHandler, Store, StoreId, StoreMut, StoreRef};
|
|
#[cfg(feature = "sys")]
|
|
pub use store::{TrapHandlerFn, Tunables};
|
|
pub use typed_function::TypedFunction;
|
|
pub use value::Value;
|
|
|
|
// Reexport from other modules
|
|
|
|
pub use wasmer_derive::ValueType;
|
|
// TODO: OnCalledAction is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451
|
|
pub use wasmer_types::{
|
|
is_wasm, Bytes, CompileError, CpuFeature, DeserializeError, ExportIndex, ExportType,
|
|
ExternType, FunctionType, GlobalInit, GlobalType, ImportType, LocalFunctionIndex, MemoryError,
|
|
MemoryType, MiddlewareError, Mutability, OnCalledAction, Pages, ParseCpuFeatureError,
|
|
SerializeError, TableType, Target, Type, ValueType, WasmError, WasmResult, WASM_MAX_PAGES,
|
|
WASM_MIN_PAGES, WASM_PAGE_SIZE,
|
|
};
|
|
#[cfg(feature = "wat")]
|
|
pub use wat::parse_bytes as wat2wasm;
|
|
|
|
#[cfg(feature = "wasmparser")]
|
|
pub use wasmparser;
|
|
|
|
// Deprecated types
|
|
|
|
/// This type is deprecated, it has been replaced by TypedFunction.
|
|
#[deprecated(
|
|
since = "3.0.0",
|
|
note = "NativeFunc has been replaced by TypedFunction"
|
|
)]
|
|
pub type NativeFunc<Args = (), Rets = ()> = TypedFunction<Args, Rets>;
|
|
|
|
/// Version number of this crate.
|
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|