Skip to content
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

Add experimental [cfgs] section to decribe the expected cfgs #11631

Closed
wants to merge 4 commits into from
Closed
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
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {

let nightly_features_allowed = cx.bcx.config.nightly_features_allowed;
let extra_check_cfg = match cx.bcx.config.cli_unstable().check_cfg {
Some((_, _, _, output)) => output,
Some((_, _, _, output, _)) => output,
None => false,
};
let targets: Vec<Target> = unit.pkg.targets().to_vec();
Expand Down Expand Up @@ -989,7 +989,7 @@ fn prev_build_output(cx: &mut Context<'_, '_>, unit: &Unit) -> (Option<BuildOutp
&prev_script_out_dir,
&script_out_dir,
match cx.bcx.config.cli_unstable().check_cfg {
Some((_, _, _, output)) => output,
Some((_, _, _, output, _)) => output,
None => false,
},
cx.bcx.config.nightly_features_allowed,
Expand Down
42 changes: 41 additions & 1 deletion src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,7 @@ fn features_args(unit: &Unit) -> Vec<OsString> {

/// Generate the --check-cfg arguments for the unit
fn check_cfg_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
if let Some((features, well_known_names, well_known_values, _output)) =
if let Some((features, well_known_names, well_known_values, _output, _cfgs)) =
cx.bcx.config.cli_unstable().check_cfg
{
let mut args = Vec::with_capacity(unit.pkg.summary().features().len() * 2 + 4);
Expand All @@ -1153,6 +1153,46 @@ fn check_cfg_args(cx: &Context<'_, '_>, unit: &Unit) -> Vec<OsString> {
args.push(arg);
}

if let Some(cfgs) = unit.pkg.cfgs() {
let mut names = OsString::from("names(");
let mut has_names = false;

for name in cfgs
.iter()
.filter_map(|(name, values)| values.as_ref().is_none().then_some(name))
{
if has_names {
names.push(",");
}
names.push(name);
has_names = true;
}

if has_names {
names.push(")");
args.push(OsString::from("--check-cfg"));
args.push(names);
}

for (name, values) in cfgs
.iter()
.filter_map(|(name, values)| values.as_ref().map(|values| (name, values)))
{
let mut arg = OsString::from("values(");

arg.push(name);
for val in values {
arg.push(", \"");
arg.push(&val);
arg.push("\"");
}
arg.push(")");

args.push(OsString::from("--check-cfg"));
args.push(arg);
}
}

if well_known_names {
args.push(OsString::from("--check-cfg"));
args.push(OsString::from("names()"));
Expand Down
17 changes: 13 additions & 4 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ unstable_cli_options!(
config_include: bool = ("Enable the `include` key in config files"),
credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"),
#[serde(deserialize_with = "deserialize_check_cfg")]
check_cfg: Option<(/*features:*/ bool, /*well_known_names:*/ bool, /*well_known_values:*/ bool, /*output:*/ bool)> = ("Specify scope of compile-time checking of `cfg` names/values"),
check_cfg: Option<(/*features:*/ bool, /*well_known_names:*/ bool, /*well_known_values:*/ bool, /*output:*/ bool, /*cfgs:*/ bool)> = ("Specify scope of compile-time checking of `cfg` names/values"),
doctest_in_workspace: bool = ("Compile doctests with paths relative to the workspace root"),
doctest_xcompile: bool = ("Compile and run doctests for non-host target using runner config"),
dual_proc_macros: bool = ("Build proc-macros for both the host and the target"),
Expand Down Expand Up @@ -774,7 +774,7 @@ where

fn deserialize_check_cfg<'de, D>(
deserializer: D,
) -> Result<Option<(bool, bool, bool, bool)>, D::Error>
) -> Result<Option<(bool, bool, bool, bool, bool)>, D::Error>
where
D: serde::Deserializer<'de>,
{
Expand All @@ -789,27 +789,36 @@ where

fn parse_check_cfg(
it: impl Iterator<Item = impl AsRef<str>>,
) -> CargoResult<Option<(bool, bool, bool, bool)>> {
) -> CargoResult<Option<(bool, bool, bool, bool, bool)>> {
let mut features = false;
let mut well_known_names = false;
let mut well_known_values = false;
let mut output = false;
let mut cfgs = false;

let mut had_options = false;
for e in it {
match e.as_ref() {
"features" => features = true,
"names" => well_known_names = true,
"values" => well_known_values = true,
"output" => output = true,
_ => bail!("unstable check-cfg only takes `features`, `names`, `values` or `output` as valid inputs"),
"cfgs" => cfgs = true,
_ => bail!("unstable check-cfg only takes `features`, `names`, `values`, `output` or `cfgs` as valid inputs"),
}
had_options = true;
}

if !had_options {
bail!("unstable check-cfg must take one or more of these options: `features`, `names`, `values`, `output` or `cfgs`");
}

Ok(Some((
features,
well_known_names,
well_known_values,
output,
cfgs,
)))
}

Expand Down
6 changes: 6 additions & 0 deletions src/cargo/core/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub struct Manifest {
default_run: Option<String>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
cfgs: Option<BTreeMap<String, Option<Vec<String>>>>,
}

/// When parsing `Cargo.toml`, some warnings should silenced
Expand Down Expand Up @@ -405,6 +406,7 @@ impl Manifest {
original: Rc<TomlManifest>,
metabuild: Option<Vec<String>>,
resolve_behavior: Option<ResolveBehavior>,
cfgs: Option<BTreeMap<String, Option<Vec<String>>>>,
) -> Manifest {
Manifest {
summary,
Expand All @@ -430,6 +432,7 @@ impl Manifest {
default_run,
metabuild,
resolve_behavior,
cfgs,
}
}

Expand Down Expand Up @@ -497,6 +500,9 @@ impl Manifest {
pub fn links(&self) -> Option<&str> {
self.links.as_deref()
}
pub fn cfgs(&self) -> &Option<BTreeMap<String, Option<Vec<String>>>> {
&self.cfgs
}

pub fn workspace_config(&self) -> &WorkspaceConfig {
&self.workspace
Expand Down
5 changes: 5 additions & 0 deletions src/cargo/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub struct SerializedPackage {
dependencies: Vec<Dependency>,
targets: Vec<Target>,
features: BTreeMap<InternedString, Vec<InternedString>>,
// cfgs: BTreeMap<String, Option<Vec<String>>>,
manifest_path: PathBuf,
metadata: Option<toml::Value>,
publish: Option<Vec<String>>,
Expand Down Expand Up @@ -164,6 +165,10 @@ impl Package {
pub fn authors(&self) -> &Vec<String> {
&self.manifest().metadata().authors
}
/// Gets the cfgs.
pub fn cfgs(&self) -> &Option<BTreeMap<String, Option<Vec<String>>>> {
self.manifest().cfgs()
}

/// Returns `None` if the package is set to publish.
/// Returns `Some(allowed_registries)` if publishing is limited to specified
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/util/config/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ fn parse_links_overrides(
) -> CargoResult<BTreeMap<String, BuildOutput>> {
let mut links_overrides = BTreeMap::new();
let extra_check_cfg = match config.cli_unstable().check_cfg {
Some((_, _, _, output)) => output,
Some((_, _, _, output, _)) => output,
None => false,
};

Expand Down
39 changes: 39 additions & 0 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,31 @@ pub struct TomlManifest {
#[serde(rename = "build_dependencies")]
build_dependencies2: Option<BTreeMap<String, MaybeWorkspaceDependency>>,
features: Option<BTreeMap<InternedString, Vec<InternedString>>>,
cfgs: Option<BTreeMap<String, TomlCfg>>,
target: Option<BTreeMap<String, TomlPlatform>>,
replace: Option<BTreeMap<String, TomlDependency>>,
patch: Option<BTreeMap<String, BTreeMap<String, TomlDependency>>>,
workspace: Option<TomlWorkspace>,
badges: Option<MaybeWorkspaceField<BTreeMap<String, BTreeMap<String, String>>>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum TomlCfg {
List(Vec<String>),
Values { values: bool },
}

impl TomlCfg {
pub(crate) fn into_option_vec(self) -> Option<Vec<String>> {
match self {
TomlCfg::List(l) => Some(l),
TomlCfg::Values { values: true } => Some(Vec::new()),
TomlCfg::Values { values: false } => None,
}
}
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
pub struct TomlProfiles(BTreeMap<InternedString, TomlProfile>);

Expand Down Expand Up @@ -1558,6 +1576,7 @@ impl TomlManifest {
)?,
build_dependencies2: None,
features: self.features.clone(),
cfgs: self.cfgs.clone(),
target: match self.target.as_ref().map(|target_map| {
target_map
.iter()
Expand Down Expand Up @@ -1793,6 +1812,15 @@ impl TomlManifest {
)));
}

if me.cfgs.is_some()
&& matches!(
&config.cli_unstable().check_cfg,
None | Some((_, _, _, _, false))
)
{
bail!("`[cfgs]` section requires `-Zcheck-cfg=cfgs`");
}

let rust_version = if let Some(rust_version) = &package.rust_version {
let rust_version = rust_version
.clone()
Expand Down Expand Up @@ -2220,6 +2248,12 @@ impl TomlManifest {
}
}

let cfgs = me.cfgs.as_ref().map(|cfgs| {
cfgs.iter()
.map(|(name, toml_cfg)| (name.clone(), toml_cfg.clone().into_option_vec()))
.collect()
});

let default_kind = package
.default_target
.as_ref()
Expand Down Expand Up @@ -2249,6 +2283,7 @@ impl TomlManifest {
build_dependencies: build_deps,
build_dependencies2: None,
features: me.features.clone(),
cfgs: me.cfgs.clone(),
target,
replace: me.replace.clone(),
patch: me.patch.clone(),
Expand Down Expand Up @@ -2281,6 +2316,7 @@ impl TomlManifest {
Rc::new(resolved_toml),
package.metabuild.clone().map(|sov| sov.0),
resolve_behavior,
cfgs,
);
if package.license_file.is_some() && package.license.is_some() {
manifest.warnings_mut().add_warning(
Expand Down Expand Up @@ -2344,6 +2380,9 @@ impl TomlManifest {
if me.features.is_some() {
bail!("this virtual manifest specifies a [features] section, which is not allowed");
}
if me.cfgs.is_some() {
bail!("this virtual manifest specifies a [cfgs] section, which is not allowed");
}
if me.target.is_some() {
bail!("this virtual manifest specifies a [target] section, which is not allowed");
}
Expand Down
30 changes: 28 additions & 2 deletions src/doc/src/reference/unstable.md
Original file line number Diff line number Diff line change
Expand Up @@ -1197,17 +1197,26 @@ It's values are:
- `names`: enables well known names checking via `--check-cfg=names()`.
- `values`: enables well known values checking via `--check-cfg=values()`.
- `output`: enable the use of `rustc-check-cfg` in build script.
- `cfgs`: enable the use of the `#[cfgs]` in the `Cargo.toml` manifest.

For instance:

```
cargo check -Z unstable-options -Z check-cfg=features
cargo check -Z unstable-options -Z check-cfg=names
cargo check -Z unstable-options -Z check-cfg=values
cargo check -Z unstable-options -Z check-cfg=features,names,values
cargo check -Z unstable-options -Z check-cfg=cfgs
cargo check -Z unstable-options -Z check-cfg=features,names,values,cfgs
```

Or for `output`:
Those values can also be set in the `[unstable]` section of `.cargo/config.toml`:

```toml
[unstable]
check-cfg = ["cfgs", "features"]
```

#### Usage of `output`

```rust,no_run
// build.rs
Expand All @@ -1218,6 +1227,23 @@ println!("cargo:rustc-check-cfg=names(foo, bar)");
cargo check -Z unstable-options -Z check-cfg=output
```

#### Usage of `cfgs`

In `Cargo.toml`:

```toml
[cfgs]
"use_libc" = [] # means `--check-cfg=values('use_libc')`
"loom" = ["yes", "no", "auto"] # means `--check-cfg=values('feature', "yes", "no", "auto")`

[cfgs."unknow_values"] # means `--check-cfg=names('unknow_values')`
values = false # aka values are unknown (so everything is accepted)
```

```
cargo check -Z unstable-options -Z check-cfg=cfgs
```

### `cargo:rustc-check-cfg=CHECK_CFG`

The `rustc-check-cfg` instruction tells Cargo to pass the given value to the
Expand Down
Loading