Lot more brittle than I would like, can't really use cargo as a library (especially paired with guppy) but everything seems to be working well so far, and can finally start analyzing the data.
LOR3KOXGQ2VYGDHXQ6MG22ZME5TMPFTUW7A5OG36IAVQANOCXBRAC use std::io::{BufRead, BufReader};use std::process::{Command, Stdio};use cargo_metadata::{PackageId, Target};use serde::{Deserialize, Serialize};// Use an alternative profile so clean-building is "sandboxed" to this toolconst CARGO_CUSOTM_PROFILE: [&str; 2] = ["--config", r#"profile.depwiz.inherits="dev""#];/// See https://docs.rs/cargo/latest/cargo/core/compiler/enum.CompileMode.html/// These are the only two cases we are interested in#[derive(Clone, Debug, Serialize, Deserialize)]#[serde(rename_all = "kebab-case")]enum Mode {Build,RunCustomBuild,}/// See https://docs.rs/cargo/latest/cargo/util/machine_message/struct.TimingInfo.html#[derive(Clone, Debug, Serialize, Deserialize)]pub struct Message {reason: String,package_id: PackageId,target: Target,mode: Mode,duration: f64,rmeta_time: Option<f64>,}pub fn generate() -> Vec<Message> {// TODO: `cargo build --timings=json` seems to only work on a clean buildCommand::new("cargo").arg("clean").args(CARGO_CUSOTM_PROFILE).args(&["--profile", "depwiz"]).stdout(Stdio::inherit()).stderr(Stdio::inherit()).output().unwrap();let timings_ouput = Command::new("cargo").arg("build").args(CARGO_CUSOTM_PROFILE).args(&["--profile","depwiz","-Zunstable-options","--timings=json",]).stderr(Stdio::inherit()).output().unwrap();let mut timings = Vec::new();let mut timings_buffer = BufReader::new(timings_ouput.stdout.as_slice());let mut message_buffer = Vec::new();loop {timings_buffer.read_until(b'\n', &mut message_buffer).unwrap();let json_message: Message = match serde_json::from_slice(&message_buffer) {Ok(message) => message,Err(err) => {use serde_json::error::Category;match err.classify() {Category::Eof => break,Category::Data => todo!("JSON object not properly handled, got `{err:?}` for message: `{}`",String::from_utf8(message_buffer.clone()).unwrap()),_ => {panic!("Unexpected error while parsing: {err:?}");}}}};// Make sure it's actually a timings messageassert_eq!(json_message.reason, "timing-info");timings.push(json_message);message_buffer.clear();}timings}
serde = { version = "1.0.198", features = ["serde_derive"] }serde_json = "1.0.116"