Skip to content
Open
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
43 changes: 27 additions & 16 deletions src/doc/src/reference/build-script-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ available. The following is a sample of some popular crates[^†]:
[^†]: This list is not an endorsement. Evaluate your dependencies to see which
is right for your project.

Note: The examples in this guide use the `build-rs` crate. This is the recommended way to emit build script instructions, as it ensures type safety and correct formatting. To use it, add build-rs to your [build-dependencies].

## Code generation

Some Cargo packages need to have code generated just before they are compiled
Expand Down Expand Up @@ -50,6 +52,9 @@ Here we can see that we have a `build.rs` build script and our binary in
name = "hello-from-generated-code"
version = "0.1.0"
edition = "2024"

[build-dependencies]
build-rs= "0.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this being in the docs, how are we going to keep it up-to-date?

```

Let’s see what’s inside the build script:
Expand All @@ -71,7 +76,7 @@ fn main() {
}
"
).unwrap();
println!("cargo::rerun-if-changed=build.rs");
build_rs::output::rerun_if_changed("build.rs");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple lines above OUT_DIR is read and could instead use out_dir()

}
```

Expand Down Expand Up @@ -156,6 +161,9 @@ Pretty similar to before! Next, the manifest:
name = "hello-world-from-c"
version = "0.1.0"
edition = "2024"

[build-dependencies]
build-rs= "0.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
build-rs= "0.3.0"
build-rs = "0.3.0"

```

For now we’re not going to use any build dependencies, so let’s take a look at
Expand All @@ -180,9 +188,9 @@ fn main() {
.current_dir(&Path::new(&out_dir))
.status().unwrap();

println!("cargo::rustc-link-search=native={}", out_dir);
println!("cargo::rustc-link-lib=static=hello");
println!("cargo::rerun-if-changed=src/hello.c");
build_rs::output::rustc_link_search(out_dir);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be rustc_link_search_kind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OUT_DIR again

build_rs::output::rustc_link_lib_kind("static", "hello");
build_rs::output::rerun_if_changed("src/hello.c");
}
```

Expand Down Expand Up @@ -210,6 +218,7 @@ crate](https://crates.io/crates/cc) from [crates.io]. First, add it to the
```toml
[build-dependencies]
cc = "1.0"
build-rs= "0.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
build-rs= "0.3.0"
build-rs = "0.3.0"

```

And rewrite the build script to use this crate:
Expand All @@ -221,7 +230,7 @@ fn main() {
cc::Build::new()
.file("src/hello.c")
.compile("hello");
println!("cargo::rerun-if-changed=src/hello.c");
build_rs::output::rerun_if_changed("src/hello.c");
}
```

Expand Down Expand Up @@ -310,6 +319,7 @@ links = "z"

[build-dependencies]
pkg-config = "0.3.16"
build-rs = "0.3.0"
```

Take note that we included the `links` key in the `package` table. This tells
Expand All @@ -323,7 +333,7 @@ The build script is fairly simple:

fn main() {
pkg_config::Config::new().probe("zlib").unwrap();
println!("cargo::rerun-if-changed=build.rs");
build_rs::output::rerun_if_changed("build.rs");
}
```

Expand Down Expand Up @@ -399,6 +409,7 @@ libz-sys = "1.0.25"

[build-dependencies]
cc = "1.0.46"
build-rs = "0.3.0"
```

Here we have included `libz-sys` which will ensure that there is only one
Expand All @@ -415,7 +426,7 @@ fn main() {
cfg.include(include);
}
cfg.compile("z_user");
println!("cargo::rerun-if-changed=src/z_user.c");
build_rs::output::rerun_if_changed("src/z_user.c");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use dep_metadata for DEP_Z_INCLUDE?

}
```

Expand Down Expand Up @@ -447,7 +458,7 @@ script looks something [like
this](https://github.com/sfackler/rust-openssl/blob/dc72a8e2c429e46c275e528b61a733a66e7877fc/openssl-sys/build/main.rs#L216):

```rust,ignore
println!("cargo::metadata=version_number={openssl_version:x}");
build_rs::output::metadata("version_number","openssl_version");
```

This instruction causes the `DEP_OPENSSL_VERSION_NUMBER` environment variable
Expand All @@ -463,26 +474,26 @@ values](https://github.com/sfackler/rust-openssl/blob/dc72a8e2c429e46c275e528b61
```rust,ignore
// (portion of build.rs)

