dadk_user/
context.rs

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    /// 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
40impl 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)]
105pub trait TestContextExt: TestContext {
106    fn base_context(&self) -> &BaseGlobalTestContext;
107
108    fn execute_context(&self) -> &DadkUserExecuteContext;
109}
110
111impl 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)]
126pub enum Action {
127    /// 构建所有项目
128    Build,
129    /// 清理缓存
130    Clean(UserCleanLevel),
131    /// 安装到DragonOS sysroot
132    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);