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 pub extern crate clap; 92 extern crate log; 93 extern crate serde; 94 extern crate serde_json; 95 96 #[cfg(test)] 97 extern crate test_base; 98 99 use std::{path::PathBuf, process::exit, sync::Arc}; 100 101 use log::info; 102 use parser::task::DADKTask; 103 104 use crate::{ 105 console::CommandLineArgs, context::DadkUserExecuteContextBuilder, scheduler::Scheduler, 106 }; 107 108 pub mod console; 109 mod context; 110 pub mod executor; 111 pub mod parser; 112 mod scheduler; 113 pub mod static_resources; 114 mod utils; 115 116 pub fn dadk_user_main(args: CommandLineArgs) { 117 let context = DadkUserExecuteContextBuilder::default() 118 .sysroot_dir(args.sysroot_dir) 119 .config_dir(args.config_dir) 120 .action(args.action) 121 .thread_num(args.thread) 122 .cache_dir(args.cache_dir) 123 .build() 124 .expect("Failed to build execute context"); 125 let context = Arc::new(context); 126 context.init(context.clone()); 127 // DragonOS sysroot在主机上的路径 128 129 info!( 130 "DragonOS sysroot dir: {}", 131 context 132 .sysroot_dir() 133 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 134 ); 135 info!( 136 "Config dir: {}", 137 context 138 .config_dir() 139 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 140 ); 141 info!("Action: {:?}", context.action()); 142 info!( 143 "Thread num: {}", 144 context.thread_num().map_or_else(|| 0, |t| t) 145 ); 146 147 let mut parser = parser::Parser::new(context.config_dir().unwrap().clone()); 148 let r = parser.parse(); 149 if r.is_err() { 150 exit(1); 151 } 152 let tasks: Vec<(PathBuf, DADKTask)> = r.unwrap(); 153 // info!("Parsed tasks: {:?}", tasks); 154 155 let scheduler = Scheduler::new( 156 context.clone(), 157 context.sysroot_dir().cloned().unwrap(), 158 *context.action(), 159 tasks, 160 ); 161 if scheduler.is_err() { 162 exit(1); 163 } 164 165 let r = scheduler.unwrap().run(); 166 if r.is_err() { 167 exit(1); 168 } 169 } 170