| 
 | 1 | +# `wasm32-unknown-unknown`  | 
 | 2 | + | 
 | 3 | +**Tier: 2**  | 
 | 4 | + | 
 | 5 | +The `wasm32-unknown-unknown` target is a WebAssembly compilation target which  | 
 | 6 | +does not import any functions from the host for the standard library. This is  | 
 | 7 | +the "minimal" WebAssembly in the sense of making the fewest assumptions about  | 
 | 8 | +the host environment. This target is often used when compiling to the web or  | 
 | 9 | +JavaScript environments as there is no standard for what functions can be  | 
 | 10 | +imported on the web. This target can also be useful for creating minimal or  | 
 | 11 | +bare-bones WebAssembly binaries.  | 
 | 12 | + | 
 | 13 | +The `wasm32-unknown-unknown` target has support for the Rust standard library  | 
 | 14 | +but many parts of the standard library do not work and return errors. For  | 
 | 15 | +example `println!` does nothing, `std::fs` always return errors, and  | 
 | 16 | +`std::thread::spawn` will panic. There is no means by which this can be  | 
 | 17 | +overridden. For a WebAssembly target that more fully supports the standard  | 
 | 18 | +library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or  | 
 | 19 | +[`wasm32-wasip2`](./wasm32-wasip2.md) targets.  | 
 | 20 | + | 
 | 21 | +The `wasm32-unknown-unknown` target has full support for the `core` and `alloc`  | 
 | 22 | +crates. It additionally supports the `HashMap` type in the `std` crate, although  | 
 | 23 | +hash maps are not randomized like they are on other platforms.  | 
 | 24 | + | 
 | 25 | +One existing user of this target (please feel free to edit and expand this list  | 
 | 26 | +too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen)  | 
 | 27 | +which facilitates Rust code interoperating with JavaScript code. Note, though,  | 
 | 28 | +that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web.  | 
 | 29 | + | 
 | 30 | +## Target maintainers  | 
 | 31 | + | 
 | 32 | +When this target was added to the compiler platform-specific documentation here  | 
 | 33 | +was not maintained at that time. This means that the list below is not  | 
 | 34 | +exhaustive and there are more interested parties in this target. That being  | 
 | 35 | +said since when this document was last updated those interested in maintaining  | 
 | 36 | +this target are:  | 
 | 37 | + | 
 | 38 | +- Alex Crichton, https://github.com/alexcrichton  | 
 | 39 | + | 
 | 40 | +## Requirements  | 
 | 41 | + | 
 | 42 | +This target is cross-compiled. The target includes support for `std` itself,  | 
 | 43 | +but as mentioned above many pieces of functionality that require an operating  | 
 | 44 | +system do not work and will return errors.  | 
 | 45 | + | 
 | 46 | +This target currently has no equivalent in C/C++. There is no C/C++ toolchain  | 
 | 47 | +for this target. While interop is theoretically possible it's recommended to  | 
 | 48 | +instead use one of:  | 
 | 49 | + | 
 | 50 | +* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten  | 
 | 51 | +  toolchain is typically chosen for running C/C++.  | 
 | 52 | +* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to  | 
 | 53 | +  compile C/C++ on this target and can interop with Rust code. WASI works on  | 
 | 54 | +  the web so far as there's no blocker, but an implementation of WASI APIs  | 
 | 55 | +  must be either chosen or reimplemented.  | 
 | 56 | + | 
 | 57 | +This target has no build requirements beyond what's in-tree in the Rust  | 
 | 58 | +repository. Linking binaries requires LLD to be enabled for the `wasm-ld`  | 
 | 59 | +driver. This target uses the `dlmalloc` crate as the default global allocator.  | 
 | 60 | + | 
 | 61 | +## Building the target  | 
 | 62 | + | 
 | 63 | +Building this target can be done by:  | 
 | 64 | + | 
 | 65 | +* Configure the `wasm32-unknown-unknown` target to get built.  | 
 | 66 | +* Configure LLD to be built.  | 
 | 67 | +* Ensure the `WebAssembly` target backend is not disabled in LLVM.  | 
 | 68 | + | 
 | 69 | +These are all controlled through `config.toml` options. It should be possible  | 
 | 70 | +to build this target on any platform.  | 
 | 71 | + | 
 | 72 | +## Building Rust programs  | 
 | 73 | + | 
 | 74 | +Rust programs can be compiled by adding this target via rustup:  | 
 | 75 | + | 
 | 76 | +```sh  | 
 | 77 | +$ rustup target add wasm32-unknown-unknown  | 
 | 78 | +```  | 
 | 79 | + | 
 | 80 | +and then compiling with the target:  | 
 | 81 | + | 
 | 82 | +```sh  | 
 | 83 | +$ rustc foo.rs --target wasm32-unknown-unknown  | 
 | 84 | +$ file foo.wasm  | 
 | 85 | +```  | 
 | 86 | + | 
 | 87 | +## Cross-compilation  | 
 | 88 | + | 
 | 89 | +This target can be cross-compiled from any host.  | 
 | 90 | + | 
 | 91 | +## Testing  | 
 | 92 | + | 
 | 93 | +This target is not tested in CI for the rust-lang/rust repository. Many tests  | 
 | 94 | +must be disabled to run on this target and failures are non-obvious because  | 
 | 95 | +`println!` doesn't work in the standard library. It's recommended to test the  | 
 | 96 | +`wasm32-wasip1` target instead for WebAssembly compatibility.  | 
 | 97 | + | 
 | 98 | +## Conditionally compiling code  | 
 | 99 | + | 
 | 100 | +It's recommended to conditionally compile code for this target with:  | 
 | 101 | + | 
 | 102 | +```text  | 
 | 103 | +#[cfg(all(target_family = "wasm", target_os = "unknown"))]  | 
 | 104 | +```  | 
 | 105 | + | 
 | 106 | +Note that there is no way to tell via `#[cfg]` whether code will be running on  | 
 | 107 | +the web or not.  | 
 | 108 | + | 
 | 109 | +## Enabled WebAssembly features  | 
 | 110 | + | 
 | 111 | +WebAssembly is an evolving standard which adds new features such as new  | 
 | 112 | +instructions over time. This target's default set of supported WebAssembly  | 
 | 113 | +features will additionally change over time. The `wasm32-unknown-unknown` target  | 
 | 114 | +inherits the default settings of LLVM which typically matches the default  | 
 | 115 | +settings of Emscripten as well.  | 
 | 116 | + | 
 | 117 | +Changes to WebAssembly go through a [proposals process][proposals] but reaching  | 
 | 118 | +the final stage (stage 5) does not automatically mean that the feature will be  | 
 | 119 | +enabled in LLVM and Rust by default. At this time the general guidance is that  | 
 | 120 | +features must be present in most engines for a "good chunk of time" before  | 
 | 121 | +they're enabled in LLVM by default. There is currently no exact number of  | 
 | 122 | +months or engines that are required to enable features by default.  | 
 | 123 | + | 
 | 124 | +[proposals]: https://github.com/WebAssembly/proposals  | 
 | 125 | + | 
 | 126 | +As of the time of this writing the proposals that are enabled by default (the  | 
 | 127 | +`generic` CPU in LLVM terminology) are:  | 
 | 128 | + | 
 | 129 | +* `multivalue`  | 
 | 130 | +* `mutable-globals`  | 
 | 131 | +* `reference-types`  | 
 | 132 | +* `sign-ext`  | 
 | 133 | + | 
 | 134 | +If you're compiling WebAssembly code for an engine that does not support a  | 
 | 135 | +feature in LLVM's default feature set then the feature must be disabled at  | 
 | 136 | +compile time. Note, though, that enabled features may be used in the standard  | 
 | 137 | +library or precompiled libraries shipped via rustup. This means that not only  | 
 | 138 | +does your own code need to be compiled with the correct set of flags but the  | 
 | 139 | +Rust standard library additionally must be recompiled.  | 
 | 140 | + | 
 | 141 | +Compiling all code for the initial release of WebAssembly looks like:  | 
 | 142 | + | 
 | 143 | +```sh  | 
 | 144 | +$ export RUSTFLAGS=-Ctarget-cpu=mvp  | 
 | 145 | +$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown  | 
 | 146 | +```  | 
 | 147 | + | 
 | 148 | +Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported  | 
 | 149 | +features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is  | 
 | 150 | +then used to recompile the standard library in addition to your own code. This  | 
 | 151 | +will produce a binary that uses only the original WebAssembly features by  | 
 | 152 | +default and no proposals since its inception.  | 
 | 153 | + | 
 | 154 | +To enable individual features it can be done with `-Ctarget-feature=+foo`.  | 
 | 155 | +Available features for Rust code itself are documented in the [reference] and  | 
 | 156 | +can also be found through:  | 
 | 157 | + | 
 | 158 | +```sh  | 
 | 159 | +$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown  | 
 | 160 | +```  | 
 | 161 | + | 
 | 162 | +You'll need to consult your WebAssembly engine's documentation to learn more  | 
 | 163 | +about the supported WebAssembly features the engine has.  | 
 | 164 | + | 
 | 165 | +[reference]: https://doc.rust-lang.org/reference/attributes/codegen.html#wasm32-or-wasm64  | 
 | 166 | + | 
 | 167 | +Note that it is still possible for Rust crates and libraries to enable  | 
 | 168 | +WebAssembly features on a per-function level. This means that the build  | 
 | 169 | +command above may not be sufficient to disable all WebAssembly features. If the  | 
 | 170 | +final binary still has SIMD instructions, for example, the function in question  | 
 | 171 | +will need to be found and the crate in question will likely contain something  | 
 | 172 | +like:  | 
 | 173 | + | 
 | 174 | +```rust,ignore (not-always-compiled-to-wasm)  | 
 | 175 | +#[target_feature(enable = "simd128")]  | 
 | 176 | +fn foo() {  | 
 | 177 | +    // ...  | 
 | 178 | +}  | 
 | 179 | +```  | 
 | 180 | + | 
 | 181 | +In this situation there is no compiler flag to disable emission of SIMD  | 
 | 182 | +instructions and the crate must instead be modified to not include this function  | 
 | 183 | +at compile time either by default or through a Cargo feature. For crate authors  | 
 | 184 | +it's recommended to avoid `#[target_feature(enable = "...")]` except where  | 
 | 185 | +necessary and instead use:  | 
 | 186 | + | 
 | 187 | +```rust,ignore (not-always-compiled-to-wasm)  | 
 | 188 | +#[cfg(target_feature = "simd128")]  | 
 | 189 | +fn foo() {  | 
 | 190 | +    // ...  | 
 | 191 | +}  | 
 | 192 | +```  | 
 | 193 | + | 
 | 194 | +That is to say instead of enabling target features it's recommended to  | 
 | 195 | +conditionally compile code instead. This is notably different to the way native  | 
 | 196 | +platforms such as x86\_64 work, and this is due to the fact that WebAssembly  | 
 | 197 | +binaries must only contain code the engine understands. Native binaries work so  | 
 | 198 | +long as the CPU doesn't execute unknown code dynamically at runtime.  | 
0 commit comments