Skip to content

Commit

Permalink
Add support for boolean literals in target cfgs
Browse files Browse the repository at this point in the history
  • Loading branch information
Urgau committed Oct 9, 2024
1 parent 20bbe3b commit 6bc170b
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 47 deletions.
14 changes: 12 additions & 2 deletions crates/cargo-platform/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub enum CfgExpr {
All(Vec<CfgExpr>),
Any(Vec<CfgExpr>),
Value(Cfg),
True,
False,
}

/// A cfg value.
Expand Down Expand Up @@ -87,6 +89,8 @@ impl CfgExpr {
CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
CfgExpr::Value(ref e) => cfg.contains(e),
CfgExpr::True => true,
CfgExpr::False => false,
}
}

Expand All @@ -106,7 +110,7 @@ impl CfgExpr {
}
Ok(())
}
CfgExpr::Value(_) => Ok(()),
CfgExpr::Value(_) | CfgExpr::True | CfgExpr::False => Ok(()),
}
}

Expand Down Expand Up @@ -137,6 +141,8 @@ impl fmt::Display for CfgExpr {
CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
CfgExpr::Value(ref e) => write!(f, "{}", e),
CfgExpr::True => write!(f, "true"),
CfgExpr::False => write!(f, "false"),
}
}
}
Expand Down Expand Up @@ -191,7 +197,11 @@ impl<'a> Parser<'a> {
self.eat(&Token::RightParen)?;
Ok(CfgExpr::Not(Box::new(e)))
}
Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
Some(Ok(..)) => self.cfg().map(|v| match v {
Cfg::Name(n) if n == "true" => CfgExpr::True,
Cfg::Name(n) if n == "false" => CfgExpr::False,
v => CfgExpr::Value(v),
}),
Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
None => Err(ParseError::new(
self.t.orig,
Expand Down
1 change: 1 addition & 0 deletions crates/cargo-platform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ impl Platform {
))
},
}
CfgExpr::True | CfgExpr::False => {},
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ features! {

/// Allow paths that resolve relatively to a base specified in the config.
(unstable, path_bases, "", "reference/unstable.html#path-bases"),

/// Allow boolean literals in `[target.'cfg(<true/false>)']`
(unstable, cfg_boolean_literals, "", "reference/unstable.html#cfg-boolean-literals"),
}

