use std::{fs, io::Write, path::PathBuf}; use toml::Value; use crate::utils::cargo_handler::CargoHandler; /// 内核编译配置的构建器 pub struct KConfigBuilder; impl KConfigBuilder { pub fn build() { // 如果存在kernel.config,才去解析 if fs::metadata("kernel.config").is_ok() { // 获取kernel.config所包含的模块 let modules = ConfigParser::parse_kernel_config(); // 扫描各模块下以及其包含模块的d.config,然后将所有d.config路径添加到r中 let mut r = Vec::new(); for m in modules.iter() { if m.enable() { Self::dfs(m, &mut r); } } // 扫描所有d.config以获取features let features = ConfigParser::parse_d_configs(&r); // 添加feature CargoHandler::emit_features(features.as_slice()); // 生成最终内核编译配置文件D.config Self::make_compile_cfg(&features); } } /// 生成最终编译配置文件D.config fn make_compile_cfg(features: &Vec) { let mut cfg_content = String::new(); for f in features.iter() { if f.enable() { cfg_content.push_str(&format!("{} = y\n", f.name())); } else { cfg_content.push_str(&format!("{} = n\n", f.name())); } } let mut file = fs::File::create("D.config").expect("Failed to create file: D.config"); file.write_all(cfg_content.as_bytes()) .expect("Failed to write D.config"); } /// 递归找所有模块下的d.config文件路径 /// /// ## 参数 /// /// `module` - 当前模块 /// `r` - 保存所有d.config文件路径 /// ## 返回值 /// /// 无 fn dfs(module: &Module, r: &mut Vec) { println!("{}", module.name()); let path_str = module.path().as_path().to_str().unwrap().to_string(); let d_config_str = format!("{}/d.config", path_str); let d_config_path = PathBuf::from(&d_config_str); let dcfg_content = fs::read_to_string(&d_config_path).expect(&format!("Failed to read {}", d_config_str)); let m_include = ConfigParser::include(&dcfg_content); for m in m_include.iter() { if m.enable() { Self::dfs(m, r); } } r.push(d_config_path); } } /// 内核编译配置文件解析器 struct ConfigParser; impl ConfigParser { /// 扫描kernel.config获取所包含的模块 pub fn parse_kernel_config() -> Vec { let cfg_content = fs::read_to_string("kernel.config").expect("Failed to read kernel.config."); let r = Self::include(&cfg_content); return r; } /// 扫描所有d.config以获取所有feature pub fn parse_d_configs(d_configs: &Vec) -> Vec { let mut r = Vec::new(); for d_config in d_configs.iter() { r.extend(Self::parse_d_config(d_config)); } return r; } /// 扫描当前d.config文件获取feature pub fn parse_d_config(d_config: &PathBuf) -> Vec { let path_str = d_config.as_path().to_str().unwrap().to_string(); let dcfg_content = fs::read_to_string(d_config).expect(&format!("Failed to read {}", path_str)); let dcfg_table: Value = toml::from_str(&dcfg_content).expect(&format!("Failed to parse {}", path_str)); let mut r = Vec::new(); if let Some(features) = dcfg_table.get("module").unwrap().get("features") { for f in features.as_array().unwrap().iter() { let name = f.get("name").unwrap().as_str().unwrap().to_string(); let enable = f.get("enable").unwrap().as_str().unwrap().to_string() == "y"; r.push(Feature::new(name, enable)); } } return r; } /// 获取所包含的模块 /// /// ## 参数 /// /// `cfg_content` -配置文件内容 /// /// ## 返回值 /// /// 包含的模块集合 pub fn include(cfg_content: &str) -> Vec { let cfg_table: Value = toml::from_str(&cfg_content).expect("Failed to parse kernel.config"); let mut r = Vec::new(); if let Some(include) = cfg_table.get("module").unwrap().get("include") { for module in include.as_array().unwrap().iter() { let name = module.get("name").unwrap().as_str().unwrap().to_string(); let path = PathBuf::from(module.get("path").unwrap().as_str().unwrap()); let enable = module.get("enable").unwrap().as_str().unwrap() == "y"; r.push(Module::new(name, path, enable)); } } return r; } } /// 模块 struct Module { /// 模块名 name: String, /// 模块文件路径 path: PathBuf, /// 是否启用 enable: bool, } impl Module { pub fn new(name: String, path: PathBuf, enable: bool) -> Module { Module { name, path, enable } } pub fn name(&self) -> String { self.name.clone() } pub fn path(&self) -> PathBuf { self.path.clone() } pub fn enable(&self) -> bool { self.enable.clone() } } /// feature pub struct Feature { /// feature标签名 name: String, /// 是否启用 enable: bool, } impl Feature { pub fn new(name: String, enable: bool) -> Feature { Feature { name, enable } } pub fn name(&self) -> String { self.name.clone() } pub fn enable(&self) -> bool { self.enable.clone() } }