Преглед на файлове

Merge pull request #49 from woshiluo/patch-1

feat(xtask): add xtask log
guttatus преди 3 месеца
родител
ревизия
1aae2a1e94
променени са 8 файла, в които са добавени 135 реда и са изтрити 37 реда
  1. 12 0
      Cargo.lock
  2. 2 0
      xtask/Cargo.toml
  3. 3 0
      xtask/src/bench.rs
  4. 55 0
      xtask/src/logger.rs
  5. 14 1
      xtask/src/main.rs
  6. 45 36
      xtask/src/prototyper.rs
  7. 3 0
      xtask/src/test.rs
  8. 1 0
      xtask/src/utils/envs.rs

+ 12 - 0
Cargo.lock

@@ -91,6 +91,16 @@ dependencies = [
  "clap_derive",
 ]
 
+[[package]]
+name = "clap-verbosity-flag"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2678fade3b77aa3a8ff3aae87e9c008d3fb00473a41c71fbf74e91c8c7b37e84"
+dependencies = [
+ "clap",
+ "log",
+]
+
 [[package]]
 name = "clap_builder"
 version = "4.5.23"
@@ -599,6 +609,8 @@ name = "xtask"
 version = "0.1.0"
 dependencies = [
  "clap",
+ "clap-verbosity-flag",
+ "log",
 ]
 
 [[package]]

+ 2 - 0
xtask/Cargo.toml

@@ -7,3 +7,5 @@ repository.workspace = true
 
 [dependencies]
 clap = { version = "4.5.4", features = ["derive", "env", "suggestions"] }
+log = "0.4.21"
+clap-verbosity-flag = "3.0.2"

+ 3 - 0
xtask/src/bench.rs

