c2rust:基于 LLVM 和 Clang 的 C 到 Rust 代码转换工具项目

Migrate C code to Rust

分支324Tags35
文件最后提交记录最后更新时间
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

ci GitHub Actions Status c2rust-testsuite GitHub Actions Status Latest Version Rustc Version

简介

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

夜间版工具

c2rustc2rust-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)也可以通过 c2rustc2rust 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 文件可通过 cmakemesonbearintercept-buildcompiledb 自动创建。

建议从编译数据库中移除优化选项(-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,这一点与 cmakemeson 不同)。对于 cmakemeson 来说,它也很有用,因为它会记录子命令执行的所有编译过程,从而生成完整 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-buildclang 捆绑在一起,位于 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:“批准公开发布,分发不受限制。”

项目介绍

将C代码迁移至Rust语言【此简介由AI生成】

定制我的领域
534.8 K312访问 GitHub