|
| 1 | +--- |
| 2 | +sidebar_position: 1 |
| 3 | +--- |
| 4 | + |
| 5 | +# 总体架构 |
| 6 | + |
| 7 | +Axvisor 是一个基于 Rust 的虚拟机监视器(Hypervisor)项目,采用了 `Cargo xtask` 构建系统来支持复杂的多平台、多架构的虚拟化解决方案。本文档将从源码角度详细分析 Axvisor 的构建系统,包括 xtask 的实现细节、构建配置管理、链接脚本生成、多平台支持等方面,帮助开发者深入理解项目的工作原理和构建流程。 |
| 8 | + |
| 9 | +## 总体架构 |
| 10 | + |
| 11 | +作为一个虚拟机监视器项目,Axvisor 需要支持多种硬件平台(如 ARM、x86、RISC-V)和不同的开发板(如 QEMU、Orange Pi、Phytium Pi 等),同时还要管理多个虚拟机配置以及处理在不同开发板上的开发调试。 |
| 12 | + |
| 13 | +这种复杂性要求一个高度灵活且可扩展的构建系统,最终我们选择采用 `Cargo xtask` 这套解决方案。为此,我们分别添加实现了构建和调试相关的命令,即支持一键构建,也可以一键调试! |
| 14 | + |
| 15 | +### 构建系统架构图 |
| 16 | + |
| 17 | +下图展示了 Axvisor 构建系统的整体架构,包括各个组件之间的关系和数据流向: |
| 18 | + |
| 19 | +```mermaid |
| 20 | +graph TB |
| 21 | + A[开发者] -->|cargo xtask| B[xtask 主程序] |
| 22 | + B --> C[命令解析] |
| 23 | + C --> D[defconfig] |
| 24 | + C --> E[build] |
| 25 | + C --> F[clippy] |
| 26 | + C --> G[qemu] |
| 27 | + C --> H[uboot] |
| 28 | + C --> I[image] |
| 29 | + C --> J[menuconfig] |
| 30 | + |
| 31 | + D --> K[板级配置管理] |
| 32 | + E --> L[构建配置加载] |
| 33 | + F --> M[代码质量检查] |
| 34 | + G --> N[QEMU 运行] |
| 35 | + H --> O[U-Boot 运行] |
| 36 | + I --> P[镜像管理] |
| 37 | + J --> Q[交互式配置] |
| 38 | + |
| 39 | + K --> R[configs/board/] |
| 40 | + L --> S[.build.toml] |
| 41 | + L --> T[环境变量设置] |
| 42 | + M --> U[多目标检查] |
| 43 | + N --> V[QEMU 配置] |
| 44 | + O --> W[U-Boot 配置] |
| 45 | + P --> X[镜像下载/验证] |
| 46 | + Q --> Y[配置界面] |
| 47 | + |
| 48 | + L --> Z[Cargo 构建] |
| 49 | + Z --> AA[内核构建] |
| 50 | + AA --> AB[链接脚本生成] |
| 51 | + AB --> AC[最终二进制] |
| 52 | + |
| 53 | + subgraph "配置文件" |
| 54 | + R |
| 55 | + S |
| 56 | + AD[configs/vms/] |
| 57 | + AE[defconfig.toml] |
| 58 | + end |
| 59 | + |
| 60 | + subgraph "构建产物" |
| 61 | + AC |
| 62 | + AF[链接脚本] |
| 63 | + AG[生成的 Rust 代码] |
| 64 | + end |
| 65 | +``` |
| 66 | + |
| 67 | +### 构建流程时序图 |
| 68 | + |
| 69 | +下面的时序图展示了 Axvisor 构建系统的主要工作流程,从配置设置到最终构建完成的整个过程: |
| 70 | + |
| 71 | +```mermaid |
| 72 | +sequenceDiagram |
| 73 | + participant Dev as 开发者 |
| 74 | + participant XT as xtask |
| 75 | + participant BC as 构建配置 |
| 76 | + participant Cargo as Cargo |
| 77 | + participant BS as 构建脚本 |
| 78 | + participant LS as 链接脚本 |
| 79 | + participant Bin as 最终二进制 |
| 80 | +
|
| 81 | + Dev->>XT: cargo xtask defconfig board |
| 82 | + XT->>BC: 复制板级配置 |
| 83 | + BC-->>XT: 配置完成 |
| 84 | + |
| 85 | + Dev->>XT: cargo xtask build |
| 86 | + XT->>BC: 加载构建配置 |
| 87 | + BC-->>XT: 返回配置参数 |
| 88 | + XT->>Cargo: 调用 cargo build |
| 89 | + Cargo->>BS: 执行 build.rs |
| 90 | + BS->>LS: 生成链接脚本 |
| 91 | + BS->>BS: 生成配置代码 |
| 92 | + BS-->>Cargo: 构建完成 |
| 93 | + Cargo-->>XT: 构建成功 |
| 94 | + XT-->>Dev: 构建完成 |
| 95 | + |
| 96 | + Dev->>XT: cargo xtask qemu |
| 97 | + XT->>BC: 加载构建配置 |
| 98 | + XT->>Bin: 启动 QEMU |
| 99 | + Bin-->>XT: 系统运行 |
| 100 | + XT-->>Dev: QEMU 运行中 |
| 101 | + |
| 102 | + Dev->>XT: cargo xtask uboot |
| 103 | + XT->>BC: 加载构建配置 |
| 104 | + XT->>Bin: 启动 U-Boot |
| 105 | + Bin-->>XT: 系统运行 |
| 106 | + XT-->>Dev: U-Boot 运行中 |
| 107 | +``` |
| 108 | + |
| 109 | +## 什么是 Cargo xtask? |
| 110 | + |
| 111 | +Cargo xtask 是 Rust 生态系统中的一种常见模式,用于管理项目的开发任务和构建流程。它本质上是一个独立的 Rust 二进制程序,通常位于项目的 `xtask/` 目录下,通过 Cargo 运行来执行各种项目特定的任务。 |
| 112 | + |
| 113 | +与传统使用 Makefile 或其他构建工具不同,xtask 允许开发者使用 Rust 语言本身来编写构建脚本,这样可以充分利用 Rust 的类型系统、错误处理和生态系统。对于像 Axvisor 这样的复杂项目,xtask 提供了更加灵活和强大的构建管理能力。 |
| 114 | + |
| 115 | +### xtask 的优势 |
| 116 | + |
| 117 | +1. **一致性**:使用熟悉的 Rust 生态系统和工具链,开发者不需要学习新的构建语言或工具 |
| 118 | +2. **可扩展性**:可以轻松添加新的构建任务和功能,利用 Rust 的模块化特性组织代码 |
| 119 | +3. **跨平台**:与 Cargo 一样,支持多平台构建,无需为不同平台编写不同的构建脚本 |
| 120 | +4. **集成性**:与现有 Rust 工具链无缝集成,可以直接使用 Cargo 的各种功能和插件 |
| 121 | +5. **类型安全**:利用 Rust 的类型系统,在编译时就能发现构建脚本中的错误 |
| 122 | +6. **丰富的生态系统**:可以使用 Cargo 生态系统中的所有库来编写构建脚本 |
| 123 | + |
| 124 | +## Axvisor 的 xtask 架构 |
| 125 | + |
| 126 | +Axvisor 的 xtask 实现采用了模块化设计,将不同的功能分散到独立的模块中,每个模块负责特定的任务。这种设计使得代码结构清晰,易于维护和扩展。 |
| 127 | + |
| 128 | +### 项目结构 |
| 129 | + |
| 130 | +每个模块都有明确的职责分工,这种模块化设计使得代码更加清晰和易于维护。例如,`image.rs` 专门负责虚拟机镜像的下载、验证和管理,而 `clippy.rs` 则专注于代码质量检查。 |
| 131 | + |
| 132 | +``` |
| 133 | +xtask/ |
| 134 | +├── Cargo.toml # xtask 依赖配置 |
| 135 | +└── src/ |
| 136 | + ├── main.rs # 主入口点和命令行解析 |
| 137 | + ├── cargo.rs # Cargo 相关操作(QEMU、U-Boot 运行) |
| 138 | + ├── clippy.rs # 代码质量检查 |
| 139 | + ├── ctx.rs # 上下文管理 |
| 140 | + ├── image.rs # 客户机镜像管理 |
| 141 | + ├── menuconfig.rs # 交互式配置 |
| 142 | + ├── tbuld.rs # 构建配置管理 |
| 143 | + └── vmconfig.rs # 虚拟机配置 |
| 144 | +``` |
| 145 | + |
| 146 | +### 核心组件 |
| 147 | + |
| 148 | +#### 主入口点 |
| 149 | + |
| 150 | +[`main.rs`](https://github.com/arceos-hypervisor/axvisor/tree/next/xtask/src/main.rs) 是 xtask 的入口点,使用 `clap` 库进行命令行参数解析。该文件定义了所有可用的命令和它们的参数结构。通过使用 Rust 的强类型系统和 `clap` 的派生宏,代码既简洁又类型安全。 |
| 151 | + |
| 152 | +```rust |
| 153 | +#[derive(Parser)] |
| 154 | +#[command(name = "xtask")] |
| 155 | +#[command(about = "ArceOS build configuration management tool")] |
| 156 | +struct Cli { |
| 157 | + #[command(subcommand)] |
| 158 | + command: Commands, |
| 159 | +} |
| 160 | + |
| 161 | +#[derive(Subcommand)] |
| 162 | +enum Commands { |
| 163 | + /// Set default build configuration from board configs |
| 164 | + Defconfig { board_name: String }, |
| 165 | + Build, |
| 166 | + /// Run clippy checks across all targets and feature combinations |
| 167 | + Clippy(ClippyArgs), |
| 168 | + Qemu(QemuArgs), |
| 169 | + Uboot(UbootArgs), |
| 170 | + Vmconfig, |
| 171 | + Menuconfig, |
| 172 | + /// Guest Image management |
| 173 | + Image(image::ImageArgs), |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +这种设计模式使得添加新命令变得非常简单,只需要在 `Commands` 枚举中添加新的变体,并在 `main` 函数中添加相应的处理逻辑即可。每个命令都可以有自己的参数结构,实现了高度的可扩展性。 |
| 178 | + |
| 179 | +#### 与 ostool 的集成 |
| 180 | + |
| 181 | +[`ctx.rs`](https://github.com/arceos-hypervisor/axvisor/tree/next/xtask/src/ctx.rs) 提供了构建上下文管理,这是整个 xtask 系统的核心数据结构。它封装了构建过程中需要的所有状态信息,包括工作目录、构建配置路径和虚拟机配置列表等。 |
| 182 | + |
| 183 | +```rust |
| 184 | +pub struct Context { |
| 185 | + pub ctx: AppContext, |
| 186 | + pub build_config_path: Option<std::path::PathBuf>, |
| 187 | + pub vmconfigs: Vec<String>, |
| 188 | +} |
| 189 | +``` |
| 190 | + |
| 191 | +通过将状态集中管理,避免了在各个模块之间传递大量参数,简化了代码结构。`AppContext` 来自 `ostool` 库,它是 Axvisor 的 xtask 系统与 `ostool` 紧密集成的桥接点,而 `Context` 在此基础上扩展了 Axvisor 特定的需求。这种集成方式带来了以下优势: |
| 192 | + |
| 193 | +1. **功能复用**:充分利用 `ostool` 的成熟功能,避免重复开发 |
| 194 | +2. **类型安全**:通过 Rust 类型系统确保配置和操作的类型安全 |
| 195 | +3. **扩展性**:可以轻松扩展 `ostool` 的功能,而不影响 xtask 的核心逻辑 |
| 196 | +4. **维护性**:将通用功能集中在 `ostool` 中,降低维护成本 |
| 197 | + |
| 198 | +#### 构建配置管理 |
| 199 | + |
| 200 | +[`tbuld.rs`](https://github.com/arceos-hypervisor/axvisor/tree/next/xtask/src/tbuld.rs) 定义了构建配置结构和管理逻辑,这是 xtask 系统中最复杂的模块之一。它负责解析构建配置文件,验证参数,并将配置转换为 Cargo 可以理解的格式。 |
| 201 | + |
| 202 | +```rust |
| 203 | +#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)] |
| 204 | +pub struct Config { |
| 205 | + /// target triple |
| 206 | + pub target: String, |
| 207 | + /// features to enable |
| 208 | + pub features: Vec<String>, |
| 209 | + /// log level feature |
| 210 | + pub log: Option<LogLevel>, |
| 211 | + /// other cargo args |
| 212 | + pub cargo_args: Vec<String>, |
| 213 | + /// whether to output as binary |
| 214 | + pub to_bin: bool, |
| 215 | + pub smp: Option<usize>, |
| 216 | + pub vm_configs: Vec<String>, |
| 217 | +} |
| 218 | +``` |
| 219 | + |
| 220 | +这个配置结构体使用了多个 derive 宏,包括 `Serialize`、`Deserialize` 和 `JsonSchema`,使得配置可以被序列化为多种格式(TOML、JSON 等),并且可以自动生成 JSON Schema 用于验证。这种设计使得配置系统既灵活又类型安全,可以在编译时捕获配置错误。 |
| 221 | + |
| 222 | +该模块还实现了配置加载逻辑,包括路径解析、文件读取、错误处理等复杂功能。它支持相对路径和绝对路径,可以自动扩展环境变量,并提供了详细的错误信息来帮助用户诊断配置问题。 |
0 commit comments