feat(xtask): 统一 rootfs 存放,libc-test 成为子模块

This commit is contained in:
YdrMaster 2022-05-11 09:36:50 +08:00
parent 35306f14c1
commit b8f66237d7
8 changed files with 113 additions and 81 deletions

1
.gitignore vendored
View File

@ -12,7 +12,6 @@ Cargo.lock
/ignored
/rootfs
/riscv_rootfs
/prebuilt/linux/**/minirootfs.tar.*
zCore/src/platform/riscv/kernel-vars.ld

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "tests"]
path = tests
url = https://github.com/rcore-os/zcore-tests.git
[submodule "libc-test"]
path = libc-test
url = https://github.com/rcore-os/libc-test

1
libc-test Submodule

@ -0,0 +1 @@
Subproject commit 1426bea9f3482dec1aa98c31dcc3733a750fb090

9
xtask/CHANGLOG.md Normal file
View File

@ -0,0 +1,9 @@
# 更新公告
最新的更新将出现在最上方。
## 20220511(YdrMaster)
- 现在用于 linux 模式的 rootfs 统一放在 rootfs/$ARCH未来新增 aarch64 或更多架构也将放在这个目录;
- libc-test 现在是一个子模块,不再需要单独 git clone
- 使用 `std::os::unix::fs::symlink` 建立符号链接,不再依赖 `ln` 应用程序;

View File

@ -1,5 +1,7 @@
# zCore tasks
[更新公告](CHANGLOG.md)
## 使用说明
使用 `cargo xtask help` 将打印出命令说明。对主要子命令的简要说明如下:
@ -12,7 +14,7 @@
6. `libc-test <arch>`: 向启动文件系统加入 libc 测试;
7. `image <arch>`: 打包指定架构的系统镜像;
其中 5、6、7 必须顺序执行,后者依赖前者的结果
其中 6、7 执行时若 5 的结果不存在,将自动递归执行 5
## 项目愿景

View File

