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