1use anyhow::Result;2use clap::Parser;3use xshell::{Shell, cmd};45#[cfg(all(target_arch = "x86_64", target_os = "linux"))]6mod bench;7mod sourcegen;89#[derive(Parser)]10enum Opts {11 12 Sourcegen,13 14 Profile {15 #[arg(long, default_value = "true")]16 hyperfine: bool,17 #[arg(long)]18 callgrind: bool,19 #[arg(long)]20 cachegrind: bool,21 #[arg(long, default_value = env!("TARGET_PLATFORM"))]22 target: String,23 args: Vec<String>,24 },25 26 Lint {27 28 #[arg(long)]29 fix: bool,30 },31 32 TestCBindings {33 #[arg(long, default_value = env!("TARGET_PLATFORM"))]34 target: String,35 36 #[arg(long, default_value = "libjsonnet_test_file")]37 test_file: String,38 args: Vec<String>,39 },40 41 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]42 Bench {43 #[arg(long, default_value_t = 10)]44 runs: u32,45 #[arg(long, default_value_t = 1)]46 warmup: u32,47 48 #[arg(long, short = 'q')]49 output: bool,50 #[arg(trailing_var_arg = true, required = true)]51 args: Vec<String>,52 },53}5455fn main() -> Result<()> {56 let sh = Shell::new()?;57 match Opts::parse() {58 Opts::Sourcegen => sourcegen::generate_ungrammar(),59 Opts::Profile {60 hyperfine,61 callgrind,62 cachegrind,63 args,64 target,65 } => {66 let out = sh.create_temp_dir()?;6768 cmd!(sh, "cargo build --target={target} --profile releasedebug").run()?;69 let built = format!("./target/{target}/releasedebug/jrsonnet");70 let bench_cmd = format!("{built} {}", args.join(" "));71 if hyperfine {72 cmd!(sh, "hyperfine {bench_cmd}").run()?;73 }74 if callgrind {75 let args = args.clone();76 let mut callgrind_out = out.path().to_owned();77 callgrind_out.push("callgrind.out.1");78 cmd!(sh, "valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --callgrind-out-file={callgrind_out} {built} {args...}").run()?;79 cmd!(sh, "kcachegrind {callgrind_out}").run()?;80 }81 if cachegrind {82 let mut cachegrind_out = out.path().to_owned();83 cachegrind_out.push("cachegrind.out.1");84 cmd!(85 sh,86 "valgrind --tool=cachegrind --cachegrind-out-file={cachegrind_out} {built} {args...}"87 )88 .run()?;89 cmd!(sh, "kcachegrind {cachegrind_out}").run()?;90 }9192 Ok(())93 }94 Opts::Lint { fix } => {95 let fmt_check = if fix { None } else { Some("--check") };96 cmd!(sh, "cargo fmt {fmt_check...}").run()?;97 Ok(())98 }99 Opts::TestCBindings {100 target,101 test_file,102 args,103 } => {104 cmd!(105 sh,106 "cargo build -p libjsonnet --target={target} --release --no-default-features --features=interop-common,interop-threading"107 )108 .run()?;109 let built = format!("./target/{target}/release/libjsonnet.a");110 let c_bindings = "./bindings/c/";111 cmd!(sh, "cp {built} {c_bindings}").run()?;112 sh.change_dir(c_bindings);113114 115 cmd!(sh, "gcc -c {test_file}.c").run()?;116 cmd!(sh, "gcc -o {test_file} -lc -lm {test_file}.o libjsonnet.a").run()?;117 let sh = Shell::new()?;118119 cmd!(sh, "{c_bindings}{test_file} {args...}").run()?;120121 Ok(())122 }123 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]124 Opts::Bench {125 runs,126 warmup,127 output,128 args,129 } => bench::bench_cmd(&args, runs, warmup, output),130 }131}