feat(xtask): 从顶层启动 qemu

This commit is contained in:
YdrMaster 2022-05-12 19:43:45 +08:00
parent 3d0186d95e
commit 9d8316b9b6
11 changed files with 215 additions and 142 deletions

View File

@ -3,8 +3,12 @@ xtask = "run --package xtask --"
git-proxy = "xtask git-proxy"
setup = "xtask setup"
update-all = "xtask update-all"
check-style = "xtask check-style"
rootfs = "xtask rootfs"
libc-test = "xtask libc-test"
other-test = "xtask other-test"
image = "xtask image"
qemu = "xtask qemu"

View File

@ -1,6 +1,9 @@
//! 平台相关的操作。
use crate::{dir, download::wget, make::Make, CommandExt, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE};
use crate::{
command::{dir, download::wget, Cargo, CommandExt, Ext, Make, Tar},
ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE,
};
use dircpy::copy_dir;
use std::{
ffi::{OsStr, OsString},
@ -8,7 +11,6 @@ use std::{
io::Write,
os::unix,
path::{Path, PathBuf},
process::Command,
};
#[derive(Args)]
@ -156,15 +158,12 @@ impl Arch {
.map(|entry| entry.path())
.filter(|path| path.extension().map_or(false, |ext| ext == OsStr::new("c")))
.for_each(|c| {
Command::new("gcc")
Ext::new("gcc")
.arg(&c)
.arg("-o")
.arg(bin.join(c.file_prefix().unwrap()))
.arg("-Wl,--dynamic-linker=/lib/ld-musl-x86_64.so.1")
.status()
.unwrap()
.exit_ok()
.expect("FAILED: gcc {c:?}");
.invoke();
});
}
}
@ -203,12 +202,49 @@ impl Arch {
image
}
};
Command::new("qemu-img")
.args(&["resize", &image, "+5M"])
.status()
.unwrap()
.exit_ok()
.expect("FAILED: qemu-img resize");
Ext::new("qemu-img")
.arg("resize")
.args(&["-f", "raw"])
.arg(image)
.arg("+5M")
.invoke();
}
/// 在 qemu 中启动。
pub fn qemu(&self) {
self.image();
match self.command {
ArchCommands::Riscv64 => {
Cargo::build()
.package("zcore")
.features(false, &["linux", "board-qemu"])
.target("zCore/riscv64.json")
.args(&["-Z", "build-std=core,alloc"])
.args(&["-Z", "build-std-features=compiler-builtins-mem"])
.release()
.invoke();
Ext::new("rust-objcopy")
.arg("--binary-architecture=riscv64")
.arg("target/riscv64/release/zcore")
.arg("--strip-all")
.args(&["-O", "binary", "target/riscv64/release/zcore.bin"])
.invoke();
Ext::new("qemu-system-riscv64")
.args(&["-smp", "1"])
.args(&["-machine", "virt"])
.args(&["-bios", "default"])
.args(&["-m", "512M"])
.args(&["-serial", "mon:stdio"])
.args(&["-kernel", "target/riscv64/release/zcore.bin"])
.args(&["-initrd", "zCore/riscv64.img"])
.args(&["-append", "\"LOG=warn\""])
.args(&["-display", "none"])
.arg("-no-reboot")
.arg("-nographic")
.invoke();
}
ArchCommands::X86_64 => todo!(),
}
}
/// 下载并解压 minirootfs。
@ -239,33 +275,6 @@ impl Arch {
}
}
struct Tar(Command);
impl AsRef<Command> for Tar {
fn as_ref(&self) -> &Command {
&self.0
}
}
impl AsMut<Command> for Tar {
fn as_mut(&mut self) -> &mut Command {
&mut self.0
}
}
impl CommandExt for Tar {}
impl Tar {
fn xf(src: &impl AsRef<OsStr>, dst: Option<impl AsRef<OsStr>>) -> Self {
let mut cmd = Command::new("tar");
cmd.arg("xf").arg(src);
if let Some(dst) = dst {
cmd.arg("-C").arg(dst);
}
Self(cmd)
}
}
/// 下载 riscv64-musl 工具链。
fn riscv64_linux_musl_cross() -> OsString {
const NAME: &str = "riscv64-linux-musl-cross";

View File

@ -1,4 +1,4 @@
use crate::CommandExt;
use super::CommandExt;
use std::{ffi::OsStr, process::Command};
pub(crate) struct Cargo {
@ -44,6 +44,10 @@ impl Cargo {
Self::new("doc")
}
pub fn build() -> Self {
Self::new("build")
}
pub fn all_features(&mut self) -> &mut Self {
self.arg("--all-features");
self
@ -72,7 +76,6 @@ impl Cargo {
self
}
#[allow(unused)]
pub fn target(&mut self, target: impl AsRef<OsStr>) -> &mut Self {
self.arg("--target").arg(target);
self
@ -82,4 +85,9 @@ impl Cargo {
self.arg("--package").arg(package);
self
}
pub fn release(&mut self) -> &mut Self {
self.arg("--release");
self
}
}

View File

@ -1,4 +1,4 @@
use crate::{dir, git::Git, CommandExt};
use super::{dir, git::Git, CommandExt};
use std::{ffi::OsStr, fs, path::Path, process::Command};
pub(crate) fn wget(url: impl AsRef<OsStr>, dst: impl AsRef<Path>) {

View File

@ -1,9 +1,9 @@
//! 操作 git。
use crate::CommandExt;
use super::CommandExt;
use std::{ffi::OsStr, process::Command};
pub(super) struct Git {
pub(crate) struct Git {
cmd: Command,
}

View File

@ -1,4 +1,4 @@
use crate::CommandExt;
use super::CommandExt;
use std::process::Command;
pub(crate) struct Make(Command);

106
xtask/src/command/mod.rs Normal file
View File

@ -0,0 +1,106 @@
use std::{
ffi::{OsStr, OsString},
path::Path,
process::{Command, ExitStatus},
};
mod cargo;
pub mod dir;
pub mod download;
mod git;
mod make;
mod tar;
pub(crate) use cargo::Cargo;
pub(crate) use git::Git;
pub(crate) use make::Make;
pub(crate) use tar::Tar;
pub(crate) trait CommandExt: AsRef<Command> + AsMut<Command> {
fn arg(&mut self, s: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().arg(s);
self
}
fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
for arg in args {
self.arg(arg);
}
self
}
fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self {
self.as_mut().current_dir(dir);
self
}
fn env(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().env(key, val);
self
}
fn status(&mut self) -> ExitStatus {
self.as_mut().status().unwrap()
}
fn info(&self) -> OsString {
let cmd = self.as_ref();
let mut msg = OsString::new();
if let Some(dir) = cmd.get_current_dir() {
msg.push("cd ");
msg.push(dir);
msg.push(" && ");
}
msg.push(cmd.get_program());
for a in cmd.get_args() {
msg.push(" ");
msg.push(a);
}
for (k, v) in cmd.get_envs() {
msg.push(" ");
msg.push(k);
if let Some(v) = v {
msg.push("=");
msg.push(v);
}
}
msg
}
fn invoke(&mut self) {
let status = self.status();
if !status.success() {
panic!(
"Failed with code {}: {:?}",
status.code().unwrap(),
self.info()
);
}
}
}
pub(crate) struct Ext(Command);
impl AsRef<Command> for Ext {
fn as_ref(&self) -> &Command {
&self.0
}
}
impl AsMut<Command> for Ext {
fn as_mut(&mut self) -> &mut Command {
&mut self.0
}
}
impl CommandExt for Ext {}
impl Ext {
pub fn new(program: impl AsRef<OsStr>) -> Self {
Self(Command::new(program))
}
}

29
xtask/src/command/tar.rs Normal file
View File

@ -0,0 +1,29 @@
use super::CommandExt;
use std::{ffi::OsStr, process::Command};
pub(crate) struct Tar(Command);
impl AsRef<Command> for Tar {
fn as_ref(&self) -> &Command {
&self.0
}
}
impl AsMut<Command> for Tar {
fn as_mut(&mut self) -> &mut Command {
&mut self.0
}
}
impl CommandExt for Tar {}
impl Tar {
pub fn xf(src: &impl AsRef<OsStr>, dst: Option<impl AsRef<OsStr>>) -> Self {
let mut cmd = Command::new("tar");
cmd.arg("xf").arg(src);
if let Some(dst) = dst {
cmd.arg("-C").arg(dst);
}
Self(cmd)
}
}

View File

@ -6,26 +6,14 @@ extern crate clap;
use clap::Parser;
use clap_verbosity_flag::Verbosity;
use std::{
ffi::{OsStr, OsString},
fs::read_to_string,
net::Ipv4Addr,
path::Path,
process::{Command, ExitStatus},
};
use std::{fs::read_to_string, net::Ipv4Addr};
mod arch;
mod cargo;
mod dir;
mod download;
mod command;
mod dump;
mod git;
mod make;
use arch::Arch;
use cargo::Cargo;
use git::Git;
use make::Make;
use command::{Cargo, CommandExt, Ext, Git, Make};
const ALPINE_WEBSITE: &str = "https://dl-cdn.alpinelinux.org/alpine/v3.12/releases";
const ALPINE_ROOTFS_VERSION: &str = "3.12.0";
@ -67,8 +55,8 @@ enum Commands {
/// Build image
Image(Arch),
/// Unit test
Test,
/// Run zCore in qemu
Qemu(Arch),
}
#[derive(Args)]
@ -117,7 +105,7 @@ fn main() {
Commands::LibcTest(arch) => arch.libc_test(),
Commands::OtherTest(arch) => arch.other_test(),
Commands::Image(arch) => arch.image(),
Commands::Test => todo!(),
Commands::Qemu(arch) => arch.qemu(),
}
}
@ -143,12 +131,7 @@ fn git_submodule_update(init: bool) {
/// 更新工具链和依赖。
fn update_all() {
git_submodule_update(false);
Command::new("rustup")
.arg("update")
.status()
.unwrap()
.exit_ok()
.expect("FAILED: rustup update");
Ext::new("rustup").arg("update").invoke();
Cargo::update().invoke();
}
@ -185,15 +168,17 @@ fn check_style() {
Cargo::fmt().arg("--all").arg("--").arg("--check").invoke();
Cargo::clippy().all_features().invoke();
Cargo::doc().all_features().arg("--no-deps").invoke();
println!("Check libos");
Cargo::clippy()
.package("zcore")
.features(false, &["zircon libos"])
.features(false, &["zircon", "libos"])
.invoke();
Cargo::clippy()
.package("zcore")
.features(false, &["linux libos"])
.features(false, &["linux", "libos"])
.invoke();
println!("Check bare-metal");
Make::new(None)
.arg("clippy")
@ -207,70 +192,3 @@ fn check_style() {
.current_dir("zCore")
.invoke();
}
trait CommandExt: AsRef<Command> + AsMut<Command> {
fn arg(&mut self, s: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().arg(s);
self
}
fn args<I, S>(&mut self, args: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
for arg in args {
self.arg(arg);
}
self
}
fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self {
self.as_mut().current_dir(dir);
self
}
fn env(&mut self, key: impl AsRef<OsStr>, val: impl AsRef<OsStr>) -> &mut Self {
self.as_mut().env(key, val);
self
}
fn status(&mut self) -> ExitStatus {
self.as_mut().status().unwrap()
}
fn info(&self) -> OsString {
let cmd = self.as_ref();
let mut msg = OsString::new();
if let Some(dir) = cmd.get_current_dir() {
msg.push("cd ");
msg.push(dir);
msg.push(" && ");
}
msg.push(cmd.get_program());
for a in cmd.get_args() {
msg.push(" ");
msg.push(a);
}
for (k, v) in cmd.get_envs() {
msg.push(" ");
msg.push(k);
if let Some(v) = v {
msg.push("=");
msg.push(v);
}
}
msg
}
fn invoke(&mut self) {
let status = self.status();
if !status.success() {
panic!(
"Failed with code {}: {:?}",
status.code().unwrap(),
self.info()
);
}
}
}

View File

@ -4,11 +4,10 @@ fn main() {
//println!("cargo:rerun-if-env-changed=PLATFORM");
if std::env::var("TARGET").unwrap().contains("riscv64") {
let board = std::env::var("PLATFORM").unwrap();
let kernel_base_addr: u64 = if board.contains("d1") {
let kernel_base_addr: u64 = if std::env::var("PLATFORM").map_or(false, |p| p.contains("d1"))
{
0xffffffffc0100000
} else {
// opensbi仍旧把kernel放在0x80200000物理内存中
0xffffffff80200000
};