Skip to content
tezvyn:

Purpose and mechanism of a Rust build.rs script

Source: interviewHardHow cards are made

Summary

Cargo's build pipeline.

Key points

build.rs compiles and runs before the crate, emitting cargo: directives via stdout to set link flags, env vars, and rerun triggers; used to compile C, generate code, or probe the system.

What's really being asked

Whether you understand Cargo's extensibility point for build-time logic, how it communicates with the compiler, and when native linking or code generation requires it.

The full answer

A build.rs at the crate root is a separate Rust program. Before compiling the crate, Cargo compiles build.rs for the host and runs it, capturing its stdout. The script influences the build by printing directives, for example cargo:rustc-link-lib=foo to link a library, cargo:rustc-link-search=native=/path to add a search directory, cargo:rerun-if-changed=path to scope rebuilds, cargo:rustc-cfg=feature to enable conditional compilation, and cargo:rustc-env to inject environment values readable via env! at compile time. Outputs are placed in OUT_DIR, which the crate can include! to pull in generated source. Common jobs are compiling bundled C or assembly with the cc crate, generating FFI bindings with bindgen, probing the system with pkg-config or vcpkg, and embedding build metadata such as a git hash.

The mistakes people make

Saying build.rs runs when the final binary executes; it runs at build time only. Believing it edits your committed source; it writes to OUT_DIR. Forgetting rerun-if-changed, which causes stale or excessive rebuilds.

What usually comes next

How do you avoid rebuilding every time? How do build-dependencies differ from normal dependencies? How does cross-compilation affect the host versus target distinction? How do you statically versus dynamically link the native library?

A concrete example

Linking against a vendored C compression library: build.rs uses cc::Build to compile the .c sources into a static archive in OUT_DIR, then prints cargo:rustc-link-lib=static=zfast and cargo:rustc-link-search=native plus the OUT_DIR path. The Rust crate declares the C functions in an extern block, and Cargo links the archive into the final binary, all driven by the script.

Interview question

How does a build.rs script tell the Rust compiler to link against a native library it just compiled?

  • a.By modifying Cargo.toml at runtime to add the library
  • b.By placing the library in the target/ directory where rustc auto-discovers it
  • c.By calling rustc directly with command-line link flags
  • d.By printing cargo:rustc-link-lib and cargo:rustc-link-search directives to stdoutCorrect
Why?

Cargo reads the script's stdout and acts on cargo: directives like rustc-link-lib and rustc-link-search. The script does not edit Cargo.toml or invoke rustc itself, and rustc does not auto-discover libraries by directory.

Just read this? Test yourself on what you have been reading.

Read the original → doc.rust-lang.org

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on rust — each one lists the topics its interview covers.

See open roles