From 36480ce012ef0a1f908cc11b2051b02eaf61cdf2 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 8 Jun 2025 18:05:27 -0700 Subject: [PATCH] Plumb rustc `-Zhint-mostly-unused` flag through as a profile option The rustc `-Zhint-mostly-unused` flag tells rustc that most of a crate will go unused. This is useful for speeding up compilation of large dependencies from which you only use a few items. Plumb that option through as a profile option, to allow specifying it for specific dependencies: ```toml [profile.dev.package.huge-mostly-unused-dependency] hint-mostly-unused = true ``` To enable this feature, pass `-Zprofile-hint-mostly-unused`. However, since this option is a hint, using it without passing `-Zprofile-hint-mostly-unused` will only warn and ignore the profile option. Versions of Cargo prior to the introduction of this feature will give an "unused manifest key" warning, but will otherwise function without erroring. This allows using the hint in a crate's `Cargo.toml` without mandating the use of a newer Cargo to build it. Add a test verifying that the profile option gets ignored with a warning without passing `-Zprofile-hint-mostly-unused`, and another test verifying that it gets handled when passing `-Zprofile-hint-mostly-unused`. --- .../cargo-util-schemas/manifest.schema.json | 8 ++ crates/cargo-util-schemas/src/manifest/mod.rs | 6 ++ src/cargo/core/compiler/mod.rs | 11 +++ src/cargo/core/features.rs | 2 + src/cargo/core/profiles.rs | 7 ++ src/doc/src/reference/unstable.md | 19 ++++ tests/testsuite/cargo/z_help/stdout.term.svg | 94 ++++++++++--------- tests/testsuite/config.rs | 1 + tests/testsuite/profiles.rs | 80 ++++++++++++++++ 9 files changed, 182 insertions(+), 46 deletions(-) diff --git a/crates/cargo-util-schemas/manifest.schema.json b/crates/cargo-util-schemas/manifest.schema.json index e8a53b5dc..2024fea84 100644 --- a/crates/cargo-util-schemas/manifest.schema.json +++ b/crates/cargo-util-schemas/manifest.schema.json @@ -1385,6 +1385,14 @@ } ], "default": null + }, + "hint-mostly-unused": { + "description": "Unstable feature `hint-mostly-unused`", + "type": [ + "boolean", + "null" + ], + "default": null } } }, diff --git a/crates/cargo-util-schemas/src/manifest/mod.rs b/crates/cargo-util-schemas/src/manifest/mod.rs index db0176b52..b28aa38fb 100644 --- a/crates/cargo-util-schemas/src/manifest/mod.rs +++ b/crates/cargo-util-schemas/src/manifest/mod.rs @@ -907,6 +907,8 @@ pub struct TomlProfile { pub build_override: Option>, /// Unstable feature `-Ztrim-paths`. pub trim_paths: Option, + /// Unstable feature `hint-mostly-unused` + pub hint_mostly_unused: Option, } impl TomlProfile { @@ -998,6 +1000,10 @@ impl TomlProfile { if let Some(v) = &profile.trim_paths { self.trim_paths = Some(v.clone()) } + + if let Some(v) = profile.hint_mostly_unused { + self.hint_mostly_unused = Some(v); + } } } diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 9bd925a20..2775e1d22 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -1135,6 +1135,7 @@ fn build_base_args( strip, rustflags: profile_rustflags, trim_paths, + hint_mostly_unused, .. } = unit.profile.clone(); let test = unit.mode.is_any_test(); @@ -1325,6 +1326,16 @@ fn build_base_args( opt(cmd, "-C", "incremental=", Some(dir)); } + if hint_mostly_unused { + if bcx.gctx.cli_unstable().profile_hint_mostly_unused { + cmd.arg("-Zhint-mostly-unused"); + } else { + bcx.gctx + .shell() + .warn("ignoring 'hint-mostly-unused' profile option, pass `-Zprofile-hint-mostly-unused` to enable it")?; + } + } + let strip = strip.into_inner(); if strip != StripInner::None { cmd.arg("-C").arg(format!("strip={}", strip)); diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index a05152626..a79695e87 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -845,6 +845,7 @@ unstable_cli_options!( no_index_update: bool = ("Do not update the registry index even if the cache is outdated"), package_workspace: bool = ("Handle intra-workspace dependencies when packaging"), panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"), + profile_hint_mostly_unused: bool = ("Enable the `hint-mostly-unused` setting in profiles to mark a crate as mostly unused."), profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"), public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"), publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"), @@ -1366,6 +1367,7 @@ impl CliUnstable { "package-workspace" => self.package_workspace = parse_empty(k, v)?, "panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?, "public-dependency" => self.public_dependency = parse_empty(k, v)?, + "profile-hint-mostly-unused" => self.profile_hint_mostly_unused = parse_empty(k, v)?, "profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?, "trim-paths" => self.trim_paths = parse_empty(k, v)?, "publish-timeout" => self.publish_timeout = parse_empty(k, v)?, diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 2a4cc47b1..0989475a7 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -577,6 +577,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) { if let Some(trim_paths) = &toml.trim_paths { profile.trim_paths = Some(trim_paths.clone()); } + if let Some(hint_mostly_unused) = toml.hint_mostly_unused { + profile.hint_mostly_unused = hint_mostly_unused; + } profile.strip = match toml.strip { Some(StringOrBool::Bool(true)) => Strip::Resolved(StripInner::Named("symbols".into())), Some(StringOrBool::Bool(false)) => Strip::Resolved(StripInner::None), @@ -626,6 +629,8 @@ pub struct Profile { // remove when `-Ztrim-paths` is stablized #[serde(skip_serializing_if = "Option::is_none")] pub trim_paths: Option, + #[serde(skip_serializing_if = "std::ops::Not::not")] + pub hint_mostly_unused: bool, } impl Default for Profile { @@ -647,6 +652,7 @@ impl Default for Profile { strip: Strip::Deferred(StripInner::None), rustflags: vec![], trim_paths: None, + hint_mostly_unused: false, } } } @@ -676,6 +682,7 @@ compact_debug! { strip rustflags trim_paths + hint_mostly_unused )] } } diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index e2b321665..bdae79bbd 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -924,6 +924,25 @@ profile-rustflags = true rustflags = [ "-C", "..." ] ``` +## Profile `hint-mostly-unused` option +* Tracking Issue: [#15644](https://github.com/rust-lang/cargo/issues/15644) + +This feature provides a new option in the `[profile]` section to enable the +rustc `hint-mostly-unused` option. This is primarily useful to enable for +specific dependencies: + +```toml +[profile.dev.package.huge-mostly-unused-dependency] +hint-mostly-unused = true +``` + +To enable this feature, pass `-Zprofile-hint-mostly-unused`. However, since +this option is a hint, using it without passing `-Zprofile-hint-mostly-unused` +will only warn and ignore the profile option. Versions of Cargo prior to the +introduction of this feature will give an "unused manifest key" warning, but +will otherwise function without erroring. This allows using the hint in a +crate's `Cargo.toml` without mandating the use of a newer Cargo to build it. + ## rustdoc-map * Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296) diff --git a/tests/testsuite/cargo/z_help/stdout.term.svg b/tests/testsuite/cargo/z_help/stdout.term.svg index b10ddce37..b0dc5c541 100644 --- a/tests/testsuite/cargo/z_help/stdout.term.svg +++ b/tests/testsuite/cargo/z_help/stdout.term.svg @@ -1,4 +1,4 @@ - +