asterinas/osdk/src/base_crate/mod.rs

109 lines
3.4 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
//! The base crate is the OSDK generated crate that is ultimately built by cargo.
//! It will depend on the kernel crate.
//!
use std::path::Path;
use std::process::Command;
use std::str::FromStr;
use std::{fs, process};
use crate::error::Errno;
use crate::error_msg;
pub fn new_base_crate(
base_crate_path: impl AsRef<Path>,
dep_crate_name: &str,
dep_crate_path: impl AsRef<Path>,
) {
if base_crate_path.as_ref().exists() {
std::fs::remove_dir_all(&base_crate_path).unwrap();
}
let mut cmd = Command::new("cargo");
cmd.arg("new").arg("--bin").arg(base_crate_path.as_ref());
cmd.arg("--vcs").arg("none");
if !cmd.status().unwrap().success() {
error_msg!(
"Failed to create base crate at: {:#?}",
base_crate_path.as_ref()
);
process::exit(Errno::CreateBaseCrate as _);
}
// Set the current directory to the target osdk directory
let original_dir = std::env::current_dir().unwrap();
std::env::set_current_dir(&base_crate_path).unwrap();
// Add linker.ld file
let linker_ld = include_str!("x86_64-custom.ld.template");
fs::write("x86_64-custom.ld", linker_ld).unwrap();
// Add target json file
let target_json = include_str!("x86_64-custom.json.template");
fs::write("x86_64-custom.json", target_json).unwrap();
// Overrite the main.rs file
let main_rs = include_str!("main.rs.template");
// Replace all occurence of `#TARGET_NAME#` with the `dep_crate_name`
let main_rs = main_rs.replace("#TARGET_NAME#", &dep_crate_name.replace("-", "_"));
fs::write("src/main.rs", main_rs).unwrap();
// Add dependencies to the Cargo.toml
add_manifest_dependency(dep_crate_name, dep_crate_path);
// Copy the manifest configurations from the target crate to the base crate
copy_manifest_configurations(base_crate_path);
// Get back to the original directory
std::env::set_current_dir(&original_dir).unwrap();
}
fn add_manifest_dependency(crate_name: &str, crate_path: impl AsRef<Path>) {
let mainfest_path = "Cargo.toml";
let mut manifest: toml::Table = {
let content = fs::read_to_string(mainfest_path).unwrap();
toml::from_str(&content).unwrap()
};
let dependencies = manifest.get_mut("dependencies").unwrap();
let dep = toml::Table::from_str(&format!(
"{} = {{ path = \"{}\"}}",
crate_name,
crate_path.as_ref().display()
))
.unwrap();
dependencies.as_table_mut().unwrap().extend(dep);
let content = toml::to_string(&manifest).unwrap();
fs::write(mainfest_path, content).unwrap();
}
fn copy_manifest_configurations(target_crate_path: impl AsRef<Path>) {
let target_manifest_path = target_crate_path.as_ref().join("Cargo.toml");
let manifest_path = "Cargo.toml";
let target_manifest: toml::Table = {
let content = fs::read_to_string(target_manifest_path).unwrap();
toml::from_str(&content).unwrap()
};
let mut manifest: toml::Table = {
let content = fs::read_to_string(manifest_path).unwrap();
toml::from_str(&content).unwrap()
};
// Copy the profile configurations
let profile = target_manifest.get("profile");
if let Some(profile) = profile {
manifest.insert("profile".to_string(), profile.clone());
}
let content = toml::to_string(&manifest).unwrap();
fs::write(manifest_path, content).unwrap();
}