println!("cargo::rustc-check-cfg=cfg(ossl101,ossl102)");
println!("cargo::rustc-check-cfg=cfg(ossl110,ossl110g,ossl111)");
build_rs::output::rustc_check_cfgs(&["ossl101","ossl102",]);
build_rs::output::rustc_check_cfgs(&["ossl110","ossl110g","ossl111",]);
Comment on lines +477 to +478
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clean up the code style


if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&version, 16).unwrap();

if version >= 0x1_00_01_00_0 {
println!("cargo::rustc-cfg=ossl101");
build_rs::output::rustc_check_cfgs(&["ossl101"]);
}
if version >= 0x1_00_02_00_0 {
println!("cargo::rustc-cfg=ossl102");
build_rs::output::rustc_check_cfgs(&["ossl102"]);
}
if version >= 0x1_01_00_00_0 {
println!("cargo::rustc-cfg=ossl110");
build_rs::output::rustc_check_cfgs(&["ossl110"]);
}
if version >= 0x1_01_00_07_0 {
println!("cargo::rustc-cfg=ossl110g");
build_rs::output::rustc_check_cfgs(&["ossl110g"]);
}
if version >= 0x1_01_01_00_0 {
println!("cargo::rustc-cfg=ossl111");
build_rs::output::rustc_check_cfgs(&["ossl111"]);
}
}
```
Expand Down Expand Up @@ -512,5 +523,5 @@ libraries, which could cause problems.
[`rustc-cfg` instructions]: build-scripts.md#rustc-cfg
[`openssl` crate]: https://crates.io/crates/openssl
[`openssl-sys` crate]: https://crates.io/crates/openssl-sys

[`build-rs` crate]: https://crates.io/crates/build-rs
[crates.io]: https://crates.io/
57 changes: 54 additions & 3 deletions src/doc/src/reference/build-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,25 @@ that script and execute it just before building the package.
// Example custom build script.
fn main() {
// Tell Cargo that if the given file changes, to rerun this build script.
println!("cargo::rerun-if-changed=src/hello.c");
//recommended method(using the build_rs crate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment doesn't quite read correctly to me

build_rs::rerun_if_changed("src/hello.c");
// Use the `cc` crate to build a C file and statically link it.
cc::Build::new()
.file("src/hello.c")
.compile("hello");
}
```

> **Note**
> Build scripts communicate with Cargo by printing specially formatted lines to stdout.
> While you can print these lines manually (e.g., `println!("cargo::rerun-if-changed=build.rs")`),
> we recommend using the [`build-rs`](https://crates.io/crates/build-rs) crate.
> It provides a type-safe API that ensures your build instructions are formatted correctly.
>
> The examples in this reference guide use `build-rs` to demonstrate best practices,
> while the section headers preserve the raw protocol strings for specification purposes.
Comment on lines +27 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is partly covered under " Life Cycle of a Build Script". Seems like adding a note about build-rs being an API for this to that would be cleaner



Some example use cases of build scripts are:

* Building a bundled C library.
Expand Down Expand Up @@ -157,6 +168,9 @@ option][link-arg] to the compiler, but only when building supported targets
highly platform specific. It is useful to set the shared library version or
linker script.

**Recommended:** Use [`build_rs::output::rustc_link_arg`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg.html) from the `build-rs` crate.


[link-arg]: ../../rustc/codegen-options/index.md#link-arg

