Skip to content

Commit e353f2e

Browse files
committed
Allow named debuginfo options in Cargo.toml
Rustc supports these since rust-lang/rust#109808. It's technically possible to set a named debuginfo level through `RUSTFLAGS`, but in practice cargo always passes its own opinion of what the debuginfo level is, so allow it to be configured through cargo too.
1 parent 0e474cf commit e353f2e

File tree

8 files changed

+86
-36
lines changed

8 files changed

+86
-36
lines changed

src/cargo/core/compiler/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,13 @@ fn link_targets(cx: &mut Context<'_, '_>, unit: &Unit, fresh: bool) -> CargoResu
603603
}
604604

605605
if json_messages {
606+
let debuginfo = profile.debuginfo.to_option().map(|d| match d.parse() {
607+
Ok(n) => machine_message::ArtifactDebuginfo::Int(n),
608+
Err(_) => machine_message::ArtifactDebuginfo::Named(d.to_string()),
609+
});
606610
let art_profile = machine_message::ArtifactProfile {
607611
opt_level: profile.opt_level.as_str(),
608-
debuginfo: profile.debuginfo.to_option(),
612+
debuginfo,
609613
debug_assertions: profile.debug_assertions,
610614
overflow_checks: profile.overflow_checks,
611615
test: unit_mode.is_any_test(),

src/cargo/core/profiles.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ use crate::core::dependency::Artifact;
2626
use crate::core::resolver::features::FeaturesFor;
2727
use crate::core::{PackageId, PackageIdSpec, Resolve, Shell, Target, Workspace};
2828
use crate::util::interning::InternedString;
29-
use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
29+
use crate::util::toml::{
30+
ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBoolOrString,
31+
};
3032
use crate::util::{closest_msg, config, CargoResult, Config};
3133
use anyhow::{bail, Context as _};
3234
use std::collections::{BTreeMap, HashMap, HashSet};
@@ -276,15 +278,13 @@ impl Profiles {
276278
// platform which has a stable `-Csplit-debuginfo` option for rustc,
277279
// and it's typically much faster than running `dsymutil` on all builds
278280
// in incremental cases.
279-
if let Some(debug) = profile.debuginfo.to_option() {
280-
if profile.split_debuginfo.is_none() && debug > 0 {
281-
let target = match &kind {
282-
CompileKind::Host => self.rustc_host.as_str(),
283-
CompileKind::Target(target) => target.short_name(),
284-
};
285-
if target.contains("-apple-") {
286-
profile.split_debuginfo = Some(InternedString::new("unpacked"));
287-
}
281+
if profile.debuginfo.is_turned_on() && profile.split_debuginfo.is_none() {
282+
let target = match &kind {
283+
CompileKind::Host => self.rustc_host.as_str(),
284+
CompileKind::Target(target) => target.short_name(),
285+
};
286+
if target.contains("-apple-") {
287+
profile.split_debuginfo = Some(InternedString::new("unpacked"));
288288
}
289289
}
290290

@@ -529,9 +529,12 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
529529
profile.codegen_units = toml.codegen_units;
530530
}
531531
match toml.debug {
532-
Some(U32OrBool::U32(debug)) => profile.debuginfo = DebugInfo::Explicit(debug),
533-
Some(U32OrBool::Bool(true)) => profile.debuginfo = DebugInfo::Explicit(2),
534-
Some(U32OrBool::Bool(false)) => profile.debuginfo = DebugInfo::None,
532+
Some(U32OrBoolOrString::U32(debug)) => {
533+
profile.debuginfo = DebugInfo::Explicit(debug.to_string().into())
534+
}
535+
Some(U32OrBoolOrString::Bool(true)) => profile.debuginfo = DebugInfo::Explicit("2".into()),
536+
Some(U32OrBoolOrString::Bool(false)) => profile.debuginfo = DebugInfo::None,
537+
Some(U32OrBoolOrString::String(ref s)) => profile.debuginfo = DebugInfo::Explicit(s.into()),
535538
None => {}
536539
}
537540
if let Some(debug_assertions) = toml.debug_assertions {
@@ -683,7 +686,7 @@ impl Profile {
683686
Profile {
684687
name: InternedString::new("dev"),
685688
root: ProfileRoot::Debug,
686-
debuginfo: DebugInfo::Explicit(2),
689+
debuginfo: DebugInfo::Explicit("2".into()),
687690
debug_assertions: true,
688691
overflow_checks: true,
689692
incremental: true,
@@ -743,7 +746,7 @@ pub enum DebugInfo {
743746
/// No debuginfo level was set.
744747
None,
745748
/// A debuginfo level that is explicitly set, by a profile or a user.
746-
Explicit(u32),
749+
Explicit(InternedString),
747750
/// For internal purposes: a deferred debuginfo level that can be optimized
748751
/// away, but has this value otherwise.
749752
///
@@ -753,22 +756,25 @@ pub enum DebugInfo {
753756
/// faster to build (see [DebugInfo::weaken]).
754757
///
755758
/// In all other situations, this level value will be the one to use.
756-
Deferred(u32),
759+
Deferred(InternedString),
757760
}
758761

759762
impl DebugInfo {
760763
/// The main way to interact with this debuginfo level, turning it into an Option.
761-
pub fn to_option(&self) -> Option<u32> {
764+
pub fn to_option(self) -> Option<InternedString> {
762765
match self {
763766
DebugInfo::None => None,
764-
DebugInfo::Explicit(v) | DebugInfo::Deferred(v) => Some(*v),
767+
DebugInfo::Explicit(v) | DebugInfo::Deferred(v) => Some(v),
765768
}
766769
}
767770

768771
/// Returns true if the debuginfo level is high enough (at least 1). Helper
769772
/// for a common operation on the usual `Option` representation.
770773
pub(crate) fn is_turned_on(&self) -> bool {
771-
self.to_option().unwrap_or(0) != 0
774+
match self.to_option().as_deref() {
775+
None | Some("0") | Some("none") => false,
776+
Some(_) => true,
777+
}
772778
}
773779

774780
pub(crate) fn is_deferred(&self) -> bool {

src/cargo/util/machine_message.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,20 @@ impl<'a> Message for Artifact<'a> {
5555
#[derive(Serialize)]
5656
pub struct ArtifactProfile {
5757
pub opt_level: &'static str,
58-
pub debuginfo: Option<u32>,
58+
pub debuginfo: Option<ArtifactDebuginfo>,
5959
pub debug_assertions: bool,
6060
pub overflow_checks: bool,
6161
pub test: bool,
6262
}
6363

64+
/// Internally this is just a string, but keep using 0/1/2 as integers for compatibility.
65+
#[derive(Serialize)]
66+
#[serde(untagged)]
67+
pub enum ArtifactDebuginfo {
68+
Int(u32),
69+
Named(String),
70+
}
71+
6472
#[derive(Serialize)]
6573
pub struct BuildScript<'a> {
6674
pub package_id: PackageId,

src/cargo/util/toml/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,10 +443,11 @@ impl ser::Serialize for TomlOptLevel {
443443
}
444444

445445
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
446-
#[serde(untagged, expecting = "expected a boolean or an integer")]
447-
pub enum U32OrBool {
446+
#[serde(untagged, expecting = "expected a boolean, integer, or string")]
447+
pub enum U32OrBoolOrString {
448448
U32(u32),
449449
Bool(bool),
450+
String(String),
450451
}
451452

452453
#[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)]
@@ -456,7 +457,7 @@ pub struct TomlProfile {
456457
pub lto: Option<StringOrBool>,
457458
pub codegen_backend: Option<InternedString>,
458459
pub codegen_units: Option<u32>,
459-
pub debug: Option<U32OrBool>,
460+
pub debug: Option<U32OrBoolOrString>,
460461
pub split_debuginfo: Option<String>,
461462
pub debug_assertions: Option<bool>,
462463
pub rpath: Option<bool>,

tests/testsuite/bad_config.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,14 +1313,45 @@ fn bad_debuginfo() {
13131313
.file("src/lib.rs", "")
13141314
.build();
13151315

1316+
p.cargo("check")
1317+
.with_status(101)
1318+
.with_stderr(
1319+
"\
1320+
[CHECKING] foo v0.0.0 ([CWD])
1321+
error: incorrect value `a` for codegen option `debuginfo` [..]
1322+
1323+
error: could not compile `foo` (lib) due to previous error
1324+
",
1325+
)
1326+
.run();
1327+
}
1328+
1329+
#[cargo_test]
1330+
fn bad_debuginfo2() {
1331+
let p = project()
1332+
.file(
1333+
"Cargo.toml",
1334+
r#"
1335+
[package]
1336+
name = "foo"
1337+
version = "0.0.0"
1338+
authors = []
1339+
1340+
[profile.dev]
1341+
debug = 3.6
1342+
"#,
1343+
)
1344+
.file("src/lib.rs", "")
1345+
.build();
1346+
13161347
p.cargo("check")
13171348
.with_status(101)
13181349
.with_stderr(
13191350
"\
13201351
error: failed to parse manifest at `[..]`
13211352
13221353
Caused by:
1323-
expected a boolean or an integer
1354+
expected a boolean, integer, or string
13241355
in `profile.dev.debug`
13251356
",
13261357
)

tests/testsuite/config.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ lto = false
401401
opt_level: Some(cargo_toml::TomlOptLevel("s".to_string())),
402402
lto: Some(cargo_toml::StringOrBool::Bool(true)),
403403
codegen_units: Some(5),
404-
debug: Some(cargo_toml::U32OrBool::Bool(true)),
404+
debug: Some(cargo_toml::U32OrBoolOrString::Bool(true)),
405405
debug_assertions: Some(true),
406406
rpath: Some(true),
407407
panic: Some("abort".to_string()),
@@ -444,15 +444,15 @@ fn profile_env_var_prefix() {
444444
.build();
445445
let p: cargo_toml::TomlProfile = config.get("profile.dev").unwrap();
446446
assert_eq!(p.debug_assertions, None);
447-
assert_eq!(p.debug, Some(cargo_toml::U32OrBool::U32(1)));
447+
assert_eq!(p.debug, Some(cargo_toml::U32OrBoolOrString::U32(1)));
448448

449449
let config = ConfigBuilder::new()
450450
.env("CARGO_PROFILE_DEV_DEBUG_ASSERTIONS", "false")
451451
.env("CARGO_PROFILE_DEV_DEBUG", "1")
452452
.build();
453453
let p: cargo_toml::TomlProfile = config.get("profile.dev").unwrap();
454454
assert_eq!(p.debug_assertions, Some(false));
455-
assert_eq!(p.debug, Some(cargo_toml::U32OrBool::U32(1)));
455+
assert_eq!(p.debug, Some(cargo_toml::U32OrBoolOrString::U32(1)));
456456
}
457457

458458
#[cargo_test]
@@ -1511,7 +1511,7 @@ fn all_profile_options() {
15111511
lto: Some(cargo_toml::StringOrBool::String("thin".to_string())),
15121512
codegen_backend: Some(InternedString::new("example")),
15131513
codegen_units: Some(123),
1514-
debug: Some(cargo_toml::U32OrBool::U32(1)),
1514+
debug: Some(cargo_toml::U32OrBoolOrString::U32(1)),
15151515
split_debuginfo: Some("packed".to_string()),
15161516
debug_assertions: Some(true),
15171517
rpath: Some(true),

tests/testsuite/profile_config.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ fn named_config_profile() {
436436
assert_eq!(p.name, "foo");
437437
assert_eq!(p.codegen_units, Some(2)); // "foo" from config
438438
assert_eq!(p.opt_level, "1"); // "middle" from manifest
439-
assert_eq!(p.debuginfo.to_option(), Some(1)); // "bar" from config
439+
assert_eq!(p.debuginfo.to_option(), Some("1".into())); // "bar" from config
440440
assert_eq!(p.debug_assertions, true); // "dev" built-in (ignore build-override)
441441
assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
442442

@@ -445,7 +445,7 @@ fn named_config_profile() {
445445
assert_eq!(bo.name, "foo");
446446
assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
447447
assert_eq!(bo.opt_level, "0"); // default to zero
448-
assert_eq!(bo.debuginfo.to_option(), Some(1)); // SAME as normal
448+
assert_eq!(bo.debuginfo.to_option(), Some("1".into())); // SAME as normal
449449
assert_eq!(bo.debug_assertions, false); // "foo" build override from manifest
450450
assert_eq!(bo.overflow_checks, true); // SAME as normal
451451

@@ -454,7 +454,7 @@ fn named_config_profile() {
454454
assert_eq!(po.name, "foo");
455455
assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
456456
assert_eq!(po.opt_level, "1"); // SAME as normal
457-
assert_eq!(po.debuginfo.to_option(), Some(1)); // SAME as normal
457+
assert_eq!(po.debuginfo.to_option(), Some("1".into())); // SAME as normal
458458
assert_eq!(po.debug_assertions, true); // SAME as normal
459459
assert_eq!(po.overflow_checks, false); // "middle" package override from manifest
460460
}

tests/testsuite/unit_graph.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn simple() {
7272
"codegen_backend": null,
7373
"codegen_units": null,
7474
"debug_assertions": true,
75-
"debuginfo": 2,
75+
"debuginfo": "2",
7676
"incremental": false,
7777
"lto": "false",
7878
"name": "dev",
@@ -117,7 +117,7 @@ fn simple() {
117117
"codegen_backend": null,
118118
"codegen_units": null,
119119
"debug_assertions": true,
120-
"debuginfo": 2,
120+
"debuginfo": "2",
121121
"incremental": false,
122122
"lto": "false",
123123
"name": "dev",
@@ -155,7 +155,7 @@ fn simple() {
155155
"codegen_backend": null,
156156
"codegen_units": null,
157157
"debug_assertions": true,
158-
"debuginfo": 2,
158+
"debuginfo": "2",
159159
"incremental": false,
160160
"lto": "false",
161161
"name": "dev",
@@ -198,7 +198,7 @@ fn simple() {
198198
"codegen_backend": null,
199199
"codegen_units": null,
200200
"debug_assertions": true,
201-
"debuginfo": 2,
201+
"debuginfo": "2",
202202
"incremental": false,
203203
"lto": "false",
204204
"name": "dev",

0 commit comments

Comments
 (0)