Skip to content

Commit 0655dd2

Browse files
committed
Auto merge of #10217 - zhamlin:feat/profile-rustflags, r=ehuss
feat: support rustflags per profile Fix for issue #7878
2 parents aee9262 + 68fd673 commit 0655dd2

File tree

8 files changed

+149
-5
lines changed

8 files changed

+149
-5
lines changed

src/cargo/core/compiler/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ fn link_targets(cx: &mut Context<'_, '_>, unit: &Unit, fresh: bool) -> CargoResu
448448
let export_dir = cx.files().export_dir();
449449
let package_id = unit.pkg.package_id();
450450
let manifest_path = PathBuf::from(unit.pkg.manifest_path());
451-
let profile = unit.profile;
451+
let profile = unit.profile.clone();
452452
let unit_mode = unit.mode;
453453
let features = unit.features.iter().map(|s| s.to_string()).collect();
454454
let json_messages = bcx.build_config.emit_json();
@@ -853,8 +853,9 @@ fn build_base_args(
853853
ref panic,
854854
incremental,
855855
strip,
856+
rustflags,
856857
..
857-
} = unit.profile;
858+
} = unit.profile.clone();
858859
let test = unit.mode.is_any_test();
859860

860861
cmd.arg("--crate-name").arg(&unit.target.crate_name());
@@ -904,6 +905,10 @@ fn build_base_args(
904905
cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
905906
}
906907

908+
if !rustflags.is_empty() {
909+
cmd.args(&rustflags);
910+
}
911+
907912
if *panic != PanicStrategy::Unwind {
908913
cmd.arg("-C").arg(format!("panic={}", panic));
909914
}

src/cargo/core/features.rs

