use cargo_metadata::diagnostic::DiagnosticLevel; use cargo_metadata::Message; use std::error::Error; use std::process::Command; pub fn run_cargo( cargo_command: &str, sub_command: &str, params: &[&str], mut message_handler: impl FnMut(&cargo_metadata::Message) -> Result<(), Box>, ) -> Result> { let mut cmd = Command::new(cargo_command) .arg(sub_command) .arg("--message-format=json") .args(params) .stdout(std::process::Stdio::piped()) .spawn() .unwrap(); let reader = std::io::BufReader::new(cmd.stdout.take().unwrap()); for message in cargo_metadata::Message::parse_stream(reader) { message_handler(&message.unwrap())?; } Ok(cmd.wait()?) } pub fn native_library_dependencies( cargo_command: &str, build_params: &[&str], package: &str, ) -> Result> { let mut native_library_dependencies = String::new(); let mut libs_params = vec!["-p", package]; libs_params.extend(build_params); libs_params.extend(["--", "--print=native-static-libs"].iter()); run_cargo(cargo_command, "rustc", &libs_params, |message| { match message { Message::CompilerMessage(msg) => { let message = &msg.message; const NATIVE_LIBS_PREFIX: &str = "native-static-libs:"; if matches!(message.level, DiagnosticLevel::Note) && message.message.starts_with(NATIVE_LIBS_PREFIX) { let native_libs = message.message[NATIVE_LIBS_PREFIX.len()..].trim(); native_library_dependencies.push_str(native_libs.into()); native_library_dependencies.push_str(" "); } } _ => (), } Ok(()) })?; Ok(native_library_dependencies.trim().into()) } pub struct TestCase { pub source: String, pub path: std::path::PathBuf, } pub fn collect_test_cases() -> std::io::Result> { let mut results = vec![]; for entry in std::fs::read_dir(format!("{}/../cases", env!("CARGO_MANIFEST_DIR")))? { let entry = entry?; let path = entry.path(); if let Some(ext) = path.extension() { if ext == "60" { let source = std::fs::read_to_string(&path)?; results.push(TestCase { source, path }); } } } Ok(results) }