From 3fcc1f42f311016f1cc7633dfb0dcd94e9de11d2 Mon Sep 17 00:00:00 2001 From: YdrMaster Date: Thu, 12 May 2022 22:04:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(xtask):=20=E4=B8=8B=E8=BD=BD=20rustsbi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xtask/src/arch.rs | 124 +++++++++++++++++++++---------------- xtask/src/command/cargo.rs | 24 ++----- xtask/src/command/git.rs | 24 ++----- xtask/src/command/make.rs | 16 +---- xtask/src/command/mod.rs | 41 +++++++----- xtask/src/command/qemu.rs | 17 +++++ xtask/src/command/tar.rs | 16 +---- xtask/src/main.rs | 12 ++-- 8 files changed, 134 insertions(+), 140 deletions(-) create mode 100644 xtask/src/command/qemu.rs diff --git a/xtask/src/arch.rs b/xtask/src/arch.rs index 22547143..5589eed8 100644 --- a/xtask/src/arch.rs +++ b/xtask/src/arch.rs @@ -1,7 +1,7 @@ //! 平台相关的操作。 use crate::{ - command::{dir, download::wget, Cargo, CommandExt, Ext, Make, Tar}, + command::{dir, download::wget, Cargo, CommandExt, Ext, Make, Qemu, Tar}, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE, }; use dircpy::copy_dir; @@ -14,24 +14,24 @@ use std::{ }; #[derive(Args)] -pub(super) struct Arch { +pub(crate) struct ArchArg { #[clap(subcommand)] - command: ArchCommands, + arch: Arch, } -#[derive(Subcommand)] -enum ArchCommands { +#[derive(Subcommand, Clone, Copy)] +pub(crate) enum Arch { #[clap(name = "riscv64")] Riscv64, #[clap(name = "x86_64")] X86_64, } -impl ArchCommands { - const fn as_str(&self) -> &'static str { +impl Arch { + pub const fn as_str(&self) -> &'static str { match self { - ArchCommands::Riscv64 => "riscv64", - ArchCommands::X86_64 => "x86_64", + Arch::Riscv64 => "riscv64", + Arch::X86_64 => "x86_64", } } @@ -65,13 +65,13 @@ impl ArchCommands { } } -impl Arch { +impl ArchArg { /// 构造启动内存文件系统 rootfs。 /// 对于 x86_64,这个文件系统可用于 libos 启动。 /// 若设置 `clear`,将清除已存在的目录。 pub fn rootfs(&self, clear: bool) { // 若已存在且不需要清空,可以直接退出 - let dir = self.command.rootfs(); + let dir = self.arch.rootfs(); if dir.is_dir() && !clear { return; } @@ -84,10 +84,10 @@ impl Arch { // 拷贝 busybox fs::copy(src.join("bin/busybox"), dir.join("bin/busybox")).unwrap(); // 拷贝 libc.so - let libc_so = format!("lib/ld-musl-{arch}.so.1", arch = self.command.as_str()); - let so = match self.command { - ArchCommands::Riscv64 => src.join(&libc_so), - ArchCommands::X86_64 => PathBuf::from("prebuilt/linux/libc-libos.so"), + let libc_so = format!("lib/ld-musl-{arch}.so.1", arch = self.arch.as_str()); + let so = match self.arch { + Arch::Riscv64 => src.join(&libc_so), + Arch::X86_64 => PathBuf::from("prebuilt/linux/libc-libos.so"), }; fs::copy(so, dir.join(libc_so)).unwrap(); // 为常用功能建立符号链接 @@ -107,28 +107,28 @@ impl Arch { // 递归 rootfs self.rootfs(false); // 拷贝仓库 - let dir = self.command.libc_test(); + let dir = self.arch.libc_test(); dir::rm(&dir).unwrap(); copy_dir("libc-test", &dir).unwrap(); // 编译 fs::copy(dir.join("config.mak.def"), dir.join("config.mak")).unwrap(); - match self.command { - ArchCommands::Riscv64 => { + match self.arch { + Arch::Riscv64 => { Make::new(None) - .env("ARCH", self.command.as_str()) + .env("ARCH", self.arch.as_str()) .env("CROSS_COMPILE", "riscv64-linux-musl-") .env("PATH", riscv64_linux_musl_cross()) .current_dir(&dir) .invoke(); fs::copy( - self.command + self.arch .target() .join("rootfs/libc-test/functional/tls_align-static.exe"), dir.join("src/functional/tls_align-static.exe"), ) .unwrap(); } - ArchCommands::X86_64 => { + Arch::X86_64 => { fs::OpenOptions::new() .append(true) .open(dir.join("config.mak")) @@ -144,13 +144,13 @@ impl Arch { pub fn other_test(&self) { // 递归 rootfs self.rootfs(false); - let rootfs = self.command.rootfs(); - match self.command { - ArchCommands::Riscv64 => { - let target = self.command.target(); + let rootfs = self.arch.rootfs(); + match self.arch { + Arch::Riscv64 => { + let target = self.arch.target(); copy_dir(target.join("rootfs/oscomp"), rootfs.join("oscomp")).unwrap(); } - ArchCommands::X86_64 => { + Arch::X86_64 => { let bin = rootfs.join("bin"); fs::read_dir("linux-syscall/test") .unwrap() @@ -173,17 +173,17 @@ impl Arch { pub fn image(&self) { // 递归 rootfs self.rootfs(false); - let arch_str = self.command.as_str(); - let image = match self.command { - ArchCommands::Riscv64 => { + let arch_str = self.arch.as_str(); + let image = match self.arch { + Arch::Riscv64 => { let rootfs = format!("rootfs/{arch_str}"); let image = format!("zCore/{arch_str}.img"); fuse(rootfs, &image); image } - ArchCommands::X86_64 => { - let target = self.command.target(); - let rootfs = self.command.rootfs(); + Arch::X86_64 => { + let target = self.arch.target(); + let rootfs = self.arch.rootfs(); fs::copy( target.join("rootfs/lib/ld-musl-x86_64.so.1"), rootfs.join("lib/ld-musl-x86_64.so.1"), @@ -202,7 +202,7 @@ impl Arch { image } }; - Ext::new("qemu-img") + Qemu::img() .arg("resize") .args(&["-f", "raw"]) .arg(image) @@ -212,9 +212,10 @@ impl Arch { /// 在 qemu 中启动。 pub fn qemu(&self) { + // 递归 image self.image(); - match self.command { - ArchCommands::Riscv64 => { + match self.arch { + Arch::Riscv64 => { Cargo::build() .package("zcore") .features(false, &["linux", "board-qemu"]) @@ -229,10 +230,11 @@ impl Arch { .arg("--strip-all") .args(&["-O", "binary", "target/riscv64/release/zcore.bin"]) .invoke(); - Ext::new("qemu-system-riscv64") + Qemu::system(self.arch) .args(&["-smp", "1"]) .args(&["-machine", "virt"]) - .args(&["-bios", "default"]) + .arg("-bios") + .arg(rustsbi_qemu()) .args(&["-m", "512M"]) .args(&["-serial", "mon:stdio"]) .args(&["-kernel", "target/riscv64/release/zcore.bin"]) @@ -243,33 +245,33 @@ impl Arch { .arg("-nographic") .invoke(); } - ArchCommands::X86_64 => todo!(), + Arch::X86_64 => todo!(), } } /// 下载并解压 minirootfs。 fn prebuild_rootfs(&self) -> PathBuf { // 构造压缩文件路径 - let file_name = match self.command { - ArchCommands::Riscv64 => "minirootfs.tar.xz", - ArchCommands::X86_64 => "minirootfs.tar.gz", + let file_name = match self.arch { + Arch::Riscv64 => "minirootfs.tar.xz", + Arch::X86_64 => "minirootfs.tar.gz", }; - let tar = self.command.origin().join(file_name); + let tar = self.arch.origin().join(file_name); // 若压缩文件不存在,需要下载 if !tar.exists() { - let url = match self.command { - ArchCommands::Riscv64 => String::from("https://github.com/rcore-os/libc-test-prebuilt/releases/download/0.1/prebuild.tar.xz"), - ArchCommands::X86_64 => format!("{ALPINE_WEBSITE}/x86_64/alpine-minirootfs-{ALPINE_ROOTFS_VERSION}-x86_64.tar.gz"), + let url = match self.arch { + Arch::Riscv64 => String::from("https://github.com/rcore-os/libc-test-prebuilt/releases/download/0.1/prebuild.tar.xz"), + Arch::X86_64 => format!("{ALPINE_WEBSITE}/x86_64/alpine-minirootfs-{ALPINE_ROOTFS_VERSION}-x86_64.tar.gz"), }; wget(url, &tar); } // 解压到目标路径 - let dir = self.command.target().join("rootfs"); + let dir = self.arch.target().join("rootfs"); dir::clear(&dir).unwrap(); let mut tar = Tar::xf(&tar, Some(&dir)); - match self.command { - ArchCommands::Riscv64 => tar.args(&["--strip-components", "1"]).invoke(), - ArchCommands::X86_64 => tar.invoke(), + match self.arch { + Arch::Riscv64 => tar.args(&["--strip-components", "1"]).invoke(), + Arch::X86_64 => tar.invoke(), } dir } @@ -279,14 +281,14 @@ impl Arch { fn riscv64_linux_musl_cross() -> OsString { const NAME: &str = "riscv64-linux-musl-cross"; - let origin = ArchCommands::Riscv64.origin(); - let target = ArchCommands::Riscv64.target(); + let origin = Arch::Riscv64.origin(); + let target = Arch::Riscv64.target(); let tgz = origin.join(format!("{NAME}.tgz")); let dir = target.join(NAME); dir::rm(&dir).unwrap(); - wget(&format!("https://musl.cc/{NAME}.tgz"), &tgz); + wget(format!("https://musl.cc/{NAME}.tgz"), &tgz); Tar::xf(&tgz, Some(target)).invoke(); // 将交叉工具链加入 PATH 环境变量 @@ -321,3 +323,21 @@ fn fuse(dir: impl AsRef, image: impl AsRef) { .expect("failed to create sfs"); zip_dir(dir.as_ref(), fs.root_inode()).expect("failed to zip fs"); } + +fn rustsbi_qemu() -> PathBuf { + const NAME: &str = "rustsbi-qemu-release"; + + let origin = Arch::Riscv64.origin(); + let target = Arch::Riscv64.target(); + + let zip = origin.join(format!("{NAME}.zip")); + let dir = target.join(NAME); + let url = + format!("https://github.com/rustsbi/rustsbi-qemu/releases/download/v0.1.1/{NAME}.zip"); + + dir::rm(&dir).unwrap(); + wget(url, &zip); + Ext::new("unzip").arg("-d").arg(&dir).arg(zip).invoke(); + + dir.join("rustsbi-qemu.bin") +} diff --git a/xtask/src/command/cargo.rs b/xtask/src/command/cargo.rs index 7292b032..0a253c50 100644 --- a/xtask/src/command/cargo.rs +++ b/xtask/src/command/cargo.rs @@ -1,29 +1,13 @@ -use super::CommandExt; +use super::{ext, CommandExt}; use std::{ffi::OsStr, process::Command}; -pub(crate) struct Cargo { - cmd: Command, -} +pub(crate) struct Cargo(Command); -impl AsRef for Cargo { - fn as_ref(&self) -> &Command { - &self.cmd - } -} - -impl AsMut for Cargo { - fn as_mut(&mut self) -> &mut Command { - &mut self.cmd - } -} - -impl CommandExt for Cargo {} +ext!(Cargo); impl Cargo { fn new(sub: &(impl AsRef + ?Sized)) -> Self { - let mut git = Self { - cmd: Command::new("cargo"), - }; + let mut git = Self(Command::new("cargo")); git.arg(sub); git } diff --git a/xtask/src/command/git.rs b/xtask/src/command/git.rs index c555192e..965149fa 100644 --- a/xtask/src/command/git.rs +++ b/xtask/src/command/git.rs @@ -1,31 +1,15 @@ //! 操作 git。 -use super::CommandExt; +use super::{ext, CommandExt}; use std::{ffi::OsStr, process::Command}; -pub(crate) struct Git { - cmd: Command, -} +pub(crate) struct Git(Command); -impl AsRef for Git { - fn as_ref(&self) -> &Command { - &self.cmd - } -} - -impl AsMut for Git { - fn as_mut(&mut self) -> &mut Command { - &mut self.cmd - } -} - -impl CommandExt for Git {} +ext!(Git); impl Git { fn new(sub: impl AsRef) -> Self { - let mut git = Self { - cmd: Command::new("git"), - }; + let mut git = Self(Command::new("git")); git.arg(sub); git } diff --git a/xtask/src/command/make.rs b/xtask/src/command/make.rs index c9f68772..04d19093 100644 --- a/xtask/src/command/make.rs +++ b/xtask/src/command/make.rs @@ -1,21 +1,9 @@ -use super::CommandExt; +use super::{ext, CommandExt}; use std::process::Command; pub(crate) struct Make(Command); -impl AsRef for Make { - fn as_ref(&self) -> &Command { - &self.0 - } -} - -impl AsMut for Make { - fn as_mut(&mut self) -> &mut Command { - &mut self.0 - } -} - -impl CommandExt for Make {} +ext!(Make); impl Make { pub fn new(j: Option) -> Self { diff --git a/xtask/src/command/mod.rs b/xtask/src/command/mod.rs index fa4c94e2..8e61cf9e 100644 --- a/xtask/src/command/mod.rs +++ b/xtask/src/command/mod.rs @@ -1,4 +1,5 @@ -use std::{ +use m::ext; +use std::{ ffi::{OsStr, OsString}, path::Path, process::{Command, ExitStatus}, @@ -9,11 +10,13 @@ pub mod dir; pub mod download; mod git; mod make; +mod qemu; mod tar; pub(crate) use cargo::Cargo; pub(crate) use git::Git; pub(crate) use make::Make; +pub(crate) use qemu::Qemu; pub(crate) use tar::Tar; pub(crate) trait CommandExt: AsRef + AsMut { @@ -85,22 +88,32 @@ pub(crate) trait CommandExt: AsRef + AsMut { pub(crate) struct Ext(Command); -impl AsRef for Ext { - fn as_ref(&self) -> &Command { - &self.0 - } -} - -impl AsMut for Ext { - fn as_mut(&mut self) -> &mut Command { - &mut self.0 - } -} - -impl CommandExt for Ext {} +ext!(Ext); impl Ext { pub fn new(program: impl AsRef) -> Self { Self(Command::new(program)) } } + +mod m { + macro_rules! ext { + ($ty:ty) => { + impl AsRef for $ty { + fn as_ref(&self) -> &Command { + &self.0 + } + } + + impl AsMut for $ty { + fn as_mut(&mut self) -> &mut Command { + &mut self.0 + } + } + + impl super::CommandExt for $ty {} + }; + } + + pub(crate) use ext; +} diff --git a/xtask/src/command/qemu.rs b/xtask/src/command/qemu.rs new file mode 100644 index 00000000..6f7ef89a --- /dev/null +++ b/xtask/src/command/qemu.rs @@ -0,0 +1,17 @@ +use super::ext; +use crate::arch::Arch; +use std::process::Command; + +pub(crate) struct Qemu(Command); + +ext!(Qemu); + +impl Qemu { + pub fn img() -> Self { + Self(Command::new("qemu-img")) + } + + pub fn system(arch: Arch) -> Self { + Self(Command::new(format!("qemu-system-{}", arch.as_str()))) + } +} diff --git a/xtask/src/command/tar.rs b/xtask/src/command/tar.rs index 5ad745da..5f1de897 100644 --- a/xtask/src/command/tar.rs +++ b/xtask/src/command/tar.rs @@ -1,21 +1,9 @@ -use super::CommandExt; +use super::ext; use std::{ffi::OsStr, process::Command}; pub(crate) struct Tar(Command); -impl AsRef for Tar { - fn as_ref(&self) -> &Command { - &self.0 - } -} - -impl AsMut for Tar { - fn as_mut(&mut self) -> &mut Command { - &mut self.0 - } -} - -impl CommandExt for Tar {} +ext!(Tar); impl Tar { pub fn xf(src: &impl AsRef, dst: Option>) -> Self { diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4b964eb0..d261e947 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,7 +12,7 @@ mod arch; mod command; mod dump; -use arch::Arch; +use arch::ArchArg; use command::{Cargo, CommandExt, Ext, Git, Make}; const ALPINE_WEBSITE: &str = "https://dl-cdn.alpinelinux.org/alpine/v3.12/releases"; @@ -47,16 +47,16 @@ enum Commands { CheckStyle, /// Build rootfs - Rootfs(Arch), + Rootfs(ArchArg), /// Put libc test into rootfs. - LibcTest(Arch), + LibcTest(ArchArg), /// Put other test into rootfs. - OtherTest(Arch), + OtherTest(ArchArg), /// Build image - Image(Arch), + Image(ArchArg), /// Run zCore in qemu - Qemu(Arch), + Qemu(ArchArg), } #[derive(Args)]