1use anyhow::Result;2use clap::Parser;3use xshell::{cmd, Shell};45mod sourcegen;67#[derive(Parser)]8enum Opts {9 10 Sourcegen,11 12 Profile {13 #[arg(long, default_value = "true")]14 hyperfine: bool,15 #[arg(long)]16 callgrind: bool,17 #[arg(long)]18 cachegrind: bool,19 #[arg(long, default_value = env!("TARGET_PLATFORM"))]20 target: String,21 args: Vec<String>,22 },23 24 Lint {25 26 #[arg(long)]27 fix: bool,28 },29 30 TestCBindings {31 #[arg(long, default_value = env!("TARGET_PLATFORM"))]32 target: String,33 34 #[arg(long, default_value = "libjsonnet_test_file")]35 test_file: String,36 args: Vec<String>,37 },38 39 UpdateTestsuites,40}4142fn main() -> Result<()> {43 let sh = Shell::new()?;44 match Opts::parse() {45 Opts::Sourcegen => sourcegen::generate_ungrammar(),46 Opts::Profile {47 hyperfine,48 callgrind,49 cachegrind,50 args,51 target,52 } => {53 let out = sh.create_temp_dir()?;5455 cmd!(sh, "cargo build --target={target} --profile releasedebug").run()?;56 let built = format!("./target/{target}/releasedebug/jrsonnet");57 let bench_cmd = format!("{built} {}", args.join(" "));58 if hyperfine {59 cmd!(sh, "hyperfine {bench_cmd}").run()?;60 }61 if callgrind {62 let args = args.clone();63 let mut callgrind_out = out.path().to_owned();64 callgrind_out.push("callgrind.out.1");65 cmd!(sh, "valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --callgrind-out-file={callgrind_out} {built} {args...}").run()?;66 cmd!(sh, "kcachegrind {callgrind_out}").run()?;67 }68 if cachegrind {69 let mut cachegrind_out = out.path().to_owned();70 cachegrind_out.push("cachegrind.out.1");71 cmd!(sh, "valgrind --tool=cachegrind --cachegrind-out-file={cachegrind_out} {built} {args...}").run()?;72 cmd!(sh, "kcachegrind {cachegrind_out}").run()?;73 }7475 Ok(())76 }77 Opts::Lint { fix } => {78 let fmt_check = if fix { None } else { Some("--check") };79 cmd!(sh, "cargo fmt {fmt_check...}").run()?;80 Ok(())81 }82 Opts::TestCBindings {83 target,84 test_file,85 args,86 } => {87 cmd!(88 sh,89 "cargo build -p libjsonnet --target={target} --release --no-default-features --features=interop-common,interop-threading"90 )91 .run()?;92 let built = format!("./target/{target}/release/libjsonnet.a");93 let c_bindings = "./bindings/c/";94 cmd!(sh, "cp {built} {c_bindings}").run()?;95 sh.change_dir(c_bindings);9697 98 cmd!(sh, "gcc -c {test_file}.c").run()?;99 cmd!(sh, "gcc -o {test_file} -lc -lm {test_file}.o libjsonnet.a").run()?;100 let sh = Shell::new()?;101102 cmd!(sh, "{c_bindings}{test_file} {args...}").run()?;103104 Ok(())105 }106 Opts::UpdateTestsuites => {107 let _pushd = sh.push_dir("tests");108 let git_dir = sh.create_temp_dir()?;109 let git_dir_path = git_dir.path();110 cmd!(111 sh,112 "git clone https://github.com/google/jsonnet.git --depth=1 {git_dir_path}/jsonnet"113 )114 .run()?;115 cmd!(116 sh,117 "git clone https://github.com/google/go-jsonnet.git --depth=1 {git_dir_path}/go-jsonnet"118 )119 .run()?;120 sh.remove_path("cpp_test_suite")?;121 sh.remove_path("go_testdata")?;122 cmd!(sh, "mv {git_dir_path}/jsonnet/test_suite cpp_test_suite").run()?;123 cmd!(sh, "mv {git_dir_path}/go-jsonnet/testdata go_testdata").run()?;124125 Ok(())126 }127 }128}