### `cargo::rustc-link-arg-cdylib=FLAG` {#rustc-cdylib-link-arg}
Expand All @@ -169,38 +183,50 @@ to set the shared library version or the runtime-path.
For historical reasons, the `cargo::rustc-cdylib-link-arg` form is an alias
for `cargo::rustc-link-arg-cdylib`, and has the same meaning.

**Recommended:** Use [`build_rs::output::rustc_cdylib_link_arg`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_cdylib_link_arg.html) from the `build-rs` crate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to recommend this under every entry


### `cargo::rustc-link-arg-bin=BIN=FLAG` {#rustc-link-arg-bin}

The `rustc-link-arg-bin` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building
the binary target with name `BIN`. Its usage is highly platform specific. It is useful
to set a linker script or other linker options.

**Recommended:** Use [`build_rs::output::rustc_link_arg_bin`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg_bin.html) from the `build-rs` crate.

### `cargo::rustc-link-arg-bins=FLAG` {#rustc-link-arg-bins}

The `rustc-link-arg-bins` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
binary target. Its usage is highly platform specific. It is useful
to set a linker script or other linker options.

**Recommended:** Use [`build_rs::output::rustc_link_arg_bins`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg_bins.html) from the `build-rs` crate.

### `cargo::rustc-link-arg-tests=FLAG` {#rustc-link-arg-tests}

The `rustc-link-arg-tests` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a
tests target.

**Recommended:** Use [`build_rs::output::rustc_link_arg_tests`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg_tests.html) from the `build-rs` crate.

### `cargo::rustc-link-arg-examples=FLAG` {#rustc-link-arg-examples}

The `rustc-link-arg-examples` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building an examples
target.

**Recommended:** Use [`build_rs::output::rustc_link_arg_examples`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg_examples.html) from the `build-rs` crate.

### `cargo::rustc-link-arg-benches=FLAG` {#rustc-link-arg-benches}

The `rustc-link-arg-benches` instruction tells Cargo to pass the [`-C
link-arg=FLAG` option][link-arg] to the compiler, but only when building a benchmark
target.

**Recommended:** Use [`build_rs::output::rustc_link_arg_benches`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_arg_benches.html) from the `build-rs` crate.

### `cargo::rustc-link-lib=LIB` {#rustc-link-lib}

The `rustc-link-lib` instruction tells Cargo to link the given library using
Expand All @@ -222,6 +248,8 @@ through the library target's public API.
The optional `KIND` may be one of `dylib`, `static`, or `framework`. See the
[rustc book][option-link] for more detail.

**Recommended:** Use [`build_rs::output::rustc_link_lib`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_lib.html) from the `build-rs` crate.

[option-link]: ../../rustc/command-line-arguments.md#option-l-link-lib
[FFI]: ../../nomicon/ffi.md

Expand All @@ -241,6 +269,8 @@ difficult to use the resulting binary. In general, it is best to avoid
creating dynamic libraries in a build script (using existing system libraries
is fine).

**Recommended:** Use [`build_rs::output::rustc_link_search`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_link_search.html) from the `build-rs` crate.

[option-search]: ../../rustc/command-line-arguments.md#option-l-search-path

