ax-plat-macros 技术文档
路径:
components/axplat_crates/axplat-macros类型:过程宏库 分层:组件层 / 可复用基础组件 版本:0.1.0文档依据:Cargo.toml、README.md、src/lib.rs
ax-plat-macros 是 axplat 体系的过程宏实现层。它的作用非常集中:一类宏把内核/运行时入口函数导出为固定符号名,另一类宏把 axplat 内部的平台 trait 接口转换成 crate_interface 风格的可调用分发表。这个 crate 本身几乎没有运行时逻辑,但它决定了平台入口契约和平台接口调用方式的生成语义。
1. 架构设计分析
1.1 设计定位
这个 crate 的定位 不是“给所有人直接使用的宏工具箱”,而是 axplat 的内部宏后端:
main/secondary_main:把运行时入口绑定到固定导出符号,服务平台早期引导。def_plat_interface:把平台 trait 接口接到crate_interface调用机制,服务运行期平台能力分发。- 它本身不提供
ax-percpu、不负责板级初始化,也不包含任何硬件抽象实现。
README.md 也明确说明:通常不应直接依赖 ax-plat-macros,而应通过 axplat 间接使用。
1.2 宏入口划分
#[ax_plat::main]对应的底层过程宏main:导出主核入口符号__axplat_main。#[ax_plat::secondary_main]对应的底层过程宏secondary_main:导出从核入口符号__axplat_secondary_main。#[def_plat_interface]:只在axplat内部使用,把 trait 变成def_interface + call_interface组合。
1.3 最关键的生成语义
main / secondary_main
这两个宏不会包装函数体,也不会生成额外入口逻辑,它们只做两件事:
- 校验函数签名。
- 在原函数上附加
#[unsafe(export_name = "...")]。
也就是说,宏的语义是“建立链接级契约”,而不是“建立运行时包装层”。
def_plat_interface
这个宏的生成结果包括三部分:
- 原始 trait 本身。
- trait 上附着
crate::__priv::def_interface。 - 为每个无
self的 trait 方法生成同名自由函数,内部转发到crate::__priv::call_interface!(Trait::method, ...)。
因此,def_plat_interface 把“平台 trait 定义”转成了“trait + 全局分发函数”双重接口模型,使 ax_plat::console::putchar() 这类调用可以像普通函数一样存在,同时底层仍由唯一的平台注册实现承接。
1.4 与 axplat 平台入口契约的关系
axplat 在运行期暴露 call_main(cpu_id, arg) 和可选 call_secondary_main(cpu_id),而这些函数又声明会调用外部 Rust 符号:
__axplat_main(cpu_id, arg) -> !__axplat_secondary_main(cpu_id) -> !
ax-plat-macros 的 main / secondary_main 正是负责把用户写的 Rust 函数导出成这两个固定符号。因此:
- 平台启动汇编或裸入口只需跳到
ax_plat::call_main/call_secondary_main。 - 运行时实现只需用
#[ax_plat::main]/#[ax_plat::secondary_main]标记自己的入口函数。
这就是平台包与运行时之间的链接级耦合点。
1.5 与 ax-percpu 的边界
ax-plat-macros 不提供 ax-percpu 宏能力。ax_plat::percpu 使用的是单独的 ax-percpu crate。因此在文档中不能把 ax-percpu 初始化或 #[ax_percpu::def_percpu] 误归为 ax-plat-macros 的职责。
2. 核心功能说明
2.1 主要功能
- 为主核和次核入口建立固定导出符号名。
- 为
axplat内部的平台 trait 接口生成统一的分发函数。 - 在编译期尽早拒绝错误签名或错误 trait 形态。
2.2 关键宏与使用场景
#[ax_plat::main]:用于主核运行时入口函数。#[ax_plat::secondary_main]:用于 SMP 从核入口函数。#[def_plat_interface]:用于axplat自己定义InitIf、ConsoleIf、MemIf、TimeIf、PowerIf、IrqIf等平台接口。
2.3 典型使用方式
正常使用方式应当通过 axplat 提供的对外宏入口,而不是直接依赖 ax-plat-macros:
#[ax_plat::main]
fn rust_main(cpu_id: usize, arg: usize) -> ! {
loop {}
}
3. 依赖关系图谱
3.1 关键直接依赖
syn:解析函数和 trait 语法树。quote、proc-macro2:生成导出属性和分发函数代码。
3.2 关键直接消费者
axplat:唯一最核心的直接消费者。对外 re-exportmain/secondary_main,对内使用def_plat_interface。
3.3 间接消费者
ax-runtime:通过#[ax_plat::main]/#[ax_plat::secondary_main]接入平台入口。components/axplat_crates/examples/*:最小平台样例。- 通过
axplat体系间接复用入口契约的 ArceOS、StarryOS 和 Axvisor 路径。
4. 开发指南
4.1 使用约束
main目标函数必须精确符合fn(cpu_id: usize, arg: usize) -> !。secondary_main目标函数必须精确符合fn(cpu_id: usize) -> !。- 两者属性参数都必须为空。
def_plat_interface只能作用于 trait,且 trait 方法不能带self。