Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions libwild/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ edition.workspace = true
ahash = { version = "0.8.11", default-features = false, features = ["std"] }
anyhow = "1.0.97"
bitflags = "2.9.0"
bpaf = "0.9"
bytemuck = { version = "1.22.0", features = ["derive"] }
crossbeam-queue = "0.3.12"
crossbeam-utils = "0.8.21"
Expand Down
215 changes: 215 additions & 0 deletions libwild/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::save_dir::SaveDir;
use anyhow::Context as _;
use anyhow::bail;
use anyhow::ensure;
use bpaf::Parser;
use rayon::ThreadPoolBuilder;
use std::num::NonZeroUsize;
use std::path::Path;
Expand Down Expand Up @@ -571,6 +572,82 @@ pub(crate) fn parse<S: AsRef<str>, I: Iterator<Item = S>>(mut input: I) -> Resul
Ok(args)
}

fn output() -> impl Parser<Arc<PathBuf>> {
bpaf::short('o')
.argument("OUTPUT")
.fallback(PathBuf::from("a.out"))
.map(Arc::new)
}

fn single_dash_flag(name: &'static str, flag_present_value: bool) -> impl Parser<bool> {
bpaf::any::<String, _, _>("", move |s| {
if let Some(rest) = s.strip_prefix('-') {
(rest == name).then_some(flag_present_value)
} else {
None
}
})
.anywhere()
.hide()
}

fn long_arg_flag(name: &'static str, flag_present_value: bool) -> impl Parser<bool> {
let long = bpaf::long(name)
.flag(flag_present_value, !flag_present_value);

let single_dash = single_dash_flag(name, flag_present_value);

bpaf::construct!([long, single_dash])
}

fn short_long_arg_flag(short: char, long: &'static str, flag_present_value: bool) -> impl Parser<bool> {
let short_long_parser = bpaf::short(short)
.long(long)
.flag(flag_present_value, !flag_present_value);

let single_dash = single_dash_flag(long, flag_present_value);

bpaf::construct!([short_long_parser, single_dash])
}

#[derive(Debug, Clone)]
struct BpafArgs {
output: Arc<PathBuf>,
time_phases: bool,
strip_all: bool,
strip_debug: bool,
should_fork: bool,
}

fn bpaf_main_parser() -> impl Parser<BpafArgs> {
let time_phases = long_arg_flag("time", true);

// TODO: We should also set strip_debug = true in this case.
let strip_all = short_long_arg_flag('s', "strip-all", true);

let strip_debug = short_long_arg_flag('S', "strip-debug", true);

let should_fork = long_arg_flag("no-fork", false);

bpaf::construct!(BpafArgs { output(), time_phases, strip_all, strip_debug, should_fork })
}

fn bpaf_options() -> bpaf::OptionParser<BpafArgs> {
bpaf_main_parser()
.to_options()
}

pub(crate) fn parse_with_bpaf<S: AsRef<str>, I: Iterator<Item = S>>(mut _input: I) -> Result<Args> {
println!("{:?}", bpaf_options().run());
bail!("parse_with_bpaf is not fully implemented")
}

fn time_phases() -> impl Parser<bool> {
let time_phases = long_arg_flag("time", true);

time_phases
}

const fn default_target_arch() -> Architecture {
// We default to targeting the architecture that we're running on. We don't support running on
// architectures that we can't target.
Expand Down Expand Up @@ -820,6 +897,7 @@ fn warn_unsupported(opt: &str) -> Result {
#[cfg(test)]
mod tests {
use super::SILENTLY_IGNORED_FLAGS;
use super::*;
use crate::args::InputSpec;
use itertools::Itertools;
use std::num::NonZeroUsize;
Expand Down Expand Up @@ -1009,4 +1087,141 @@ mod tests {
assert!(!flag.starts_with('-'));
}
}

#[test]
fn test_bpaf_output() {
let args = bpaf_options()
.run_inner(&["-o", "output_name"])
.unwrap();
assert_eq!(args.output, Arc::new(PathBuf::from("output_name")));
}

#[test]
fn test_bpaf_output_fallback() {
let args = bpaf_options()
.run_inner(&[])
.unwrap();
assert_eq!(args.output, Arc::new(PathBuf::from("a.out")));
}

#[test]
fn test_bpaf_time_with_two_dashes() {
let args = bpaf_options()
.run_inner(&["--time"])
.unwrap();
assert_eq!(args.time_phases, true);
}

#[test]
fn test_bpaf_time_with_single_dash() {
let args = bpaf_options()
.run_inner(&["-time"])
.unwrap();
assert_eq!(args.time_phases, true);
}

#[test]
fn test_bpaf_time_fallback() {
let args = bpaf_options()
.run_inner(&[])
.unwrap();
assert_eq!(args.time_phases, false);
}

#[test]
fn test_bpaf_strip_all_with_two_dashes() {
let args = bpaf_options()
.run_inner(&["--strip-all"])
.unwrap();
assert_eq!(args.strip_all, true);
}

#[test]
fn test_bpaf_strip_all_with_single_dash() {
let args = bpaf_options()
.run_inner(&["-strip-all"])
.unwrap();
assert_eq!(args.strip_all, true);
}

#[test]
fn test_bpaf_strip_all_with_short() {
let args = bpaf_options()
.run_inner(&["-s"])
.unwrap();
assert_eq!(args.strip_all, true);
}

#[test]
fn test_bpaf_strip_all_fallback() {
let args = bpaf_options()
.run_inner(&[])
.unwrap();
assert_eq!(args.strip_all, false);
}

#[test]
fn test_bpaf_strip_debug_with_two_dashes() {
let args = bpaf_options()
.run_inner(&["--strip-debug"])
.unwrap();
assert_eq!(args.strip_debug, true);
}

#[test]
fn test_bpaf_strip_debug_with_single_dash() {
let args = bpaf_options()
.run_inner(&["-strip-debug"])
.unwrap();
assert_eq!(args.strip_debug, true);
}

#[test]
fn test_bpaf_strip_debug_with_short() {
let args = bpaf_options()
.run_inner(&["-S"])
.unwrap();
assert_eq!(args.strip_debug, true);
}

#[test]
fn test_bpaf_strip_debug_fallback() {
let args = bpaf_options()
.run_inner(&[])
.unwrap();
assert_eq!(args.strip_debug, false);
}

#[test]
fn test_bpaf_should_fork_with_two_dashes() {
let args = bpaf_options()
.run_inner(&["--no-fork"])
.unwrap();
assert_eq!(args.should_fork, false);
}

#[test]
fn test_bpaf_should_fork_with_single_dash() {
let args = bpaf_options()
.run_inner(&["-no-fork"])
.unwrap();
assert_eq!(args.should_fork, false);
}

#[test]
fn test_bpaf_should_fork_fallback() {
let args = bpaf_options()
.run_inner(&[])
.unwrap();
assert_eq!(args.should_fork, true);
}

#[test]
fn test_separate_bpaf_time_with_two_dashes() {
let result = time_phases()
.to_options()
.run_inner(&["--time", "unknown"])
.unwrap();
assert_eq!(result, true);
}
}