### `cargo::rustc-flags=FLAGS` {#rustc-flags}
Expand All @@ -250,6 +280,8 @@ flags to the compiler. This only allows the `-l` and `-L` flags, and is
equivalent to using [`rustc-link-lib`](#rustc-link-lib) and
[`rustc-link-search`](#rustc-link-search).

**Recommended:** Use [`build_rs::output::rustc_flags`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_flags.html) from the `build-rs` crate.

### `cargo::rustc-cfg=KEY[="VALUE"]` {#rustc-cfg}

The `rustc-cfg` instruction tells Cargo to pass the given value to the
Expand All @@ -270,6 +302,8 @@ of `feature=`). Or an arbitrary key/value pair may be used with an `=` symbol
like `cargo::rustc-cfg=my_component="foo"`. The key should be a Rust
identifier, the value should be a string.

**Recommended:** Use [`build_rs::output::rustc_cfg`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_cfg.html) from the `build-rs` crate.

[cargo features]: features.md
[conditional compilation]: ../../reference/conditional-compilation.md
[option-cfg]: ../../rustc/command-line-arguments.md#option-cfg
Expand All @@ -287,9 +321,12 @@ The instruction can be used like this:

```rust,no_run
// build.rs
println!("cargo::rustc-check-cfg=cfg(foo, values(\"bar\"))");
build_rs::output::rustc_check_cfg_values(
"foo",
&["bar"],
);
if foo_bar_condition {
println!("cargo::rustc-cfg=foo=\"bar\"");
build_rs::output::rustc_cfg_value("foo", "bar");
}
```

Expand All @@ -303,6 +340,8 @@ avoid typos, missing check-cfg, stale cfgs...
See also the
[conditional compilation][conditional-compilation-example] example.

**Recommended:** Use [`build_rs::output::rustc_check_cfgs`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_check_cfgs.html) from the `build-rs` crate.

> **MSRV:** Respected as of 1.80

[checking-conditional-configurations]: ../../rustc/check-cfg.html
Expand All @@ -326,6 +365,8 @@ Cargo][env-cargo].
> Normally, these environment variables should only be checked at compile-time
> with the `env!` macro.

**Recommended:** Use [`build_rs::output::rustc_env`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.rustc_env.html) from the `build-rs` crate.

[env-macro]: ../../std/macro.env.html
[env-cargo]: environment-variables.md#environment-variables-cargo-sets-for-crates

Expand All @@ -340,6 +381,9 @@ has finished running, and then fail the build.
> The caller can then decide whether or not to display the `Err` variant
> using `cargo::error`.


**Recommended:** Use [`build_rs::output::error`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.error.html) from the `build-rs` crate.

> **MSRV:** Respected as of 1.84

### `cargo::warning=MESSAGE` {#cargo-warning}
Expand All @@ -351,6 +395,8 @@ out in [crates.io] crates are not emitted by default, unless the build fails.
The `-vv` "very verbose" flag may be used to have Cargo display warnings for
all crates.

**Recommended:** Use [`build_rs::output::warning`](https://docs.rs/build-rs/0.3.3/build_rs/output/fn.warning.html) from the `build-rs` crate.

## Build Dependencies

Build scripts are also allowed to have dependencies on other Cargo-based crates.
Expand Down Expand Up @@ -407,6 +453,8 @@ automatically handles whether or not the script itself needs to be recompiled,
and of course the script will be re-run after it has been recompiled.
Otherwise, specifying `build.rs` is redundant and unnecessary.

**Recommended**: Use `build_rs::rerun_if_changed` to emit this instruction safely. The behavior is similar to `cargo::rerun-if-changed`.

### `cargo::rerun-if-env-changed=NAME` {#rerun-if-env-changed}

The `rerun-if-env-changed` instruction tells Cargo to re-run the build script
Expand All @@ -423,6 +471,8 @@ source code will automatically detect changes and trigger rebuilds.
`rerun-if-env-changed` is no longer needed for variables already referenced by
these macros.

**Recommended**: Use `build_rs::output::rerun_if_env_changed` to monitor environment variables. Its behavior similar to that of `cargo::rerun-if-env-changed`.

[option-env-macro]: ../../std/macro.option_env.html

## The `links` Manifest Key
Expand Down Expand Up @@ -548,4 +598,5 @@ at the same time.
[`cc` crate]: https://crates.io/crates/cc
[`jobserver` crate]: https://crates.io/crates/jobserver
[jobserver protocol]: http://make.mad-scientist.net/papers/jobserver-implementation/
[`build-rs` crate]: https://crates.io/crates/build-rs
[crates.io]: https://crates.io/