> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# 构建 Rust 示例程序

执行事件 SDK 由两个包组成，分别名为 `monad-event-ring` 和 `monad-exec-events`。它们在 [Rust API 指南](/zh/execution-events/rust-api)中有更详细的描述，但现在知道它们的名字就足够了。

未来，Category Labs 可能会将这些包发布到 [crates.io](https://crates.io)，但目前 SDK 的分发方式不是这样。

相反，用户的 `Cargo.toml` 文件声明这些依赖的上游来源为 SDK 源代码所在 git 仓库的某个特定发布标签。来自 git 而非 crates.io 的依赖在 Cargo Book 的[本节](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories)中解释。

## Rust SDK 源代码在哪里？

执行事件 Rust SDK 位于与执行层守护进程相同的源代码仓库中（[此处](https://github.com/category-labs/monad)）。此仓库中的大多数代码是用 C 或 C++ 编写的，即执行层守护进程本身使用的语言。仓库还包含一些 Rust 包装 API，其中一个是 Rust 执行事件 SDK。所有 Rust 组件的顶层 `Cargo.toml` 文件位于 `rust/` 子目录中。

执行事件 C SDK 中的许多函数通过 FFI 接口被 Rust 重用。这作为 Rust 用户对您的主要影响是：您必须确保在 Cargo 从 SDK 的 [`build.rs` 构建脚本](https://doc.rust-lang.org/cargo/reference/build-scripts.html) 调用 CMake 和 bindgen 时选择足够新的 C 编译器。

C SDK 使用了 C23 的一些较新语言特性，并需要 gcc-13 或 clang-19。如果您运行 `cc -v` 并且它报告较旧的编译器，则需要设置 `CC` 环境变量以告知 CMake 选择较新的编译器。

## 构建示例程序

### 步骤 1：安装前置开发包

您可能已经安装了其中一些，但请确保至少达到最低所需版本（较新版本可能可以工作，但未明确测试）。

除了 Rust 工具链外，您还需要：

| 要求           | Ubuntu 包名         | 最低版本       | 用途                                                       |
| ------------ | ----------------- | ---------- | -------------------------------------------------------- |
| C 编译器        | gcc-13 或 clang-19 | 见包名        | 核心事件库（`libmonad_event.a`）用 C 编写，被 Rust 库使用               |
| C++ 编译器      | g++-13 或 clang-19 | 见包名        | Rust 不使用可选的 C++ 组件，但如果 CMake configure 步骤找不到 C++ 编译器会报错  |
| CMake        | cmake             | CMake 3.23 | `libmonad_event.a` 通过 CMake 构建，与 cargo 通过 `build.rs` 集成  |
| zstd 库       | libzstd-dev       | 任意版本       | 快照 event ring 文件使用 zstd 压缩；此库用于解压                        |
| libhugetlbfs | libhugetlbfs-dev  | 任意版本       | `libhugetlbfs` 用于定位存放 event ring 共享内存文件的默认 hugetlbfs 挂载点 |
| libclang     | clang-19          | clang-19   | Rust 的 bindgen 需要较新版本的 libclang 库                        |

我们还需要 git 和 curl。

#### macOS 兼容性

实时数据需要 Linux 主机（因为执行层守护进程本身需要），但您可以在 macOS 上编译并运行处理历史数据的示例程序。这允许您在花费精力在 Linux 上搭建 Monad 节点之前"先试后买"并探索 SDK。

在这种情况下，您不需要 `libhugetlbfs`（这是仅 Linux 的库），但您需要较新的 XCode 工具链、`libzstd` 压缩库和 CMake。后两者不包含在默认 XCode 开发工具中，因此您可能希望使用 [Homebrew](https://brew.sh/) 或 [MacPorts](https://www.macports.org/) 将其安装到系统上。至于 XCode 本身，自 16.3 版本以来的任何版本都应该可以工作，但仅使用 23.2 版本进行过测试（实际要求是 Apple Clang 17）。[^1]

[^1]: "Apple Clang"基于但不同于原始 LLVM [Clang](https://clang.llvm.org/)。Apple Clang 17 基于 LLVM/Clang 19，因此需求表中存在差异。

#### 依赖快速安装

要在 Ubuntu 24.04 或更高版本上一次性安装所有依赖，请运行此命令（也可以使用更新版本，例如 `clang-20`）：

```shell theme={null}
$ sudo apt install git curl gcc g++ cmake clang-19 libzstd-dev libhugetlbfs-dev
```

<Info title="`libclang` 与 clang 版本">
  即使您使用 gcc 编译 `libmonad_event.a`，Rust [bindgen](https://rust-lang.github.io/rust-bindgen/) 工具仍然使用 [libclang](https://clang.llvm.org/docs/Tooling.html#libclang) 工具以编程方式为 C 代码生成 Rust 绑定。从技术上讲，您不需要完整的 clang 编译器，只需要 libclang 包，但一些用户报告说不安装它会有问题。

  您需要 19 版（或更高版本）的原因是 clang-19 是第一个支持足够 C23 语言标准特性以编译 SDK 的版本。如果您看到暗示 bindgen 无法理解 `constexpr` 关键字的错误，则说明 bindgen 自动选择了过旧的 libclang 版本。

  如果系统上有多个 libclang 版本（Ubuntu 24.04 上默认 clang 是 18 版），安装较新版本可能没有帮助，如果底层问题是 bindgen 默认选择错误的版本。稍后在本指南中（在 `cargo build` 步骤中）我们将更多地解释如何解决一些常见的 libclang 版本选择问题。
</Info>

### 步骤 2：创建一个新包并将示例代码复制到其中

首先，为示例程序创建一个新的 cargo 包：

```shell theme={null}
$ cargo new --bin event-sdk-example-rust
$ cd event-sdk-example-rust
```

接下来，我们将用从 github 下载的示例程序代码覆盖默认的 "Hello world" `main.rs` 源文件：

```text theme={null}
$ curl https://raw.githubusercontent.com/category-labs/monad/refs/tags/release/exec-events-sdk-v1.1/rust/crates/monad-exec-events/examples/eventwatch.rs > src/main.rs
```

### 步骤 3：与 SDK 包集成

创建以下 `Cargo.toml` 文件：

```Cargo.toml theme={null}
[package]
name = "event-sdk-example-rust"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "0.4.34"
clap = { version = "4.2", features = ["derive"] }
lazy_static = "1.5.0"

[dependencies.monad-event-ring]
git = "https://github.com/category-labs/monad"
tag = "release/exec-events-sdk-v1.1"

[dependencies.monad-exec-events]
git = "https://github.com/category-labs/monad"
tag = "release/exec-events-sdk-v1.1"
```

### 步骤 4：构建项目

```shell theme={null}
cargo build
```

第一次构建会\_非常\_慢，因为它将获取 monad 仓库和所有传递的 git 子模块。SDK 不需要它们，但 cargo 会检出它们，目前没有办法覆盖此行为（参见[此 issue](https://github.com/rust-lang/cargo/issues/4247)）。幸运的是，git 缓存通常在所有 Cargo 项目之间共享（在 `$HOME/.cargo/git` 中），因此这次漫长的下载只会发生一次，而不是每个项目一次。

您可能需要告诉 CMake 使用比它检测到的默认编译器更新的 C 编译器，可以使用 `CC` 环境变量。下面的示例使用 bash 简洁语法在下一个要运行命令的作用域内设置环境变量：

```shell theme={null}
CC=clang-19 cargo build
```

如果您遇到任何构建错误，请查看下一节的"故障排除"。否则，构建应该会生成一个可用的可执行文件。尝试使用 `-h` 标志运行它以打印帮助：

```shell theme={null}
cargo run -- -h
```

如果一切顺利，请继续[指南的下一步](/zh/execution-events/getting-started/snapshot)。

### 常见构建错误故障排除

#### libclang 错误

构建时最常见的错误来源是 bindgen 选择了过时的 libclang 版本，如前所述。这通常表现为：

* 明确提及 `libclang` 的错误 或
* 包含文本 "Unable to generate bindings" 的消息

设置环境变量 `CC=clang-19` 仅影响 CMake 用于构建 C SDK 库 `libmonad_event.a` 的编译器。也就是说，它不影响 bindgen 用于生成绑定的 libclang 版本。`CC` 指定特定的二进制程序，而 libclang 是由 `build.rs` 构建脚本动态加载的共享库。它们（大部分情况下）\_不\_受相同的环境变量影响。

有许多环境变量控制 libclang 的定位和配置方式，它们在 [Rust libclang 绑定库](https://crates.io/crates/clang-sys)的"环境变量"部分中有文档说明。

我们发现效果良好的一些建议：

* 将 `LLVM_CONFIG_PATH` 设置为指向 `llvm-config` 二进制的完整路径是最佳选择；此命令内置了关于 LLVM 如何在系统上构建和安装的许多细节，以便让 LLVM 用户（如 bindgen）更容易找到所需配置
* 在一些不寻常的情况下，您可能选择了正确的 libclang，但其配置很奇怪，以至于它无法再找到基本的 libc 头文件（典型症状是声称找不到 `stddef.h`、`assert.h` 或 `string.h`）；您可以找出这些文件在系统上的位置，并通过 `BINDGEN_EXTRA_CLANG_ARGS` 环境变量将其作为系统包含目录（`-isystem` clang 选项）通过 bindgen 传递给 libclang；在 macOS 上如下所示：
  ```text theme={null}
  BINDGEN_EXTRA_CLANG_ARGS="-isystem $(xcrun --show-sdk-path)/usr/include"
  ```
  在典型 Linux 设置中如下所示：
  ```text theme={null}
  BINDGEN_EXTRA_CLANG_ARGS="-isystem /usr/include"
  ```

#### zstd 库错误

macOS 上 MacPorts 的常见错误是 C 编译器无法找到 `zstd.h` 头文件，或链接器无法找到 `libzstd` 库。这是因为系统 C 编译器默认不会在 `/opt/local` 目录层次结构中搜索。要解决此问题，请按如下方式导出 `CFLAGS` 和 `RUSTFLAGS` 环境变量：

```shell theme={null}
export CFLAGS=-I/opt/local/include
export RUSTFLAGS=-L/opt/local/lib
```

或者，您可以将 `CC` 设置为 MacPorts 提供的 C 编译器，它会知道在那里搜索。
