xref: /wasmtime-44.0.1/src/commands/settings.rs (revision d3087487)
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