2017-07-25 15 views
6

Tôi có thể tạo một tập tin wasm bằng cách nào đó, nó sẽ tự hoạt động như mô tả in MDN here (bằng cách instatiating các đối tượng và các chức năng gọi điện trên chúng)?Tôi có thể bằng cách nào đó xây dựng mã webassembly * mà không có * các emscripten "keo"?

Tất cả các hướng dẫn tôi có thể tìm thấy (such as this one on MDN) khuyên bạn nên sử dụng emscripten; tuy nhiên, sẽ bao gồm ~ 70kB "mã keo" (với mô phỏng hệ thống tập tin tùy chọn ~ 50 kB), có logic bổ sung (như nút phát hiện/môi trường trình duyệt và tìm nạp tự động v.v.) và có thể một số mô phỏng khác.

Điều gì sẽ xảy ra nếu tôi không muốn "mã keo" đó và muốn tạo WASM trực tiếp (có thể từ mã C, nhưng có thể có điều gì đó khác)? Điều đó có khả thi ngay bây giờ không?

+0

câu hỏi Có thể liên quan với câu trả lời - https://stackoverflow.com/questions/45146099/how-do-i-compile-ac-file-to -webassembly –

Trả lời

4

Bạn có thể sử dụng emscripten để tạo ra đầu ra mã khá nhỏ.

Hãy xem xét các tập tin sau đây tầm thường adder.c:

int adder (int a, int b) { 
    return a + b; 
} 

Compile nó như thế này (yêu cầu một emscripten khá gần đây):

emcc -O2 -s WASM=1 -s SIDE_MODULE=1 -o adder.wasm 

Để xem những gì nó tạo ra, tháo rời nó để hình thành văn bản wast sử dụng số nhị phân của wasm-dis (bạn cũng có thể sử dụng wasm2wast từ wabt):

wasm-dis adder.wasm -o adder.wast 

Nguồn tháo rời nên tìm một cái gì đó như thế này:

(module 
(type $0 (func (param i32 i32) (result i32))) 
(type $1 (func)) 
(import "env" "memoryBase" (global $import$0 i32)) 
(import "env" "memory" (memory $0 256)) 
(import "env" "table" (table 0 anyfunc)) 
(import "env" "tableBase" (global $import$3 i32)) 
(global $global$0 (mut i32) (i32.const 0)) 
(global $global$1 (mut i32) (i32.const 0)) 
(export "__post_instantiate" (func $2)) 
(export "runPostSets" (func $1)) 
(export "_adder" (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) 
) 
) 
(func $1 (type $1) 
    (nop) 
) 
(func $2 (type $1) 
    (block $label$0 
    (set_global $global$0 
    (get_global $import$0) 
    ) 
    (set_global $global$1 
    (i32.add 
    (get_global $global$0) 
    (i32.const 5242880) 
    ) 
    ) 
    (call $1) 
) 
) 
;; custom section "dylink", size 5 
) 

Sau đó, bạn có thể chạy trong nút (v8.X hoặc mới hơn) như thế này:

const WA = WebAssembly, 
     env = {memoryBase: 0, 
      tableBase: 0, 
      memory: new WA.Memory({initial: 256}), 
      table: new WA.Table({initial: 0, element: 'anyfunc'})}, 
     code = new Uint8Array(require('fs').readFileSync('adder.wasm')) 
WA.compile(code).then(m => { 
    return new WA.Instance(m, {env: env}) 
}).then(i => { 
    console.log(i.exports._adder(7, 8)) 
}) 

Lưu ý rằng nếu bạn muốn hỗ trợ mã sử dụng ngăn xếp và/hoặc bộ nhớ heap mọi thứ trở nên phức tạp hơn. I E.ít nhất bạn cũng cần phải đặt memoryBase và gọi __post_instantiate từ môi trường máy chủ của bạn trước khi bạn gọi bất kỳ xuất khẩu nào khác.

Nếu bạn muốn giải thích mã WebAssembly mà không cần môi trường JavaScript, bạn có thể chạy nó bằng cách sử dụng wac/wace (tiết lộ đầy đủ: Tôi đã tạo dự án này). Lưu ý rằng wace giả sử bạn đã xác định hàm "_main" hoặc "main".

+0

+1 cho wac! Tôi đã cố gắng để xây dựng một cái gì đó tương tự bằng cách sử dụng thông dịch viên wabt, nhưng thấy nó thiếu cho mục đích của tôi. Có vẻ như bạn đã cứu tôi một loạt công việc :) – kazemakase

+0