@ -1,13 +1,10 @@
use crate::{
dir,
download::{git_clone, wget},
CommandExt, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE,
};
use crate::{dir, download::wget, CommandExt, ALPINE_ROOTFS_VERSION, ALPINE_WEBSITE};
use dircpy::copy_dir;
use std::{
ffi::{OsStr, OsString},
fs,
io::Write,
os::unix,
path::{Path, PathBuf},
process::Command,
};
@ -26,53 +23,62 @@ enum ArchCommands {
X86_64,
}
impl ArchCommands {
const fn as_str(&self) -> &'static str {
match self {
ArchCommands::Riscv64 => "riscv64",
ArchCommands::X86_64 => "x86_64",
}
}
}
impl Arch {
/// 构造启动内存文件系统 rootfs。
///
/// 将在文件系统中放置必要的库文件,并下载用于交叉编译的工具链。
/// 若 `clear` == true将清除已存在的目录。
///
/// 将在文件系统中放置必要的库文件。
pub fn rootfs(&self, clear: bool) {
self.wget_alpine();
match self.command {
ArchCommands::Riscv64 => {
const DIR: &str = "riscv_rootfs";
const ARCH: &str = "riscv64";
const ARCH: &str = ArchCommands::Riscv64.as_str();
let dir = Path::new(DIR);
let dir = PathBuf::from(format!("rootfs/{ARCH}"));
if dir.is_dir() && !clear {
return;
}
dir::clear(dir).unwrap();
dir::clear(&dir).unwrap();
let tar = dir::detect(&format!("prebuilt/linux/{ARCH}"), "minirootfs").unwrap();
Tar::xf(&tar, Some(DIR))
Tar::xf(&tar, Some(&dir))
.args(&["--strip-components", "1"])
.join();
Command::new("ln")
.args(&["-s", "busybox", "riscv_rootfs/bin/ls"])
.status()
.unwrap()
.exit_ok()
.expect("FAILED: ln -s busybox riscv_rootfs/bin/ls");
let mut ls = dir;
ls.push("bin");
ls.push("ls");
unix::fs::symlink("busybox", ls).unwrap();
}
ArchCommands::X86_64 => {
const DIR: &str = "rootfs";
const ARCH: &str = "x86_64";
const ARCH: &str = ArchCommands::X86_64.as_str();
let dir = Path::new(DIR);
let dir = PathBuf::from(format!("rootfs/{ARCH}"));
if dir.is_dir() && !clear {
return;
}
dir::clear(DIR).unwrap();
let tar = dir::detect(&format!("prebuilt/linux/{ARCH}"), "minirootfs").unwrap();
Tar::xf(&tar, Some(DIR)).join();
// libc-libos.so (convert syscall to function call) is from https://github.com/rcore-os/musl/tree/rcore
fs::copy(
"prebuilt/linux/libc-libos.so",
format!("{DIR}/lib/ld-musl-{ARCH}.so.1"),
)
.unwrap();
{
dir::clear(&dir).unwrap();
let tar = dir::detect(&format!("prebuilt/linux/{ARCH}"), "minirootfs").unwrap();
Tar::xf(&tar, Some(&dir)).join();
// libc-libos.so (convert syscall to function call) is from https://github.com/rcore-os/musl/tree/rcore
let mut dir = dir.clone();
dir.push("lib");
dir.push(format!("ld-musl-{ARCH}.so.1"));
fs::copy("prebuilt/linux/libc-libos.so", dir).unwrap();
}
{
const TEST_DIR: &str = "linux-syscall/test";
const DEST_DIR: &str = "rootfs/bin/";
let mut dest_dir = dir;
dest_dir.push("bin");
// for linux syscall tests
fs::read_dir(TEST_DIR)
.unwrap()
@ -80,13 +86,12 @@ impl Arch {
.map(|entry| entry.path())
.filter(|path| path.extension().map_or(false, |ext| ext == OsStr::new("c")))
.for_each(|c| {
let o = format!(
"{DEST_DIR}/{}",
c.file_prefix().and_then(|s| s.to_str()).unwrap()
);
let mut o = dest_dir.clone();
o.push(c.file_prefix().and_then(|s| s.to_str()).unwrap());
Command::new("gcc")
.arg(&c)
.args(&["-o", &o])
.arg("-o")
.arg(&o)
.arg("-Wl,--dynamic-linker=/lib/ld-musl-x86_64.so.1")
.status()
.unwrap()
@ -101,44 +106,46 @@ impl Arch {
/// 将 libc-test 放入 rootfs。
pub fn libc_test(&self) {
self.rootfs(false);
git_clone(
"https://github.com/rcore-os/libc-test.git",
"ignored/libc-test",
);
match self.command {
ArchCommands::Riscv64 => {
const DIR: &str = "riscv_rootfs/libc-test";
const PRE: &str = "riscv_rootfs/libc-test-prebuild";
const ARCH: &str = ArchCommands::Riscv64.as_str();
fs::rename(DIR, PRE).unwrap();
copy_dir("ignored/libc-test", DIR).unwrap();
fs::copy(format!("{DIR}/config.mak.def"), format!("{DIR}/config.mak")).unwrap();
let rootfs = format!("rootfs/{ARCH}");
let dir = format!("{rootfs}/libc-test");
let pre = format!("{rootfs}/libc-test-prebuilt");
fs::rename(&dir, &pre).unwrap();
copy_dir("libc-test", &dir).unwrap();
fs::copy(format!("{dir}/config.mak.def"), format!("{dir}/config.mak")).unwrap();
Make::new(None)
.env("ARCH", "riscv64")
.env("ARCH", ARCH)
.env("CROSS_COMPILE", "riscv64-linux-musl-")
.env("PATH", riscv64_linux_musl_cross())
.current_dir(DIR)
.current_dir(&dir)
.join();
fs::copy(
format!("{PRE}/functional/tls_align-static.exe"),
format!("{DIR}/src/functional/tls_align-static.exe"),
format!("{pre}/functional/tls_align-static.exe"),
format!("{dir}/src/functional/tls_align-static.exe"),
)
.unwrap();
dir::rm(PRE).unwrap();
dir::rm(pre).unwrap();
}
ArchCommands::X86_64 => {
const DIR: &str = "rootfs/libc-test";
const ARCH: &str = ArchCommands::X86_64.as_str();
dir::rm(DIR).unwrap();
copy_dir("ignored/libc-test", DIR).unwrap();
fs::copy(format!("{DIR}/config.mak.def"), format!("{DIR}/config.mak")).unwrap();
let rootfs = format!("rootfs/{ARCH}");
let dir = format!("{rootfs}/libc-test");
dir::rm(&dir).unwrap();
copy_dir("libc-test", &dir).unwrap();
fs::copy(format!("{dir}/config.mak.def"), format!("{dir}/config.mak")).unwrap();
fs::OpenOptions::new()
.append(true)
.open(format!("{DIR}/config.mak"))
.open(format!("{dir}/config.mak"))
.unwrap()
.write_all(b"CC := musl-gcc\nAR := ar\nRANLIB := ranlib")
.unwrap();
Make::new(None).current_dir(DIR).join();
Make::new(None).current_dir(dir).join();
}
}
}
@ -148,35 +155,45 @@ impl Arch {
self.rootfs(false);
let image = match self.command {
ArchCommands::Riscv64 => {
const ARCH: &str = "riscv64";
const ARCH: &str = ArchCommands::Riscv64.as_str();
let rootfs = format!("rootfs/{ARCH}");
let image = format!("zCore/{ARCH}.img");
fuse("riscv_rootfs", &image);
fuse(rootfs, &image);
image
}
ArchCommands::X86_64 => {
const ARCH: &str = "x86_64";
const TMP_ROOTFS: &str = "/tmp/rootfs";
const ROOTFS_LIB: &str = "rootfs/lib";
const ARCH: &str = ArchCommands::X86_64.as_str();
let tmp: usize = rand::random();
let tmp_rootfs = format!("/tmp/{tmp}");
let rootfs = format!("rootfs/{ARCH}");
let rootfs_lib = format!("{rootfs}/lib");
// ld-musl-x86_64.so.1 替换为适用 bare-matel 的版本
dir::clear(TMP_ROOTFS).unwrap();
dir::clear(&tmp_rootfs).unwrap();
dir::clear(&rootfs_lib).unwrap();
let tar = dir::detect(&format!("prebuilt/linux/{ARCH}"), "minirootfs").unwrap();
Tar::xf(&tar, Some(TMP_ROOTFS)).join();
dir::clear(ROOTFS_LIB).unwrap();
Tar::xf(&tar, Some(&tmp_rootfs)).join();
fs::copy(
format!("{TMP_ROOTFS}/lib/ld-musl-x86_64.so.1"),
format!("{ROOTFS_LIB}/ld-musl-x86_64.so.1"),
format!("{tmp_rootfs}/lib/ld-musl-x86_64.so.1"),
format!("{rootfs_lib}/ld-musl-x86_64.so.1"),
)
.unwrap();
dir::rm(tmp_rootfs).unwrap();
let image = format!("zCore/{ARCH}.img");
fuse(rootfs, &image);
fs::copy(
"prebuilt/linux/libc-libos.so",
format!("{rootfs_lib}/ld-musl-x86_64.so.1"),
)
.unwrap();
let image = format!("zCore/{ARCH}.img");
fuse("rootfs", &image);
fs::copy(
"prebuilt/linux/libc-libos.so",
format!("{ROOTFS_LIB}/ld-musl-x86_64.so.1"),
)
.unwrap();
image
}
};
@ -273,7 +290,7 @@ impl AsMut<Command> for Tar {
impl CommandExt for Tar {}
impl Tar {
fn xf(src: &impl AsRef<OsStr>, dst: Option<&str>) -> Self {
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 {

View File

@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
/// 删除指定路径。
///
/// 如果返回 `Ok(())``path` 将不存在。
pub fn rm(path: &(impl AsRef<Path> + ?Sized)) -> std::io::Result<()> {
pub fn rm(path: impl AsRef<Path>) -> std::io::Result<()> {
let path = path.as_ref();
if !path.exists() {
Ok(())
@ -19,15 +19,15 @@ pub fn rm(path: &(impl AsRef<Path> + ?Sized)) -> std::io::Result<()> {
/// 清理 `path` 目录。
///
/// 如果返回 `Ok(())``path` 将是一个存在的空目录。
pub fn clear(path: &(impl AsRef<Path> + ?Sized)) -> std::io::Result<()> {
rm(path)?;
std::fs::create_dir_all(path)
pub fn clear(path: impl AsRef<Path>) -> std::io::Result<()> {
rm(&path)?;
std::fs::create_dir_all(&path)
}
/// 在 `dir` 目录中根据文件名前半部分 `prefix` 找到对应文件。
///
/// 不会递归查找。
pub fn detect(path: &(impl AsRef<Path> + ?Sized), prefix: &str) -> Option<PathBuf> {
pub fn detect(path: impl AsRef<Path>, prefix: impl AsRef<str>) -> Option<PathBuf> {
path.as_ref()
.read_dir()
.ok()?
@ -37,6 +37,6 @@ pub fn detect(path: &(impl AsRef<Path> + ?Sized), prefix: &str) -> Option<PathBu
.find(|path| {
path.file_name()
.and_then(|s| s.to_str())
.map_or(false, |s| s.starts_with(prefix))
.map_or(false, |s| s.starts_with(prefix.as_ref()))
})
}

View File

@ -26,6 +26,7 @@ pub(crate) fn wget(url: impl AsRef<OsStr>, dst: impl AsRef<Path>) {
}
}
#[allow(unused)]
pub(crate) fn git_clone(repo: impl AsRef<OsStr>, dst: impl AsRef<Path>) {
let dst = dst.as_ref();
if dst.is_dir() {