如何在CMake工程中使用Rust库blazesym

【eBPF 入门实践教程十二:使用 eBPF 程序 profile 进行性能分析】 这篇文章中, profiler 工具的实现是使用了 rust 编写的 blazesym 库,而我现在打算使用 C++ 实现,还好这个库提供了 C API,但是需要我们将这个 Rust 库的构建集成到 CMake 中。

Corrosion 可将 Rust 集成到现有 CMake 项目中,它是一个 CMake 工具链,旨在让 CMake 像对待原生 C++ 子项目一样对待 Rust 的 Cargo 项目。Corrosion 将手动调用 cargo build,处理复杂的跨平台路径、构建配置(Debug/Release)以及繁琐的链接参数这些过程完全自动化了。

Corrosion 的核心功能

Corrosion 的工作原理是在 CMake 层面为 Cargo 包装了一层“外壳”,其主要功能包括:

  • 自动处理构建类型:CMake 的 ReleaseDebug 模式会自动映射到 Cargo 的 --release 或默认模式。
  • 目标导入:将 Rust 的 staticlibcdylib 导入为标准的 CMake 目标(Targets),你可以直接对它们使用 target_link_libraries
  • 跨平台交叉编译:它能自动将 CMake 的交叉编译设置(如 Android, iOS, 嵌入式等)传递给 Rust 的目标三元组(Target Triple)。
  • 多包支持:支持 Cargo 工作区(Workspaces)和单个 Crate。

项目结构

在我的项目 profiler 中使用 Corrosion 时,项目布局如下:

1
2
3
4
5
6
profiler/
├── CMakeLists.txt
├── src
├── third_party/
│   └── blazesym
└── cmake/             # 存放 Corrosion 脚本

如何在 CMake 中使用 Corrosion

(1)通过 FetchContent 自动下载并集成

1
2
3
4
5
6
7
8
include(FetchContent)

FetchContent_Declare(
    Corrosion
    GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
    GIT_TAG v0.6.0
)
FetchContent_MakeAvailable(Corrosion)

(2)导入 Rust 项目

1
2
3
4
5
# 这里的路径指向包含 Cargo.toml 的目录
corrosion_import_crate(
    MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/third_party/blazesym/Cargo.toml
    NO_AUTO_EXE
)

(3)配置静态库

在 blazesym 的 C API 构建时,文档中说明了需要链接的 C 库:

1
-lrt -ldl -lpthread -lm

为了方便后面的构建目标使用 blazesym 库,我的做法是将其制作的静态库和头文件“打包”,方便构建目标通过 target_link_libraries 使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
find_package(Threads REQUIRED)
find_library(LIB_RT rt)
find_library(LIB_DL dl)
find_library(LIB_M m)

# 定义并配置静态库目标
add_library(blazesym STATIC IMPORTED GLOBAL)

set_target_properties(blazesym PROPERTIES
    IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libblazesym_c.a"
    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/third_party/blazesym/capi/include"
    INTERFACE_LINK_LIBRARIES "Threads::Threads;${LIB_RT};${LIB_DL};${LIB_M}"
)

(4)使用静态库

可以将刚刚的三步的代码合并成一个 cmake 文件中放在项目根目录下的 cmake 目录中(例如我这里的 cmake/SetupBlazesym.cmake),然后在项目的 CMakelists.txt 中 通过 include 使用:

1
2
3
4
5
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/SetupBlazesym.cmake")

add_executable(profiler src/...)

target_link_libraries(profiler PRIVATE blazesym)
使用 Hugo 构建
主题 StackJimmy 设计