Library / SDK
rust-lang/cc-rs avatar
rust-lang/cc-rs

cc-rs: The Build Script Compiler Wrapper That Every Rust Project With C Code Needs

Rust library for build scripts to compile C/C++ code into a Rust library

2,155 stars616 forksRustApache-2.0

At a glance

What is it?
cc-rs is a Rust library for Cargo build scripts that compiles C, C++, assembly, and CUDA sources into static archives. It delegates to the platform's default compiler and handles cross-compilation detection automatically.
Who is it for?
Adopt cc-rs if you are writing a Rust crate that must link C or C++ code and you want a battle-tested wrapper that handles compiler detection and cross-compilation. Skip it if you need fine-grained control over compiler flags or if your project is pure Rust.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem: Linking C Code in Rust Without Reinventing the Wheel

Rust crates often need to call into C libraries, either because the functionality is only available in C or because performance demands it. The Cargo build script is the standard place to compile that C code, but writing a build script that invokes the right compiler, handles cross-compilation, and produces a static archive is tedious and error-prone. cc-rs exists to remove that boilerplate. It targets developers who maintain Rust crates with a C/C++ component, such as bindings to native libraries or performance-critical kernels. The README is explicit: cc-rs is a library for Cargo build scripts to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo to link. If your project has no native code, you do not need this crate.

How cc-rs Works: Delegation, Not Compilation

The mechanism is straightforward from a user perspective. In a build.rs file, you instantiate a cc::Build, add source files, and call compile. The Build type exposes methods to set the compiler, flags, include paths, and define macros. The crate reads environment variables like CC, CFLAGS, and CXX to override defaults. The documentation, referenced in the README, provides detailed usage instructions, but the core flow is: create a Build, add files, compile. This is a thin wrapper over the system compiler, but it handles many edge cases that a naive script would miss, such as distinguishing between C and C++ compilers and setting the correct archive tool.

Getting Started: Commands and Configuration

To use cc-rs, you add it as a build-dependency in your Cargo.toml. The README does not show a full example, but the pattern is standard for Cargo build scripts. You would write something like: [build-dependencies] cc = "1.0". Then, in build.rs, you use the cc crate. A minimal example, based on the crate's typical usage, would be: fn main() { cc::Build::new().file("src/foo.c").compile("foo"); }. This compiles src/foo.c and produces a static archive named libfoo.a (or foo.lib on MSVC). The compile method takes the library name without the lib prefix. You can add multiple files with .file("src/bar.c"), set include paths with .include("src"), and define macros with .define("FOO", Some("bar")). For C++ code, you use the .cpp(true) method or name the file with a .cpp extension. The crate respects the standard environment variables: CC for the C compiler, CXX for C++, and CFLAGS/CXXFLAGS for flags. This is the extent of what the README confirms; for more advanced options, such as CUDA support, you would need to consult the full documentation.

Limitations and When It Is the Wrong Tool

cc-rs is not a full build system. It does not handle dependency tracking, incremental compilation, or complex build logic. If your C code has a large build with many generated files or requires a custom build step, cc-rs may be too simplistic. The README notes that it compiles a set of files into a static archive, but it does not mention support for shared libraries or dynamic linking. If you need to produce a .so or .dylib, cc-rs is not designed for that. Another limitation is that it relies on the default compiler for the platform. If you need a specific compiler version or a compiler that is not the default, you must set environment variables manually. The automatic detection works for common cases, but it may not cover exotic targets. Also, because it delegates to an external compiler, the build can fail if that compiler is not installed, which is a common issue on fresh systems. For projects that need fine-grained control over the compilation process, such as custom flags per file or complex link-time options, a hand-written build script or a more powerful tool like CMake might be better.

Alternatives: Hand-Rolled Build Scripts and CMake

The most direct alternative is writing a build script from scratch using std::process::Command to invoke the compiler. This gives you complete control but requires you to handle cross-compilation detection, platform-specific archive creation, and environment variable parsing yourself. That is a lot of work and error-prone, which is why cc-rs exists. Another alternative is using a CMake-based build system, either by invoking cmake from the build script or using a crate like cmake. The difference in approach is fundamental: cc-rs is a thin wrapper that assumes you are compiling a small set of files with the system compiler, while CMake is a full build system that can generate build files for many platforms and handle complex dependencies. If your C codebase is large or has its own build system, CMake is often a better fit. However, CMake adds a significant dependency and complexity, whereas cc-rs is a single crate with a simple API. For most Rust crates with a handful of C files, cc-rs is the pragmatic choice, but for anything more complex, the extra control of a custom script or CMake may be worth the effort.

Maintenance and License Implications

cc-rs is actively maintained, with recent releases including cc-v1.4.4 and cc-v1.4.3 in August 2026, and it is part of the rust-lang organization, which suggests a certain level of community trust. The project is dual-licensed under Apache-2.0 and MIT, at your option. This is a permissive license, so you can use it in commercial projects without concern, but you must include the license notice if you redistribute the crate. The dual licensing means you can choose the license that best fits your project's legal requirements. As a build-dependency, cc-rs is only used during compilation and does not end up in your final binary, so its license does not affect your distributed artifact. The maintenance cost is low because the API is stable and the crate is widely used, but you should still update it periodically to get bug fixes and new platform support. The recent release activity indicates that the project is actively evolving, so you can expect continued support for new Rust versions and platforms.

Editorial conclusion

Adopt cc-rs if you are writing a Rust crate that must link C or C++ code and you want a battle-tested wrapper that handles compiler detection and cross-compilation. Skip it if you need fine-grained control over compiler flags or if your project is pure Rust. Before integrating, verify that your target platform's default compiler is installed and that the environment variables cc-rs respects (like CC and CFLAGS) are set correctly for your build.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Community notes

Community notes