// 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 download; mod gen; mod util; use anyhow::{Context, Result}; use clap::{arg, Arg}; use gnrt_lib::*; 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 = clap::Command::new("gnrt") .subcommand( clap::Command::new("gen") .about("Generate GN build rules from third_party/rust crates") .arg(arg!(--"output-cargo-toml" "Output third_party/rust/Cargo.toml then exit \ immediately")) .arg( Arg::new("cargo-path") .long("cargo-path") .value_name("CARGO_PATH") .value_parser(clap::value_parser!(String)) .num_args(1) .help("Path to the cargo executable"), ) .arg( Arg::new("rustc-path") .long("rustc-path") .value_name("RUSTC_PATH") .value_parser(clap::value_parser!(String)) .num_args(1) .help("Path to the rustc executable"), ) .arg( Arg::new("for-std") .long("for-std") .value_parser(clap::value_parser!(String)) .value_name("RUST_SRC_ROOT") .num_args(1) .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.", ), ), ) .subcommand( clap::Command::new("download") .about("Download the crate with the given name and version to third_party/rust.") .arg(arg!( "Name of the crate to download")) .arg( arg!( "Version of the crate to download") .value_parser(clap::value_parser!(semver::Version)), ) .arg( arg!(--"security-critical" "Whether the crate is considered to be \ security critical." ) .value_parser(["yes", "no"]) .required(true), ) .arg( arg!(--"shipped" "Whether the crate contributes to code shipped to \ users." ) .value_parser(["yes", "no"]) .required(true), ), ) .get_matches(); let paths = paths::ChromiumPaths::new().context("Could not find chromium checkout paths")?; match args.subcommand() { Some(("gen", args)) => gen::generate(args, &paths), Some(("download", args)) => { let security = download::SecurityCritical::from( args.get_one::("security-critical").unwrap() == "yes", ); let shipped = download::Shipped::from(args.get_one::("shipped").unwrap() == "yes"); let name = args.get_one::("name").unwrap(); let version = args.get_one::("version").unwrap().clone(); download::download(name, version, security, shipped, &paths) } _ => unreachable!("Invalid subcommand"), } } 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()) }