Conditional compilation for WASM


#1

I’ve a function that I want to compile with:

  1. ‘#[wasm_bindgen]’ if I’m compiling for ‘wasm’
  2. ‘#[no_mangle]’ if I’m compiling for other platforms

The function I work with is below, it relieved a c_char/String parameter named ‘to’, and return ‘hello to’,
like relieve ‘world’ and return ‘hello world’

use std::os::raw::{c_char};
use std::ffi::{CString, CStr};

#[no_mangle]
pub extern fn rust_greeting(to: *const c_char) -> *mut c_char {
    let c_str = unsafe { CStr::from_ptr(to) };
    let recipient = match c_str.to_str() {
        Err(_) => "there",
        Ok(string) => string,
    };

    CString::new("Hello ".to_owned() + recipient).unwrap().into_raw()
}

I did not find any reference to WASM here


#2

You can use cfg_attr to conditionally allow attributes

Syntax

#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[cfg_attr(not(target_arch = "wasm32"), no_mangle)]
struct Item {}

#3

I got the below:

error[E0658]: The attribute `wasm_bindgen` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
  --> src/lib.rs:19:36
   |
19 | #[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
   |                                    ^^^^^^^^^^^^
   |
   = help: add #![feature(custom_attribute)] to the crate attributes to enable

I tried:

#[cfg_attr(target_arch = "wasm32", !#[feature(wasm_bindgen)] )]

But got:

error: expected identifier, found `!`
  --> src/lib.rs:19:36
   |
19 | #[cfg_attr(target_arch = "wasm32", !#[feature(wasm_bindgen)] )]
   |                                    ^ expected identifier

I tried:

#[cfg_attr(target_arch = "wasm32", feature = "wasm_bindgen" )]

But got:

 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
    --> src/lib.rs:19:36
     |
  19 | #[cfg_attr(target_arch = "wasm32", feature = "wasm_bindgen" )]
     |                                    ^^^^^^^^^^^^^^^^^^^^^^^^

I tried:

#[cfg_attr(target_arch = "wasm32", feature(wasm_bindgen) )]

But got:

  warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
    --> src/lib.rs:19:36
     |
  19 | #[cfg_attr(target_arch = "wasm32", feature(wasm_bindgen) )]

And tried:

#[cfg_attr(target_arch = "wasm32", !#feature(wasm_bindgen) )]

But got:

error: expected identifier, found `!`
  --> src/lib.rs:19:36
   |
19 | #[cfg_attr(target_arch = "wasm32", !#feature(wasm_bindgen) )]
   |                                    ^ expected identifier

#4

Did you use the wasm_bindgen macro from wasm_bindgen_macro? It is re exported from the wasm_bindgen crate in its prelude.


#5

Not getting your point, how to do it?
I’m not mentioning ‘wasm_bindgen_macro’ any where.


#6

The wasm_bindgen attribute is from the wasm_bindgen_macro crate. It isn’t part of the standard library.

Here’s a book for an introduction to working with wasm in Rust
https://rustwasm.github.io/book/introduction.html


#7

If you mean adding:

extern crate wasm_bindgen;

Then it is no more required in rust 2018, as per my understanding, below line is enough:

use wasm_bindgen::prelude::*;

If you mean, using:

#![feature(wasm_bindgen_macro)]

Then I got the below error:

 Compiling cargo v0.1.0 (/Users/h_ajsf/Documents/old/greetings/rust_lib_for_android)
  error[E0635]: unknown feature `wasm_bindgen_macro`
   --> src/lib.rs:1:12
    |
  1 | #![feature(wasm_bindgen_macro)]
    |

#8

I meant, use wasm_bindgen::prelude::*;, then I’m not sure why #[cfg_attr(target_arch = "wasm32", wasm_bindgen)] doesn’t work.

when I try (in Rust 2018)

use wasm_bindgen::prelude::*;

#[cfg_attr(not(target_arch = "wasm32"), no_mangle)]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
pub fn test() {

}

and compile with cargo build --target wasm-unknown-unknown it compiles fine, and so does cargo build. With cargo build it warns me that use wasm_bindgen::prelude::*; is unused, but not when I use cargo build --target wasm-unknown-unknown.


edit

I also tried it with cargo build --target wasm32-unknown-emscripten and that also compiled.