Skip to content

Commit d18e4b3

Browse files
committed
Auto merge of #8246 - GabrielMajeri:add-strip-option, r=alexcrichton
Add option to strip binaries This PR adds a Cargo option for stripping symbols from generated binaries. This is based on the `-Z strip` flag for `rustc`, which has been [recently implemented](rust-lang/rust#71757). Notes for reviewers: I'm not entirely sure how we test this, I've created a crate locally and it seems to be working. Supersedes my previous work in #8191. Fixes #3483.
2 parents 500b2bd + 2cd41e1 commit d18e4b3

File tree

6 files changed

+168
-6
lines changed

6 files changed

+168
-6
lines changed

src/cargo/core/compiler/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use self::output_depinfo::output_depinfo;
4646
use self::unit_graph::UnitDep;
4747
pub use crate::core::compiler::unit::{Unit, UnitInterner};
4848
use crate::core::manifest::TargetSourcePath;
49-
use crate::core::profiles::{PanicStrategy, Profile};
49+
use crate::core::profiles::{PanicStrategy, Profile, Strip};
5050
use crate::core::{Edition, Feature, InternedString, PackageId, Target};
5151
use crate::util::errors::{self, CargoResult, CargoResultExt, ProcessError, VerboseError};
5252
use crate::util::machine_message::Message;
@@ -732,6 +732,7 @@ fn build_base_args(
732732
rpath,
733733
ref panic,
734734
incremental,
735+
strip,
735736
..
736737
} = unit.profile;
737738
let test = unit.mode.is_any_test();
@@ -910,6 +911,10 @@ fn build_base_args(
910911
opt(cmd, "-C", "incremental=", Some(dir));
911912
}
912913

914+
if strip != Strip::None {
915+
cmd.arg("-Z").arg(format!("strip={}", strip));
916+
}
917+
913918
if unit.is_std {
914919
// -Zforce-unstable-if-unmarked prevents the accidental use of
915920
// unstable crates within the sysroot (such as "extern crate libc" or

src/cargo/core/features.rs

+3
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ features! {
214214

215215
// Opt-in new-resolver behavior.
216216
[unstable] resolver: bool,
217+
218+
// Allow to specify whether binaries should be stripped.
219+
[unstable] strip: bool,
217220
}
218221
}
219222

src/cargo/core/profiles.rs

+32
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
565565
if let Some(incremental) = toml.incremental {
566566
profile.incremental = incremental;
567567
}
568+
if let Some(strip) = toml.strip {
569+
profile.strip = strip;
570+
}
568571
}
569572

570573
/// The root profile (dev/release).
@@ -595,6 +598,7 @@ pub struct Profile {
595598
pub rpath: bool,
596599
pub incremental: bool,
597600
pub panic: PanicStrategy,
601+
pub strip: Strip,
598602
}
599603

600604
impl Default for Profile {
@@ -611,6 +615,7 @@ impl Default for Profile {
611615
rpath: false,
612616
incremental: false,
613617
panic: PanicStrategy::Unwind,
618+
strip: Strip::None,
614619
}
615620
}
616621
}
@@ -635,6 +640,7 @@ compact_debug! {
635640
rpath
636641
incremental
637642
panic
643+
strip
638644
)]
639645
}
640646
}
@@ -721,6 +727,7 @@ impl Profile {
721727
bool,
722728
bool,
723729
PanicStrategy,
730+
Strip,
724731
) {
725732
(
726733
self.opt_level,
@@ -732,6 +739,7 @@ impl Profile {
732739
self.rpath,
733740
self.incremental,
734741
self.panic,
742+
self.strip,
735743
)
736744
}
737745
}
@@ -776,6 +784,30 @@ impl fmt::Display for PanicStrategy {
776784
}
777785
}
778786

787+
/// The setting for choosing which symbols to strip
788+
#[derive(
789+
Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
790+
)]
791+
#[serde(rename_all = "lowercase")]
792+
pub enum Strip {
793+
/// Only strip debugging symbols
794+
DebugInfo,
795+
/// Don't remove any symbols
796+
None,
797+
/// Strip all non-exported symbols from the final binary
798+
Symbols,
799+
}
800+
801+
impl fmt::Display for Strip {
802+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
803+
match *self {
804+
Strip::DebugInfo => "debuginfo",
805+
Strip::None => "abort",
806+
Strip::Symbols => "symbols",
807+
}
808+
.fmt(f)
809+
}
810+
}
779811
/// Flags used in creating `Unit`s to indicate the purpose for the target, and
780812
/// to ensure the target's dependencies have the correct settings.
781813
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]

src/cargo/util/toml/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use url::Url;
1515

1616
use crate::core::dependency::DepKind;
1717
use crate::core::manifest::{ManifestMetadata, TargetSourcePath, Warnings};
18+
use crate::core::profiles::Strip;
1819
use crate::core::resolver::ResolveBehavior;
1920
use crate::core::{Dependency, InternedString, Manifest, PackageId, Summary, Target};
2021
use crate::core::{Edition, EitherManifest, Feature, Features, VirtualManifest, Workspace};
@@ -407,6 +408,7 @@ pub struct TomlProfile {
407408
pub build_override: Option<Box<TomlProfile>>,
408409
pub dir_name: Option<InternedString>,
409410
pub inherits: Option<InternedString>,
411+
pub strip: Option<Strip>,
410412
}
411413

