Skip to content

Commit d9cc290

Browse files
committed
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: ```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`.
1 parent fc1518e commit d9cc290

File tree

8 files changed

+135
-1
lines changed

8 files changed

+135
-1
lines changed

crates/cargo-util-schemas/manifest.schema.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,14 @@
13851385
}
13861386
],
13871387
"default": null
1388+
},
1389+
"hint-mostly-unused": {
1390+
"description": "Unstable feature `hint-mostly-unused`.",
1391+
"type": [
1392+
"boolean",
1393+
"null"
1394+
],
1395+
"default": null
13881396
}
13891397
}
13901398
},
@@ -1423,4 +1431,4 @@
14231431
]
14241432
}
14251433
}
1426-
}
1434+
}

crates/cargo-util-schemas/src/manifest/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,8 @@ pub struct TomlProfile {
907907
pub build_override: Option<Box<TomlProfile>>,
908908
/// Unstable feature `-Ztrim-paths`.
909909
pub trim_paths: Option<TomlTrimPaths>,
910+
/// Unstable feature `hint-mostly-unused`
911+
pub hint_mostly_unused: Option<bool>,
910912
}
911913

912914
impl TomlProfile {
@@ -998,6 +1000,10 @@ impl TomlProfile {
9981000
if let Some(v) = &profile.trim_paths {
9991001
self.trim_paths = Some(v.clone())
10001002
}
1003+
1004+
if let Some(v) = profile.hint_mostly_unused {
1005+
self.hint_mostly_unused = Some(v);
1006+
}
10011007
}
10021008
}
10031009

src/cargo/core/compiler/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,7 @@ fn build_base_args(
11301130
strip,
11311131
rustflags: profile_rustflags,
11321132
trim_paths,
1133+
hint_mostly_unused,
11331134
..
11341135
} = unit.profile.clone();
11351136
let test = unit.mode.is_any_test();
@@ -1320,6 +1321,16 @@ fn build_base_args(
13201321
opt(cmd, "-C", "incremental=", Some(dir));
13211322
}
13221323

