C2Rust helps you migrate C99-compliant code to Rust. It provides:
- a C to Rust translator,
- a Rust code refactoring tool, and
- a way to cross-check the C code against the new Rust code.
The translator (or transpiler), produces unsafe Rust code that closely mirrors the input C code. The primary goal of the translator is to produce code that is functionally identical to the input C code. Generating safe or idomatic Rust is not a goal for the translator. Rather, we think the best approach is to gradually clean up the translator using dedicated refactoring tools. See the rust-refactor
directory to learn about the idiomize
tool that we are working on.
Some refactoring will have to be done by hand which may introduce errors. We provide plugins for clang
and rustc
so you can compile and run two binaries and check that they behave identically (at the level of function calls).
See details in the cross-checks
directory and in the cross checking tutorial. Here's the big picture:
To learn more, check out our RustConf'18 talk on YouTube and try the C2Rust translator online at www.c2rust.com.
There are three ways to build the C2Rust project:
- Using Vagrant. See our vagrant README.
- Using Docker. See our docker README.
- Manually, as explained below.
The previous two options automatically install all prerequisites during provisioning. You can also provision a macOS or Linux system manually.
-
If you are on a Debian-based OS, you can run
scripts/provision_deb.sh
to do so. -
If you are on macOS, install the Xcode command-line tools (e.g.,
xcode-select --install
) and homebrew first. Then runscripts/provision_mac.sh
. -
If you prefer to install dependencies yourself, or are using a non Debian-based Linux OS, our dependencies are as follows:
- cmake >= 3.9.1
- dirmngr
- curl
- git
- gnupg2
- gperf
- ninja
- unzip
- clang 5.0+
- intercept-build or bear - see why here
- python-dev
- python 3.6+
- python dependencies
- rustc version
- rustfmt-preview component for the above rustc version
- libssl (development library, dependency of the refactoring tool)
Building from scratch takes a little while. The script has been tested on recent versions of macOS and Ubuntu.
$ ./scripts/build_translator.py
To use the cross checking functionality, add the following option.
$ ./scripts/build_translator.py --with-clang
Tests are found in the tests
folder. If you build the translator successfully, you should be able to run the tests with:
$ ./scripts/test_translator.py tests
This basically tests that the original C file and translated Rust file produce the same output when compiled and run. More details about tests are in this README.
The translator is driven by a compile_commands.json
file. This is a standard way to capture compiler invocations and is used by many other tools. The best way to generate
compile_commands.json
files depends on your build system.
$ ./scripts/transpile.py path/to/compile_commands.json
To generate a Cargo.toml
template for a Rust library, add the -e
option:
$ ./scripts/transpile.py -e path/to/compile_commands.json
To generate a Cargo.toml
template for a Rust binary, do this:
$ ./scripts/transpile.py -m myprog path/to/compile_commands.json
Where -m myprog
tells the transpiler to use the main
method from myprog.rs
as the entry point.
The translated Rust files will not depend directly on each other like normal Rust modules. They will export and import functions through the C API. These modules can be compiled together into a single static Rust library.
There are several known limitations in this translator. The translator will attempt to skip function definitions that use unsupported features.
The compile_commands.json
file can be automatically created using
either cmake
, intercept-build
, or bear
(Linux only).
It may be a good idea to remove optimizations(-OX
) from the compile commands
file, as there are optimization builtins which we do not support translating.
When creating the initial build directory with cmake specify
-DCMAKE_EXPORT_COMPILE_COMMANDS=1
. This only works on projects
configured to be built by cmake
. This works on Linux and MacOS.
$ mkdir build
$ cd build
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
Intercept build is distributed with clang and recommended for makefile projects on macOS.
$ intercept-build make
$ intercept-build xcodebuild
When building on Linux, Bear is automatically built by the
build_translator.py
script and installed into the dependencies
directory.
$ ./configure CC=clang
$ bear make
Are there release binaries? Can I install C2Rust with Cargo?
We hope to release binaries that you can cargo install
soon(tm).
I translated code on platform X but it didn't work correctly on platform Y
We run the C preprocessor before translation to Rust. This specializes the code to the host platform. For this reason, we do not support cross compiling translated code at the moment.
What platforms can C2Rust be run on?
The translator and refactoring tool support both macOS and Linux. Other features, such as cross checking the functionality between C and Rust code, are currently limited to Linux hosts.
To report issues with the translation, please use our Issue Tracker.
The development team can be reached by email at [email protected].
This material is available under the BSD-3 style license as found in the LICENSE file.
The C2Rust translator is inspired by Jamey Sharp's Corrode translator. We rely on Emscripten's Relooper algorithm to translate arbitrary C control flows.
This material is based upon work supported by the United States Air Force and DARPA under Contract No. FA8750-15-C-0124. Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the United States Air Force and DARPA. Distribution Statement A, “Approved for Public Release, Distribution Unlimited.”