@@ -25,6 +25,7 @@ pub fn run(arg: &BenchArg) -> Option<ExitStatus> {
         .join(arch)
         .join("release");
 
+    info!("Building bench kernel");
     cargo::Cargo::new("build")
         .package("rustsbi-bench-kernel")
         .target(arch)
@@ -32,6 +33,7 @@ pub fn run(arg: &BenchArg) -> Option<ExitStatus> {
         .status()
         .ok()?;
 
+    info!("Copy to binary");
     let exit_status = Command::new("rust-objcopy")
         .args(["-O", "binary"])
         .arg("--binary-architecture=riscv64")
@@ -41,6 +43,7 @@ pub fn run(arg: &BenchArg) -> Option<ExitStatus> {
         .ok()?;
 
     if arg.pack {
+        info!("Pack to image");
         match fs::exists(target_dir.join("rustsbi-prototyper.bin")) {
             Ok(true) => {}
             Ok(false) => {

+ 55 - 0
xtask/src/logger.rs

@@ -0,0 +1,55 @@
+use log::Level;
+use std::io::Write;
+
+use crate::Cli;
+
+/// Simple logger implementation for RustSBI that supports colored output.
+pub struct Logger;
+
+impl Logger {
+    /// Initialize the logger with log level from RUST_LOG env var or default to Info.
+    pub fn init(cli: &Cli) -> Result<(), log::SetLoggerError> {
+        // Set max log level from parmas env var if present, otherwise use Info
+        log::set_max_level(cli.verbose.log_level_filter());
+        log::set_logger(&Logger)
+    }
+}
+
+impl log::Log for Logger {
+    // Always enable logging for all log levels
+    #[inline]
+    fn enabled(&self, _metadata: &log::Metadata) -> bool {
+        true
+    }
+
+    // Log messages with color-coded levels
+    #[inline]
+    fn log(&self, record: &log::Record) {
+        // ANSI color codes for different log levels
+        const ERROR_COLOR: u8 = 31; // Red
+        const WARN_COLOR: u8 = 93; // Bright yellow
+        const INFO_COLOR: u8 = 32; // Green
+        const DEBUG_COLOR: u8 = 36; // Cyan
+        const TRACE_COLOR: u8 = 90; // Bright black
+
+        let color_code = match record.level() {
+            Level::Error => ERROR_COLOR,
+            Level::Warn => WARN_COLOR,
+            Level::Info => INFO_COLOR,
+            Level::Debug => DEBUG_COLOR,
+            Level::Trace => TRACE_COLOR,
+        };
+
+        eprintln!(
+            "\x1b[1;37m[RustSBI-xtask] \x1b[1;{color_code}m{:^5}\x1b[0m - {}",
+            record.level(),
+            record.args(),
+        );
+    }
+
+    // No-op flush since we use println! which is already line-buffered
+    #[inline]
+    fn flush(&self) {
+        std::io::stderr().flush().expect("Unable to flush stderr");
+    }
+}

+ 14 - 1
xtask/src/main.rs

@@ -1,12 +1,17 @@
 use clap::{Parser, Subcommand};
+use clap_verbosity_flag::{InfoLevel, Verbosity};
 use std::process::ExitCode;
 
 #[macro_use]
 mod utils;
 mod bench;
+mod logger;
 mod prototyper;
 mod test;
 
+#[macro_use]
+extern crate log;
+
 use crate::bench::BenchArg;
 use crate::prototyper::PrototyperArg;
 use crate::test::TestArg;
@@ -20,6 +25,8 @@ use crate::test::TestArg;
 struct Cli {
     #[clap(subcommand)]
     cmd: Cmd,
+    #[command(flatten)]
+    verbose: Verbosity<InfoLevel>,
 }
 
 #[derive(Subcommand)]
@@ -30,14 +37,20 @@ enum Cmd {
 }
 
 fn main() -> ExitCode {
-    if let Some(code) = match Cli::parse().cmd {
+    let cli_args = Cli::parse();
+    logger::Logger::init(&cli_args).expect("Unable to init logger");
+
+    if let Some(code) = match cli_args.cmd {
         Cmd::Prototyper(ref arg) => prototyper::run(arg),
         Cmd::Test(ref arg) => test::run(arg),
         Cmd::Bench(ref arg) => bench::run(arg),
     } {
         if code.success() {
+            info!("Finished");
             return ExitCode::SUCCESS;
         }
     }
+
+    error!("Failed to run task!");
     ExitCode::FAILURE
 }

+ 45 - 36
xtask/src/prototyper.rs

@@ -18,6 +18,9 @@ pub struct PrototyperArg {
 
     #[clap(long, env = "PROTOTYPER_PAYLOAD_PATH")]
     pub payload: Option<String>,
+
+    #[clap(long, default_value = "INFO")]
+    pub log_level: String,
 }
 
 #[must_use]
@@ -34,58 +37,64 @@ pub fn run(arg: &PrototyperArg) -> Option<ExitStatus> {
         .join(arch)
         .join("release");
 
-    let status = cargo::Cargo::new("build")
+    info!("Building Protoyper");
+    cargo::Cargo::new("build")
         .package("rustsbi-prototyper")
         .target(arch)
         .unstable("build-std", ["core"])
         .env("RUSTFLAGS", "-C relocation-model=pie -C link-arg=-pie")
         .features(&arg.features)
         .optional(arg.fdt.is_some(), |cargo| {
-            export_env!("PROTOTYPER_FDT_PATH" ?= fdt.unwrap());
+            cargo.env("PROTOTYPER_FDT_PATH", fdt.as_ref().unwrap());
             cargo.features(["fdt".to_string()])
         })
         .optional(payload.is_some(), |cargo| {
-            export_env!("PROTOTYPER_PAYLOAD_PATH" ?= payload.unwrap());
+            cargo.env("PROTOTYPER_PAYLOAD_PATH", payload.as_ref().unwrap());
             cargo.features(["payload".to_string()])
         })
+        .env("RUST_LOG", &arg.log_level)
         .release()
         .status()
         .ok()?;
 
-    if status.success() {
-        let exit_status = Command::new("rust-objcopy")
-            .args(["-O", "binary"])
-            .arg("--binary-architecture=riscv64")
-            .arg(target_dir.join("rustsbi-prototyper"))
-            .arg(target_dir.join("rustsbi-prototyper.bin"))
-            .status()
-            .ok()?;
-
-        if arg.payload.is_some() {
-            fs::copy(
-                target_dir.join("rustsbi-prototyper"),
-                target_dir.join("rustsbi-prototyper-payload.elf"),
-            )
-            .ok()?;
-            fs::copy(
-                target_dir.join("rustsbi-prototyper.bin"),
-                target_dir.join("rustsbi-prototyper-payload.bin"),
-            )
-            .ok()?;
-        } else {
-            fs::copy(
-                target_dir.join("rustsbi-prototyper"),
-                target_dir.join("rustsbi-prototyper-dynamic.elf"),
-            )
-            .ok()?;
-            fs::copy(
-                target_dir.join("rustsbi-prototyper.bin"),
-                target_dir.join("rustsbi-prototyper-dynamic.bin"),
-            ).ok()?;
-        }
+    info!("Copy to binary");
+    let exit_status = Command::new("rust-objcopy")
+        .args(["-O", "binary"])
+        .arg("--binary-architecture=riscv64")
+        .arg(target_dir.join("rustsbi-prototyper"))
+        .arg(target_dir.join("rustsbi-prototyper.bin"))
+        .status()
+        .ok()?;
+    if !exit_status.success() {
+        error!("Failed to exec rust-objcopy, please check if cargo-binutils has been installed?");
         return Some(exit_status);
+    }
+
+    if arg.payload.is_some() {
+        info!("Copy for payload mode");
+        fs::copy(
+            target_dir.join("rustsbi-prototyper"),
+            target_dir.join("rustsbi-prototyper-payload.elf"),
+        )
+        .ok()?;
+        fs::copy(
+            target_dir.join("rustsbi-prototyper.bin"),
+            target_dir.join("rustsbi-prototyper-payload.bin"),
+        )
+        .ok()?;
     } else {
-        eprintln!("Build failed with status: {:?}", status);
-        return Some(status);
+        info!("Copy for dynamic mode");
+        fs::copy(
+            target_dir.join("rustsbi-prototyper"),
+            target_dir.join("rustsbi-prototyper-dynamic.elf"),
+        )
+        .ok()?;
+        fs::copy(
+            target_dir.join("rustsbi-prototyper.bin"),
+            target_dir.join("rustsbi-prototyper-dynamic.bin"),
+        )
+        .ok()?;
     }
+
+    Some(exit_status)
 }

+ 3 - 0
xtask/src/test.rs

@@ -25,6 +25,7 @@ pub fn run(arg: &TestArg) -> Option<ExitStatus> {
         .join(arch)
         .join("release");
 
+    info!("Building test kernel");
     cargo::Cargo::new("build")
         .package("rustsbi-test-kernel")
         .target(arch)
@@ -32,6 +33,7 @@ pub fn run(arg: &TestArg) -> Option<ExitStatus> {
         .status()
         .ok()?;
 
+    info!("Copy to binary");
     let exit_status = Command::new("rust-objcopy")
         .args(["-O", "binary"])
         .arg("--binary-architecture=riscv64")
@@ -41,6 +43,7 @@ pub fn run(arg: &TestArg) -> Option<ExitStatus> {
         .ok()?;
 
     if arg.pack {
+        info!("Pack to image");
         match fs::exists(target_dir.join("rustsbi-prototyper.bin")) {
             Ok(true) => {}
             Ok(false) => {

+ 1 - 0
xtask/src/utils/envs.rs

@@ -1,3 +1,4 @@
+#[allow(unused)]
 macro_rules! export_env {
     ($env:literal ?= $val:expr) => {
         if std::env::vars_os().all(|(k, _)| k != $env) {