Tôi chấp nhận phiên bản của bạn, * nhưng * có vấn đề mà tôi không thích. Hy vọng rằng họ sẽ sửa chữa nó sớm! https://github.com/kripken/emscripten/issues/5419 –

2

Bạn có thể và nó trở nên dễ dàng hơn theo thời gian!

Nếu bạn muốn tránh C++ hoàn toàn có thể tạo mô-đun WebAssembly, ví dụ như được thực hiện trong spec tests hoặc WebKit test suite.

Ngay cả với C++ bạn có thể, không có Emscripten. wasm-stat.us làm điều đó cho ví dụ các xét nghiệm tra tấn GCC. Kiểm tra đầu ra xây dựng của nó, hoặc look at its source.

Ví dụ, nó sẽ làm như sau để biên dịch/link/lắp ráp:

# Get a .o file: 
src/work/wasm-install/bin/clang src/work/gcc/gcc/testsuite/gcc.c-torture/execute/20020227-1.c -o src/work/torture-o/20020227-1.c.o --std=gnu89 -DSTACK_SIZE=1044480 -w -Wno-implicit-function-declaration --target=wasm32-unknown-unknown-wasm -c -O2 --sysroot=src/work/wasm-install/sysroot 
# Link with libc: 
src/work/wasm-install/bin/lld -flavor wasm -entry=main --allow-undefined-file=src/work/wasm-install/sysroot/lib/wasm.syms -o src/work/torture-lld-musl/20020510-1.c.o.wasm src/work/torture-o/20020510-1.c.o src/work/wasm-install/sysroot/lib/libc.a 
# Or without a libc (you need to provide one somehow): 
src/work/wasm-install/bin/lld -flavor wasm -entry=main --allow-undefined-file=src/work/wasm-install/sysroot/lib/wasm.syms -o src/work/torture-lld/20020510-1.c.o.wasm src/work/torture-o/20020510-1.c.o 

# Or, if you want an assembly file instead: 
src/work/wasm-install/bin/clang src/work/gcc/gcc/testsuite/gcc.c-torture/execute/20020227-1.c -o src/work/torture-s/20020227-1.c.s --std=gnu89 -DSTACK_SIZE=1044480 -w -Wno-implicit-function-declaration --target=wasm32-unknown-unknown -S -O2 --sysroot=src/work/wasm-install/sysroot 
# And get the binary file: 
src/work/wasm-install/bin/wast2wasm src/work/torture-s2wasm/loop-6.c.s.wast -o src/work/torture-wast2wasm/loop-6.c.s.wast.wasm 

Bạn thậm chí có thể tải về tất cả các của thác nước xây dựng hiện vật, trong đó có dãy công cụ đầy đủ. Chỉ cần nhấp vào hộp màu xanh lục và tìm bản tải xuống bạn đang tìm kiếm.

Nếu bạn đang cảm thấy dám bạn có thể thậm chí write your libc in JavaScript thay vì liên kết một thực hiện viết bằng C.

Khi bạn nói "ngày của riêng mình", hãy nhớ hơn WebAssembly hiện không thể làm bất cứ điều gì mà không liên kết với nó trình nhúng (tức là JavaScript). Mô hình Emscripten tuân theo (và tôi hy vọng những người khác làm như vậy) là JavaScript là microkernel và cung cấp các syscalls.

+0

Cảm ơn câu trả lời! Cũng hữu ích, mặc dù tôi chấp nhận cái khác (nhưng ít nhất là upvoted của bạn) –

2

Bạn có thể sử dụng cờ ONLY_MY_CODE, điều này sẽ chỉ tạo mô-đun wasm mà không có glue.js, ví dụ:

emcc -O1 ./src/foo.cpp -o release/foo.wasm -s WASM=1 -s ONLY_MY_CODE=1 

Từ Settings.js https://github.com/kripken/emscripten/blob/master/src/settings.js#L583:

var ONLY_MY_CODE = 0; // This disables linking and other causes of adding extra code 
         // automatically, and as a result, your output compiled code 
         // (in the .asm.js file, if you emit with --separate-asm) will 
         // contain only the functions you provide. 
+0

Cảm ơn! Sẽ thử rằng –

+0

Tốt. Điều đó khác với '-s SIDE_MODULE = 1'? – kazemakase

+0

https://github.com/kripken/emscripten/wiki/Linking Theo như tôi hiểu cả hai loại bỏ mã keo được sử dụng để liên kết các mô-đun với hệ thống libaries vv nhưng 'only_my_code = 1' đi một bước nữa đảm bảo rằng chỉ mã của bạn được dịch thành wasm –

Các vấn đề liên quan