ã¾ãã¯å®é¨çãã¼ã«ã®ç´¹ä»
componentize_any
ã¨ããã³ãã³ãã©ã¤ã³ãã¼ã«ãä½ãã¾ãããRubyã§æ¸ããã®ã§ä»¥ä¸ã®æ¹æ³ã§ã¤ã³ã¹ãã¼ã«ãã¦ãã ããã
$ gem install componentize_any ## ããã㯠$ git clone https://github.com/udzura/componentize_any.git && cd componentize_any $ bundle install
以ä¸ã®ãããªã¹ã¯ãªãããç¨æãã¾ããï¼wittyãã¡ã¤ã«ã¨ã§ãåä»ãã¾ããï¼
witty do world do export "wasi:cli/[email protected]" end package "wasi:[email protected]" do interface "run" do define "run", :func, {[] => :result}, counterpart: "component_run" end end end
以ä¸ã®ãããªRubyã¨RBSã®ãã¡ã¤ã«ãç¨æãã mec
ã³ãã³ããã¤ã³ã¹ãã¼ã«ãã¦ããããæ®éã®ï¼WASI p1ä¾åãªãã®ï¼WASMãã¤ããªãç¨æã
# run.rb def component_run 0 end
# run.export.rbs def component_run: () -> Integer
$ cargo install mec --version=1.0.0-rc3 $ mec --no-wasi run.rb $ file run.wasm run.wasm: WebAssembly (wasm) binary module version 0x1 (MVP)
mec
ã¨ã¯Rubyã®ã¹ã¯ãªãããCore WASMã®ãã¤ããªã«ã³ã³ãã¤ã«ããã³ãã³ãã§ãã以ä¸ã®è¨äºãªã©ã§è§£èª¬ãã¦ãã¾ãã
ããããæã£ãã componentize_any
ã§Componentãä½ããã¨ãã§ãã¾ãã
$ bundle exec componentize_any \ -witty-file witty.rb \ --input run.wasm \ --output out.wasm Writing WAT to /var/folders/sv/... Compiling WAT to WASM0: /var/folders/sv/... joining WASM0 files with run.wasm created out.wasm run to check: `wasm-tools dump out.wasm 2>&1 | less`
ã¡ããã¨WIT表ç¾ãåãåºãããã¨ã確èªã
$ wasm-tools component wit out.wasm package root:component; world root { export wasi:cli/[email protected]; } package wasi:[email protected] { interface run { run: func() -> result; } }
ãã®Component㯠wasi:cli/[email protected]
ãå®è£
ãã¦ããã®ã§ãç¾å¨ã® wasmtime
ãªããã®ã¾ã¾ãã¡ã¤ã«ã渡ãã¦å®è¡å¯è½ã§ããå®è¡ãï¼ä½ãè¦åãåããã«ï¼æåãããã¨ã確èªãã¾ãã
$ wasmtime out.wasm $ echo $? 0
ãã®æãRubyã¹ã¯ãªããã® Kernel#component_run
㧠1
ãè¿ãããã«ãã¦å度ãã®æé ãè¸ãã°ãå®è¡ã¯æ£ãã失æãã¾ãã
解説ãªã©
ãã®è¨äºã§æ¸ããéãComponentåã®WASMãã¤ããªã¯WATå½¢å¼ã®ã³ã¼ãã¨wasm-toolsã§ä½ããã¨ãã§ããã
以ä¸ã®ãããªWATã®ã³ã¼ããã³ã³ãã¤ã«ããã
;; Run wasm-tools parse -o run0.wasm run0.wat (component (core module (;0;) (func $_main (;1;) (export "main0") (result i32) i32.const 0 (if (result i32) (then i32.const 0) (else i32.const 1) ) ) ) (core instance $m (instantiate 0)) (func $main (result (result)) (canon lift (core func $m "main0"))) (component $C (import "main" (func $f (result (result)))) (export "run" (func $f)) ) (instance $c (instantiate $C (with "main" (func $main)))) (export "wasi:cli/[email protected]" (instance $c)) )
ãã®ææç©ã dump ããã¨ãCore WASMã®ã¢ã¸ã¥ã¼ã«ããã®ã¾ã¾åãè¾¼ã¾ãã¦ãããã¨ããããã
$ wasm-tools dump run0.wasm 0x0 | 00 61 73 6d | version 13 (Component) | 0d 00 01 00 0x8 | 01 3f | [core module 0] inline size 0xa | 00 61 73 6d | version 1 (Module) | 01 00 00 00 0x12 | 01 05 | type section 0x14 | 01 | 1 count --- rec group 0 (implicit) --- 0x15 | 60 00 01 7f | [type 0] SubType { is_final: true, supertype_idx: None, composite_type: CompositeType { inner: Func(FuncType { params: [], results: [I32] }), shared: false } } 0x19 | 03 02 | func section 0x1b | 01 | 1 count 0x1c | 00 | [func 0] type 0 0x1d | 07 09 | export section 0x1f | 01 | 1 count 0x20 | 05 6d 61 69 | export Export { name: "main0", kind: Func, index: 0 } | 6e 30 00 00 0x28 | 0a 0e | code section 0x2a | 01 | 1 count ============== func 0 ==================== 0x2b | 0c | size of function 0x2c | 00 | 0 local blocks 0x2d | 41 00 | i32_const value:0 0x2f | 04 7f | if blockty:Type(I32) 0x31 | 41 01 | i32_const value:1 0x33 | 05 | else 0x34 | 41 02 | i32_const value:2 0x36 | 0b | end 0x37 | 0b | end 0x38 | 00 0f | custom section 0x3a | 04 6e 61 6d | name: "name" | 65 0x3f | 01 08 | function name section 0x41 | 01 | 1 count 0x42 | 00 05 5f 6d | Naming { index: 0, name: "_main" } | 61 69 6e 0x49 | 02 04 | core instance section 0x4b | 01 | 1 count 0x4c | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } ...
Componentå½¢å¼ã®WASMãã¤ããªã¯ã»ã¯ã·ã§ã³ããã¹ããããã¨ãã§ãããããã¹ãããå ´åã§ããåè¦ç´ å ¨ä½ã®é·ããå«ããããã®ããå¾ã«ãã»ã¯ã·ã§ã³ã®å¡ããã®ã¾ã¾åãè¾¼ã¾ããããã®è¾ºã®ãããã®ä»æ§ã¯Core WASMã®ãã¤ããªã®ããªã¨ãã¾ãå¤ãããªãã
ããã§ãcore moduleé¨åã空ã«ãã¦ã¿ãã
(component (core module) (core instance $m (;0;) (instantiate 0)) (type (;0;) (result)) (type (;1;) (func (result 0))) (alias core export $m "main0" (core func (;0;))) (func $main (;0;) (type 1) (canon lift (core func 0))) (component $C (;0;) (type (;0;) (result)) (type $main_t (func (result 0))) (import "main" (func $f (;0;) (type $main_t))) (export (;1;) "run" (func $f)) ) (instance $c (;0;) (instantiate $C (with "main" (func $main)) ) ) (export (;1;) "wasi:cli/[email protected]" (instance $c)) )
Componentã®ä»ã®ç®æã§è²ã
Core moduleãåç
§ãã¦ããããããã¯ä¸æ¦ç¡è¦ãã¦ã³ã³ãã¤ã«ã§ããããããdumpãã¦ã¿ãã [core module 0]
ã¨ãã¦ã¯ãããã空ã®ã¢ã¸ã¥ã¼ã«ãåãè¾¼ã¾ãã¦ããã
0x0 | 00 61 73 6d | version 13 (Component) | 0d 00 01 00 0x8 | 01 08 | [core module 0] inline size 0xa | 00 61 73 6d | version 1 (Module) | 01 00 00 00 0x12 | 02 04 | core instance section 0x14 | 01 | 1 count 0x15 | 00 00 00 | [core instance 0] Instantiate { module_index: 0, args: [] } ...
ãã®æã 01 08 00 61 73 6d 01 00 00 00
ã¨ãã ãã¤ããªåãä¸ç¨®ã®ãã¼ã«ã¼ã¨ãã¦ãæ£ããé·ãæ
å ±ãæãããä¸ã§æ£ãã Core WASM ã¢ã¸ã¥ã¼ã«ã®ãã¤ããªã¨ç½®ãæãã ãã¨ãã§ããã°ãçµæçã«validãªComponentãã¤ããªãä½ããã¯ãã
... ã¨ããã®ãç°¡åã«è©¦ããã®ã以ä¸ã®Rubyã®ã³ã¼ãã
def to_uleb128_bin(size) if size < 0x80 [size].pack("C") else [(size & 0x7f) | 0x80].pack("C") + to_uleb128_bin(size >> 7) end end b1 = IO.read ARGV[0], encoding: "BINARY" idx = b1.index("\x01\x08\x00\x61\x73\x6d\x01\x00\x00\x00") raise "not a component wasm file" if idx.nil? b2 = IO.read ARGV[1], encoding: "BINARY" size = b2.size data = to_uleb128_bin(size) buf = "" buf << b1[0...idx] buf << "\01" << data buf << b2 buf << b1[idx...b1.size] IO.write "combo.wasm", buf puts "created combo.wasm" puts "run: `wasm-tools dump combo.wasm 2>&1 | less`"
WATã®å®ç¾©ãããããããã«ãåãè¾¼ã¾ãã Core WASM ã¢ã¸ã¥ã¼ã«ã¯exportãããååã ãããåç §ããã®ã§ãåãè¾¼ãããã®ã¢ã¸ã¥ã¼ã«ã¯é常ã®ããã«é¢æ°ãexportãã¦ããã°åé¡ãªãã
ãã®ãã¤ããªç½®ãæããã¼ã«ã«å ããwitå½¢å¼ã®Ruby DSLã«ãã witty DSLãå®è£
ã*1ãããããã¼ã¹ã«WATå½¢å¼ãä½æãã¦ãåãè¾¼ã¿å
ã®ãã¤ããªãå
é¨ã§çæããããã«ããã®ã componentize_any
ã¨ããæãã
ãããã®æé ãå®è¡ãã¦ããã¨ãã° mec ãæ®éã«Rustçµç±ãªã©ä»ã®ãã¼ã«ã§ä½æããWASMãã¤ããªã§ç½®ãæãã¦ããåé¡ãªãåãã®ã¯æåã«ç¤ºããéãã
æ°æ¥é ãè¸ã¿ãããªã³ã¼ãã ããã¨ããããæ°ã«ãªã£ã¦ãã¦ãã£ã¦ã¿ããã£ããã¨ã¯ã§ããã®ã§ããã°ã«æ®ããã
componentize_any
ãã¡ããã¨ä½ãè¾¼ããã¯ããããªã...ã mruby/edge ã¯Fully Implemented by Rustãªã®ã§ãã®ã¾ã¾Rustã®ããã¸ã§ã¯ãã«åãè¾¼ããããã§ãã§ããã° wit-bindgen
ã§ã°ã«ã¼ã³ã¼ããæ¸ããæ¹ãç´ ç´ãªã®ã§ãããããæ¹åã®å¯¾å¿ãé²ããã¤ããã ã£ããããã...ããã®è¾ºã®ææãã¾ãããã°ã«æ¸ãã¦å
¬éãããã¨ããã
ããããcomponentizeããæ¹æ³ã¯è²ã ããï¼wit-bindgenã®READMEãè¦ãã ãã§è²ã æ³åãè¨ããï¼ããCè³ç£ã§ããªããã§ããããªæ°ããã¦ãããããä»å¹´ã¯Matz mrubyãCRubyãªã©ãªã©componentize-rbã®å¤¢ã追ã£ã¦ãã...ã¾ãã...ãï¼
*1:TODO: æ®éã®witå½¢å¼ããã¼ã¹ã§ããããã«ãªã£ãæ¹ãããã