// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![forbid(unsafe_op_in_unsafe_fn)]
#![forbid(unsafe_code)]
mod add;
mod gen;
mod update;
mod util;
mod vendor;
use anyhow::{Context, Result};
use clap::{arg, command, Parser, Subcommand};
use gnrt_lib::*;
#[derive(Debug, Parser)]
struct GnrtArgs {
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
#[command(about = "Add a new third-party crate dependency in //third_party/rust")]
Add(AddCommandArgs),
#[command(about = "Generate GN build rules from third_party/rust crates")]
Gen(GenCommandArgs),
#[command(about = "Update the Cargo.lock to newer versions for //third_party/rust")]
Update(UpdateCommandArgs),
#[command(about = "Download all third-party crate dependencies in //third_party/rust")]
Vendor(VendorCommandArgs),
}
#[derive(Debug, Parser)]
struct AddCommandArgs {
#[arg(name = "OPTIONS", help = "Options to pass through to 'cargo add'")]
passthrough: Vec<String>,
}
#[derive(Debug, Parser)]
struct GenCommandArgs {
#[arg(
long,
name = "RUST_SRC_ROOT",
help = " \
Generate build files for Rust std library. RUST_SRC_ROOT (relative to \
the root of the Chromium repo) must point to the Rust checkout to \
generate build files for. It must have vendored dependencies. \
Generated paths are rewritten to point into the toolchain package, as \
if generated by package_rust.py."
)]
for_std: Option<String>,
#[arg(
long,
help = " \
Exit before writing BUILD.gn files, instead serialize the template \
engine input and write it to a file (or files) named `gnrt-template-input.json`."
)]
dump_template_input: bool,
}
#[derive(Debug, Parser)]
struct UpdateCommandArgs {
#[arg(name = "OPTIONS", help = "Options to pass through to 'cargo update'")]
passthrough: Vec<String>,
}
#[derive(Debug, Parser)]
struct VendorCommandArgs {
#[arg(
long,
name = "CRATE_NAME",
num_args = 0..,
help = "\
Don't apply patches from the chromium_crates_io/patches directory \
to newly vendored crates. If a crate name is given as a value for the \
flag, patches will only not be applied for that crate."
)]
no_patches: Option<Vec<String>>,
#[arg(
long,
help = " \
Exit before writing README.chromium files, instead serialize the template \
engine input and write it to files named `gnrt-template-input.json`."
)]
dump_template_input: bool,
}
fn main() -> Result<()> {
let mut logger_builder = env_logger::Builder::new();
logger_builder.write_style(env_logger::WriteStyle::Always);
logger_builder.filter(None, log::LevelFilter::Warn);
logger_builder.parse_default_env();
logger_builder.format(format_log_entry);
logger_builder.init();
let args = GnrtArgs::parse();
let paths = paths::ChromiumPaths::new().context("Could not find chromium checkout paths")?;
match args.command {
Command::Add(args) => add::add(args, &paths),
Command::Gen(args) => gen::generate(args, &paths),
Command::Update(args) => update::update(args, &paths),
Command::Vendor(args) => vendor::vendor(args, &paths),
}
}
fn format_log_entry(
fmt: &mut env_logger::fmt::Formatter,
record: &log::Record,
) -> std::io::Result<()> {
use std::io::Write;
let level = fmt.default_styled_level(record.level());
write!(fmt, "[{level}")?;
if let Some(f) = record.file() {
write!(fmt, " {f}")?;
if let Some(l) = record.line() {
write!(fmt, ":{l}")?;
}
}
writeln!(fmt, "] {msg}", msg = record.args())
}