Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/doc/src/reference/build-script-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,36 @@ already installed.

// … rest of code that makes use of zlib.
```
## Reading target configuration

When a build script needs to make decisions based on the target platform, it should read the `CARGO_CFG_*` environment
variables rather than using `cfg!` or `#[cfg]` attributes. This is because
the build script is compiled for and runs on the *host* machine, while
`CARGO_CFG_*` variables reflect the *target* platform, an important distinction
when cross-compiling.
```rust,ignore
// build.rs

fn main() {
// reads the TARGET configuration
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();

if target_os == "windows" {
println!("cargo::rustc-link-lib=userenv");
} else if target_os == "linux" {
println!("cargo::rustc-link-lib=pthread");
}
}
```

Note that some configuration values may contain multiple values separated by
commas (for example, `CARGO_CFG_TARGET_FAMILY` may be `unix,wasm`). When
checking these values, be sure to handle this appropriately.

For a more convenient, typed API, consider using the [`build-rs`] crate
which handles these details for you.

[`build-rs`]: https://crates.io/crates/build-rs

## Conditional compilation

Expand Down
13 changes: 13 additions & 0 deletions src/doc/src/reference/build-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ the source directory of the build script’s package.

[build-env]: environment-variables.md#environment-variables-cargo-sets-for-build-scripts

> **Note:** When checking [configuration options] like `target_os` or `target_arch`
> in a build script, do not use the `cfg!` macro or `#[cfg]` attribute, these
> check the **host** machine (where the build script runs), not the **target**
> platform you're compiling for. This distinction matters when cross-compiling.
>
> Instead, read the corresponding [`CARGO_CFG_*`][build-env] environment variables,
> which correctly reflect the target's configuration. For a typed API, consider
> using the [`build-rs`] crate. See the [build script examples] for more details.

[configuration options]: ../../reference/conditional-compilation.html
[`build-rs`]: https://crates.io/crates/build-rs
[build script examples]: build-script-examples.md#conditional-compilation

## Outputs of the Build Script

Build scripts may save any output files or intermediate artifacts in the
Expand Down
6 changes: 6 additions & 0 deletions src/doc/src/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,11 @@ let out_dir = env::var("OUT_DIR").unwrap();
> hence variables present in one target triple might not be available in the other.
>
> Some cfg values like `test` are not available.
>
> **Tip:** For a typed API to read these values, consider using the [`build-rs`]
> crate instead of parsing environment variables manually. Also note that
> `CARGO_CFG_*` variables should be used instead of the `cfg!` macro or `#[cfg]`
> attribute in build scripts, those check the *host* platform, not the *target*.
* `OUT_DIR` --- the folder in which all output and intermediate artifacts should
be placed. This folder is inside the build directory for the package being built,
and it is unique for the package in question. Cargo does not clean or reset this
Expand Down Expand Up @@ -429,6 +434,7 @@ let out_dir = env::var("OUT_DIR").unwrap();
[`release`]: profiles.md#release
[`debug`]: profiles.md#debug
[`opt-level`]: profiles.md#opt-level
[`build-rs`]: https://crates.io/crates/build-rs

## Environment variables Cargo sets for `cargo test`

Expand Down