From acbcb0cb129d570946d4b0a3d761c77e560a73db Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 17 Aug 2020 19:42:39 +0800 Subject: [PATCH] xtask: add `cargo xtask` command This command can be used to build a full image. Signed-off-by: Sean Cross --- .cargo/config | 2 + xtask/Cargo.toml | 9 +++ xtask/src/main.rs | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 .cargo/config create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 000000000..35049cbcb --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 000000000..4eb0dcbd6 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "xtask" +version = "0.1.0" +authors = ["Sean Cross "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 000000000..2d032df9b --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,137 @@ +use std::{ + env, fs, + path::{Path, PathBuf}, + process::Command, +}; + +type DynError = Box; + +const TARGET: &str = "riscv32imac-unknown-none-elf"; + +#[derive(Debug)] +enum BuildError { + PathConversionError, +} + +impl std::fmt::Display for BuildError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + BuildError::PathConversionError => write!(f, "could not convert path to UTF-8"), + } + } +} + +impl std::error::Error for BuildError {} + +fn main() { + if let Err(e) = try_main() { + eprintln!("{}", e); + std::process::exit(-1); + } +} + +fn try_main() -> Result<(), DynError> { + let task = env::args().nth(1); + match task.as_deref() { + Some("image") => image()?, + _ => print_help(), + } + Ok(()) +} + +fn print_help() { + eprintln!( + "Tasks: +renode-image builds a test image for renode +" + ) +} + +fn image() -> Result<(), DynError> { + let debug = false; + let _ = fs::remove_dir_all(&dist_dir()); + fs::create_dir_all(&dist_dir())?; + + let kernel = build_kernel(debug)?; + let mut init = vec![]; + for pkg in &["shell", "log-server", "graphics-server"] { + init.push(build(pkg, debug, None)?); + } + + create_image(&kernel, &init, debug)?; + + Ok(()) +} + +fn build_kernel(debug: bool) -> Result { + build("kernel", debug, Some("kernel".into())) +} + +fn build(project: &str, debug: bool, directory: Option) -> Result { + let stream = if debug { "debug" } else { "release" }; + let mut args = vec!["build", "--target", TARGET, "--package", project]; + if !debug { + args.push("--release"); + } + + let mut dir = project_root(); + if let Some(subdir) = directory { + dir.push(subdir); + } + + let status = Command::new(cargo()) + .current_dir(dir) + .args(&args) + .status()?; + + if !status.success() { + return Err("cargo build failed".into()); + } + + Ok(project_root().join(&format!("target/{}/{}/{}", TARGET, stream, project))) +} + +fn create_image(kernel: &Path, init: &[PathBuf], debug: bool) -> Result { + let stream = if debug { "debug" } else { "release" }; + let mut args = vec!["run", "--package", "tools", "--bin", "create-image", "--"]; + + let output_file = format!("target/{}/{}/args.bin", TARGET, stream); + args.push(&output_file); + + args.push("--kernel"); + args.push(kernel.to_str().ok_or(BuildError::PathConversionError)?); + + for i in init { + args.push("--init"); + args.push(i.to_str().ok_or(BuildError::PathConversionError)?); + } + + args.push("--csv"); + args.push("emulation/csr.csv"); + + let status = Command::new(cargo()) + .current_dir(project_root()) + .args(&args) + .status()?; + + if !status.success() { + return Err("cargo build failed".into()); + } + Ok(project_root().join(&format!("target/{}/{}/args.bin", TARGET, stream))) +} + +fn cargo() -> String { + env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) +} + +fn project_root() -> PathBuf { + Path::new(&env!("CARGO_MANIFEST_DIR")) + .ancestors() + .nth(1) + .unwrap() + .to_path_buf() +} + +fn dist_dir() -> PathBuf { + project_root().join("target/dist") +}