412414
#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
@@ -522,6 +524,10 @@ impl TomlProfile {
522524
);
523525
}
524526
}
527+
528+
if self.strip.is_some() {
529+
features.require(Feature::strip())?;
530+
}
525531
Ok(())
526532
}
527533

@@ -641,6 +647,10 @@ impl TomlProfile {
641647
if let Some(v) = &profile.dir_name {
642648
self.dir_name = Some(*v);
643649
}
650+
651+
if let Some(v) = profile.strip {
652+
self.strip = Some(v);
653+
}
644654
}
645655
}
646656

tests/testsuite/profiles.rs

+109-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::env;
44

5-
use cargo_test_support::project;
5+
use cargo_test_support::{is_nightly, project};
66

77
#[cargo_test]
88
fn profile_overrides() {
@@ -468,3 +468,111 @@ fn thin_lto_works() {
468468
)
469469
.run();
470470
}
471+
472+
#[cargo_test]
473+
fn strip_works() {
474+
if !is_nightly() {
475+
return;
476+
}
477+
478+
let p = project()
479+
.file(
480+
"Cargo.toml",
481+
r#"
482+
cargo-features = ["strip"]
483+
484+
[package]
485+
name = "foo"
486+
version = "0.1.0"
487+
488+
[profile.release]
489+
strip = 'symbols'
490+
"#,
491+
)
492+
.file("src/main.rs", "fn main() {}")
493+
.build();
494+
495+
p.cargo("build --release -v")
496+
.masquerade_as_nightly_cargo()
497+
.with_stderr(
498+
"\
499+
[COMPILING] foo [..]
500+
[RUNNING] `rustc [..] -Z strip=symbols [..]`
501+
[FINISHED] [..]
502+
",
503+
)
504+
.run();
505+
}
506+
507+
#[cargo_test]
508+
fn strip_requires_cargo_feature() {
509+
if !is_nightly() {
510+
return;
511+
}
512+
513+
let p = project()
514+
.file(
515+
"Cargo.toml",
516+
r#"
517+
[package]
518+
name = "foo"
519+
version = "0.1.0"
520+
521+
[profile.release]
522+
strip = 'symbols'
523+
"#,
524+
)
525+
.file("src/main.rs", "fn main() {}")
526+
.build();
527+
528+
p.cargo("build --release -v")
529+
.masquerade_as_nightly_cargo()
530+
.with_status(101)
531+
.with_stderr(
532+
"\
533+
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
534+
535+
Caused by:
536+
feature `strip` is required
537+
538+
consider adding `cargo-features = [\"strip\"]` to the manifest
539+
",
540+
)
541+
.run();
542+
}
543+
#[cargo_test]
544+
fn strip_rejects_invalid_option() {
545+
if !is_nightly() {
546+
return;
547+
}
548+
549+
let p = project()
550+
.file(
551+
"Cargo.toml",
552+
r#"
553+
cargo-features = ["strip"]
554+
555+
[package]
556+
name = "foo"
557+
version = "0.1.0"
558+
559+
[profile.release]
560+
strip = 'wrong'
561+
"#,
562+
)
563+
.file("src/main.rs", "fn main() {}")
564+
.build();
565+
566+
p.cargo("build --release -v")
567+
.masquerade_as_nightly_cargo()
568+
.with_status(101)
569+
.with_stderr(
570+
"\
571+
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
572+
573+
Caused by:
574+
unknown variant `wrong`, expected one of `debuginfo`, `none`, `symbols` for key [..]
575+
",
576+
)
577+
.run();
578+
}

tests/testsuite/unit_graph.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ fn simple() {
7575
"overflow_checks": true,
7676
"rpath": false,
7777
"incremental": false,
78-
"panic": "unwind"
78+
"panic": "unwind",
79+
"strip": "none"
7980
},
8081
"platform": null,
8182
"mode": "build",
@@ -115,7 +116,8 @@ fn simple() {
115116
"overflow_checks": true,
116117
"rpath": false,
117118
"incremental": false,
118-
"panic": "unwind"
119+
"panic": "unwind",
120+
"strip": "none"
119121
},
120122
"platform": null,
121123
"mode": "build",
@@ -155,7 +157,8 @@ fn simple() {
155157
"overflow_checks": true,
156158
"rpath": false,
157159
"incremental": false,
158-
"panic": "unwind"
160+
"panic": "unwind",
161+
"strip": "none"
159162
},
160163
"platform": null,
161164
"mode": "build",
@@ -188,7 +191,8 @@ fn simple() {
188191
"overflow_checks": true,
189192
"rpath": false,
190193
"incremental": false,
191-
"panic": "unwind"
194+
"panic": "unwind",
195+
"strip": "none"
192196
},
193197
"platform": null,
194198
"mode": "build",

0 commit comments

Comments
 (0)