//! Defining an engine in Wasmer is one of the fundamental steps. //! //! As a reminder, an engine applies roughly 2 steps: //! //! 1. It compiles the Wasm module bytes to executable code, through //! the intervention of a compiler, //! 2. It stores the executable code somewhere. //! //! This example focuses on the first step: the compiler. It //! illustrates how the abstraction over the compiler is so powerful //! that it is possible to cross-compile a Wasm module. //! //! You can run the example directly by executing in Wasmer root: //! //! ```shell //! cargo run --example cross-compilation --release --features "cranelift" //! ``` //! //! Ready? use std::str::FromStr; use wasmer::{ sys::{CpuFeature, EngineBuilder}, wat2wasm, Module, RuntimeError, Store, }; use wasmer_compiler_cranelift::Cranelift; use wasmer_types::target::{Target, Triple}; fn main() -> Result<(), Box> { // Let's declare the Wasm module with the text representation. let wasm_bytes = wat2wasm( br#" (module (type $sum_t (func (param i32 i32) (result i32))) (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) local.get $x local.get $y i32.add) (export "sum" (func $sum_f))) "#, )?; // Define a compiler configuration. // // In this situation, the compiler is // `wasmer_compiler_cranelift`. The compiler is responsible to // compile the Wasm module into executable code. let compiler_config = Cranelift::default(); // Here we go. // // Let's define the target “triple”. Historically, such things had // three fields, though additional fields have been added over // time. let triple = Triple::from_str("x86_64-linux-musl") .map_err(|error| RuntimeError::new(error.to_string()))?; // Here we go again. // // Let's define a CPU feature. let mut cpu_feature = CpuFeature::set(); cpu_feature.insert(CpuFeature::from_str("sse2")?); // Here we go finally. // // Let's build the target. let target = Target::new(triple, cpu_feature); println!("Chosen target: {:?}", target); // Define the engine that will drive everything. // // That's where we specify the target for the compiler. // // Use the Universal engine. let engine = EngineBuilder::new(compiler_config).set_target(Some(target)); // Create a store, that holds the engine. let store = Store::new(engine); println!("Compiling module..."); // Let's compile the Wasm module. let _module = Module::new(&store, wasm_bytes)?; println!("Module compiled successfully."); // Congrats, the Wasm module is cross-compiled! // // What to do with that? It is possible to use an engine (probably // a headless engine) to execute the cross-compiled Wasm module an // the targeted platform. Ok(()) } #[test] #[cfg(not(any( windows, // We don't support yet crosscompilation in macOS with Apple Silicon all(target_os = "macos", target_arch = "aarch64"), target_env = "musl", )))] fn test_cross_compilation() -> Result<(), Box> { main() }