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::{global::BaseGlobalTestContext, test_context::TestContext}; 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<BaseGlobalTestContext>, 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.config_dir().is_none() { 59 error!("Config dir is required for action: {:?}", self.action()); 60 exit(1); 61 } 62 63 if self.sysroot_dir().is_none() { 64 error!( 65 "dragonos sysroot dir is required for action: {:?}", 66 self.action() 67 ); 68 exit(1); 69 } 70 } 71 72 #[allow(dead_code)] 73 pub fn self_ref(&self) -> Option<Arc<Self>> { 74 self.self_ref.lock().unwrap().upgrade() 75 } 76 77 fn set_self_ref(&self, self_ref: Weak<Self>) { 78 *self.self_ref.lock().unwrap() = self_ref; 79 } 80 81 pub fn target_arch(&self) -> &TargetArch { 82 &self.target_arch 83 } 84 85 pub fn sysroot_dir(&self) -> Option<&PathBuf> { 86 self.sysroot_dir.as_ref() 87 } 88 89 pub fn config_dir(&self) -> Option<&PathBuf> { 90 self.config_dir.as_ref() 91 } 92 93 pub fn action(&self) -> &Action { 94 &self.action 95 } 96 97 pub fn thread_num(&self) -> Option<usize> { 98 self.thread_num 99 } 100 101 pub fn cache_dir(&self) -> Option<&PathBuf> { 102 self.cache_dir.as_ref() 103 } 104 } 105 106 #[cfg(test)] 107 pub trait TestContextExt: TestContext { 108 fn base_context(&self) -> &BaseGlobalTestContext; 109 110 fn execute_context(&self) -> &DadkUserExecuteContext; 111 } 112 113 impl DadkUserExecuteContextBuilder { 114 /// 用于测试的默认构建器 115 #[cfg(test)] 116 fn default_test_execute_context_builder(base_context: &BaseGlobalTestContext) -> Self { 117 Self::default() 118 .sysroot_dir(Some(base_context.fake_dragonos_sysroot())) 119 .action(Action::Build) 120 .thread_num(None) 121 .cache_dir(Some(base_context.fake_dadk_cache_root())) 122 .base_test_context(Some(base_context.clone())) 123 .clone() 124 } 125 } 126 127 #[cfg(test)] 128 pub struct DadkExecuteContextTestBuildX86_64V1 { 129 context: Arc<DadkUserExecuteContext>, 130 } 131 132 #[cfg(test)] 133 impl TestContext for DadkExecuteContextTestBuildX86_64V1 { 134 fn setup() -> Self { 135 let base_context = BaseGlobalTestContext::setup(); 136 let context = 137 DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context) 138 .target_arch(TargetArch::X86_64) 139 .config_dir(Some(base_context.config_v1_dir())) 140 .build() 141 .expect("Failed to build DadkExecuteContextTestBuildX86_64V1"); 142 let context = Arc::new(context); 143 context.init(context.clone()); 144 DadkExecuteContextTestBuildX86_64V1 { context } 145 } 146 } 147 148 #[cfg(test)] 149 pub struct DadkExecuteContextTestBuildRiscV64V1 { 150 context: Arc<DadkUserExecuteContext>, 151 } 152 153 #[cfg(test)] 154 impl TestContext for DadkExecuteContextTestBuildRiscV64V1 { 155 fn setup() -> Self { 156 let base_context = BaseGlobalTestContext::setup(); 157 let context = 158 DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context) 159 .target_arch(TargetArch::RiscV64) 160 .config_dir(Some(base_context.config_v1_dir())) 161 .build() 162 .expect("Failed to build DadkExecuteContextTestBuildRiscV64V1"); 163 let context = Arc::new(context); 164 context.init(context.clone()); 165 DadkExecuteContextTestBuildRiscV64V1 { context } 166 } 167 } 168 169 macro_rules! impl_for_test_context { 170 ($context:ty) => { 171 #[cfg(test)] 172 impl std::ops::Deref for $context { 173 type Target = DadkUserExecuteContext; 174 175 fn deref(&self) -> &Self::Target { 176 &self.context 177 } 178 } 179 180 #[cfg(test)] 181 impl TestContextExt for $context { 182 fn base_context(&self) -> &BaseGlobalTestContext { 183 self.base_test_context.as_ref().unwrap() 184 } 185 186 fn execute_context(&self) -> &DadkUserExecuteContext { 187 &self.context 188 } 189 } 190 }; 191 } 192 193 impl_for_test_context!(DadkExecuteContextTestBuildX86_64V1); 194 impl_for_test_context!(DadkExecuteContextTestBuildRiscV64V1); 195