WIP converting from cli.rs to build/*.rs
This commit is contained in:
parent
ecc5ffd9eb
commit
90aed1615e
7 changed files with 313 additions and 27 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -309,7 +309,6 @@ dependencies = [
|
||||||
"jobslot",
|
"jobslot",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"os_pipe",
|
|
||||||
"petgraph",
|
"petgraph",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -514,16 +513,6 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "os_pipe"
|
|
||||||
version = "1.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
|
|
@ -29,7 +29,6 @@ indexmap = { version = "2.5.0", features = ["serde"] }
|
||||||
jobslot = "0.2.19"
|
jobslot = "0.2.19"
|
||||||
num-bigint = "0.4.6"
|
num-bigint = "0.4.6"
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
os_pipe = "1.2.1"
|
|
||||||
petgraph = "0.8.1"
|
petgraph = "0.8.1"
|
||||||
prettyplease = "0.2.20"
|
prettyplease = "0.2.20"
|
||||||
proc-macro2 = "1.0.83"
|
proc-macro2 = "1.0.83"
|
||||||
|
|
|
@ -25,7 +25,6 @@ hashbrown.workspace = true
|
||||||
jobslot.workspace = true
|
jobslot.workspace = true
|
||||||
num-bigint.workspace = true
|
num-bigint.workspace = true
|
||||||
num-traits.workspace = true
|
num-traits.workspace = true
|
||||||
os_pipe.workspace = true
|
|
||||||
petgraph.workspace = true
|
petgraph.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::{
|
||||||
module::Module,
|
module::Module,
|
||||||
util::{HashMap, HashSet, job_server::AcquiredJob},
|
util::{HashMap, HashSet, job_server::AcquiredJob},
|
||||||
};
|
};
|
||||||
use clap::{FromArgMatches, Subcommand};
|
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::hash_map::Entry;
|
||||||
use petgraph::{
|
use petgraph::{
|
||||||
algo::{DfsSpace, kosaraju_scc, toposort},
|
algo::{DfsSpace, kosaraju_scc, toposort},
|
||||||
|
@ -29,8 +28,10 @@ use std::{
|
||||||
sync::{Arc, OnceLock, RwLock, RwLockWriteGuard, mpsc},
|
sync::{Arc, OnceLock, RwLock, RwLockWriteGuard, mpsc},
|
||||||
thread::{self, ScopedJoinHandle},
|
thread::{self, ScopedJoinHandle},
|
||||||
};
|
};
|
||||||
|
use tempfile::TempDir;
|
||||||
|
|
||||||
pub mod external;
|
pub mod external;
|
||||||
|
pub mod firrtl;
|
||||||
|
|
||||||
macro_rules! write_str {
|
macro_rules! write_str {
|
||||||
($s:expr, $($rest:tt)*) => {
|
($s:expr, $($rest:tt)*) => {
|
||||||
|
@ -92,8 +93,6 @@ impl Ord for JobItemName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandLine {}
|
|
||||||
|
|
||||||
pub trait JobKind: 'static + Send + Sync + Hash + Eq + fmt::Debug {
|
pub trait JobKind: 'static + Send + Sync + Hash + Eq + fmt::Debug {
|
||||||
type Job: 'static + Send + Sync + Hash + Eq + fmt::Debug;
|
type Job: 'static + Send + Sync + Hash + Eq + fmt::Debug;
|
||||||
fn inputs_and_direct_dependencies<'a>(
|
fn inputs_and_direct_dependencies<'a>(
|
||||||
|
@ -779,6 +778,7 @@ impl JobKind for DynJobKind {
|
||||||
enum JobGraphNode {
|
enum JobGraphNode {
|
||||||
Job(DynJob),
|
Job(DynJob),
|
||||||
Item {
|
Item {
|
||||||
|
#[allow(dead_code, reason = "name used for debugging")]
|
||||||
name: JobItemName,
|
name: JobItemName,
|
||||||
source_job: Option<DynJob>,
|
source_job: Option<DynJob>,
|
||||||
},
|
},
|
||||||
|
@ -1551,7 +1551,7 @@ impl<Job: InternalJobTrait> JobKind for InternalJobKind<Job> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_arg_matches(&self, matches: &mut clap::ArgMatches) -> clap::error::Result<Self::Job> {
|
fn from_arg_matches(&self, matches: &mut clap::ArgMatches) -> clap::error::Result<Self::Job> {
|
||||||
InternalJob::<Job>::from_arg_matches_mut(matches)
|
clap::FromArgMatches::from_arg_matches_mut(matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_command_line(&self, job: &Self::Job) -> Interned<[Interned<str>]> {
|
fn to_command_line(&self, job: &Self::Job) -> Interned<[Interned<str>]> {
|
||||||
|
@ -1568,11 +1568,11 @@ impl<Job: InternalJobTrait> JobKind for InternalJobKind<Job> {
|
||||||
command_line: Interned<[Interned<str>]>,
|
command_line: Interned<[Interned<str>]>,
|
||||||
) -> clap::error::Result<Self::Job> {
|
) -> clap::error::Result<Self::Job> {
|
||||||
let cmd = clap::Command::new(Interned::into_inner(program_name_for_internal_jobs()));
|
let cmd = clap::Command::new(Interned::into_inner(program_name_for_internal_jobs()));
|
||||||
let mut matches = InternalJob::<Job>::augment_subcommands(cmd)
|
let mut matches = <InternalJob<Job> as clap::Subcommand>::augment_subcommands(cmd)
|
||||||
.subcommand_required(true)
|
.subcommand_required(true)
|
||||||
.arg_required_else_help(true)
|
.arg_required_else_help(true)
|
||||||
.try_get_matches_from(command_line.iter().map(|arg| &**arg))?;
|
.try_get_matches_from(command_line.iter().map(|arg| &**arg))?;
|
||||||
InternalJob::<Job>::from_arg_matches_mut(&mut matches)
|
<InternalJob<Job> as clap::FromArgMatches>::from_arg_matches_mut(&mut matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
|
@ -1657,3 +1657,202 @@ impl<Job: InternalJobTrait> clap::Subcommand for InternalJob<Job> {
|
||||||
*name == *Job::subcommand_name()
|
*name == *Job::subcommand_name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(clap::Args)]
|
||||||
|
#[clap(id = "OutputDir")]
|
||||||
|
struct OutputDirArgs {
|
||||||
|
/// the directory to put the generated main output file and associated files in
|
||||||
|
#[arg(short, long, value_hint = clap::ValueHint::DirPath, required = true)]
|
||||||
|
output: Option<String>,
|
||||||
|
#[arg(long, env = "FAYALITE_KEEP_TEMP_DIR")]
|
||||||
|
keep_temp_dir: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct OutputDir {
|
||||||
|
output: String,
|
||||||
|
temp_dir: Option<Arc<TempDir>>,
|
||||||
|
keep_temp_dir: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for OutputDir {}
|
||||||
|
|
||||||
|
impl AsRef<str> for OutputDir {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.path()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<std::path::Path> for OutputDir {
|
||||||
|
fn as_ref(&self) -> &std::path::Path {
|
||||||
|
self.path().as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputDir {
|
||||||
|
pub fn path(&self) -> &str {
|
||||||
|
&self.output
|
||||||
|
}
|
||||||
|
pub fn new(output: String) -> Self {
|
||||||
|
Self {
|
||||||
|
output,
|
||||||
|
temp_dir: None,
|
||||||
|
keep_temp_dir: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn with_keep_temp_dir(output: String, keep_temp_dir: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
output,
|
||||||
|
temp_dir: None,
|
||||||
|
keep_temp_dir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn temp(keep_temp_dir: bool) -> std::io::Result<Self> {
|
||||||
|
let temp_dir = TempDir::new()?;
|
||||||
|
let output = String::from(temp_dir.path().as_os_str().to_str().ok_or_else(|| {
|
||||||
|
std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidFilename,
|
||||||
|
format!(
|
||||||
|
"temporary directory path is not valid UTF-8: {:?}",
|
||||||
|
temp_dir.path()
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})?);
|
||||||
|
let temp_dir = if keep_temp_dir {
|
||||||
|
println!(
|
||||||
|
"created temporary directory: {}",
|
||||||
|
temp_dir.into_path().display()
|
||||||
|
);
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Arc::new(temp_dir))
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
output,
|
||||||
|
temp_dir,
|
||||||
|
keep_temp_dir,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn to_args(&self) -> Vec<Interned<str>> {
|
||||||
|
let Self {
|
||||||
|
output,
|
||||||
|
temp_dir: _,
|
||||||
|
keep_temp_dir,
|
||||||
|
} = self;
|
||||||
|
let mut retval = Vec::new();
|
||||||
|
retval.push(str::intern_owned(format!("--output={output}")));
|
||||||
|
if *keep_temp_dir {
|
||||||
|
retval.push("--keep-temp-dir".intern());
|
||||||
|
}
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
fn compare_key(&self) -> (&str, bool, bool) {
|
||||||
|
let Self {
|
||||||
|
output,
|
||||||
|
temp_dir,
|
||||||
|
keep_temp_dir,
|
||||||
|
} = self;
|
||||||
|
(output, temp_dir.is_some(), *keep_temp_dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for OutputDir {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.compare_key() == other.compare_key()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for OutputDir {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.compare_key().hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<OutputDirArgs> for OutputDir {
|
||||||
|
type Error = clap::Error;
|
||||||
|
|
||||||
|
fn try_from(value: OutputDirArgs) -> Result<Self, Self::Error> {
|
||||||
|
let OutputDirArgs {
|
||||||
|
output,
|
||||||
|
keep_temp_dir,
|
||||||
|
} = value;
|
||||||
|
match output {
|
||||||
|
Some(output) => Ok(Self::with_keep_temp_dir(output, keep_temp_dir)),
|
||||||
|
None => Ok(Self::temp(keep_temp_dir)?),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl clap::FromArgMatches for OutputDir {
|
||||||
|
fn from_arg_matches(matches: &clap::ArgMatches) -> clap::error::Result<Self> {
|
||||||
|
OutputDirArgs::from_arg_matches(matches)?.try_into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_arg_matches_mut(matches: &mut clap::ArgMatches) -> clap::error::Result<Self> {
|
||||||
|
OutputDirArgs::from_arg_matches_mut(matches)?.try_into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> clap::error::Result<()> {
|
||||||
|
*self = Self::from_arg_matches(matches)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_from_arg_matches_mut(
|
||||||
|
&mut self,
|
||||||
|
matches: &mut clap::ArgMatches,
|
||||||
|
) -> clap::error::Result<()> {
|
||||||
|
*self = Self::from_arg_matches_mut(matches)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl clap::Args for OutputDir {
|
||||||
|
fn group_id() -> Option<clap::Id> {
|
||||||
|
OutputDirArgs::group_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn augment_args(cmd: clap::Command) -> clap::Command {
|
||||||
|
OutputDirArgs::augment_args(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn augment_args_for_update(cmd: clap::Command) -> clap::Command {
|
||||||
|
OutputDirArgs::augment_args_for_update(cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(clap::Parser, Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct BaseArgs {
|
||||||
|
/// the directory to put the generated main output file and associated files in
|
||||||
|
#[command(flatten)]
|
||||||
|
pub output: OutputDir,
|
||||||
|
/// the stem of the generated main output file, e.g. to get foo.v, pass --file-stem=foo
|
||||||
|
#[arg(long)]
|
||||||
|
pub file_stem: Option<String>,
|
||||||
|
pub module_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BaseArgs {
|
||||||
|
pub fn to_args(&self) -> Vec<Interned<str>> {
|
||||||
|
let Self {
|
||||||
|
output,
|
||||||
|
file_stem,
|
||||||
|
module_name,
|
||||||
|
} = self;
|
||||||
|
let mut retval = output.to_args();
|
||||||
|
if let Some(file_stem) = file_stem {
|
||||||
|
retval.push(str::intern_owned(format!("--file-stem={file_stem}")));
|
||||||
|
}
|
||||||
|
retval.push(str::intern(module_name));
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
pub fn file_with_ext(&self, ext: &str) -> String {
|
||||||
|
let mut retval = std::path::Path::new(self.output.path())
|
||||||
|
.join(self.file_stem.as_ref().unwrap_or(&self.module_name));
|
||||||
|
retval.set_extension(ext);
|
||||||
|
retval
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
.expect("known to be UTF-8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
82
crates/fayalite/src/build/firrtl.rs
Normal file
82
crates/fayalite/src/build/firrtl.rs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
build::{BaseArgs, DynJob, InternalJobTrait, JobItem, JobItemName},
|
||||||
|
firrtl::{ExportOptions, FileBackend},
|
||||||
|
intern::{Intern, Interned},
|
||||||
|
util::job_server::AcquiredJob,
|
||||||
|
};
|
||||||
|
use clap::Parser;
|
||||||
|
use std::{borrow::Cow, collections::BTreeMap};
|
||||||
|
|
||||||
|
#[derive(Parser, Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub struct FirrtlArgs {
|
||||||
|
#[command(flatten)]
|
||||||
|
pub base: BaseArgs,
|
||||||
|
#[command(flatten)]
|
||||||
|
pub export_options: ExportOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FirrtlArgs {
|
||||||
|
fn make_firrtl_file_backend(&self) -> FileBackend {
|
||||||
|
FileBackend {
|
||||||
|
dir_path: self.base.output.path().into(),
|
||||||
|
top_fir_file_stem: self.base.file_stem.clone(),
|
||||||
|
circuit_name: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn firrtl_file(&self) -> String {
|
||||||
|
self.base.file_with_ext("fir")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalJobTrait for FirrtlArgs {
|
||||||
|
fn subcommand_name() -> Interned<str> {
|
||||||
|
"firrtl".intern()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_args(&self) -> Vec<Interned<str>> {
|
||||||
|
let Self {
|
||||||
|
base,
|
||||||
|
export_options,
|
||||||
|
} = self;
|
||||||
|
let mut retval = base.to_args();
|
||||||
|
retval.extend(export_options.to_args());
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inputs_and_direct_dependencies<'a>(
|
||||||
|
&'a self,
|
||||||
|
) -> Cow<'a, BTreeMap<JobItemName, Option<DynJob>>> {
|
||||||
|
Cow::Owned(BTreeMap::from_iter([(
|
||||||
|
JobItemName::Module {
|
||||||
|
name: str::intern(&self.base.module_name),
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outputs(&self) -> Interned<[JobItemName]> {
|
||||||
|
[JobItemName::File {
|
||||||
|
path: str::intern_owned(self.firrtl_file()),
|
||||||
|
}][..]
|
||||||
|
.intern()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&self,
|
||||||
|
inputs: &[JobItem],
|
||||||
|
_acquired_job: &mut AcquiredJob,
|
||||||
|
) -> eyre::Result<Vec<JobItem>> {
|
||||||
|
let [JobItem::Module { value: module }] = inputs else {
|
||||||
|
panic!("wrong inputs, expected a single `Module`");
|
||||||
|
};
|
||||||
|
assert_eq!(*module.name(), *self.base.module_name);
|
||||||
|
crate::firrtl::export(self.make_firrtl_file_backend(), module, self.export_options)?;
|
||||||
|
Ok(vec![JobItem::File {
|
||||||
|
path: str::intern_owned(self.firrtl_file()),
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
|
@ -102,7 +102,7 @@ impl BaseArgs {
|
||||||
mut captured_output: Option<&mut String>,
|
mut captured_output: Option<&mut String>,
|
||||||
) -> io::Result<process::ExitStatus> {
|
) -> io::Result<process::ExitStatus> {
|
||||||
if self.redirect_output_for_rust_test || captured_output.is_some() {
|
if self.redirect_output_for_rust_test || captured_output.is_some() {
|
||||||
let (reader, writer) = os_pipe::pipe()?;
|
let (reader, writer) = io::pipe()?;
|
||||||
let mut reader = io::BufReader::new(reader);
|
let mut reader = io::BufReader::new(reader);
|
||||||
command.stderr(writer.try_clone()?);
|
command.stderr(writer.try_clone()?);
|
||||||
command.stdout(writer); // must not leave writer around after spawning child
|
command.stdout(writer); // must not leave writer around after spawning child
|
||||||
|
|
|
@ -1206,9 +1206,7 @@ impl<'a> Exporter<'a> {
|
||||||
| CanonicalType::AsyncReset(_)
|
| CanonicalType::AsyncReset(_)
|
||||||
| CanonicalType::Reset(_) => Ok(format!("asUInt({value_str})")),
|
| CanonicalType::Reset(_) => Ok(format!("asUInt({value_str})")),
|
||||||
CanonicalType::PhantomConst(_) => Ok("UInt<0>(0)".into()),
|
CanonicalType::PhantomConst(_) => Ok("UInt<0>(0)".into()),
|
||||||
CanonicalType::DynSimOnly(_) => {
|
CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()),
|
||||||
Err(FirrtlError::SimOnlyValuesAreNotPermitted.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn expr_cast_bits_to_bundle(
|
fn expr_cast_bits_to_bundle(
|
||||||
|
@ -1429,9 +1427,7 @@ impl<'a> Exporter<'a> {
|
||||||
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
definitions.add_definition_line(format_args!("{extra_indent}invalidate {retval}"));
|
||||||
return Ok(retval.to_string());
|
return Ok(retval.to_string());
|
||||||
}
|
}
|
||||||
CanonicalType::DynSimOnly(_) => {
|
CanonicalType::DynSimOnly(_) => Err(FirrtlError::SimOnlyValuesAreNotPermitted.into()),
|
||||||
Err(FirrtlError::SimOnlyValuesAreNotPermitted.into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn expr_unary<T: Type>(
|
fn expr_unary<T: Type>(
|
||||||
|
@ -2758,7 +2754,7 @@ pub struct ExportOptions {
|
||||||
#[clap(long = "no-simplify-memories", action = clap::ArgAction::SetFalse)]
|
#[clap(long = "no-simplify-memories", action = clap::ArgAction::SetFalse)]
|
||||||
pub simplify_memories: bool,
|
pub simplify_memories: bool,
|
||||||
#[clap(long, value_parser = OptionSimplifyEnumsKindValueParser, default_value = "replace-with-bundle-of-uints")]
|
#[clap(long, value_parser = OptionSimplifyEnumsKindValueParser, default_value = "replace-with-bundle-of-uints")]
|
||||||
pub simplify_enums: std::option::Option<SimplifyEnumsKind>,
|
pub simplify_enums: std::option::Option<SimplifyEnumsKind>, // use std::option::Option instead of Option to avoid clap mis-parsing
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[clap(skip = ExportOptionsPrivate(()))]
|
#[clap(skip = ExportOptionsPrivate(()))]
|
||||||
/// `#[non_exhaustive]` except allowing struct update syntax
|
/// `#[non_exhaustive]` except allowing struct update syntax
|
||||||
|
@ -2772,6 +2768,28 @@ impl fmt::Debug for ExportOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExportOptions {
|
impl ExportOptions {
|
||||||
|
pub fn to_args(&self) -> Vec<Interned<str>> {
|
||||||
|
let Self {
|
||||||
|
simplify_memories,
|
||||||
|
simplify_enums,
|
||||||
|
__private: ExportOptionsPrivate(()),
|
||||||
|
} = self;
|
||||||
|
let mut retval = Vec::new();
|
||||||
|
if !*simplify_memories {
|
||||||
|
retval.push("--no-simplify-memories".intern());
|
||||||
|
}
|
||||||
|
let simplify_enums = simplify_enums.map(|v| {
|
||||||
|
clap::ValueEnum::to_possible_value(&v).expect("there are no skipped variants")
|
||||||
|
});
|
||||||
|
let simplify_enums = match &simplify_enums {
|
||||||
|
None => OptionSimplifyEnumsKindValueParser::NONE_NAME,
|
||||||
|
Some(v) => v.get_name(),
|
||||||
|
};
|
||||||
|
retval.push(str::intern_owned(format!(
|
||||||
|
"--simplify-enums={simplify_enums}"
|
||||||
|
)));
|
||||||
|
retval
|
||||||
|
}
|
||||||
fn debug_fmt(
|
fn debug_fmt(
|
||||||
&self,
|
&self,
|
||||||
f: &mut fmt::Formatter<'_>,
|
f: &mut fmt::Formatter<'_>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue