tezvyn:

Rust Build Scripts: Compiling More Than Just Rust

AI-drafted, machine-checkedSource: doc.rust-lang.orgadvanced

A `build.rs` script is a pre-compilation hook for tasks outside Rust's scope, like compiling C code or generating Rust modules. It's essential for FFI or code generation. A key footgun: `cfg!` checks the host, not the target, breaking cross-compilation.

WHY IT EXISTS Some packages need to perform tasks that Cargo's standard build process doesn't cover, like compiling C libraries, finding system dependencies, or running code generators. Build scripts provide an integrated way to run custom logic before the main crate compilation begins, bridging the gap between Rust and other toolchains.

THE MENTAL MODEL Think of build.rs as a programmable pre-build step. Before Cargo compiles your crate, it first compiles and runs this script. The script can then prepare the environment, build dependencies, or generate code that the main crate will use. It's a bridge between the pure Rust world and external requirements.

HOW IT WORKS A file named build.rs in your package root is compiled and executed by Cargo. This script communicates with Cargo by printing specially formatted lines to standard output, like cargo::rerun-if-changed=src/my_header.h. It receives its configuration via environment variables, such as OUT_DIR for placing generated files and CARGO_CFG_* for target platform details. It can use other crates (like cc or bindgen) to perform its work.

WHEN TO USE IT Use a build script when your crate needs to: first, build a bundled C/C++ library; second, find and link against a C/C++ library on the host system; third, generate Rust source code from a specification like a Protobuf or a parser grammar.

WHEN NOT TO USE IT Avoid build scripts for simple configuration that can be handled by Cargo features. A major footgun is using them to download files from the internet during the build; this breaks offline builds and reproducibility. Also, be aware that OUT_DIR is not cleaned between builds, so your script must manage its own state if it needs a clean directory.

ONE CANONICAL EXAMPLE A crate wrapping a C library often uses a build script. The script would use the cc crate to compile a hello.c file. It then prints instructions like println!("cargo:rustc-link-lib=static=hello"); to tell rustc to link the resulting library. A critical detail is that cfg! macros check the build host's architecture, not the target's. For cross-compilation, you must read the CARGO_CFG_TARGET_ARCH environment variable instead.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.