1 //! The module that implements the `wasmtime settings` command. 2 3 use anyhow::{anyhow, Result}; 4 use clap::Parser; 5 use std::collections::BTreeMap; 6 use std::str::FromStr; 7 use wasmtime_environ::{FlagValue, Setting, SettingKind}; 8 9 /// Displays available Cranelift settings for a target. 10 #[derive(Parser)] 11 #[clap(name = "run")] 12 pub struct SettingsCommand { 13 /// The target triple to get the settings for; defaults to the host triple. 14 #[clap(long, value_name = "TARGET")] 15 target: Option<String>, 16 } 17 18 impl SettingsCommand { 19 /// Executes the command. 20 pub fn execute(self) -> Result<()> { 21 let mut builder = wasmtime_cranelift::builder(); 22 if let Some(target) = &self.target { 23 let target = target_lexicon::Triple::from_str(target).map_err(|e| anyhow!(e))?; 24 builder.target(target)?; 25 } 26 27 let mut enums = (Vec::new(), 0, "Enum settings:"); 28 let mut nums = (Vec::new(), 0, "Numerical settings:"); 29 let mut bools = (Vec::new(), 0, "Boolean settings:"); 30 let mut presets = (Vec::new(), 0, "Presets:"); 31 32 for setting in builder.settings() { 33 let (collection, max, _) = match setting.kind { 34 SettingKind::Enum => &mut enums, 35 SettingKind::Num => &mut nums, 36 SettingKind::Bool => &mut bools, 37 SettingKind::Preset => &mut presets, 38 }; 39 40 if setting.name.len() > *max { 41 *max = setting.name.len(); 42 } 43 44 collection.push(setting); 45 } 46 47 if enums.0.is_empty() && nums.0.is_empty() && bools.0.is_empty() && presets.0.is_empty() { 48 println!("Target '{}' has no settings.", builder.triple()); 49 return Ok(()); 50 } 51 52 println!("Cranelift settings for target '{}':", builder.triple()); 53 54 for (collection, max, header) in &mut [enums, nums, bools, presets] { 55 if collection.is_empty() { 56 continue; 57 } 58 59 collection.sort_by_key(|k| k.name); 60 println!(); 61 Self::print_settings(header, collection, *max); 62 } 63 64 if self.target.is_none() { 65 let compiler = builder.build()?; 66 println!(); 67 println!("Settings inferred for the current host:"); 68 69 let values = compiler.isa_flags().into_iter().collect::<BTreeMap<_, _>>(); 70 71 for (name, value) in values { 72 if let FlagValue::Bool(true) = value { 73 println!(" {}", name); 74 } 75 } 76 } 77 78 Ok(()) 79 } 80 81 fn print_settings(header: &str, settings: &[Setting], width: usize) { 82 println!("{}", header); 83 for setting in settings { 84 println!( 85 " {:width$} {}{}", 86 setting.name, 87 setting.description, 88 setting 89 .values 90 .map(|v| format!(" Supported values: {}.", v.join(", "))) 91 .unwrap_or("".to_string()), 92 width = width + 2 93 ); 94 } 95 } 96 } 97