+3
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ features! {
409409

410410
// Allow specifying different binary name apart from the crate name
411411
(unstable, different_binary_name, "", "reference/unstable.html#different-binary-name"),
412+
413+
// Allow specifying rustflags directly in a profile
414+
(unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"),
412415
}
413416

414417
pub struct Feature {

src/cargo/core/profiles.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ impl ProfileMaker {
500500
is_member: bool,
501501
unit_for: UnitFor,
502502
) -> Profile {
503-
let mut profile = self.default;
503+
let mut profile = self.default.clone();
504504

505505
// First apply profile-specific settings, things like
506506
// `[profile.release]`
@@ -626,6 +626,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
626626
if let Some(incremental) = toml.incremental {
627627
profile.incremental = incremental;
628628
}
629+
if let Some(flags) = &toml.rustflags {
630+
profile.rustflags = flags.clone();
631+
}
629632
profile.strip = match toml.strip {
630633
Some(StringOrBool::Bool(true)) => Strip::Named(InternedString::new("symbols")),
631634
None | Some(StringOrBool::Bool(false)) => Strip::None,
@@ -647,7 +650,7 @@ pub enum ProfileRoot {
647650

648651
/// Profile settings used to determine which compiler flags to use for a
649652
/// target.
650-
#[derive(Clone, Copy, Eq, PartialOrd, Ord, serde::Serialize)]
653+
#[derive(Clone, Eq, PartialOrd, Ord, serde::Serialize)]
651654
pub struct Profile {
652655
pub name: InternedString,
653656
pub opt_level: InternedString,
@@ -666,6 +669,9 @@ pub struct Profile {
666669
pub incremental: bool,
667670
pub panic: PanicStrategy,
668671
pub strip: Strip,
672+
#[serde(skip_serializing_if = "Vec::is_empty")] // remove when `rustflags` is stablized
673+
// Note that `rustflags` is used for the cargo-feature `profile_rustflags`
674+
pub rustflags: Vec<InternedString>,
669675
}
670676

671677
impl Default for Profile {
@@ -685,6 +691,7 @@ impl Default for Profile {
685691
incremental: false,
686692
panic: PanicStrategy::Unwind,
687693
strip: Strip::None,
694+
rustflags: vec![],
688695
}
689696
}
690697
}
@@ -712,6 +719,7 @@ compact_debug! {
712719
incremental
713720
panic
714721
strip
722+
rustflags
715723
)]
716724
}
717725
}

src/cargo/ops/cargo_compile.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ fn traverse_and_share(
16061606
let new_unit = interner.intern(
16071607
&unit.pkg,
16081608
&unit.target,
1609-
unit.profile,
1609+
unit.profile.clone(),
16101610
new_kind,
16111611
unit.mode,
16121612
unit.features.clone(),

src/cargo/util/toml/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,8 @@ pub struct TomlProfile {
413413
pub dir_name: Option<InternedString>,
414414
pub inherits: Option<InternedString>,
415415
pub strip: Option<StringOrBool>,
416+
// Note that `rustflags` is used for the cargo-feature `profile_rustflags`
417+
pub rustflags: Option<Vec<InternedString>>,
416418
// These two fields must be last because they are sub-tables, and TOML
417419
// requires all non-tables to be listed first.
418420
pub package: Option<BTreeMap<ProfilePackageSpec, TomlProfile>>,
@@ -530,6 +532,10 @@ impl TomlProfile {
530532
}
531533
}
532534

535+
if self.rustflags.is_some() {
536+
features.require(Feature::profile_rustflags())?;
537+
}
538+
533539
if let Some(codegen_backend) = &self.codegen_backend {
534540
features.require(Feature::codegen_backend())?;
535541
if codegen_backend.contains(|c: char| !c.is_ascii_alphanumeric() && c != '_') {
@@ -691,6 +697,10 @@ impl TomlProfile {
691697
self.incremental = Some(v);
692698
}
693699

700+
if let Some(v) = &profile.rustflags {
701+
self.rustflags = Some(v.clone());
702+
}
703+
694704
if let Some(other_package) = &profile.package {
695705
match &mut self.package {
696706
Some(self_package) => {

src/doc/src/reference/unstable.md

+19
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Each new feature described below should explain how to use it.
8989
* [rustdoc-map](#rustdoc-map) — Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/).
9090
* `Cargo.toml` extensions
9191
* [Profile `strip` option](#profile-strip-option) — Forces the removal of debug information and symbols from executables.
92+
* [Profile `rustflags` option](#profile-rustflags-option) — Passed directly to rustc.
9293
* [per-package-target](#per-package-target) — Sets the `--target` to use for each individual package.
9394
* Information and metadata
9495
* [Build-plan](#build-plan) — Emits JSON information on which commands will be run.
@@ -820,6 +821,24 @@ The following is a description of the JSON structure:
820821
}
821822
```
822823

824+
### Profile `rustflags` option
825+
* Original Issue: [rust-lang/cargo#7878](https://github.com/rust-lang/cargo/issues/7878)
826+
* Tracking Issue: [rust-lang/cargo#10271](https://github.com/rust-lang/cargo/issues/10271)
827+
828+
This feature provides a new option in the `[profile]` section to specify flags
829+
that are passed directly to rustc.
830+
This can be enabled like so:
831+
832+
```toml
833+
cargo-features = ["profile-rustflags"]
834+
835+
[package]
836+
# ...
837+
838+
[profile.release]
839+
rustflags = [ "-C", "..." ]
840+
```
841+
823842
### rustdoc-map
824843
* Tracking Issue: [#8296](https://github.com/rust-lang/cargo/issues/8296)
825844

tests/testsuite/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,7 @@ fn all_profile_options() {
14841484
strip: Some(toml::StringOrBool::String("symbols".to_string())),
14851485
package: None,
14861486
build_override: None,
1487+
rustflags: None,
14871488
};
14881489
let mut overrides = BTreeMap::new();
14891490
let key = toml::ProfilePackageSpec::Spec(PackageIdSpec::parse("foo").unwrap());

tests/testsuite/profiles.rs

+98
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,101 @@ fn strip_accepts_false_to_disable_strip() {
595595
.with_stderr_does_not_contain("-C strip")
596596
.run();
597597
}
598+
599+
#[cargo_test]
600+
fn rustflags_works() {
601+
let p = project()
602+
.file(
603+
"Cargo.toml",
604+
r#"
605+
cargo-features = ["profile-rustflags"]
606+
607+
[profile.dev]
608+
rustflags = ["-C", "link-dead-code=yes"]
609+
610+
[package]
611+
name = "foo"
612+
version = "0.0.1"
613+
"#,
614+
)
615+
.file("src/main.rs", "fn main() {}")
616+
.build();
617+
618+
p.cargo("build -v")
619+
.masquerade_as_nightly_cargo()
620+
.with_stderr(
621+
"\
622+
[COMPILING] foo [..]
623+
[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]
624+
[FINISHED] [..]
625+
",
626+
)
627+
.run();
628+
}
629+
630+
#[cargo_test]
631+
fn rustflags_works_with_env() {
632+
let p = project()
633+
.file(
634+
"Cargo.toml",
635+
r#"
636+
cargo-features = ["profile-rustflags"]
637+
638+
[package]
639+
name = "foo"
640+
version = "0.0.1"
641+
"#,
642+
)
643+
.file("src/main.rs", "fn main() {}")
644+
.build();
645+
646+
p.cargo("build -v")
647+
.env("CARGO_PROFILE_DEV_RUSTFLAGS", "-C link-dead-code=yes")
648+
.masquerade_as_nightly_cargo()
649+
.with_stderr(
650+
"\
651+
[COMPILING] foo [..]
652+
[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]
653+
[FINISHED] [..]
654+
",
655+
)
656+
.run();
657+
}
658+
659+
#[cargo_test]
660+
fn rustflags_requires_cargo_feature() {
661+
let p = project()
662+
.file(
663+
"Cargo.toml",
664+
r#"
665+
[profile.dev]
666+
rustflags = ["-C", "link-dead-code=yes"]
667+
668+
[package]
669+
name = "foo"
670+
version = "0.0.1"
671+
"#,
672+
)
673+
.file("src/main.rs", "fn main() {}")
674+
.build();
675+
676+
p.cargo("build -v")
677+
.masquerade_as_nightly_cargo()
678+
.with_status(101)
679+
.with_stderr(
680+
"\
681+
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
682+
683+
Caused by:
684+
feature `profile-rustflags` is required
685+
686+
The package requires the Cargo feature called `profile-rustflags`, but that feature is \
687+
not stabilized in this version of Cargo (1.[..]).
688+
Consider adding `cargo-features = [\"profile-rustflags\"]` to the top of Cargo.toml \
689+
(above the [package] table) to tell Cargo you are opting in to use this unstable feature.
690+
See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option \
691+
for more information about the status of this feature.
692+
",
693+
)
694+
.run();
695+
}

0 commit comments

Comments
 (0)