-
Notifications
You must be signed in to change notification settings - Fork 301
Announce automatic checking of cfgs at compile-time #1313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 12 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
c560529
Announce automatic checking of cfgs at compile-time
Urgau 3fdb571
Apply some suggestions from programmerjake
Urgau b02d576
Apply second round of suggestions from code review
Urgau d9f2a08
Apply suggestions and update links to rustc book
Urgau 8375ca8
Add section for non-Cargo based build systems + fix typos
Urgau 6b2803f
Host the SVG on the blog directly instead of a third-party website
Urgau 80c2bb9
Schedule for the 8th of may and populate last remaining links
Urgau 2682b15
Change the schedule to tomorrow (2024-05-05)
Urgau b360281
Stylist nitpicks
Urgau 97e7058
Double-column and put unconditional in bold
Urgau 09e360c
Update SVG with latest diagnostics updates
Urgau 1337ead
Changed publication date to 2024-05-06
Urgau e65e0ad
Apply suggestions from epage
Urgau File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
--- | ||
layout: post | ||
title: "Automatic checking of cfgs at compile-time" | ||
author: Urgau | ||
team: The Cargo Team <https://www.rust-lang.org/governance/teams/dev-tools#cargo> | ||
--- | ||
|
||
The Cargo and Compiler team are delighted to announce that starting with Rust 1.80 (or nightly-2024-05-05) every _reachable_ `#[cfg]` will be **automatically checked** that they match the **expected config names and values**. | ||
|
||
This can help with verifying that the crate is correctly handling conditional compilation for different target platforms or features. It ensures that the cfg settings are consistent between what is intended and what is used, helping to catch potential bugs or errors early in the development process. | ||
|
||
This addresses a common pitfall for new and advanced users. | ||
|
||
This is another step to our commitment to provide user-focused tooling and we are eager and excited to finally see it fixed, after more than two years since the original [RFC 3013](https://github.com/rust-lang/rfcs/pull/3013)[^1]. | ||
|
||
[^1]: The stabilized implementation and RFC 3013 diverge significantly, in particular there is only one form for `--check-cfg`: `cfg()` (instead of `values()` and `names()` being incomplete and subtlety incompatible with each other). | ||
|
||
## A look at the feature | ||
|
||
Every time a Cargo feature is declared that feature is transformed into a config that is passed to `rustc` (the Rust compiler) so it can verify with its [well known cfgs](https://doc.rust-lang.org/nightly/rustc/check-cfg.html#well-known-names-and-values) if any of the `#[cfg]`, `#![cfg_attr]` and `cfg!` have unexpected configs and report a warning with the `unexpected_cfgs` lint. | ||
|
||
*`Cargo.toml`*: | ||
|
||
```toml | ||
[package] | ||
name = "foo" | ||
|
||
[features] | ||
lasers = [] | ||
zapping = [] | ||
``` | ||
|
||
*`src/lib.rs`:* | ||
|
||
```rust | ||
#[cfg(feature = "lasers")] // This condition is expected | ||
// as "lasers" is an expected value | ||
// of the `feature` cfg | ||
fn shoot_lasers() {} | ||
|
||
#[cfg(feature = "monkeys")] // This condition is UNEXPECTED | ||
// as "monkeys" is NOT an expected | ||
// value of the `feature` cfg | ||
fn write_shakespeare() {} | ||
|
||
#[cfg(windosw)] // This condition is UNEXPECTED | ||
// it's supposed to be `windows` | ||
fn win() {} | ||
``` | ||
|
||
*`cargo check`*: | ||
|
||
 | ||
|
||
## Custom cfgs and build scripts | ||
|
||
> In Cargo point-of-view: a custom cfg is one that is neither defined by `rustc` nor by a Cargo feature. Think of `tokio_unstable`, `has_foo`, ... but not `feature = "lasers"`, `unix` or `debug_assertions` | ||
|
||
Some crates use custom cfgs that they either expected from the environment (`RUSTFLAGS`or other means) or is enabled by some logic in the crate `build.rs`. For those crates Cargo provides a new instruction: [`cargo::rustc-check-cfg`](https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg)[^2] (or `cargo:rustc-check-cfg` for older Cargo version). | ||
|
||
[^2]: `cargo::rustc-check-cfg` will start working in Rust 1.80 (or nightly-2024-05-05). From Rust 1.77 to Rust 1.79 *(inclusive)* it is silently ignored. In Rust 1.76 and below a warning is emitted when used without the unstable Cargo flag `-Zcheck-cfg`. | ||
|
||
The syntax to use is described in the [rustc book](https://doc.rust-lang.org/nightly/rustc/) section [checking configuration](https://doc.rust-lang.org/nightly/rustc/check-cfg.html), but in a nutshell the basic syntax of `--check-cfg` is: | ||
|
||
``` | ||
cfg(name, values("value1", "value2", ..., "valueN")) | ||
``` | ||
|
||
Note that every custom cfgs must always be expected, regardless if the cfg is active or not! | ||
|
||
### `build.rs` example | ||
|
||
`build.rs`: | ||
```rust | ||
fn main() { | ||
println!("cargo::rustc-check-cfg=cfg(has_foo)"); | ||
// ^^^^^^^^^^^^^^^^^^^^^^ new with Cargo 1.80 | ||
if has_foo() { | ||
println!("cargo::rustc-cfg=has_foo"); | ||
} | ||
} | ||
``` | ||
|
||
> Each `cargo::rustc-cfg` must always have a accompanying **unconditional** `cargo::rustc-check-cfg` directive otherwise you risk having warnings like this: `unexpected cfg condition name: has_foo`. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Equivalence table | ||
|
||
| `cargo::rustc-cfg` | `cargo::rustc-check-cfg` | | ||
|-------------------------|------------------------------------------------| | ||
| `foo` | `cfg(foo)` or `cfg(foo, values(none()))` | | ||
| `foo=""` | `cfg(foo, values(""))` | | ||
| `foo="bar"` | `cfg(foo, values("bar"))` | | ||
| `foo="1"` and `foo="2"` | `cfg(foo, values("1", "2"))` | | ||
| `foo="1"` and `bar="2"` | `cfg(foo, values("1"))` and `cfg(bar, values("2"))` | | ||
| `foo` and `foo="bar"` | `cfg(foo, values(none(), "bar"))` | | ||
|
||
More details can be found in the [`rustc` book](https://doc.rust-lang.org/nightly/rustc/check-cfg.html). | ||
|
||
## Frequently asked questions | ||
|
||
### Can it be disabled? | ||
|
||
The feature is **always on** and _cannot_ be disabled from Cargo, but like any other lints it can be controlled: `#![warn(unexpected_cfgs)]`. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### Does the lint affect dependencies? | ||
|
||
No, the lint only affects local packages; only those will report the lint. | ||
Urgau marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
### How does it interact with the `RUSTFLAGS` env? | ||
|
||
You should be able to use the `RUSTFLAGS` environment variable like it was before. | ||
*Currently `--cfg` arguments are not checked, only usage in code are.* | ||
|
||
This means that doing `RUSTFLAGS="--cfg tokio_unstable" cargo check` will not report any warnings, unless `tokio_unstable` is used within your local crates, in which case crate author will need to make sure that that custom cfg is expected with `cargo::rustc-check-cfg` in the `build.rs` of that crate. | ||
|
||
### How to expect custom cfgs without a `build.rs`? | ||
|
||
There is **currently no way** to expect a custom cfg other than with `cargo::rustc-check-cfg` in a `build.rs`. | ||
|
||
Crate authors that don't want to use a `build.rs` are encouraged to use Cargo features instead. | ||
|
||
### How does it interact with other build systems? | ||
|
||
Non-Cargo based build systems are not affected by the lint by default. Build system authors that wish to have the same functionality should look at the `rustc` documentation for the [`--check-cfg`](https://doc.rust-lang.org/nightly/rustc/check-cfg.html) flag for a detailed explanation of how to achieve the same functionality. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.