/// Status and metadata for a single unstable feature.
Expand Down Expand Up @@ -760,6 +763,7 @@ unstable_cli_options!(
build_std: Option<Vec<String>> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"),
build_std_features: Option<Vec<String>> = ("Configure features enabled for the standard library itself when building the standard library"),
cargo_lints: bool = ("Enable the `[lints.cargo]` table"),
cfg_boolean_literals: bool = ("Allow boolean literals in `[target.'cfg(<true/false>)']`"),
checksum_freshness: bool = ("Use a checksum to determine if output is fresh rather than filesystem mtime"),
codegen_backend: bool = ("Enable the `codegen-backend` option in profiles in .cargo/config.toml file"),
config_include: bool = ("Enable the `include` key in config files"),
Expand Down Expand Up @@ -1256,6 +1260,7 @@ impl CliUnstable {
}
"build-std-features" => self.build_std_features = Some(parse_features(v)),
"cargo-lints" => self.cargo_lints = parse_empty(k, v)?,
"cfg-boolean-literals" => self.cfg_boolean_literals = parse_empty(k, v)?,
"codegen-backend" => self.codegen_backend = parse_empty(k, v)?,
"config-include" => self.config_include = parse_empty(k, v)?,
"direct-minimal-versions" => self.direct_minimal_versions = parse_empty(k, v)?,
Expand Down
12 changes: 12 additions & 0 deletions src/cargo/util/context/target.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{ConfigKey, ConfigRelativePath, GlobalContext, OptValue, PathAndArgs, StringList, CV};
use crate::core::compiler::{BuildOutput, LinkArgTarget};
use crate::util::CargoResult;
use cargo_platform::{CfgExpr, Platform};
use serde::Deserialize;
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
Expand Down Expand Up @@ -53,6 +54,17 @@ pub(super) fn load_target_cfgs(
let target: BTreeMap<String, TargetCfgConfig> = gctx.get("target")?;
tracing::debug!("Got all targets {:#?}", target);
for (key, cfg) in target {
// Feature gate `cfg(true)`/`cfg(false)` under `-Zcfg-boolean-literals`
if !gctx.cli_unstable().cfg_boolean_literals {
if let Ok(Platform::Cfg(cfg_expr)) = key.parse() {
cfg_expr.walk_expr(|e| match e {
CfgExpr::True | CfgExpr::False => {
anyhow::bail!("`-Zcfg-boolean-literals` should be used to enable cfg boolean literals in `.cargo/config.toml`")
},
_ => Ok(()),
})?;
}
}
if key.starts_with("cfg(") {
// Unfortunately this is not able to display the location of the
// unused key. Using config::Value<toml::Value> doesn't work. One
Expand Down
8 changes: 7 additions & 1 deletion src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::str::{self, FromStr};
use crate::core::summary::MissingDependencyError;
use crate::AlreadyPrintedError;
use anyhow::{anyhow, bail, Context as _};
use cargo_platform::Platform;
use cargo_platform::{CfgExpr, Platform};
use cargo_util::paths::{self, normalize_path};
use cargo_util_schemas::manifest::{
self, PackageName, PathBaseName, TomlDependency, TomlDetailedDependency, TomlManifest,
Expand Down Expand Up @@ -1326,6 +1326,12 @@ pub fn to_real_manifest(
for (name, platform) in original_toml.target.iter().flatten() {
let platform_kind: Platform = name.parse()?;
platform_kind.check_cfg_attributes(warnings);
if let Platform::Cfg(cfg_expr) = &platform_kind {
cfg_expr.walk_expr(|e| match e {
CfgExpr::True | CfgExpr::False => features.require(Feature::cfg_boolean_literals()),
_ => Ok(()),
})?;
}
let platform_kind = Some(platform_kind);
validate_dependencies(
platform.dependencies.as_ref(),
Expand Down
24 changes: 24 additions & 0 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Each new feature described below should explain how to use it.
* [lockfile-path](#lockfile-path) --- Allows to specify a path to lockfile other than the default path `<workspace_root>/Cargo.lock`.
* [package-workspace](#package-workspace) --- Allows for packaging and publishing multiple crates in a workspace.
* [native-completions](#native-completions) --- Move cargo shell completions to native completions.
* [cfg-boolean-literals](#cfg-boolean-literals) --- Allows the use of boolean literals in `[target.'cfg(<true/false>)']`

## allow-features

Expand Down Expand Up @@ -1766,6 +1767,29 @@ When in doubt, you can discuss this in [#14520](https://github.com/rust-lang/car
- powershell:
Add `CARGO_COMPLETE=powershell cargo +nightly | Invoke-Expression` to `$PROFILE`.

## cfg-boolean-literals

* Tracking Issue: [#00000](https://github.com/rust-lang/cargo/issues/00000)

This feature allows the use of boolean literals in `[target.'cfg(<true/false>)']`.

Those boolean literals always evaluate to true and false respectively, they are **not** subject
to `RUSTFLAGS`.

For example, in this example the `b` dependencies is always compiled, while `c` is never:

```toml
cargo-features = ["cfg-boolean-literals"]

[target.'cfg(true)'.dependencies]
b = { path = 'b' }

[target.'cfg(false)'.dependencies]
c = { path = 'c' }
```

For cfgs in `.cargo/config.toml`, `-Zcfg-boolean-literals` must be used.

# Stabilized and removed features

## Compile progress
Expand Down
64 changes: 33 additions & 31 deletions tests/testsuite/cargo/z_help/stdout.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 6bc170b

Please sign in to comment.