A Rust project consisting of two complementary crates for initializing global static variables asynchronously before program startup.
- Overview
- Project Structure
- Components
- Why Separate Projects?
- Installation
- Usage
- Design
- Tech Stack
- License
The xboot project provides a comprehensive solution for async static initialization in Rust applications. It consists of two main components:
- xboot: Core async initialization orchestration using linkme's distributed slice mechanism
- static_: User-friendly declarative macro interface that builds upon xboot
This system enables modern Rust applications to initialize resources like database connections, Redis clients, and other async-dependent services as module-level static variables before the main program logic begins.
xboot/
├── static_/ # High-level macro interface
│ ├── src/
│ │ └── lib.rs # init! macro implementation
│ ├── tests/
│ │ └── main.rs # Integration tests
│ └── Cargo.toml # Package configuration
├── xboot/ # Core initialization engine
│ ├── src/
│ │ └── lib.rs # linkme-based implementation
│ ├── tests/
│ │ └── main.rs # Usage example
│ └── Cargo.toml # Package configuration
└── README.md # This file
xboot is the foundational crate that enables async static initialization using linkme's distributed slice mechanism. It collects async initialization functions at compile time and executes them at runtime startup.
Key Features:
- Zero-cost compile-time collection via linker sections
- Cross-platform support (Linux, macOS, Windows)
- Simple macro-based API for registration
- Compatible with tokio runtime
static_ provides a declarative macro interface that simplifies the usage of xboot. It handles the boilerplate of creating OnceCell instances, wrapping values, and managing initialization flow.
Key Features:
- Declarative macro for async static initialization
- Automatic error handling with logging
- Thread-safe access via
OnceCellwrapper - Seamless integration with tokio runtime
The separation of xboot and static_ into distinct projects is a deliberate architectural decision designed to avoid dependency conflicts with the linkme crate.
The linkme crate, which xboot uses for distributed slice functionality, has specific requirements about how it's linked:
- Single Instance Required:
linkmerequires that only one version of the crate be linked in the final binary - Compilation Conflicts: If multiple crates in the dependency graph depend on different versions of
linkme, linking conflicts occur - Binary Size Impact: Multiple
linkmeinstances can increase binary size and cause symbol conflicts
By separating the project into two crates:
- xboot: Contains the core
linkme-based implementation - static_: Provides a clean interface that depends on xboot
Other projects can depend on static_ (or directly on xboot) as remote dependencies from crates.io, ensuring that only one version of linkme is included in the final binary.
This architecture:
- Prevents
linkmeversion conflicts across the dependency graph - Ensures consistent behavior across all dependent projects
- Maintains a clean separation of concerns between core functionality and user interface
- Allows independent versioning of the interface layer (static_) and core implementation (xboot)
Add to your Cargo.toml:
[dependencies]
static_ = "0.1" # Recommended: Use the high-level interface
# Or
xboot = "0.1" # Direct access to core functionalityuse aok::Result;
use tokio::time::{Duration, sleep};
use log::info;
// Define a resource that needs async initialization
pub struct Database {
connection: String,
}
impl Database {
pub async fn connect(url: &str) -> Result<Self> {
info!("Connecting to database...");
sleep(Duration::from_secs(2)).await;
Ok(Self { connection: url.to_string() })
}
pub async fn query(&self, sql: &str) -> Result<()> {
info!("Executing query on {}: {}", self.connection, sql);
Ok(())
}
}
// Declare async-initialized static variable using static_
static_::init!(DB: Database async {
Database::connect("postgres://localhost/myapp").await
});
#[tokio::main]
async fn main() -> Result<()> {
// Initialize all registered statics
xboot::init().await?;
info!("All statics initialized");
// Use the initialized static like a regular variable
DB.query("SELECT * FROM users").await?;
Ok(())
}graph TD
A["Program Start"] --> B["static_::init! macro expands"]
B --> C["Creates OnceCell and registers with xboot"]
C --> D["xboot::add! macro registers function"]
D --> E["Linker collects all functions into ASYNC slice"]
E --> F["Runtime: xboot::init() called"]
F --> G["Iterates through ASYNC slice"]
G --> H["Executes all async initializations"]
H --> I["Results stored in OnceCell instances"]
I --> J["Static variables ready for use"]
- static_::init!: Creates
OnceCellinstances and registers initialization with xboot - xboot::add!: Registers async initialization functions to the distributed slice
- linkme: Collects all registered functions at link time
- xboot::init(): Executes all registered initializations at runtime
| Crate | Purpose |
|---|---|
| linkme | Distributed slice for compile-time collection |
| tokio | Async runtime and task spawning |
| async_wrap | OnceCell and Wrap types |
| paste | Macro identifier concatenation |
| gensym | Unique symbol generation |
| aok | Result type utilities |
| log | Error logging |
This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.
We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:
一个由两个互补的 Rust crate 组成的项目,用于在程序启动前异步初始化全局静态变量。
xboot 项目为 Rust 应用程序中的异步静态初始化提供了全面的解决方案。它由两个主要组件组成:
- xboot: 基于 linkme 分布式切片机制的核心异步初始化编排器
- static_: 基于 xboot 构建的声明式宏用户界面
该系统使现代 Rust 应用程序能够在主程序逻辑开始前,将数据库连接、Redis 客户端和其他依赖异步的服务初始化为模块级静态变量。
xboot/
├── static_/ # 高级宏接口
│ ├── src/
│ │ └── lib.rs # init! 宏实现
│ ├── tests/
│ │ └── main.rs # 集成测试
│ └── Cargo.toml # 包配置
├── xboot/ # 核心初始化引擎
│ ├── src/
│ │ └── lib.rs # 基于 linkme 的实现
│ ├── tests/
│ │ └── main.rs # 使用示例
│ └── Cargo.toml # 包配置
└── README.md # 本文件
xboot 是基础 crate,使用 linkme 的分布式切片机制实现异步静态初始化。它在编译期收集异步初始化函数,在运行时启动阶段执行。
主要特性:
- 通过链接器段实现零开销编译期收集
- 跨平台支持(Linux、macOS、Windows)
- 简洁的宏注册 API
- 兼容 tokio 运行时
static_ 提供声明式宏接口,简化了 xboot 的使用。它处理创建 OnceCell 实例、包装值和管理初始化流程的样板代码。
主要特性:
- 声明式宏实现异步静态初始化
- 自动错误处理与日志记录
- 基于
OnceCell的线程安全访问 - 无缝集成 tokio 运行时
将 xboot 和 static_ 分离为独立项目是经过深思熟虑的架构决策,旨在避免与 linkme crate 的依赖冲突。
linkme crate(xboot 用于分布式切片功能)对其链接方式有特定要求:
- 单一实例要求:
linkme要求最终二进制文件中只链接一个版本的 crate - 编译冲突: 如果依赖图中的多个 crate 依赖不同版本的
linkme,会发生链接冲突 - 二进制大小影响: 多个
linkme实例会增加二进制大小并可能导致符号冲突
通过将项目分离为两个 crate:
- xboot: 包含基于
linkme的核心实现 - static_: 提供依赖 xboot 的简洁接口
其他项目可以从 crates.io 作为远程依赖使用 static_(或直接使用 xboot),确保最终二进制文件中只包含一个版本的 linkme。
这种架构:
- 防止整个依赖图中的
linkme版本冲突 - 确保所有依赖项目的行为一致性
- 维护核心功能与用户界面之间的清晰关注点分离
- 允许接口层(static_)和核心实现(xboot)独立版本控制
在 Cargo.toml 中添加:
[dependencies]
static_ = "0.1" # 推荐:使用高级接口
# 或
xboot = "0.1" # 直接访问核心功能use aok::Result;
use tokio::time::{Duration, sleep};
use log::info;
// 定义需要异步初始化的资源
pub struct Database {
connection: String,
}
impl Database {
pub async fn connect(url: &str) -> Result<Self> {
info!("正在连接数据库...");
sleep(Duration::from_secs(2)).await;
Ok(Self { connection: url.to_string() })
}
pub async fn query(&self, sql: &str) -> Result<()> {
info!("在 {} 上执行查询: {}", self.connection, sql);
Ok(())
}
}
// 使用 static_ 声明异步初始化的静态变量
static_::init!(DB: Database async {
Database::connect("postgres://localhost/myapp").await
});
#[tokio::main]
async fn main() -> Result<()> {
// 初始化所有注册的静态变量
xboot::init().await?;
info!("所有静态变量初始化完成");
// 像普通变量一样使用已初始化的静态变量
DB.query("SELECT * FROM users").await?;
Ok(())
}graph TD
A["程序启动"] --> B["static_::init! 宏展开"]
B --> C["创建 OnceCell 并向 xboot 注册"]
C --> D["xboot::add! 宏注册函数"]
D --> E["链接器将所有函数收集到 ASYNC 切片"]
E --> F["运行时: 调用 xboot::init()"]
F --> G["遍历 ASYNC 切片"]
G --> H["执行所有异步初始化"]
H --> I["结果存储在 OnceCell 实例中"]
I --> J["静态变量准备就绪"]
- static_::init!: 创建
OnceCell实例并向 xboot 注册初始化 - xboot::add!: 将异步初始化函数注册到分布式切片
- linkme: 在链接期收集所有注册的函数
- xboot::init(): 在运行时执行所有注册的初始化
| Crate | 用途 |
|---|---|
| linkme | 分布式切片,编译期收集 |
| tokio | 异步运行时和任务 spawn |
| async_wrap | OnceCell 和 Wrap 类型 |
| paste | 宏标识符拼接 |
| gensym | 唯一符号生成 |
| aok | Result 类型工具 |
| log | 错误日志 |
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: