yggdrasil/xtask/src/main.rs

150 lines
4.0 KiB
Rust
Raw Normal View History

2024-10-10 18:06:54 +03:00
// #![deny(warnings)]
2024-03-12 18:17:47 +02:00
use std::{fs, path::PathBuf, process::ExitCode};
2024-03-12 18:17:47 +02:00
use build::CheckAction;
use clap::{Parser, Subcommand};
use env::{Arch, Profile};
use error::Error;
#[macro_use]
pub mod util;
pub mod build;
pub mod check;
pub mod env;
pub mod error;
pub mod qemu;
#[derive(Parser)]
struct Args {
#[clap(long, env, help = "Use --release profile for built components")]
release: bool,
#[clap(
short,
long,
env,
default_value_t,
value_enum,
help = "Target architecture"
)]
arch: Arch,
#[clap(
short,
long,
help = "Do a clean userspace rebuild (e.g. toolchain has changed)"
)]
clean_userspace: bool,
#[clap(short, long, help = "Be verbose where possible")]
verbose: bool,
2024-03-12 18:17:47 +02:00
#[clap(
short = 'C',
long,
default_value = "xtask.toml",
help = "Configuration path"
)]
config_path: PathBuf,
2024-03-12 18:17:47 +02:00
#[clap(subcommand)]
action: Option<SubArgs>,
}
#[derive(Default, Subcommand)]
enum SubArgs {
#[default]
#[clap(about = "Build the OS")]
Build,
#[clap(about = "Run `cargo check` on components")]
Check,
#[clap(about = "Run `cargo clippy` on components")]
Clippy,
#[clap(about = "Run `cargo test` on components")]
Test,
#[clap(about = "Clean all build artifacts")]
Clean {
#[clap(short, long, help = "Clean toolchain as well")]
toolchain: bool,
},
// #[clap(about = "Print `git status` for the components", alias = "gst")]
// GitStatus,
#[clap(about = "Run the OS image in QEMU")]
Qemu {
#[clap(
short,
long,
env,
help = "Override the default QEMU binary for the target"
)]
qemu: Option<PathBuf>,
#[clap(help = "Extra arguments for QEMU")]
extra_args: Vec<String>,
},
#[clap(about = "Build the Yggdrasil OS Rust toolchain")]
Toolchain { branch: Option<String> },
2024-03-12 18:17:47 +02:00
#[clap(about = "Print the host triple")]
HostTriple,
}
fn run(args: Args) -> Result<(), Error> {
let action = args.action.unwrap_or_default();
let workspace_root = std::env::current_dir()?;
let profile = if args.release {
Profile::Release
} else {
Profile::Debug
};
2024-04-01 17:23:12 +03:00
let config = toml::from_str(&fs::read_to_string(&args.config_path)?)
.map_err(|e| Error::TomlParseError(args.config_path.clone(), e))?;
let env = env::BuildEnv::new(config, args.verbose, profile, args.arch, workspace_root);
2024-03-12 18:17:47 +02:00
if args.clean_userspace && !matches!(&action, SubArgs::Clean { .. }) {
build::clean_userspace(&env)?;
}
match action {
SubArgs::Build => build::build_all(env).map(|_| ()),
SubArgs::Check => build::check_all(env, CheckAction::Check),
SubArgs::Clippy => build::check_all(env, CheckAction::Clippy),
SubArgs::Test => build::test_all(env),
SubArgs::Clean { toolchain } => build::clean_all(&env, toolchain),
// SubArgs::GitStatus => util::git_status_all(&env),
SubArgs::Qemu { qemu, extra_args } => qemu::run(env, qemu, extra_args),
SubArgs::Toolchain { branch } => {
let branch = branch.as_ref().unwrap_or(&env.config.toolchain.branch);
build::build_toolchain(&env, branch)
}
2024-03-12 18:17:47 +02:00
SubArgs::HostTriple => {
println!("{}", env.host_triple);
Ok(())
}
}
}
fn main() -> ExitCode {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.parse_default_env()
.init();
let args = Args::parse();
match run(args) {
Ok(()) => ExitCode::SUCCESS,
Err(Error::MissingTools(list)) => {
eprintln!("Missing some required tools:");
for (tool, guide) in list {
eprintln!(" * {}: {}", tool, guide);
}
ExitCode::FAILURE
}
Err(err) => {
eprintln!("Error: {}", err);
ExitCode::FAILURE
}
}
}