diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 21608b9ab..b99bf9e4b 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -667,6 +667,7 @@ unstable_cli_options!( #[serde(deserialize_with = "deserialize_build_std")] build_std: Option> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"), build_std_features: Option> = ("Configure features enabled for the standard library itself when building the standard library"), + 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"), credential_process: bool = ("Add a config setting to fetch registry authentication tokens by calling an external process"), #[serde(deserialize_with = "deserialize_check_cfg")] @@ -680,6 +681,7 @@ unstable_cli_options!( mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"), no_index_update: bool = ("Do not update the registry index even if the cache is outdated"), panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"), + profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"), host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"), sparse_registry: bool = ("Support plain-HTTP-based crate registries"), registry_auth: bool = ("Authentication for alternative registries, and generate registry authentication tokens using asymmetric cryptography"), @@ -969,6 +971,8 @@ impl CliUnstable { stabilized_warn(k, "1.59.0", STABILIZED_FUTURE_INCOMPAT_REPORT) } "timings" => stabilized_warn(k, "1.60", STABILIZED_TIMINGS), + "codegen-backend" => self.codegen_backend = parse_empty(k, v)?, + "profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?, _ => bail!("unknown `-Z` flag specified: {}", k), } diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index fba7b0ca3..87a992b6d 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -1115,7 +1115,12 @@ fn get_config_profile(ws: &Workspace<'_>, name: &str) -> CargoResult) -> CargoResult<()> { + /// Checks syntax validity and unstable feature gate for each profile. + /// + /// It's a bit unfortunate both `-Z` flags and `cargo-features` are required, + /// because profiles can now be set in either `Cargo.toml` or `config.toml`. + pub fn validate( + &self, + cli_unstable: &CliUnstable, + features: &Features, + warnings: &mut Vec, + ) -> CargoResult<()> { for (name, profile) in &self.0 { - profile.validate(name, features, warnings)?; + profile.validate(name, cli_unstable, features, warnings)?; } Ok(()) } @@ -592,21 +600,27 @@ impl fmt::Display for ProfilePackageSpec { } impl TomlProfile { + /// Checks stytax validity and unstable feature gate for a given profile. pub fn validate( &self, name: &str, + cli_unstable: &CliUnstable, features: &Features, warnings: &mut Vec, ) -> CargoResult<()> { - self.validate_profile(name, features)?; + self.validate_profile(name, cli_unstable, features)?; if let Some(ref profile) = self.build_override { profile.validate_override("build-override")?; - profile.validate_profile(&format!("{name}.build-override"), features)?; + profile.validate_profile(&format!("{name}.build-override"), cli_unstable, features)?; } if let Some(ref packages) = self.package { for (override_name, profile) in packages { profile.validate_override("package")?; - profile.validate_profile(&format!("{name}.package.{override_name}"), features)?; + profile.validate_profile( + &format!("{name}.package.{override_name}"), + cli_unstable, + features, + )?; } } @@ -751,9 +765,21 @@ impl TomlProfile { /// Validates a profile. /// /// This is a shallow check, which is reused for the profile itself and any overrides. - fn validate_profile(&self, name: &str, features: &Features) -> CargoResult<()> { + fn validate_profile( + &self, + name: &str, + cli_unstable: &CliUnstable, + features: &Features, + ) -> CargoResult<()> { if let Some(codegen_backend) = &self.codegen_backend { - features.require(Feature::codegen_backend())?; + match ( + features.require(Feature::codegen_backend()), + cli_unstable.codegen_backend, + ) { + (Err(e), false) => return Err(e), + _ => {} + } + if codegen_backend.contains(|c: char| !c.is_ascii_alphanumeric() && c != '_') { bail!( "`profile.{}.codegen-backend` setting of `{}` is not a valid backend name.", @@ -763,7 +789,13 @@ impl TomlProfile { } } if self.rustflags.is_some() { - features.require(Feature::profile_rustflags())?; + match ( + features.require(Feature::profile_rustflags()), + cli_unstable.profile_rustflags, + ) { + (Err(e), false) => return Err(e), + _ => {} + } } Ok(()) } @@ -2065,7 +2097,8 @@ impl TomlManifest { let profiles = me.profile.clone(); if let Some(profiles) = &profiles { - profiles.validate(&features, &mut warnings)?; + let cli_unstable = config.cli_unstable(); + profiles.validate(cli_unstable, &features, &mut warnings)?; } let publish = package @@ -2254,7 +2287,7 @@ impl TomlManifest { }; let profiles = me.profile.clone(); if let Some(profiles) = &profiles { - profiles.validate(&features, &mut warnings)?; + profiles.validate(config.cli_unstable(), &features, &mut warnings)?; } let resolve_behavior = me .workspace diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index 1523642e7..ae4a0b9da 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -85,6 +85,7 @@ Each new feature described below should explain how to use it. * [rustdoc-map](#rustdoc-map) — Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/). * `Cargo.toml` extensions * [Profile `rustflags` option](#profile-rustflags-option) — Passed directly to rustc. + * [codegen-backend](#codegen-backend) — Select the codegen backend used by rustc. * [per-package-target](#per-package-target) — Sets the `--target` to use for each individual package. * [artifact dependencies](#artifact-dependencies) - Allow build artifacts to be included into other build artifacts and build them for different targets. * Information and metadata @@ -681,6 +682,18 @@ cargo-features = ["profile-rustflags"] rustflags = [ "-C", "..." ] ``` +To set this in a profile in Cargo configuration, you need to use either +`-Z profile-rustflags` or `[unstable]` table to enable it. For example, + +```toml +# .cargo/config.toml +[unstable] +profile-rustflags = true + +[profile.release] +rustflags = [ "-C", "..." ] +``` + ### rustdoc-map * Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296) @@ -1378,6 +1391,18 @@ serde = "1.0.117" codegen-backend = "cranelift" ``` +To set this in a profile in Cargo configuration, you need to use either +`-Z codegen-backend` or `[unstable]` table to enable it. For example, + +```toml +# .cargo/config.toml +[unstable] +codegen-backend = true + +[profile.dev.package.foo] +codegen-backend = "cranelift" +``` + ### patch-in-config The `-Z patch-in-config` flag, and the corresponding support for diff --git a/tests/testsuite/profile_config.rs b/tests/testsuite/profile_config.rs index 8830dd20f..ed1295624 100644 --- a/tests/testsuite/profile_config.rs +++ b/tests/testsuite/profile_config.rs @@ -4,6 +4,67 @@ use cargo_test_support::paths::CargoPathExt; use cargo_test_support::registry::Package; use cargo_test_support::{basic_lib_manifest, paths, project}; +// TODO: this should be remove once -Zprofile-rustflags is stabilized +#[cargo_test] +fn rustflags_works_with_zflag() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + "#, + ) + .build(); + + p.cargo("check -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_status(101) + .with_stderr_contains("[..]feature `profile-rustflags` is required[..]") + .run(); + + p.cargo("check -v -Zprofile-rustflags") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr( + "\ +[CHECKING] foo [..] +[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..] +[FINISHED] [..] +", + ) + .run(); + + p.change_file( + ".cargo/config.toml", + r#" + [unstable] + profile-rustflags = true + + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + "#, + ); + + p.cargo("check -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr( + "\ +[FRESH] foo [..] +[FINISHED] [..] +", + ) + .run(); +} + #[cargo_test] fn profile_config_validate_warnings() { let p = project()