Migrate C code to Rust
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 26 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 25 天前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 6 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 27 天前 | ||
| 2 个月前 | ||
| 1 年前 | ||
| 4 个月前 | ||
| 1 个月前 | ||
| 1 年前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 4 年前 | ||
| 1 个月前 | ||
| 9 个月前 | ||
| 2 年前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 11 个月前 | ||
| 1 个月前 |
C2Rust
简介
C2Rust 可帮助您将符合 C99 标准的代码迁移至 Rust。
其转换器 c2rust transpile 能够生成不安全的 Rust 代码,该代码与输入的 C 代码高度相似。
转换器的主要目标是确保功能得以保留,翻译完成后测试套件应能继续通过。
c2rust transpile 生成的代码是不安全且非惯用的,这仅仅是漫长迁移过程的第一步。
要从 C 代码生成安全且符合 Rust 风格的代码,还需要进一步的工作。
这些工作可由人工、大型语言模型、确定性工具或它们的某种组合来完成。
flowchart LR
A[C sources] --> B
subgraph "C2Rust toolchain"
B["`c2rust transpile`"] --> C["`c2rust refactor`"]
C --> D["`c2rust postprocess`"]
end
D --> E[Human and/or agentic workflow]
E --> F[Safe, idiomatic Rust]
click B "https://github.com/immunant/c2rust/tree/master/c2rust-transpile" "c2rust transpile"
click C "https://github.com/immunant/c2rust/tree/master/c2rust-refactor" "c2rust refactor"
click D "https://github.com/immunant/c2rust/tree/master/c2rust-postprocess" "c2rust postprocess"
例如,我们提供了一个确定性的重构工具,用于自动清理 c2rust transpile 生成的文件。
我们还提供了一个基于 LLM 的后处理工具,用于处理其他难以确定性完成的清理工作。
尽管后处理器会验证 LLM 的输出,但它仍可能引入错误;因此,我们建议结合可靠的测试套件一起使用。
您可以在 Compiler Explorer 中直接试用 c2rust transpile。
它使用当前的 master 分支,每晚更新。
文档
要了解更多关于使用和开发 C2Rust 的信息,请查阅手册。 该手册仍在完善中,如果您找不到所需内容,请告诉我们。 c2rust.com/manual/ 自 2019 年左右起未再更新, 因此,有关最新的说明,请参考代码库中的 ./manual/。
安装
前提条件
C2Rust 需要 LLVM 15 或更高版本,以及相应的 clang 编译器和库。
同时还需要 Python(通过 uv)、CMake 3.5 或更高版本以及 openssl(1.0)。
根据您的平台,可以使用以下命令安装这些前提条件:
Python:
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv
uv pip install -r scripts/requirements.txt
-
Ubuntu 22.04、Debian 12 及更高版本:
apt install build-essential llvm clang libclang-dev cmake libssl-dev pkg-config git
根据 LLVM 发行版的不同,可能还需要 llvm-dev 包。
例如,来自 apt.llvm.org 的官方 LLVM 包需要安装 llvm-dev。
-
Arch Linux:
pacman -S base-devel llvm clang cmake openssl -
NixOS / nix:
nix-shell -
macOS: 需要 Xcode 命令行工具和最新的 LLVM(我们推荐 Homebrew 版本)。
xcode-select --install brew install llvm cmake openssl
C2Rust 转换器现在可使用稳定版 Rust 编译器构建。 如果您要开发其他功能, 可能需要安装正确的 nightly 编译器版本。
从 crates.io 安装
cargo install --locked c2rust
如果您安装了多个 LLVM 版本,也可以显式设置 LLVM 版本,例如:
LLVM_CONFIG_PATH=llvm-config-15 cargo install --locked c2rust
如果您使用的是来自 Homebrew 的 LLVM(无论是在 Apple Silicon、Intel Mac 还是 Linuxbrew 上),您可以运行:
LLVM_CONFIG_PATH="$(brew --prefix)/opt/llvm/bin/llvm-config" cargo install --locked c2rust
或针对特定的 LLVM 版本,
LLVM_CONFIG_PATH="$(brew --prefix)/opt/llvm@22/bin/llvm-config" cargo install --locked c2rust
在 Gentoo 系统上,你需要按以下方式将构建系统指向 libclang.so 和 llvm-config 的位置:
LLVM_CONFIG_PATH=/path/to/llvm-config LIBCLANG_PATH=/path/to/libclang.so cargo install --locked c2rust
如果您在构建和安装过程中遇到问题,或者希望从最新的 master 分支进行构建,开发者文档 提供了有关构建系统的更多详细信息。
从 Git 安装
如果您想体验我们最近开发的功能,或者急需 c2rust 的某个 bug 修复版本,可以直接从 Git 安装:
cargo install --locked --git https://github.com/immunant/c2rust.git c2rust
请注意,master 分支处于持续开发中,您可能会遇到问题或崩溃。
如果需要,您还应按照上述说明相应地设置 LLVM_CONFIG_PATH。
夜间版工具
c2rust 和 c2rust-transpile 默认已安装,并且可以在 stable rustc 上构建。
然而,其他工具(如 c2rust-refactor)使用 rustc 内部 API,因此被固定到特定的 rustc nightly 版本:nightly-2023-04-15。
这些工具也未发布到 crates.io。
要安装这些工具,可以使用固定的 nightly 版本通过 cargo 进行安装。例如,
cargo +nightly-2023-04-15 install --locked --git https://github.com/immunant/c2rust.git c2rust-refactor
不过,我们建议通过完整克隆代码库进行安装,这样可以自动解析固定的 nightly 版本:
git clone https://github.com/immunant/c2rust.git
cd c2rust
cargo build --release
这些工具(例如 c2rust-refactor)也可以通过 c2rust 以 c2rust refactor 的形式调用,前提是它们安装在同一目录中。
将 C 代码转换为 Rust
要转换 compile_commands.json 中指定的 C 文件(详见下文),请使用 transpile 子命令运行 c2rust 工具:
c2rust transpile compile_commands.json
c2rust 还支持对源文件进行简单的转译,例如:
c2rust transpile project/*.c project/*.h
对于非小型项目,转换器需要用于构建 C 代码的确切编译器命令。
此信息通过名为 compile_commands.json 的编译数据库文件提供(请注意,该文件的名称必须 exactly 为 compile_commands.json;否则 libclangTooling 在正确解析它时可能会遇到(静默)问题)。
(在此处阅读有关编译数据库的更多信息)。
许多构建系统可以自动生成此文件;我们在下面展示了几个示例。
一旦你有了描述 C 构建的 compile_commands.json 文件,就可以使用以下命令将 C 代码转换为 Rust:
c2rust transpile path/to/compile_commands.json
要为 Rust 库生成 Cargo.toml 模板,请添加 --emit-build-files 选项:
c2rust transpile --emit-build-files path/to/compile_commands.json
要生成 Rust 二进制文件的 Cargo.toml 模板,请执行以下操作:
c2rust transpile --binary myprog path/to/compile_commands.json
其中,--binary myprog 用于告知转译器将 myprog.rs 中的 main 函数用作二进制文件的入口点。此参数可重复多次,以支持多个二进制文件。
经过翻译的 Rust 文件不会像普通 Rust 模块那样直接相互依赖。它们将通过 C API 导出和导入函数。这些模块可以一起编译成单个静态 Rust 库或二进制文件。
您可以使用 --reorganize-definitions(该选项会调用 c2rust-refactor)运行,它将对定义进行去重,并通过 use 语句直接导入,而非通过 C API。
重构器也可以单独运行,以执行其他重构过程:
c2rust refactor --cargo $transform
此翻译器存在若干已知限制。 对于无法翻译的函数定义,翻译器会发出警告并尝试跳过。
生成 compile_commands.json 文件
compile_commands.json 文件可通过 cmake、meson、bear、intercept-build 或 compiledb 自动创建。
建议从编译数据库中移除优化选项(-OX),因为我们尚不支持翻译某些优化内建函数。
使用 cmake 生成
使用 cmake 创建初始构建目录时,需指定 -DCMAKE_EXPORT_COMPILE_COMMANDS=1。
此方法仅适用于配置为使用 cmake 构建的项目,且在 Linux 和 MacOS 系统上有效。
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ...
使用 meson
使用 meson 创建初始构建目录时,它会在 <build_dir> 内自动生成一个 compile_commands.json 文件。
meson setup <build_dir>
... 使用 bear
bear 推荐用于那些构建系统不会自动生成 compile_commands.json 的项目(例如 make,这一点与 cmake 或 meson 不同)。对于 cmake 和 meson 来说,它也很有用,因为它会记录子命令执行的所有编译过程,从而生成完整 compile_commands.json 的子集。
可以通过以下方式安装它:
apt install bear
或
brew install bear
使用方法:
bear -- <build command>
<build command> 可以是 make、针对单个目标的 make/cmake,或者是单次 cc 编译:
bear -- make
bear -- cmake --build . --target $target
bear -- cc -c program.c
请注意,由于它会检测编译过程,因此如果编译结果被缓存(例如通过 make 缓存),你需要先进行干净构建(例如执行 make clean)。
使用 intercept-build
intercept-build(是 scan-build 的一部分)与之非常相似,但在更新及时性和全面性方面并不总是能与 bear 相媲美。intercept-build 与 clang 捆绑在一起,位于 tools/scan-build-py 目录下,但也可以通过 pip 轻松安装独立版本:
uv tool install scan-build
...借助 compiledb
如果其他工具无法正常工作,compiledb 软件包也可用于 make 项目。
与其他工具不同,它不需要干净的构建或执行 make clean。
可通过 pip 安装,命令如下:
uv tool install compiledb
使用方法:
# After running
./autogen.sh && ./configure # etc.
# Run
compiledb make
联系方式
如在代码翻译或重构过程中遇到问题,请使用我们的 问题跟踪器 进行反馈。
如需联系开发团队,可加入我们的 Discord 频道,或发送邮件至 c2rust@immunant.com。
常见问题
我在平台 X 上翻译的代码,在平台 Y 上无法正常运行。
我们在将代码翻译为 Rust 之前会运行 C 预处理器。
这会使代码针对目标平台(通常是主机平台)进行特化处理。
不过,我们支持通过使用不同的 sysroot 进行跨架构转译(跨操作系统转译难度较大,因为获取目标操作系统的 sysroot 可能存在困难)。
例如,在 aarch64-linux-gnu 主机上,要跨架构转译到 x86_64-linux-gnu,可以运行
sudo apt install gcc-x86-64-linux-gnu # install cross-compiler, which comes with a sysroot
c2rust transpile ${existing_args[@]} -- --target=x86_64-linux-gnu --sysroot=/usr/x86_64-linux-gnu
这些额外参数会传递给 c2rust-transpile 所使用的 libclangTooling。有时您还需要传递额外的头文件,因为偶尔头文件会全局安装在默认系统根目录中,而在交叉编译的系统根目录下可能无法找到。
C2Rust 可以在哪些平台上运行?
转换器和重构工具支持 macOS 和 Linux 系统。
c2rust transpile 的应用案例
以下是我们已知的所有使用 c2rust transpile 的重要案例列表:
| Rust | C | 作者 | 安全性 | 描述 |
|---|---|---|---|---|
rav1d |
dav1d |
@memorysafety、@immunant | 完全安全 | AV1 解码器 |
rexpat |
libexpat |
@immunant | 安全性未完成 | 流式 XML 解析器 |
unsafe-libyaml |
libyaml |
@dtolnay | 少量清理,完全不安全 | 供 serde_yaml 使用的 YAML 解析器和写入器 |
libyaml-safer |
libyaml |
@simonask | 完全安全 | unsafe-libyaml 的安全分支 |
libbzip2-rs |
bzip2 |
@trifectatechfoundation | 完全安全 | 文件压缩 |
tsuki |
lua |
@ultimaweapon | 完全安全 | Lua 解释器 |
spiro.rlib |
spiro |
@ctrlcctrlv | 完全安全 | 样条插值 |
sapp-kms |
sokol |
@not-fl3 | 已清理,仍不安全 | 应用渲染库 |
lhdcv5 |
(未知) | (未知) | 完全安全 | 蓝牙音频编解码器 |
如果有其他项目成功使用了 c2rust,欢迎在此处添加您的移植项目。
致谢与许可
本资料采用 BSD-3 风格许可,详见 LICENSE 文件。
C2Rust 转换器的灵感来源于 Jamey Sharp 的 Corrode 转换器。我们依赖 Emscripten 的 Relooper 算法来转换任意 C 控制流。许多个人为 C2Rust 贡献了错误修复和改进,在此表示衷心感谢!
本资料基于美国空军和 DARPA 支持的工作,合同编号为 FA8750-15-C-0124、HR0011-22-C-0020 和 HR00112590133。本资料中表达的任何观点、发现、结论或建议均为作者个人观点,不一定反映美国空军或 DARPA 的观点。
分发声明 A:“批准公开发布,分发不受限制。”