* Remove unnecessary into_iter/map Forgotten from a previous refactoring, this variable was already of the right type! * Move `wasmtime_jit::Compiler` into `wasmtime` This `Compiler` struct is mostly a historical artifact at this point and wasn't necessarily pulling much weight any more. This organization also doesn't lend itself super well to compiling out `cranelift` when the `Compiler` here is used for both parallel iteration configuration settings as well as compilation. The movement into `wasmtime` is relatively small, with `Module::build_artifacts` being the main function added here which is a merging of the previous functions removed from the `wasmtime-jit` crate. * Add a `cranelift` compile-time feature to `wasmtime` This commit concludes the saga of refactoring Wasmtime and making Cranelift an optional dependency by adding a new Cargo feature to the `wasmtime` crate called `cranelift`, which is enabled by default. This feature is implemented by having a new cfg for `wasmtime` itself, `cfg(compiler)`, which is used wherever compilation is necessary. This bubbles up to disable APIs such as `Module::new`, `Func::new`, `Engine::precompile_module`, and a number of `Config` methods affecting compiler configuration. Checks are added to CI that when built in this mode Wasmtime continues to successfully build. It's hoped that although this is effectively "sprinkle `#[cfg]` until things compile" this won't be too too bad to maintain over time since it's also an use case we're interested in supporting. With `cranelift` disabled the only way to create a `Module` is with the `Module::deserialize` method, which requires some form of precompiled artifact. Two consequences of this change are: * `Module::serialize` is also disabled in this mode. The reason for this is that serialized modules contain ISA/shared flags encoded in them which were used to produce the compiled code. There's no storage for this if compilation is disabled. This could probably be re-enabled in the future if necessary, but it may not end up being all that necessary. * Deserialized modules are not checked to ensure that their ISA/shared flags are compatible with the host CPU. This is actually already the case, though, with normal modules. We'll likely want to fix this in the future using a shared implementation for both these locations. Documentation should be updated to indicate that `cranelift` can be disabled, although it's not really the most prominent documentation because this is expected to be a somewhat niche use case (albeit important, just not too common). * Always enable cranelift for the C API * Fix doc example builds * Fix check tests on GitHub Actions
97 lines
3.1 KiB
Rust
97 lines
3.1 KiB
Rust
//! The module that implements the `wasmtime settings` command.
|
|
|
|
use anyhow::{anyhow, Result};
|
|
use std::collections::BTreeMap;
|
|
use std::str::FromStr;
|
|
use structopt::StructOpt;
|
|
use wasmtime_environ::{FlagValue, Setting, SettingKind};
|
|
|
|
/// Displays available Cranelift settings for a target.
|
|
#[derive(StructOpt)]
|
|
#[structopt(name = "run")]
|
|
pub struct SettingsCommand {
|
|
/// The target triple to get the settings for; defaults to the host triple.
|
|
#[structopt(long, value_name = "TARGET")]
|
|
target: Option<String>,
|
|
}
|
|
|
|
impl SettingsCommand {
|
|
/// Executes the command.
|
|
pub fn execute(self) -> Result<()> {
|
|
let mut builder = wasmtime_cranelift::builder();
|
|
if let Some(target) = &self.target {
|
|
let target = target_lexicon::Triple::from_str(target).map_err(|e| anyhow!(e))?;
|
|
builder.target(target)?;
|
|
}
|
|
|
|
let mut enums = (Vec::new(), 0, "Enum settings:");
|
|
let mut nums = (Vec::new(), 0, "Numerical settings:");
|
|
let mut bools = (Vec::new(), 0, "Boolean settings:");
|
|
let mut presets = (Vec::new(), 0, "Presets:");
|
|
|
|
for setting in builder.settings() {
|
|
let (collection, max, _) = match setting.kind {
|
|
SettingKind::Enum => &mut enums,
|
|
SettingKind::Num => &mut nums,
|
|
SettingKind::Bool => &mut bools,
|
|
SettingKind::Preset => &mut presets,
|
|
};
|
|
|
|
if setting.name.len() > *max {
|
|
*max = setting.name.len();
|
|
}
|
|
|
|
collection.push(setting);
|
|
}
|
|
|
|
if enums.0.is_empty() && nums.0.is_empty() && bools.0.is_empty() && presets.0.is_empty() {
|
|
println!("Target '{}' has no settings.", builder.triple());
|
|
return Ok(());
|
|
}
|
|
|
|
println!("Cranelift settings for target '{}':", builder.triple());
|
|
|
|
for (collection, max, header) in &mut [enums, nums, bools, presets] {
|
|
if collection.is_empty() {
|
|
continue;
|
|
}
|
|
|
|
collection.sort_by_key(|k| k.name);
|
|
println!();
|
|
Self::print_settings(header, collection, *max);
|
|
}
|
|
|
|
if self.target.is_none() {
|
|
let compiler = builder.build();
|
|
println!();
|
|
println!("Settings inferred for the current host:");
|
|
|
|
let values = compiler.isa_flags().into_iter().collect::<BTreeMap<_, _>>();
|
|
|
|
for (name, value) in values {
|
|
if let FlagValue::Bool(true) = value {
|
|
println!(" {}", name);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn print_settings(header: &str, settings: &[Setting], width: usize) {
|
|
println!("{}", header);
|
|
for setting in settings {
|
|
println!(
|
|
" {:width$} {}{}",
|
|
setting.name,
|
|
setting.description,
|
|
setting
|
|
.values
|
|
.map(|v| format!(" Supported values: {}.", v.join(", ")))
|
|
.unwrap_or("".to_string()),
|
|
width = width + 2
|
|
);
|
|
}
|
|
}
|
|
}
|