@@ -3,8 +3,9 @@ use clap::{ArgAction, CommandFactory, FromArgMatches};
33use lexopt:: Arg ;
44use std:: env;
55use std:: ffi:: OsString ;
6- use std:: path:: PathBuf ;
6+ use std:: path:: { Path , PathBuf } ;
77use std:: process:: Command ;
8+ use std:: str:: FromStr ;
89use wasmparser:: Payload ;
910
1011struct LldFlag {
@@ -171,10 +172,10 @@ struct App {
171172#[ derive( clap:: Parser , Default ) ]
172173#[ command( version) ]
173174struct ComponentLdArgs {
174- /// Instructs the "proxy" adapter to be used for use in a `wasi:http/proxy`
175- /// world .
176- #[ clap( long) ]
177- wasi_proxy_adapter : bool ,
175+ /// Which default WASI adapter, if any, to use when creating the output
176+ /// component .
177+ #[ clap( long, name = "command|reactor|proxy|none" ) ]
178+ wasi_adapter : Option < WasiAdapter > ,
178179
179180 /// Location of where to find `wasm-ld`.
180181 ///
@@ -199,6 +200,58 @@ struct ComponentLdArgs {
199200 /// This defaults to `true`.
200201 #[ clap( long) ]
201202 validate_component : Option < bool > ,
203+
204+ /// Adapters to use when creating the final component.
205+ #[ clap( long = "adapt" , value_name = "[NAME=]MODULE" , value_parser = parse_adapter) ]
206+ adapters : Vec < ( String , Vec < u8 > ) > ,
207+ }
208+
209+ fn parse_adapter ( s : & str ) -> Result < ( String , Vec < u8 > ) > {
210+ let ( name, path) = parse_optionally_name_file ( s) ;
211+ let wasm = wat:: parse_file ( path) ?;
212+ Ok ( ( name. to_string ( ) , wasm) )
213+ }
214+
215+ fn parse_optionally_name_file ( s : & str ) -> ( & str , & str ) {
216+ let mut parts = s. splitn ( 2 , '=' ) ;
217+ let name_or_path = parts. next ( ) . unwrap ( ) ;
218+ match parts. next ( ) {
219+ Some ( path) => ( name_or_path, path) ,
220+ None => {
221+ let name = Path :: new ( name_or_path)
222+ . file_name ( )
223+ . unwrap ( )
224+ . to_str ( )
225+ . unwrap ( ) ;
226+ let name = match name. find ( '.' ) {
227+ Some ( i) => & name[ ..i] ,
228+ None => name,
229+ } ;
230+ ( name, name_or_path)
231+ }
232+ }
233+ }
234+
235+ #[ derive( Debug , Copy , Clone ) ]
236+ enum WasiAdapter {
237+ Command ,
238+ Reactor ,
239+ Proxy ,
240+ None ,
241+ }
242+
243+ impl FromStr for WasiAdapter {
244+ type Err = anyhow:: Error ;
245+
246+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
247+ match s {
248+ "none" => Ok ( WasiAdapter :: None ) ,
249+ "command" => Ok ( WasiAdapter :: Command ) ,
250+ "reactor" => Ok ( WasiAdapter :: Reactor ) ,
251+ "proxy" => Ok ( WasiAdapter :: Proxy ) ,
252+ _ => bail ! ( "unknown wasi adapter {s}, must be one of: none, command, reactor, proxy" ) ,
253+ }
254+ }
202255}
203256
204257fn main ( ) {
@@ -426,22 +479,35 @@ impl App {
426479 }
427480 }
428481
429- let adapter = if exports_start {
430- & command_adapter[ ..]
431- } else if self . component . wasi_proxy_adapter {
432- & proxy_adapter[ ..]
482+ let mut encoder = wit_component:: ComponentEncoder :: default ( )
483+ . module ( & core_module)
484+ . context ( "failed to parse core wasm for componentization" ) ?
485+ . validate ( self . component . validate_component . unwrap_or ( true ) ) ;
486+ let adapter = self . component . wasi_adapter . unwrap_or ( if exports_start {
487+ WasiAdapter :: Command
433488 } else {
434- & reactor_adapter[ ..]
489+ WasiAdapter :: Reactor
490+ } ) ;
491+ let adapter = match adapter {
492+ WasiAdapter :: Command => Some ( & command_adapter[ ..] ) ,
493+ WasiAdapter :: Reactor => Some ( & reactor_adapter[ ..] ) ,
494+ WasiAdapter :: Proxy => Some ( & proxy_adapter[ ..] ) ,
495+ WasiAdapter :: None => None ,
435496 } ;
436497
437- let component = wit_component:: ComponentEncoder :: default ( )
438- . module ( & core_module)
439- . context ( "failed to parse core wasm for componentization" ) ?
440- . adapter ( "wasi_snapshot_preview1" , adapter)
441- . context ( "failed to inject adapter" ) ?
442- . validate ( self . component . validate_component . unwrap_or ( true ) )
443- . encode ( )
444- . context ( "failed to encode component" ) ?;
498+ if let Some ( adapter) = adapter {
499+ encoder = encoder
500+ . adapter ( "wasi_snapshot_preview1" , adapter)
501+ . context ( "failed to inject adapter" ) ?;
502+ }
503+
504+ for ( name, adapter) in self . component . adapters . iter ( ) {
505+ encoder = encoder
506+ . adapter ( name, adapter)
507+ . with_context ( || format ! ( "failed to inject adapter {name:?}" ) ) ?;
508+ }
509+
510+ let component = encoder. encode ( ) . context ( "failed to encode component" ) ?;
445511
446512 std:: fs:: write ( self . component . output . as_ref ( ) . unwrap ( ) , & component)
447513 . context ( "failed to write output file" ) ?;
0 commit comments