> ## 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.

# Building the Rust example program

The execution event SDK is made up of two packages, called `monad-event-ring`
and `monad-exec-events`. These are described in more detail in the
[Rust API guide](/execution-events/rust-api),
but for now it's enough to just know their names.

In the future, Category Labs may publish these packages to
[crates.io](https://crates.io),
but that is not how the SDK is currently distributed.

Instead, the user's `Cargo.toml` file declares the upstream source of these
dependencies to be a particular release tag of the git repository where the
SDK source code is located. Dependencies which are sourced from git rather
than crates.io are explained in
[this section](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories)
of the Cargo Book.

## Where is the Rust SDK source code?

The execution event Rust SDK lives in same source code repository as the
execution daemon ([here](https://github.com/category-labs/monad)). Most
of the code in this repository in written in either C or C++, the languages
used by the execution daemon itself. The repository also contains a few Rust
wrapper APIs, one of which is the Rust execution events SDK. The top-level
`Cargo.toml` file for all the Rust components is located in the `rust/`
subdirectory.

Many of the functions in the execution events C SDK are reused by Rust, via
an FFI interface. The main way this affects you as a Rust user is that you
must ensure that a recent enough C compiler is selected when Cargo calls
CMake and bindgen from the SDK's
[`build.rs` build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html).

The C SDK uses some recent C23 language features, and requires either gcc-13 or
clang-19. If you run `cc -v` and it reports an older compiler, you will need to
set the `CC` environment variable to tell CMake to select a newer compiler.

## Building the example program

### Step 1: install prerequisite development packages

You might already have some of these installed, but make sure you have at least
the minimum required version (newer versions will probably work, but are not
explicitly tested).

In addition to a Rust toolchain, you will need:

| Requirement  | Ubuntu package name | Minimum version   | What is it used for?                                                                                                                 |
| ------------ | ------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| C compiler   | gcc-13 or clang-19  | see package names | The core event library (`libmonad_event.a`) is written in C, and is used by the Rust library                                         |
| C++ compiler | g++-13 or clang-19  | see package names | The optional C++ components are not used by Rust, but the CMake configure step will report an error if it cannot find a C++ compiler |
| CMake        | cmake               | CMake 3.23        | `libmonad_event.a` is built with CMake, via `build.rs` integration with cargo                                                        |
| zstd library | libzstd-dev         | any               | Snapshot event ring files are compressed with zstd; this library is needed to decompress them                                        |
| libhugetlbfs | libhugetlbfs-dev    | any               | `libhugetlbfs` is used to locate the default hugetlbfs mount point that holds event ring shared memory files                         |
| libclang     | clang-19            | clang-19          | Rust's bindgen requires the a recent version of the libclang library                                                                 |

We will also need git and curl.

#### macOS compatiblity

Real-time data requires a Linux host (because the execution daemon itself
does), but you can compile and run the example program on historical data
using macOS. This allows you to "try before you buy" and explore the SDK
before going through the trouble of setting up a Monad node on Linux.

In this case, you do not need `libhugetlbfs` (which is a Linux-only library),
but you will need a recent XCode toolchain, the `libzstd` compression
library, and CMake. The last two are not included in the default XCode
development tools, so you'll probably want to use
[Homebrew](https://brew.sh/) or
[MacPorts](https://www.macports.org/)
to install these onto your system. As for XCode itself, any version since
16.3 should work, but it has only been tested with version 23.2 (the real
requirement is for Apple Clang 17).[^1]

[^1]: "Apple Clang" is based on, but different than, vanilla LLVM
    [Clang](https://clang.llvm.org/). Apple Clang 17 is based on LLVM/Clang 19,
    thus the discrepancy in the requirements table.

#### Dependencies quickstart

To install all of the dependenices in one shot on Ubuntu 24.04 or higher, run
this command (feel free to use more recent verions, e.g., `clang-20`):

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

<Info title="`libclang` and clang versions">
  Even if you compile `libmonad_event.a` with gcc, the Rust
  [bindgen](https://rust-lang.github.io/rust-bindgen/) utility still uses the
  [libclang](https://clang.llvm.org/docs/Tooling.html#libclang) tool to
  programmatically generate Rust bindings to C code. Technically you should
  not need the full clang compiler, just the libclang package, but some users
  have reported trouble without installing it.

  The reason you need version 19 (or greater) is that clang-19 was the first
  version to support enough features from the C23 language standard to be able
  to compile the SDK. If you see errors that imply that bindgen cannot understand
  the `constexpr` keyword, then bindgen has automatically selected a libclang
  version that is too old.

  If you have multiple libclang versions on the system (the default clang is
  version 18 on Ubuntu 24.04), installing a newer version may not help, if the
  underlying problem is that bindgen is selecting the wrong one by default.
  Later on in this guide (during the `cargo build` step) we'll explain more
  about how to fix some common problems with libclang version selection.
</Info>

### Step 2: create a new package and copy the example code into it

First, create a new cargo package for the example program:

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

Next, we'll overwrite the default "Hello world" `main.rs` source file with the
example program code, downloaded from github:

```
$ 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
```

### Step 3: integrating with the SDK packages

Create the following `Cargo.toml` file:

```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"
```

### Step 4: build the project

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

The first time you build will be *very* slow, because it will fetch the monad
repository and all transitive git submodules. None of them are needed for the
SDK, but cargo checks them out and there is currently no way to override this
(see [this issue](https://github.com/rust-lang/cargo/issues/4247)). Thankfully,
the git cache is usually shared by all Cargo projects (in `$HOME/.cargo/git`)
so this long download should only happen a single time, not once per project.

You may need to tell CMake to use a more recent C compiler than the default
one it detects, which you can do using the `CC` environment variable. The
example below uses the bash terse syntax for setting environment variables
in the scope of the next command to be run:

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

If you encounter any build errors, check out the "trouble-shooting" section
after this one. Otherwise, the build should produce a working executable file.
Try running it with the `-h` flag to print the help:

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

If all was successful, continue on to the [next step in the guide](/execution-events/getting-started/snapshot).

### Trouble-shooting common build errors

#### libclang errors

The most common source of errors when building is when bindgen selects an
outdated libclang version, as explained earlier. This typically appears
as either:

* An error explicitly mentioning `libclang` OR
* A message that includes the text "Unable to generate bindings"

Setting the environment variable `CC=clang-19` only influences the compiler
that CMake uses to build the C SDK library, `libmonad_event.a`. Namely, it
does not the affect the libclang version that is used by bindgen to generate
the bindings. `CC` specifies a particular binary program, whereas libclang
is a shared library that is dynamically loaded by a `build.rs` build script.
They are (for the most part) *not* affected by the same environment variables.

There are a number of environment variables that control the behavior of how
libclang is located and configured, and they're documented in the "Environment
Variables" section of the
[Rust libclang bindings library](https://crates.io/crates/clang-sys).

Some advice we have found works well:

* Setting `LLVM_CONFIG_PATH` to point to the full path to the `llvm-config`
  binary is the best option; this command bakes in a lot of details about
  how LLVM was built and installed on the system, to make it easier for
  users of LLVM (such as bindgen) to find the configuration they need

* In some unusual cases, you may select the right libclang but it may
  be configured strangely, so that it cannot find the basic libc header
  files anymore (typical symptoms are claims that `stddef.h`, `assert.h`,
  or `string.h` are missing); you can can figure out the location of these
  files on the system and pass them as system include directories (the
  `-isystem` clang option) to libclang through bindgen using the
  `BINDGEN_EXTRA_CLANG_ARGS` environment variable; on macOS this looks like:

  ```
  BINDGEN_EXTRA_CLANG_ARGS="-isystem $(xcrun --show-sdk-path)/usr/include"
  ```

  and in a typical Linux setup it looks like this:

  ```
  BINDGEN_EXTRA_CLANG_ARGS="-isystem /usr/include"
  ```

#### zstd library errors

A common error with MacPorts on macOS is the inability of the C compiler to
find the `zstd.h` header file, or the inability of the linker to find the
`libzstd` library. This is because the system C compiler will not search in
the `/opt/local` directory hierarchy by default. To fix this, export the
`CFLAGS` and `RUSTFLAGS` environment variables as follows:

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

Alternatively, you can set `CC` to a MacPorts-provided C compiler, which will
know to search there.
