A build.rs file runs before compiling your crate, enabling code generation, FFI binding generation, or environment checks. I use build scripts to generate Rust code from proto files (with prost), compile C libraries, or set cfg flags based on the target platform. The script communicates with cargo via println!("cargo:...") directives. For example, println!("cargo:rerun-if-changed=proto") tells cargo when to re-run. Build scripts have access to the crate's manifest and can depend on build-time-only crates. They're powerful but add complexity, so I use them judiciously. For code gen, they're often the cleanest solution.