1324+
if hint_mostly_unused {
1325+
if bcx.gctx.cli_unstable().profile_hint_mostly_unused {
1326+
cmd.arg("-Zhint-mostly-unused");
1327+
} else {
1328+
bcx.gctx
1329+
.shell()
1330+
.warn("ignoring 'hint-mostly-unused' profile option, pass `-Zprofile-hint-mostly-unused` to enable it")?;
1331+
}
1332+
}
1333+
13231334
let strip = strip.into_inner();
13241335
if strip != StripInner::None {
13251336
cmd.arg("-C").arg(format!("strip={}", strip));

src/cargo/core/features.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ unstable_cli_options!(
845845
no_index_update: bool = ("Do not update the registry index even if the cache is outdated"),
846846
package_workspace: bool = ("Handle intra-workspace dependencies when packaging"),
847847
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
848+
profile_hint_mostly_unused: bool = ("Enable the `hint-mostly-unused` setting in profiles to mark a crate as mostly unused."),
848849
profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"),
849850
public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"),
850851
publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"),
@@ -1366,6 +1367,7 @@ impl CliUnstable {
13661367
"package-workspace" => self.package_workspace = parse_empty(k, v)?,
13671368
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
13681369
"public-dependency" => self.public_dependency = parse_empty(k, v)?,
1370+
"profile-hint-mostly-unused" => self.profile_hint_mostly_unused = parse_empty(k, v)?,
13691371
"profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?,
13701372
"trim-paths" => self.trim_paths = parse_empty(k, v)?,
13711373
"publish-timeout" => self.publish_timeout = parse_empty(k, v)?,

src/cargo/core/profiles.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
577577
if let Some(trim_paths) = &toml.trim_paths {
578578
profile.trim_paths = Some(trim_paths.clone());
579579
}
580+
if let Some(hint_mostly_unused) = toml.hint_mostly_unused {
581+
profile.hint_mostly_unused = hint_mostly_unused;
582+
}
580583
profile.strip = match toml.strip {
581584
Some(StringOrBool::Bool(true)) => {
582585
Strip::Resolved(StripInner::Named(InternedString::new("symbols")))
@@ -630,6 +633,8 @@ pub struct Profile {
630633
// remove when `-Ztrim-paths` is stablized
631634
#[serde(skip_serializing_if = "Option::is_none")]
632635
pub trim_paths: Option<TomlTrimPaths>,
636+
#[serde(skip_serializing_if = "std::ops::Not::not")]
637+
pub hint_mostly_unused: bool,
633638
}
634639

635640
impl Default for Profile {
@@ -651,6 +656,7 @@ impl Default for Profile {
651656
strip: Strip::Deferred(StripInner::None),
652657
rustflags: vec![],
653658
trim_paths: None,
659+
hint_mostly_unused: false,
654660
}
655661
}
656662
}
@@ -680,6 +686,7 @@ compact_debug! {
680686
strip
681687
rustflags
682688
trim_paths
689+
hint_mostly_unused
683690
)]
684691
}
685692
}

src/doc/src/reference/unstable.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,25 @@ profile-rustflags = true
924924
rustflags = [ "-C", "..." ]
925925
```
926926

927+
## Profile `hint-mostly-unused` option
928+
* Tracking Issue: FIXME
929+
930+
This feature provides a new option in the `[profile]` section to enable the
931+
rustc `hint-mostly-unused` option. This is primarily useful to enable for
932+
specific dependencies:
933+
934+
```toml
935+
[profile.dev.package.huge-mostly-unused-dependency]
936+
hint-mostly-unused = true
937+
```
938+
939+
To enable this feature, pass `-Zprofile-hint-mostly-unused`. However, since
940+
this option is a hint, using it without passing `-Zprofile-hint-mostly-unused`
941+
will only warn and ignore the profile option. Versions of Cargo prior to the
942+
introduction of this feature will give an "unused manifest key" warning, but
943+
will otherwise function without erroring. This allows using the hint in a
944+
crate's `Cargo.toml` without mandating the use of a newer Cargo to build it.
945+
927946
## rustdoc-map
928947
* Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296)
929948

tests/testsuite/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,7 @@ fn all_profile_options() {
16661666
build_override: None,
16671667
rustflags: None,
16681668
trim_paths: None,
1669+
hint_mostly_unused: None,
16691670
};
16701671
let mut overrides = BTreeMap::new();
16711672
let key = cargo_toml::ProfilePackageSpec::Spec(PackageIdSpec::parse("foo").unwrap());

tests/testsuite/profiles.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,83 @@ fn debug_options_valid() {
876876
.with_stderr_does_not_contain("[..]-C debuginfo[..]")
877877
.run();
878878
}
879+
880+
#[cargo_test]
881+
fn profile_hint_mostly_unused_warn_without_gate() {
882+
Package::new("bar", "1.0.0").publish();
883+
let p = project()
884+
.file(
885+
"Cargo.toml",
886+
r#"
887+
[package]
888+
name = "foo"
889+
version = "0.0.1"
890+
edition = "2015"
891+
892+
[dependencies]
893+
bar = "1.0"
894+
895+
[profile.dev.package.bar]
896+
hint-mostly-unused = true
897+
"#,
898+
)
899+
.file("src/main.rs", "fn main() {}")
900+
.build();
901+
p.cargo("build -v")
902+
.with_stderr_data(str![[r#"
903+
[UPDATING] `dummy-registry` index
904+
[LOCKING] 1 package to latest compatible version
905+
[DOWNLOADING] crates ...
906+
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
907+
[WARNING] ignoring 'hint-mostly-unused' profile option, pass `-Zprofile-hint-mostly-unused` to enable it
908+
[COMPILING] bar v1.0.0
909+
[RUNNING] `rustc --crate-name bar [..]`
910+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
911+
[RUNNING] `rustc --crate-name foo [..]`
912+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
913+
914+
"#]])
915+
.with_stderr_does_not_contain("-Zhint-mostly-unused")
916+
.run();
917+
}
918+
919+
#[cargo_test(nightly, reason = "-Zhint-mostly-unused is unstable")]
920+
fn profile_hint_mostly_unused_nightly() {
921+
Package::new("bar", "1.0.0").publish();
922+
let p = project()
923+
.file(
924+
"Cargo.toml",
925+
r#"
926+
[package]
927+
name = "foo"
928+
version = "0.0.1"
929+
edition = "2015"
930+
931+
[dependencies]
932+
bar = "1.0"
933+
934+
[profile.dev.package.bar]
935+
hint-mostly-unused = true
936+
"#,
937+
)
938+
.file("src/main.rs", "fn main() {}")
939+
.build();
940+
p.cargo("build -Zprofile-hint-mostly-unused -v")
941+
.masquerade_as_nightly_cargo(&["profile-hint-mostly-unused"])
942+
.with_stderr_data(str![[r#"
943+
[UPDATING] `dummy-registry` index
944+
[LOCKING] 1 package to latest compatible version
945+
[DOWNLOADING] crates ...
946+
[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`)
947+
[COMPILING] bar v1.0.0
948+
[RUNNING] `rustc --crate-name bar [..] -Zhint-mostly-unused [..]`
949+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
950+
[RUNNING] `rustc --crate-name foo [..]`
951+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
952+
953+
"#]])
954+
.with_stderr_does_not_contain(
955+
"[RUNNING] `rustc --crate-name foo [..] -Zhint-mostly-unused [..]",
956+
)
957+
.run();
958+
}

0 commit comments

Comments
 (0)