221 lines
7.0 KiB
Rust
Raw Normal View History

2024-04-01 17:23:12 +03:00
use std::{
collections::HashMap,
ffi::OsStr,
path::{Path, PathBuf},
process::Command,
};
use serde::Deserialize;
2024-03-12 18:17:47 +02:00
use crate::{
env::{BuildEnv, Profile},
error::Error,
};
2024-04-01 17:23:12 +03:00
#[derive(Debug, Clone, Deserialize)]
pub struct ModuleDependency {
pub version: Option<semver::VersionReq>,
pub path: PathBuf,
}
#[derive(Debug, Deserialize)]
pub struct ModuleManifest {
pub name: String,
pub version: semver::Version,
#[serde(default)]
pub dependencies: HashMap<String, ModuleDependency>,
}
#[derive(Debug)]
pub struct ModuleInfo {
pub dependencies: Vec<(String, String, ModuleDependency)>,
pub module_dir_name: PathBuf,
pub manifest_dir: PathBuf,
pub manifest: ModuleManifest,
}
2024-03-12 18:17:47 +02:00
pub enum CargoBuilder<'e> {
Host(bool),
2024-03-12 18:17:47 +02:00
Userspace(&'e BuildEnv),
2024-11-11 15:19:36 +02:00
Ygglibc(&'e BuildEnv),
2024-03-12 18:17:47 +02:00
Kernel(&'e BuildEnv),
2024-04-01 17:23:12 +03:00
Module(&'e BuildEnv, &'e ModuleInfo),
2024-03-12 18:17:47 +02:00
}
impl<'e> CargoBuilder<'e> {
pub fn run<P: AsRef<Path>, S: AsRef<OsStr>>(self, dir: P, arg: S) -> Result<(), Error> {
let mut command = Command::new("cargo");
command.current_dir(dir);
match self {
Self::Userspace(env) => {
// Add clippy dependency libraries to LD_LIBRARY_PATH
let toolchain_libs_path = env
.workspace_root
.join("toolchain/build")
.join(&env.host_triple)
.join("stage1/lib/rustlib")
.join(&env.host_triple)
.join("lib");
let ld_library_path = std::env::var("LD_LIBRARY_PATH");
let ld_library_path = match ld_library_path {
Ok(path) => format!("{}:{}", toolchain_libs_path.display(), path),
Err(_) => toolchain_libs_path.display().to_string(),
};
command.env("LD_LIBRARY_PATH", ld_library_path);
command
.arg("+ygg-stage1")
.arg(arg)
.arg(&format!("--target={}", env.arch.user_triple()));
if env.verbose {
command.arg("-v");
}
2024-03-12 18:17:47 +02:00
if env.profile == Profile::Release {
command.arg("--release");
}
}
2024-11-11 15:19:36 +02:00
Self::Ygglibc(env) => {
2024-11-12 17:07:06 +02:00
let target = format!(
"{}/{:?}-unknown-none.json",
env.workspace_root
.join("userspace/lib/ygglibc/etc")
.display(),
env.arch
);
2024-11-11 15:19:36 +02:00
command
.arg(arg)
.arg("-Zbuild-std=core,alloc,compiler_builtins")
.arg(&format!("--target={target}"));
if env.verbose {
command.arg("-v");
}
if env.profile == Profile::Release {
command.arg("--release");
}
}
Self::Host(verbose) => {
2024-03-12 18:17:47 +02:00
command.arg("+nightly").arg(arg);
if verbose {
command.arg("-v");
}
2024-03-12 18:17:47 +02:00
}
Self::Kernel(env) => {
2024-04-01 17:23:12 +03:00
command.env(
"RUSTFLAGS",
format!(
"-C link-arg=-T{}/etc/{}.ld",
env.workspace_root.display(),
env.arch.kernel_triple()
),
);
2024-03-12 18:17:47 +02:00
command.arg("+nightly").arg(arg);
if env.verbose {
command.arg("-v");
}
2024-03-12 18:17:47 +02:00
let target_spec_arg = format!(
"--target={}/etc/{}.json",
env.workspace_root.display(),
env.arch.kernel_triple()
);
command.arg(target_spec_arg);
command.args(["-Z", "build-std=core,alloc,compiler_builtins"]);
2024-04-01 17:23:12 +03:00
if env.profile == Profile::Release {
command.arg("--release");
}
}
Self::Module(env, module) => {
let mut lib_paths = vec![];
let mut extern_libs = vec![];
let mut dependency_list = String::new();
for (i, (name, dep)) in module.manifest.dependencies.iter().enumerate() {
if i != 0 {
dependency_list.push(':');
}
let dep_path = module.manifest_dir.join(&dep.path).canonicalize()?;
let output_dir = dep_path.join(format!(
"target/{}/{}",
env.arch.kernel_triple(),
env.profile.name()
));
let dependency_so = output_dir.join(format!("lib{}.so", name));
lib_paths.push(output_dir.join("deps"));
lib_paths.push(output_dir.clone());
lib_paths.push(dep_path.join(format!("target/{}/deps", env.profile.name())));
dependency_list.push_str(&format!("{}={}", name, dependency_so.display()));
extern_libs.push((name.clone(), dependency_so));
}
lib_paths.push(env.kernel_output_dir.join("deps"));
lib_paths.push(env.kernel_output_dir.clone());
lib_paths.push(
env.workspace_root
.join(format!("target/{}/deps", env.profile.name())),
);
extern_libs.push(("libk".into(), env.kernel_output_dir.join("liblibk.so")));
let mut rust_flags = Vec::new();
for lib_path in lib_paths {
rust_flags.push(format!("-L{}", lib_path.display()));
}
for (lib, path) in extern_libs {
rust_flags.push(format!("--extern {}={}", lib, path.display()));
}
rust_flags.push("-Cprefer-dynamic".into());
command.env("RUSTFLAGS", rust_flags.join(" "));
command.env("MOD_DEPENDENCIES", dependency_list);
command.env("MOD_LIBK_SO", env.kernel_output_dir.join("liblibk.so"));
command.arg("+nightly").arg(arg);
if env.verbose {
command.arg("-v");
}
let target_spec_arg = format!(
"--target={}/etc/{}.json",
env.workspace_root.display(),
env.arch.kernel_triple()
);
command.arg(target_spec_arg);
2024-03-12 18:17:47 +02:00
if env.profile == Profile::Release {
command.arg("--release");
}
}
}
log::trace!("Run cargo: {:?}", command);
let status = command.status()?;
if status.success() {
Ok(())
} else {
Err(Error::CargoFailed)
}
}
pub fn build<P: AsRef<Path>>(self, dir: P) -> Result<(), Error> {
self.run(dir, "build")
}
}