1use std::{
2 path::PathBuf,
3 process::exit,
4 sync::{Arc, Mutex, Weak},
5};
6
7use dadk_config::{common::target_arch::TargetArch, user::UserCleanLevel};
8use derive_builder::Builder;
9use log::error;
10#[cfg(test)]
11use test_base::{global::BaseGlobalTestContext, test_context::TestContext};
12
13use crate::{executor::cache::cache_root_init, scheduler::task_deque::TASK_DEQUE};
14
15#[derive(Debug, Builder)]
16#[builder(setter(into))]
17pub struct DadkUserExecuteContext {
18 sysroot_dir: Option<PathBuf>,
20 config_dir: Option<PathBuf>,
22 action: Action,
24 thread_num: Option<usize>,
26 cache_dir: Option<PathBuf>,
28
29 #[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
40impl DadkUserExecuteContext {
41 pub fn init(&self, self_arc: Arc<Self>) {
42 self.set_self_ref(Arc::downgrade(&self_arc));
43
44 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)]
105pub trait TestContextExt: TestContext {
106 fn base_context(&self) -> &BaseGlobalTestContext;
107
108 fn execute_context(&self) -> &DadkUserExecuteContext;
109}
110
111impl DadkUserExecuteContextBuilder {
112 #[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)]
126pub enum Action {
127 Build,
129 Clean(UserCleanLevel),
131 Install,
133}
134
135#[cfg(test)]
136pub struct DadkExecuteContextTestBuildX86_64V1 {
137 context: Arc<DadkUserExecuteContext>,
138}
139
140#[cfg(test)]
141impl 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)]
157pub struct DadkExecuteContextTestBuildRiscV64V1 {
158 context: Arc<DadkUserExecuteContext>,
159}
160
161#[cfg(test)]
162impl 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
177macro_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
201impl_for_test_context!(DadkExecuteContextTestBuildX86_64V1);
202impl_for_test_context!(DadkExecuteContextTestBuildRiscV64V1);