blob: 095dc6105554860aae840d3fec5e332ef88d5b3f [file] [log] [blame]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::{
ffi::{OsStr, OsString},
fs::File,
io::{BufRead, BufReader},
path::{Path, PathBuf},
sync::OnceLock,
};
use anyhow::{Context, Result};
use clap::Parser;
use commands::{archive_logs::archive_logs, prebuilts::compute_prebuilts};
use processors::build_event::BuildEventProcessor;
use proto::build_event_stream::BuildEvent;
mod commands;
mod processors;
mod proto;
/// Loads a newline-deliminated JSON file containing Build Event Protocol data.
fn load_build_events_jsonl(path: &Path) -> Result<Vec<BuildEvent>> {
let f = File::open(path).with_context(|| format!("Failed to open {}", path.display()))?;
let f = BufReader::new(f);
let mut events: Vec<BuildEvent> = Vec::new();
for (i, line) in f.lines().enumerate() {
let line = line.with_context(|| format!("Failed to parse {}", path.display()))?;
let event = serde_json::from_str(&line)
.with_context(|| format!("Failed to parse {}: line {}", path.display(), i + 1))?;
events.push(event);
}
Ok(events)
}
fn get_default_workspace_dir() -> &'static OsStr {
static CACHE: OnceLock<OsString> = OnceLock::new();
CACHE.get_or_init(|| std::env::var_os("BUILD_WORKSPACE_DIRECTORY").unwrap_or(".".into()))
}
/// Bazel build result postprocessor.
///
/// This program is responsible for translating build artifacts left in bazel-out/ to files that
/// can be interpreted by other programs outside of //bazel. Since bazel-out/ contains a lot of
/// implementation details internal to //bazel, external programs should not try to interpret them;
/// otherwise they can break for subtle changes to the internal layout. This program works as
/// the bridge for the API boundary.
#[derive(Parser, Debug)]
struct Args {
/// Path to the Build Event Protocol JSONL file.
#[arg(long, required = true)]
build_events_jsonl: PathBuf,
/// Path to the Bazel workspace where bazel-* symlinks are located.
/// [default: $BUILD_WORKSPACE_DIRECTORY]
#[arg(long, default_value = get_default_workspace_dir(), hide_default_value = true)]
workspace: PathBuf,
/// If set, creates a tarball containing all logs created in the build to this file path.
/// Compression algorithm is selected by the file name extension (using GNU tar's
/// --auto-compress option).
#[arg(long)]
archive_logs: Option<PathBuf>,
/// If set, a .bzl file will be generated that contains --@portage//<package>_prebuilt
/// flags pointing to the CAS for the packages specified in the BEP file..
#[arg(long)]
prebuilts: Option<PathBuf>,
}
fn main() -> Result<()> {
let args = Args::parse();
let events = load_build_events_jsonl(&args.build_events_jsonl)?;
let processor = BuildEventProcessor::from(&events);
if let Some(output_path) = &args.archive_logs {
archive_logs(output_path, &args.workspace, &processor)?;
}
if let Some(output_path) = &args.prebuilts {
compute_prebuilts(output_path, &args.workspace, &processor)?;
}
Ok(())
}