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 context::DadkUserExecuteContext; 102 use log::info; 103 use parser::task::DADKTask; 104 105 use crate::scheduler::Scheduler; 106 107 pub mod context; 108 pub mod executor; 109 pub mod parser; 110 mod scheduler; 111 mod utils; 112 113 pub fn dadk_user_main(context: DadkUserExecuteContext) { 114 let context = Arc::new(context); 115 context.init(context.clone()); 116 // DragonOS sysroot在主机上的路径 117 118 info!( 119 "DragonOS sysroot dir: {}", 120 context 121 .sysroot_dir() 122 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 123 ); 124 info!( 125 "Config dir: {}", 126 context 127 .config_dir() 128 .map_or_else(|| "None".to_string(), |d| d.display().to_string()) 129 ); 130 info!("Action: {:?}", context.action()); 131 info!( 132 "Thread num: {}", 133 context.thread_num().map_or_else(|| 0, |t| t) 134 ); 135 136 let mut parser = parser::Parser::new(context.config_dir().unwrap().clone()); 137 let r = parser.parse(); 138 if r.is_err() { 139 exit(1); 140 } 141 let tasks: Vec<(PathBuf, DADKTask)> = r.unwrap(); 142 // info!("Parsed tasks: {:?}", tasks); 143 144 let scheduler = Scheduler::new( 145 context.clone(), 146 context.sysroot_dir().cloned().unwrap(), 147 *context.action(), 148 tasks, 149 ); 150 if scheduler.is_err() { 151 exit(1); 152 } 153 154 let r = scheduler.unwrap().run(); 155 if r.is_err() { 156 exit(1); 157 } 158 } 159