1 //! # DADK - DragonOS Application Development Kit 2 //! # DragonOS 应用开发工具 3 //! 4 //! ## 简介 5 //! 6 //! DADK是一个用于开发DragonOS应用的工具包,设计目的是为了让开发者能够更加方便的开发DragonOS应用。 7 //! 8 //! ### DADK做什么? 9 //! 10 //! - 自动配置libc等编译用户程序所需的环境 11 //! - 自动处理软件库的依赖关系 12 //! - 自动处理软件库的编译 13 //! - 一键将软件库安装到DragonOS系统中 14 //! 15 //! ### DADK不做什么? 16 //! 17 //! - DADK不会帮助开发者编写代码 18 //! - DADK不提供任何开发DragonOS应用所需的API。这部分工作由libc等库来完成 19 //! 20 //! ## License 21 //! 22 //! DADK is licensed under the [GPLv2 License](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html). 23 //! 24 //! ## 快速开始 25 //! 26 //! ### 安装DADK 27 //! 28 //! DADK是一个Rust程序,您可以通过Cargo来安装DADK。 29 //! 30 //! ```shell 31 //! # 从GitHub安装最新版 32 //! cargo install --git https://github.com/DragonOS-Community/DADK.git 33 //! 34 //! # 从crates.io下载 35 //! cargo install dadk 36 //! 37 //! ``` 38 //! 39 //! ## DADK的工作原理 40 //! 41 //! DADK使用(任务名,任务版本)来标识每个构建目标。当使用DADK构建DragonOS应用时,DADK会根据用户的配置文件,自动完成以下工作: 42 //! 43 //! - 解析配置文件,生成DADK任务列表 44 //! - 根据DADK任务列表,进行拓扑排序。这一步会自动处理软件库的依赖关系。 45 //! - 收集环境变量信息,并根据DADK任务列表,设置全局环境变量、任务环境变量。 46 //! - 根据拓扑排序后的DADK任务列表,自动执行任务。 47 //! 48 //! ### DADK与环境变量 49 //! 50 //! 环境变量的设置是DADK能正常工作的关键因素之一,您可以在您的编译脚本中,通过引用环境变量,来获得其他软件库的编译信息。 51 //! 这是使得您的应用能够自动依赖其他软件库的关键一步。 52 //! 53 //! 只要您的编译脚本能够正确地引用环境变量,DADK就能够自动处理软件库的依赖关系。 54 //! 55 //! DADK会设置以下全局环境变量: 56 //! 57 //! - `DADK_CACHE_ROOT`:DADK的缓存根目录。您可以在编译脚本中,通过引用该环境变量,来获得DADK的缓存根目录。 58 //! - `DADK_BUILD_CACHE_DIR_任务名_任务版本`:DADK的任务构建结果缓存目录。当您要引用其他软件库的构建结果时,可以通过该环境变量来获得。 59 //! 同时,您也要在构建您的app时,把构建结果放到您的软件库的构建结果缓存目录(通过对应的环境变量获得)中。 60 //! - `DADK_SOURCE_CACHE_DIR_任务名_任务版本`:DADK的某个任务的源码目录。当您要引用其他软件库的源码目录时,可以通过该环境变量来获得。 61 //! 62 //! 同时,DADK会为每个任务设置其自身在配置文件中指定的环境变量。 63 //! 64 //! #### 全局环境变量命名格式 65 //! 66 //! 全局环境变量中的任务名和任务版本,都会被转换为大写字母,并对特殊字符进行替换。替换表如下: 67 //! 68 //! | 原字符 | 替换字符 | 69 //! | ------ | -------- | 70 //! | `.` | `_` | 71 //! | `-` | `_` | 72 //! | `\t` | `_` | 73 //! | 空格 | `_` | 74 //! | `+` | `_` | 75 //! | `*` | `_` | 76 //! 77 //! **举例**:对于任务`libc-0.1.0`,其构建结果的全局环境变量名为`DADK_BUILD_CACHE_DIR_LIBC_0_1_0`。 78 //! 79 //! 80 //! ## TODO 81 //! 82 //! - 支持从在线归档文件下载源码、构建好的软件库 83 //! - 支持自动更新 84 //! - 完善clean命令的逻辑 85 86 #![feature(extract_if)] 87 #![feature(io_error_more)] 88 89 #[macro_use] 90 extern crate lazy_static; 91 extern crate log; 92 extern crate serde; 93 extern crate serde_json; 94 95 #[cfg(test)] 96 extern crate test_base; 97 98 use std::{path::PathBuf, process::exit, sync::Arc}; 99 100 use clap::Parser; 101 102 use log::info; 103 use parser::task::DADKTask; 104 105 use crate::{ 106 console::CommandLineArgs, context::DadkUserExecuteContextBuilder, scheduler::Scheduler, 107 }; 108 109 mod console; 110 mod context; 111 mod executor; 112 pub mod parser; 113 mod scheduler; 114 pub mod static_resources; 115 mod utils; 116 117 pub fn dadk_user_main() { 118 let args = CommandLineArgs::parse(); 119 120 info!("DADK run with args: {:?}", &args); 121 122 let context = DadkUserExecuteContextBuilder::default() 123 .sysroot_dir(args.sysroot_dir) 124 .config_dir(args.config_dir) 125 .action(args.action) 126 .thread_num(args.thread) 127 .cache_dir(args.cache_dir) 128 .build() 129 .expect("Failed to build execute context"); 130 let context = Arc::new(context); 131 context.init(context.clone()); 132 // DragonOS sysroot在主机上的路径 133 134 info!( 135 "DragonOS sysroot dir: {}", 136 context 137 .sysroot_dir() 138 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 139 ); 140 info!( 141 "Config dir: {}", 142 context 143 .config_dir() 144 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 145 ); 146 info!("Action: {:?}", context.action()); 147 info!( 148 "Thread num: {}", 149 context.thread_num().map_or_else(|| 0, |t| t) 150 ); 151 152 let mut parser = parser::Parser::new(context.config_dir().unwrap().clone()); 153 let r = parser.parse(); 154 if r.is_err() { 155 exit(1); 156 } 157 let tasks: Vec<(PathBuf, DADKTask)> = r.unwrap(); 158 // info!("Parsed tasks: {:?}", tasks); 159 160 let scheduler = Scheduler::new( 161 context.clone(), 162 context.sysroot_dir().cloned().unwrap(), 163 *context.action(), 164 tasks, 165 ); 166 if scheduler.is_err() { 167 exit(1); 168 } 169 170 let r = scheduler.unwrap().run(); 171 if r.is_err() { 172 exit(1); 173 } 174 } 175