xref: /DragonOS/build-scripts/kernel_build/src/kconfig/mod.rs (revision e4600f7f7d8f2295dbf970812ab1fcab81eb6eae)
1*e4600f7fSJomo use std::{fs, io::Write, path::PathBuf};
2*e4600f7fSJomo 
3*e4600f7fSJomo use toml::Value;
4*e4600f7fSJomo 
5*e4600f7fSJomo use crate::utils::cargo_handler::CargoHandler;
6*e4600f7fSJomo 
7*e4600f7fSJomo /// 内核编译配置的构建器
8*e4600f7fSJomo pub struct KConfigBuilder;
9*e4600f7fSJomo 
10*e4600f7fSJomo impl KConfigBuilder {
build()11*e4600f7fSJomo     pub fn build() {
12*e4600f7fSJomo         // 如果存在kernel.config,才去解析
13*e4600f7fSJomo         if fs::metadata("kernel.config").is_ok() {
14*e4600f7fSJomo             // 获取kernel.config所包含的模块
15*e4600f7fSJomo             let modules = ConfigParser::parse_kernel_config();
16*e4600f7fSJomo 
17*e4600f7fSJomo             // 扫描各模块下以及其包含模块的d.config,然后将所有d.config路径添加到r中
18*e4600f7fSJomo             let mut r = Vec::new();
19*e4600f7fSJomo             for m in modules.iter() {
20*e4600f7fSJomo                 if m.enable() {
21*e4600f7fSJomo                     Self::dfs(m, &mut r);
22*e4600f7fSJomo                 }
23*e4600f7fSJomo             }
24*e4600f7fSJomo 
25*e4600f7fSJomo             // 扫描所有d.config以获取features
26*e4600f7fSJomo             let features = ConfigParser::parse_d_configs(&r);
27*e4600f7fSJomo 
28*e4600f7fSJomo             // 添加feature
29*e4600f7fSJomo             CargoHandler::emit_features(features.as_slice());
30*e4600f7fSJomo 
31*e4600f7fSJomo             // 生成最终内核编译配置文件D.config
32*e4600f7fSJomo             Self::make_compile_cfg(&features);
33*e4600f7fSJomo         }
34*e4600f7fSJomo     }
35*e4600f7fSJomo 
36*e4600f7fSJomo     /// 生成最终编译配置文件D.config
make_compile_cfg(features: &Vec<Feature>)37*e4600f7fSJomo     fn make_compile_cfg(features: &Vec<Feature>) {
38*e4600f7fSJomo         let mut cfg_content = String::new();
39*e4600f7fSJomo         for f in features.iter() {
40*e4600f7fSJomo             if f.enable() {
41*e4600f7fSJomo                 cfg_content.push_str(&format!("{} = y\n", f.name()));
42*e4600f7fSJomo             } else {
43*e4600f7fSJomo                 cfg_content.push_str(&format!("{} = n\n", f.name()));
44*e4600f7fSJomo             }
45*e4600f7fSJomo         }
46*e4600f7fSJomo 
47*e4600f7fSJomo         let mut file = fs::File::create("D.config").expect("Failed to create file: D.config");
48*e4600f7fSJomo         file.write_all(cfg_content.as_bytes())
49*e4600f7fSJomo             .expect("Failed to write D.config");
50*e4600f7fSJomo     }
51*e4600f7fSJomo 
52*e4600f7fSJomo     /// 递归找所有模块下的d.config文件路径
53*e4600f7fSJomo     ///
54*e4600f7fSJomo     /// ## 参数
55*e4600f7fSJomo     ///
56*e4600f7fSJomo     /// `module` - 当前模块
57*e4600f7fSJomo     /// `r` - 保存所有d.config文件路径
58*e4600f7fSJomo     /// ## 返回值
59*e4600f7fSJomo     ///
60*e4600f7fSJomo     /// 无
dfs(module: &Module, r: &mut Vec<PathBuf>)61*e4600f7fSJomo     fn dfs(module: &Module, r: &mut Vec<PathBuf>) {
62*e4600f7fSJomo         println!("{}", module.name());
63*e4600f7fSJomo 
64*e4600f7fSJomo         let path_str = module.path().as_path().to_str().unwrap().to_string();
65*e4600f7fSJomo         let d_config_str = format!("{}/d.config", path_str);
66*e4600f7fSJomo         let d_config_path = PathBuf::from(&d_config_str);
67*e4600f7fSJomo         let dcfg_content =
68*e4600f7fSJomo             fs::read_to_string(&d_config_path).expect(&format!("Failed to read {}", d_config_str));
69*e4600f7fSJomo         let m_include = ConfigParser::include(&dcfg_content);
70*e4600f7fSJomo 
71*e4600f7fSJomo         for m in m_include.iter() {
72*e4600f7fSJomo             if m.enable() {
73*e4600f7fSJomo                 Self::dfs(m, r);
74*e4600f7fSJomo             }
75*e4600f7fSJomo         }
76*e4600f7fSJomo 
77*e4600f7fSJomo         r.push(d_config_path);
78*e4600f7fSJomo     }
79*e4600f7fSJomo }
80*e4600f7fSJomo 
81*e4600f7fSJomo /// 内核编译配置文件解析器
82*e4600f7fSJomo struct ConfigParser;
83*e4600f7fSJomo 
84*e4600f7fSJomo impl ConfigParser {
85*e4600f7fSJomo     /// 扫描kernel.config获取所包含的模块
parse_kernel_config() -> Vec<Module>86*e4600f7fSJomo     pub fn parse_kernel_config() -> Vec<Module> {
87*e4600f7fSJomo         let cfg_content =
88*e4600f7fSJomo             fs::read_to_string("kernel.config").expect("Failed to read kernel.config.");
89*e4600f7fSJomo 
90*e4600f7fSJomo         let r = Self::include(&cfg_content);
91*e4600f7fSJomo 
92*e4600f7fSJomo         return r;
93*e4600f7fSJomo     }
94*e4600f7fSJomo 
95*e4600f7fSJomo     /// 扫描所有d.config以获取所有feature
parse_d_configs(d_configs: &Vec<PathBuf>) -> Vec<Feature>96*e4600f7fSJomo     pub fn parse_d_configs(d_configs: &Vec<PathBuf>) -> Vec<Feature> {
97*e4600f7fSJomo         let mut r = Vec::new();
98*e4600f7fSJomo         for d_config in d_configs.iter() {
99*e4600f7fSJomo             r.extend(Self::parse_d_config(d_config));
100*e4600f7fSJomo         }
101*e4600f7fSJomo         return r;
102*e4600f7fSJomo     }
103*e4600f7fSJomo 
104*e4600f7fSJomo     /// 扫描当前d.config文件获取feature
parse_d_config(d_config: &PathBuf) -> Vec<Feature>105*e4600f7fSJomo     pub fn parse_d_config(d_config: &PathBuf) -> Vec<Feature> {
106*e4600f7fSJomo         let path_str = d_config.as_path().to_str().unwrap().to_string();
107*e4600f7fSJomo         let dcfg_content =
108*e4600f7fSJomo             fs::read_to_string(d_config).expect(&format!("Failed to read {}", path_str));
109*e4600f7fSJomo         let dcfg_table: Value =
110*e4600f7fSJomo             toml::from_str(&dcfg_content).expect(&format!("Failed to parse {}", path_str));
111*e4600f7fSJomo 
112*e4600f7fSJomo         let mut r = Vec::new();
113*e4600f7fSJomo         if let Some(features) = dcfg_table.get("module").unwrap().get("features") {
114*e4600f7fSJomo             for f in features.as_array().unwrap().iter() {
115*e4600f7fSJomo                 let name = f.get("name").unwrap().as_str().unwrap().to_string();
116*e4600f7fSJomo                 let enable = f.get("enable").unwrap().as_str().unwrap().to_string() == "y";
117*e4600f7fSJomo                 r.push(Feature::new(name, enable));
118*e4600f7fSJomo             }
119*e4600f7fSJomo         }
120*e4600f7fSJomo         return r;
121*e4600f7fSJomo     }
122*e4600f7fSJomo 
123*e4600f7fSJomo     /// 获取所包含的模块
124*e4600f7fSJomo     ///
125*e4600f7fSJomo     /// ## 参数
126*e4600f7fSJomo     ///
127*e4600f7fSJomo     /// `cfg_content` -配置文件内容
128*e4600f7fSJomo     ///
129*e4600f7fSJomo     /// ## 返回值
130*e4600f7fSJomo     ///
131*e4600f7fSJomo     /// 包含的模块集合
include(cfg_content: &str) -> Vec<Module>132*e4600f7fSJomo     pub fn include(cfg_content: &str) -> Vec<Module> {
133*e4600f7fSJomo         let cfg_table: Value = toml::from_str(&cfg_content).expect("Failed to parse kernel.config");
134*e4600f7fSJomo         let mut r = Vec::new();
135*e4600f7fSJomo         if let Some(include) = cfg_table.get("module").unwrap().get("include") {
136*e4600f7fSJomo             for module in include.as_array().unwrap().iter() {
137*e4600f7fSJomo                 let name = module.get("name").unwrap().as_str().unwrap().to_string();
138*e4600f7fSJomo                 let path = PathBuf::from(module.get("path").unwrap().as_str().unwrap());
139*e4600f7fSJomo                 let enable = module.get("enable").unwrap().as_str().unwrap() == "y";
140*e4600f7fSJomo                 r.push(Module::new(name, path, enable));
141*e4600f7fSJomo             }
142*e4600f7fSJomo         }
143*e4600f7fSJomo         return r;
144*e4600f7fSJomo     }
145*e4600f7fSJomo }
146*e4600f7fSJomo 
147*e4600f7fSJomo /// 模块
148*e4600f7fSJomo struct Module {
149*e4600f7fSJomo     /// 模块名
150*e4600f7fSJomo     name: String,
151*e4600f7fSJomo     /// 模块文件路径
152*e4600f7fSJomo     path: PathBuf,
153*e4600f7fSJomo     /// 是否启用
154*e4600f7fSJomo     enable: bool,
155*e4600f7fSJomo }
156*e4600f7fSJomo 
157*e4600f7fSJomo impl Module {
new(name: String, path: PathBuf, enable: bool) -> Module158*e4600f7fSJomo     pub fn new(name: String, path: PathBuf, enable: bool) -> Module {
159*e4600f7fSJomo         Module { name, path, enable }
160*e4600f7fSJomo     }
161*e4600f7fSJomo 
name(&self) -> String162*e4600f7fSJomo     pub fn name(&self) -> String {
163*e4600f7fSJomo         self.name.clone()
164*e4600f7fSJomo     }
165*e4600f7fSJomo 
path(&self) -> PathBuf166*e4600f7fSJomo     pub fn path(&self) -> PathBuf {
167*e4600f7fSJomo         self.path.clone()
168*e4600f7fSJomo     }
169*e4600f7fSJomo 
enable(&self) -> bool170*e4600f7fSJomo     pub fn enable(&self) -> bool {
171*e4600f7fSJomo         self.enable.clone()
172*e4600f7fSJomo     }
173*e4600f7fSJomo }
174*e4600f7fSJomo 
175*e4600f7fSJomo /// feature
176*e4600f7fSJomo pub struct Feature {
177*e4600f7fSJomo     /// feature标签名
178*e4600f7fSJomo     name: String,
179*e4600f7fSJomo     /// 是否启用
180*e4600f7fSJomo     enable: bool,
181*e4600f7fSJomo }
182*e4600f7fSJomo 
183*e4600f7fSJomo impl Feature {
new(name: String, enable: bool) -> Feature184*e4600f7fSJomo     pub fn new(name: String, enable: bool) -> Feature {
185*e4600f7fSJomo         Feature { name, enable }
186*e4600f7fSJomo     }
187*e4600f7fSJomo 
name(&self) -> String188*e4600f7fSJomo     pub fn name(&self) -> String {
189*e4600f7fSJomo         self.name.clone()
190*e4600f7fSJomo     }
191*e4600f7fSJomo 
enable(&self) -> bool192*e4600f7fSJomo     pub fn enable(&self) -> bool {
193*e4600f7fSJomo         self.enable.clone()
194*e4600f7fSJomo     }
195*e4600f7fSJomo }
196