Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I conditionally compile for WebAssembly in Rust?

How can I make a config flag where I conditionally choose the wasm32-unknown-unkown target?

I printed the current environment using the following build.rs:

use std::env;

fn main() {
    for (key, value) in env::vars() {
        if key.starts_with("CARGO_CFG_") {
            println!("{}: {:?}", key, value);
        }
    }
    panic!("stop and dump stdout");
}

Which prints:

CARGO_CFG_DEBUG_ASSERTIONS: ""
CARGO_CFG_TARGET_ARCH: "wasm32"
CARGO_CFG_TARGET_ENDIAN: "little"
CARGO_CFG_TARGET_ENV: ""
CARGO_CFG_TARGET_HAS_ATOMIC: "16,32,8,ptr"
CARGO_CFG_TARGET_OS: "unknown"
CARGO_CFG_TARGET_POINTER_WIDTH: "32"
CARGO_CFG_TARGET_VENDOR: "unknown"

Normally I would do #[cfg(target_os = "linux")] but that probably doesn't work in this case because #[cfg(target_os = "unknown")] probably matches more than wasm32-unknown-unknown. Do I have to use a combination of target_arch and target_os for this to work properly or maybe just target_arch?

like image 353
tversteeg Avatar asked Jan 19 '18 21:01

tversteeg


People also ask

Does Rust compile to WebAssembly?

If you have some Rust code, you can compile it into WebAssembly (wasm). This tutorial takes you through all you need to know to compile a Rust project to wasm and use it in an existing web app.

What is CFG Rust?

Rust has a special attribute, #[cfg] , which allows you to compile code based on a flag passed to the compiler.

Why Rust is good for Wasm?

Production use Rust does not force us to choose between clearly expressing intent and runtime performance. [Rust's] properties make it easy to embed the DivANS codec in a webpage with WASM, as shown above.


1 Answers

This is how stdweb is doing it:

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]

I tested it out and it looks like something simple like this works just fine:

#[cfg(target_arch = "wasm32")]
fn add_seven(x: i32) -> i32 {
    x + 7
}

#[cfg(not(target_arch = "wasm32"))]
fn add_seven(x: i32) -> i32 {
    x + 6
}

fn main() {
    let eight = add_seven(1);
    println!("{}", eight);
}

Conditional compilation in Rust allows for a great amount of granularity in that you can specify OS, architecture, etc. If you do not need that granularity then you do not have to use it.

There are unknown and emscripten OS targets for wasm32, so it would be best to differentiate the two if your code needs to be different for the two platforms.

Stdweb has chosen to use the more granular approach. If I were doing it I would follow what they are doing, but it seems like it would work either way.

like image 164
Daniel Wilkins Avatar answered Nov 15 '22 10:11

Daniel Wilkins