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