1 use std::{ 2 path::PathBuf, 3 process::exit, 4 sync::{Arc, Mutex, Weak}, 5 }; 6 7 use dadk_config::{common::target_arch::TargetArch, user::UserCleanLevel}; 8 use derive_builder::Builder; 9 use log::error; 10 #[cfg(test)] 11 use test_base::{global::BaseGlobalTestContext, test_context::TestContext}; 12 13 use crate::{executor::cache::cache_root_init, scheduler::task_deque::TASK_DEQUE}; 14 15 #[derive(Debug, Builder)] 16 #[builder(setter(into))] 17 pub struct DadkUserExecuteContext { 18 /// DragonOS sysroot在主机上的路径 19 sysroot_dir: Option<PathBuf>, 20 /// DADK任务配置文件所在目录 21 config_dir: Option<PathBuf>, 22 /// 要执行的操作 23 action: Action, 24 /// 并行线程数量 25 thread_num: Option<usize>, 26 /// dadk缓存根目录 27 cache_dir: Option<PathBuf>, 28 29 /// 目标架构 30 #[builder(default = "crate::DADKTask::default_target_arch()")] 31 target_arch: TargetArch, 32 33 #[cfg(test)] 34 base_test_context: Option<BaseGlobalTestContext>, 35 36 #[builder(setter(skip), default = "Mutex::new(Weak::new())")] 37 self_ref: Mutex<Weak<Self>>, 38 } 39 40 impl DadkUserExecuteContext { 41 pub fn init(&self, self_arc: Arc<Self>) { 42 self.set_self_ref(Arc::downgrade(&self_arc)); 43 44 // 初始化缓存目录 45 let r: Result<(), crate::executor::ExecutorError> = 46 cache_root_init(self.cache_dir().cloned()); 47 if r.is_err() { 48 error!("Failed to init cache root: {:?}", r.unwrap_err()); 49 exit(1); 50 } 51 52 if let Some(thread) = self.thread_num() { 53 TASK_DEQUE.lock().unwrap().set_thread(thread); 54 } 55 56 if self.config_dir().is_none() { 57 error!("Config dir is required for action: {:?}", self.action()); 58 exit(1); 59 } 60 61 if self.sysroot_dir().is_none() { 62 error!( 63 "dragonos sysroot dir is required for action: {:?}", 64 self.action() 65 ); 66 exit(1); 67 } 68 } 69 70 #[allow(dead_code)] 71 pub fn self_ref(&self) -> Option<Arc<Self>> { 72 self.self_ref.lock().unwrap().upgrade() 73 } 74 75 fn set_self_ref(&self, self_ref: Weak<Self>) { 76 *self.self_ref.lock().unwrap() = self_ref; 77 } 78 79 pub fn target_arch(&self) -> &TargetArch { 80 &self.target_arch 81 } 82 83 pub fn sysroot_dir(&self) -> Option<&PathBuf> { 84 self.sysroot_dir.as_ref() 85 } 86 87 pub fn config_dir(&self) -> Option<&PathBuf> { 88 self.config_dir.as_ref() 89 } 90 91 pub fn action(&self) -> &Action { 92 &self.action 93 } 94 95 pub fn thread_num(&self) -> Option<usize> { 96 self.thread_num 97 } 98 99 pub fn cache_dir(&self) -> Option<&PathBuf> { 100 self.cache_dir.as_ref() 101 } 102 } 103 104 #[cfg(test)] 105 pub trait TestContextExt: TestContext { 106 fn base_context(&self) -> &BaseGlobalTestContext; 107 108 fn execute_context(&self) -> &DadkUserExecuteContext; 109 } 110 111 impl DadkUserExecuteContextBuilder { 112 /// 用于测试的默认构建器 113 #[cfg(test)] 114 fn default_test_execute_context_builder(base_context: &BaseGlobalTestContext) -> Self { 115 Self::default() 116 .sysroot_dir(Some(base_context.fake_dragonos_sysroot())) 117 .action(Action::Build) 118 .thread_num(None) 119 .cache_dir(Some(base_context.fake_dadk_cache_root())) 120 .base_test_context(Some(base_context.clone())) 121 .clone() 122 } 123 } 124 125 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 126 pub enum Action { 127 /// 构建所有项目 128 Build, 129 /// 清理缓存 130 Clean(UserCleanLevel), 131 /// 安装到DragonOS sysroot 132 Install, 133 } 134 135 #[cfg(test)] 136 pub struct DadkExecuteContextTestBuildX86_64V1 { 137 context: Arc<DadkUserExecuteContext>, 138 } 139 140 #[cfg(test)] 141 impl TestContext for DadkExecuteContextTestBuildX86_64V1 { 142 fn setup() -> Self { 143 let base_context = BaseGlobalTestContext::setup(); 144 let context = 145 DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context) 146 .target_arch(TargetArch::X86_64) 147 .config_dir(Some(base_context.config_v1_dir())) 148 .build() 149 .expect("Failed to build DadkExecuteContextTestBuildX86_64V1"); 150 let context = Arc::new(context); 151 context.init(context.clone()); 152 DadkExecuteContextTestBuildX86_64V1 { context } 153 } 154 } 155 156 #[cfg(test)] 157 pub struct DadkExecuteContextTestBuildRiscV64V1 { 158 context: Arc<DadkUserExecuteContext>, 159 } 160 161 #[cfg(test)] 162 impl TestContext for DadkExecuteContextTestBuildRiscV64V1 { 163 fn setup() -> Self { 164 let base_context = BaseGlobalTestContext::setup(); 165 let context = 166 DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context) 167 .target_arch(TargetArch::RiscV64) 168 .config_dir(Some(base_context.config_v1_dir())) 169 .build() 170 .expect("Failed to build DadkExecuteContextTestBuildRiscV64V1"); 171 let context = Arc::new(context); 172 context.init(context.clone()); 173 DadkExecuteContextTestBuildRiscV64V1 { context } 174 } 175 } 176 177 macro_rules! impl_for_test_context { 178 ($context:ty) => { 179 #[cfg(test)] 180 impl std::ops::Deref for $context { 181 type Target = DadkUserExecuteContext; 182 183 fn deref(&self) -> &Self::Target { 184 &self.context 185 } 186 } 187 188 #[cfg(test)] 189 impl TestContextExt for $context { 190 fn base_context(&self) -> &BaseGlobalTestContext { 191 self.base_test_context.as_ref().unwrap() 192 } 193 194 fn execute_context(&self) -> &DadkUserExecuteContext { 195 &self.context 196 } 197 } 198 }; 199 } 200 201 impl_for_test_context!(DadkExecuteContextTestBuildX86_64V1); 202 impl_for_test_context!(DadkExecuteContextTestBuildRiscV64V1); 203