2017-10-10 55 views
5

Mogę wygenerować dość minimalny (203 bajtów) plik wasm z następującego kodu C, uruchamiając emcc -O3 -s WASM=1 -s SIDE_MODULE=1 -o sum.wasm sum.c.Jak wygenerować minimalny plik wasm z Rust?

#include <emscripten/emscripten.h> 

int EMSCRIPTEN_KEEPALIVE sum(int a, int b) { 
    return a + b; 
} 

wyjście Disassembled:

(module 
(type $0 (func (param i32 i32) (result i32))) 
... trim 9 lines ... 
(export "_sum" (func $0)) 
(func $0 (type $0) (param $var$0 i32) (param $var$1 i32) (result i32) 
    (i32.add 
    (get_local $var$1) 
    (get_local $var$0) 
) 
) 
... trim 17 lines ... 
) 

Ale biorąc pod uwagę następujący kod Rust

pub fn main() {} 

#[no_mangle] 
pub extern fn sum(a: i32, b: i32) -> i32 { 
    a + b 
} 

I nie wydaje się produkować coś podobnego.

rustc -O --target=wasm32-unknown-emscripten sum.rs działa, ale daje mi plik 85m i plik 128k js.

Próbowałem eksportu EMMAKEN_CFLAGS='-s WASM=1 -s SIDE_MODULE=1' ale to daje mi liczbę ostrzeżeń takiego pliku

Input „/tmp/.../rust.metadata.bin” istnieje, ale nie był to odpowiedni plik bitcode LLVM dla Emscripten. Być może przypadkowo miksujesz natywne pliki obiektów wbudowanych z Emscripten?

, a następnie nie można połączyć.

Moja wersja Rust to 1.22.0-nightly (c6884b12d 2017-09-30), a moją wersją emcc jest 1.37.21.

Co robię źle?

+0

Hah, tydzień poszukiwań i nic nie mogę znaleźć. W kilka minut po zamieszczeniu tego pytania znajduję [to] (https://gist.github.com/LukasKalbertodt/821ab8b85a25f4c54544cc43bed2c39f), które może na nie odpowiedzieć. Przekażę raport, gdy go przetestuję. – zakm

+0

W [tym pliku] (https://github.com/rust-lang/rust/blob/0defa208dcb5a0f3c1ca5bc4df7acf52759ece44/src/librustc_back/target/wasm32_unknown_emscripten.rs) prawie wszystko, co zdefiniowano w celu emscriptenów Rusta. I [tutaj] (https://github.com/rust-lang/rust/blob/b2f67c8d5676d13d83523316ac95a7056dbd19c6/src/librustc_back/target/mod.rs), komentarz mówi, że można dodać cele, pisząc plik JSON (bez rekompilacji rustc!). Możesz spróbować dodać cel niestandardowy, który przekazuje flagę 'SIDE_MODULE' do emcc. Napisałbym właściwą odpowiedź, ale nie mam teraz czasu. Przepraszam: < –

Odpowiedz

3

W przypadku celu wasm32-unknown-emscripten używasz zestawu narzędzi kompilatora opartego na Emscripten. Emscripten dodaje sporo dodatkowego kodu runtime do modułu wasm, a także dodatkowy kod JavaScript do integracji z tym w środowisku wykonawczym. Jak również zauważyłeś, Emscripten może skompilować się z opcją SIDE_MODULE, która usuwa znaczną większość tego kodu środowiska wykonawczego. Zmniejsza to rozmiar binarny wasma, ale oznacza, że ​​musisz sam sobie poradzić z takimi elementami, jak bindowanie złożonych typów.

Bardzo niedawno (listopad 2017 r.) Nowy wasm32-unknown-unknown target was added to Rust, który używa backendu LLVM (zamiast Emscriptena i jego wideokomputera), co daje minimalny wynik.

Cel ten może być stosowany w sposób opisany w setup guide:

rustup update 
rustup target add wasm32-unknown-unknown --toolchain nightly 
rustc +nightly --target wasm32-unknown-unknown -O hello.rs 
+0

Właśnie zauważyłem, istnieje zestaw narzędzi zbudowany wokół tej koncepcji https://github.com/dcodeIO/webassembly – ColinE

+0

@Shepmaster fair point - całkowicie napisałem odpowiedź – ColinE