mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Add split-debuginfo profile option
This commit adds a new `split-debuginfo` option to Cargo compilation profiles which gets forwarded to the `-Csplit-debuginfo` codegen option in rustc. This commit also sets the default, only on macOS, to be `-Csplit-debuginfo=unpacked`. The purpose of this change is to leverage rust-lang/rust#79570 to avoid running `dsymutil` on incremental builds while also preserving a pleasant debugging experience by default. This should lead to much faster incremental build times on macOS since `dsymutil` isn't exactly the speediest tool in the world. This is technically a breaking change in Cargo because we're no longer by-default producing the `*.dSYM` folders on macOS. If those are still desired, however, authors can always run `dsymutil` themselves or otherwise configure `split-debuginfo = 'packed'` in their manifest/profile configuration.
This commit is contained in:
parent
8a3361c126
commit
ed4568e108
@ -722,6 +722,16 @@ impl Execs {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_mac_dsym(&mut self) -> &mut Self {
|
||||||
|
if cfg!(target_os = "macos") {
|
||||||
|
self.env("CARGO_PROFILE_DEV_SPLIT_DEBUGINFO", "packed")
|
||||||
|
.env("CARGO_PROFILE_TEST_SPLIT_DEBUGINFO", "packed")
|
||||||
|
.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed")
|
||||||
|
.env("CARGO_PROFILE_BENCH_SPLIT_DEBUGINFO", "packed");
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
self.ran = true;
|
self.ran = true;
|
||||||
let p = (&self.process_builder).clone().unwrap();
|
let p = (&self.process_builder).clone().unwrap();
|
||||||
|
@ -40,6 +40,8 @@ pub struct TargetInfo {
|
|||||||
pub rustflags: Vec<String>,
|
pub rustflags: Vec<String>,
|
||||||
/// Extra flags to pass to `rustdoc`, see `env_args`.
|
/// Extra flags to pass to `rustdoc`, see `env_args`.
|
||||||
pub rustdocflags: Vec<String>,
|
pub rustdocflags: Vec<String>,
|
||||||
|
/// Whether or not rustc supports the `-Csplit-debuginfo` flag.
|
||||||
|
pub supports_split_debuginfo: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Kind of each file generated by a Unit, part of `FileType`.
|
/// Kind of each file generated by a Unit, part of `FileType`.
|
||||||
@ -157,6 +159,9 @@ impl TargetInfo {
|
|||||||
for crate_type in KNOWN_CRATE_TYPES.iter() {
|
for crate_type in KNOWN_CRATE_TYPES.iter() {
|
||||||
process.arg("--crate-type").arg(crate_type.as_str());
|
process.arg("--crate-type").arg(crate_type.as_str());
|
||||||
}
|
}
|
||||||
|
let supports_split_debuginfo = rustc
|
||||||
|
.cached_output(process.clone().arg("-Csplit-debuginfo=packed"))
|
||||||
|
.is_ok();
|
||||||
|
|
||||||
process.arg("--print=sysroot");
|
process.arg("--print=sysroot");
|
||||||
process.arg("--print=cfg");
|
process.arg("--print=cfg");
|
||||||
@ -231,6 +236,7 @@ impl TargetInfo {
|
|||||||
"RUSTDOCFLAGS",
|
"RUSTDOCFLAGS",
|
||||||
)?,
|
)?,
|
||||||
cfg,
|
cfg,
|
||||||
|
supports_split_debuginfo,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,6 +773,7 @@ fn build_base_args(
|
|||||||
codegen_units,
|
codegen_units,
|
||||||
debuginfo,
|
debuginfo,
|
||||||
debug_assertions,
|
debug_assertions,
|
||||||
|
split_debuginfo,
|
||||||
overflow_checks,
|
overflow_checks,
|
||||||
rpath,
|
rpath,
|
||||||
ref panic,
|
ref panic,
|
||||||
@ -825,6 +826,15 @@ fn build_base_args(
|
|||||||
|
|
||||||
cmd.args(<o_args(cx, unit));
|
cmd.args(<o_args(cx, unit));
|
||||||
|
|
||||||
|
// This is generally just an optimization on build time so if we don't pass
|
||||||
|
// it then it's ok. As of the time of this writing it's a very new flag, so
|
||||||
|
// we need to dynamically check if it's available.
|
||||||
|
if cx.bcx.target_data.info(unit.kind).supports_split_debuginfo {
|
||||||
|
if let Some(split) = split_debuginfo {
|
||||||
|
cmd.arg("-C").arg(format!("split-debuginfo={}", split));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(n) = codegen_units {
|
if let Some(n) = codegen_units {
|
||||||
cmd.arg("-C").arg(&format!("codegen-units={}", n));
|
cmd.arg("-C").arg(&format!("codegen-units={}", n));
|
||||||
}
|
}
|
||||||
|
@ -162,16 +162,17 @@ pub fn generate_std_roots(
|
|||||||
// in time is minimal, and the difference in caching is
|
// in time is minimal, and the difference in caching is
|
||||||
// significant.
|
// significant.
|
||||||
let mode = CompileMode::Build;
|
let mode = CompileMode::Build;
|
||||||
let profile = profiles.get_profile(
|
|
||||||
pkg.package_id(),
|
|
||||||
/*is_member*/ false,
|
|
||||||
/*is_local*/ false,
|
|
||||||
unit_for,
|
|
||||||
mode,
|
|
||||||
);
|
|
||||||
let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
|
let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
|
||||||
|
|
||||||
for kind in kinds {
|
for kind in kinds {
|
||||||
|
let profile = profiles.get_profile(
|
||||||
|
pkg.package_id(),
|
||||||
|
/*is_member*/ false,
|
||||||
|
/*is_local*/ false,
|
||||||
|
unit_for,
|
||||||
|
mode,
|
||||||
|
*kind,
|
||||||
|
);
|
||||||
let list = ret.entry(*kind).or_insert_with(Vec::new);
|
let list = ret.entry(*kind).or_insert_with(Vec::new);
|
||||||
list.push(interner.intern(
|
list.push(interner.intern(
|
||||||
pkg,
|
pkg,
|
||||||
|
@ -593,6 +593,7 @@ fn new_unit_dep(
|
|||||||
is_local,
|
is_local,
|
||||||
unit_for,
|
unit_for,
|
||||||
mode,
|
mode,
|
||||||
|
kind,
|
||||||
);
|
);
|
||||||
new_unit_dep_with_profile(state, parent, pkg, target, unit_for, kind, mode, profile)
|
new_unit_dep_with_profile(state, parent, pkg, target, unit_for, kind, mode, profile)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use crate::core::compiler::{CompileMode, Unit};
|
use crate::core::compiler::{CompileKind, CompileMode, Unit};
|
||||||
use crate::core::resolver::features::FeaturesFor;
|
use crate::core::resolver::features::FeaturesFor;
|
||||||
use crate::core::{Feature, Features, PackageId, PackageIdSpec, Resolve, Shell, Target};
|
use crate::core::{Feature, PackageId, PackageIdSpec, Resolve, Shell, Target, Workspace};
|
||||||
use crate::util::errors::CargoResultExt;
|
use crate::util::errors::CargoResultExt;
|
||||||
use crate::util::interning::InternedString;
|
use crate::util::interning::InternedString;
|
||||||
use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
|
use crate::util::toml::{ProfilePackageSpec, StringOrBool, TomlProfile, TomlProfiles, U32OrBool};
|
||||||
use crate::util::{closest_msg, config, CargoResult, Config};
|
use crate::util::{closest_msg, config, CargoResult, Config};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
|
use std::hash::Hash;
|
||||||
use std::{cmp, env, fmt, hash};
|
use std::{cmp, env, fmt, hash};
|
||||||
|
|
||||||
/// Collection of all profiles.
|
/// Collection of all profiles.
|
||||||
@ -24,28 +25,28 @@ pub struct Profiles {
|
|||||||
named_profiles_enabled: bool,
|
named_profiles_enabled: bool,
|
||||||
/// The profile the user requested to use.
|
/// The profile the user requested to use.
|
||||||
requested_profile: InternedString,
|
requested_profile: InternedString,
|
||||||
|
/// The host target for rustc being used by this `Profiles`.
|
||||||
|
rustc_host: InternedString,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Profiles {
|
impl Profiles {
|
||||||
pub fn new(
|
pub fn new(ws: &Workspace<'_>, requested_profile: InternedString) -> CargoResult<Profiles> {
|
||||||
profiles: Option<&TomlProfiles>,
|
let config = ws.config();
|
||||||
config: &Config,
|
|
||||||
requested_profile: InternedString,
|
|
||||||
features: &Features,
|
|
||||||
) -> CargoResult<Profiles> {
|
|
||||||
let incremental = match env::var_os("CARGO_INCREMENTAL") {
|
let incremental = match env::var_os("CARGO_INCREMENTAL") {
|
||||||
Some(v) => Some(v == "1"),
|
Some(v) => Some(v == "1"),
|
||||||
None => config.build_config()?.incremental,
|
None => config.build_config()?.incremental,
|
||||||
};
|
};
|
||||||
let mut profiles = merge_config_profiles(profiles, config, requested_profile, features)?;
|
let mut profiles = merge_config_profiles(ws, requested_profile)?;
|
||||||
|
let rustc_host = ws.config().load_global_rustc(Some(ws))?.host;
|
||||||
|
|
||||||
if !features.is_enabled(Feature::named_profiles()) {
|
if !ws.unstable_features().is_enabled(Feature::named_profiles()) {
|
||||||
let mut profile_makers = Profiles {
|
let mut profile_makers = Profiles {
|
||||||
incremental,
|
incremental,
|
||||||
named_profiles_enabled: false,
|
named_profiles_enabled: false,
|
||||||
dir_names: Self::predefined_dir_names(),
|
dir_names: Self::predefined_dir_names(),
|
||||||
by_name: HashMap::new(),
|
by_name: HashMap::new(),
|
||||||
requested_profile,
|
requested_profile,
|
||||||
|
rustc_host,
|
||||||
};
|
};
|
||||||
|
|
||||||
profile_makers.by_name.insert(
|
profile_makers.by_name.insert(
|
||||||
@ -98,6 +99,7 @@ impl Profiles {
|
|||||||
dir_names: Self::predefined_dir_names(),
|
dir_names: Self::predefined_dir_names(),
|
||||||
by_name: HashMap::new(),
|
by_name: HashMap::new(),
|
||||||
requested_profile,
|
requested_profile,
|
||||||
|
rustc_host,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::add_root_profiles(&mut profile_makers, &profiles);
|
Self::add_root_profiles(&mut profile_makers, &profiles);
|
||||||
@ -289,6 +291,7 @@ impl Profiles {
|
|||||||
is_local: bool,
|
is_local: bool,
|
||||||
unit_for: UnitFor,
|
unit_for: UnitFor,
|
||||||
mode: CompileMode,
|
mode: CompileMode,
|
||||||
|
kind: CompileKind,
|
||||||
) -> Profile {
|
) -> Profile {
|
||||||
let (profile_name, inherits) = if !self.named_profiles_enabled {
|
let (profile_name, inherits) = if !self.named_profiles_enabled {
|
||||||
// With the feature disabled, we degrade `--profile` back to the
|
// With the feature disabled, we degrade `--profile` back to the
|
||||||
@ -344,10 +347,28 @@ impl Profiles {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default macOS debug information to being stored in the "packed"
|
||||||
|
// split-debuginfo format. At the time of this writing that's the only
|
||||||
|
// platform which has a stable `-Csplit-debuginfo` option for rustc,
|
||||||
|
// and it's typically much faster than running `dsymutil` on all builds
|
||||||
|
// in incremental cases.
|
||||||
|
if let Some(debug) = profile.debuginfo {
|
||||||
|
if profile.split_debuginfo.is_none() && debug > 0 {
|
||||||
|
let target = match &kind {
|
||||||
|
CompileKind::Host => self.rustc_host.as_str(),
|
||||||
|
CompileKind::Target(target) => target.short_name(),
|
||||||
|
};
|
||||||
|
if target.contains("-apple-") {
|
||||||
|
profile.split_debuginfo = Some(InternedString::new("unpacked"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Incremental can be globally overridden.
|
// Incremental can be globally overridden.
|
||||||
if let Some(v) = self.incremental {
|
if let Some(v) = self.incremental {
|
||||||
profile.incremental = v;
|
profile.incremental = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only enable incremental compilation for sources the user can
|
// Only enable incremental compilation for sources the user can
|
||||||
// modify (aka path sources). For things that change infrequently,
|
// modify (aka path sources). For things that change infrequently,
|
||||||
// non-incremental builds yield better performance in the compiler
|
// non-incremental builds yield better performance in the compiler
|
||||||
@ -567,6 +588,9 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) {
|
|||||||
if let Some(debug_assertions) = toml.debug_assertions {
|
if let Some(debug_assertions) = toml.debug_assertions {
|
||||||
profile.debug_assertions = debug_assertions;
|
profile.debug_assertions = debug_assertions;
|
||||||
}
|
}
|
||||||
|
if let Some(split_debuginfo) = &toml.split_debuginfo {
|
||||||
|
profile.split_debuginfo = Some(InternedString::new(split_debuginfo));
|
||||||
|
}
|
||||||
if let Some(rpath) = toml.rpath {
|
if let Some(rpath) = toml.rpath {
|
||||||
profile.rpath = rpath;
|
profile.rpath = rpath;
|
||||||
}
|
}
|
||||||
@ -612,6 +636,7 @@ pub struct Profile {
|
|||||||
// `None` means use rustc default.
|
// `None` means use rustc default.
|
||||||
pub codegen_units: Option<u32>,
|
pub codegen_units: Option<u32>,
|
||||||
pub debuginfo: Option<u32>,
|
pub debuginfo: Option<u32>,
|
||||||
|
pub split_debuginfo: Option<InternedString>,
|
||||||
pub debug_assertions: bool,
|
pub debug_assertions: bool,
|
||||||
pub overflow_checks: bool,
|
pub overflow_checks: bool,
|
||||||
pub rpath: bool,
|
pub rpath: bool,
|
||||||
@ -630,6 +655,7 @@ impl Default for Profile {
|
|||||||
codegen_units: None,
|
codegen_units: None,
|
||||||
debuginfo: None,
|
debuginfo: None,
|
||||||
debug_assertions: false,
|
debug_assertions: false,
|
||||||
|
split_debuginfo: None,
|
||||||
overflow_checks: false,
|
overflow_checks: false,
|
||||||
rpath: false,
|
rpath: false,
|
||||||
incremental: false,
|
incremental: false,
|
||||||
@ -654,6 +680,7 @@ compact_debug! {
|
|||||||
root
|
root
|
||||||
codegen_units
|
codegen_units
|
||||||
debuginfo
|
debuginfo
|
||||||
|
split_debuginfo
|
||||||
debug_assertions
|
debug_assertions
|
||||||
overflow_checks
|
overflow_checks
|
||||||
rpath
|
rpath
|
||||||
@ -734,25 +761,13 @@ impl Profile {
|
|||||||
/// Compares all fields except `name`, which doesn't affect compilation.
|
/// Compares all fields except `name`, which doesn't affect compilation.
|
||||||
/// This is necessary for `Unit` deduplication for things like "test" and
|
/// This is necessary for `Unit` deduplication for things like "test" and
|
||||||
/// "dev" which are essentially the same.
|
/// "dev" which are essentially the same.
|
||||||
fn comparable(
|
fn comparable(&self) -> impl Hash + Eq {
|
||||||
&self,
|
|
||||||
) -> (
|
|
||||||
InternedString,
|
|
||||||
Lto,
|
|
||||||
Option<u32>,
|
|
||||||
Option<u32>,
|
|
||||||
bool,
|
|
||||||
bool,
|
|
||||||
bool,
|
|
||||||
bool,
|
|
||||||
PanicStrategy,
|
|
||||||
Strip,
|
|
||||||
) {
|
|
||||||
(
|
(
|
||||||
self.opt_level,
|
self.opt_level,
|
||||||
self.lto,
|
self.lto,
|
||||||
self.codegen_units,
|
self.codegen_units,
|
||||||
self.debuginfo,
|
self.debuginfo,
|
||||||
|
self.split_debuginfo,
|
||||||
self.debug_assertions,
|
self.debug_assertions,
|
||||||
self.overflow_checks,
|
self.overflow_checks,
|
||||||
self.rpath,
|
self.rpath,
|
||||||
@ -1073,12 +1088,10 @@ impl UnitFor {
|
|||||||
///
|
///
|
||||||
/// Returns a new copy of the profile map with all the mergers complete.
|
/// Returns a new copy of the profile map with all the mergers complete.
|
||||||
fn merge_config_profiles(
|
fn merge_config_profiles(
|
||||||
profiles: Option<&TomlProfiles>,
|
ws: &Workspace<'_>,
|
||||||
config: &Config,
|
|
||||||
requested_profile: InternedString,
|
requested_profile: InternedString,
|
||||||
features: &Features,
|
|
||||||
) -> CargoResult<BTreeMap<InternedString, TomlProfile>> {
|
) -> CargoResult<BTreeMap<InternedString, TomlProfile>> {
|
||||||
let mut profiles = match profiles {
|
let mut profiles = match ws.profiles() {
|
||||||
Some(profiles) => profiles.get_all().clone(),
|
Some(profiles) => profiles.get_all().clone(),
|
||||||
None => BTreeMap::new(),
|
None => BTreeMap::new(),
|
||||||
};
|
};
|
||||||
@ -1087,7 +1100,7 @@ fn merge_config_profiles(
|
|||||||
check_to_add.insert(requested_profile);
|
check_to_add.insert(requested_profile);
|
||||||
// Merge config onto manifest profiles.
|
// Merge config onto manifest profiles.
|
||||||
for (name, profile) in &mut profiles {
|
for (name, profile) in &mut profiles {
|
||||||
if let Some(config_profile) = get_config_profile(name, config, features)? {
|
if let Some(config_profile) = get_config_profile(ws, name)? {
|
||||||
profile.merge(&config_profile);
|
profile.merge(&config_profile);
|
||||||
}
|
}
|
||||||
if let Some(inherits) = &profile.inherits {
|
if let Some(inherits) = &profile.inherits {
|
||||||
@ -1106,7 +1119,7 @@ fn merge_config_profiles(
|
|||||||
std::mem::swap(&mut current, &mut check_to_add);
|
std::mem::swap(&mut current, &mut check_to_add);
|
||||||
for name in current.drain() {
|
for name in current.drain() {
|
||||||
if !profiles.contains_key(&name) {
|
if !profiles.contains_key(&name) {
|
||||||
if let Some(config_profile) = get_config_profile(&name, config, features)? {
|
if let Some(config_profile) = get_config_profile(ws, &name)? {
|
||||||
if let Some(inherits) = &config_profile.inherits {
|
if let Some(inherits) = &config_profile.inherits {
|
||||||
check_to_add.insert(*inherits);
|
check_to_add.insert(*inherits);
|
||||||
}
|
}
|
||||||
@ -1119,12 +1132,9 @@ fn merge_config_profiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for fetching a profile from config.
|
/// Helper for fetching a profile from config.
|
||||||
fn get_config_profile(
|
fn get_config_profile(ws: &Workspace<'_>, name: &str) -> CargoResult<Option<TomlProfile>> {
|
||||||
name: &str,
|
let profile: Option<config::Value<TomlProfile>> =
|
||||||
config: &Config,
|
ws.config().get(&format!("profile.{}", name))?;
|
||||||
features: &Features,
|
|
||||||
) -> CargoResult<Option<TomlProfile>> {
|
|
||||||
let profile: Option<config::Value<TomlProfile>> = config.get(&format!("profile.{}", name))?;
|
|
||||||
let profile = match profile {
|
let profile = match profile {
|
||||||
Some(profile) => profile,
|
Some(profile) => profile,
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
@ -1132,7 +1142,7 @@ fn get_config_profile(
|
|||||||
let mut warnings = Vec::new();
|
let mut warnings = Vec::new();
|
||||||
profile
|
profile
|
||||||
.val
|
.val
|
||||||
.validate(name, features, &mut warnings)
|
.validate(name, ws.unstable_features(), &mut warnings)
|
||||||
.chain_err(|| {
|
.chain_err(|| {
|
||||||
anyhow::format_err!(
|
anyhow::format_err!(
|
||||||
"config profile `{}` is not valid (defined in `{}`)",
|
"config profile `{}` is not valid (defined in `{}`)",
|
||||||
@ -1141,7 +1151,7 @@ fn get_config_profile(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
for warning in warnings {
|
for warning in warnings {
|
||||||
config.shell().warn(warning)?;
|
ws.config().shell().warn(warning)?;
|
||||||
}
|
}
|
||||||
Ok(Some(profile.val))
|
Ok(Some(profile.val))
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
|
|||||||
return rm_rf(&target_dir.into_path_unlocked(), config);
|
return rm_rf(&target_dir.into_path_unlocked(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
let profiles = Profiles::new(
|
let profiles = Profiles::new(ws, opts.requested_profile)?;
|
||||||
ws.profiles(),
|
|
||||||
config,
|
|
||||||
opts.requested_profile,
|
|
||||||
ws.unstable_features(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if opts.profile_specified {
|
if opts.profile_specified {
|
||||||
// After parsing profiles we know the dir-name of the profile, if a profile
|
// After parsing profiles we know the dir-name of the profile, if a profile
|
||||||
@ -181,9 +176,14 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
|
|||||||
// Remove dep-info file generated by rustc. It is not tracked in
|
// Remove dep-info file generated by rustc. It is not tracked in
|
||||||
// file_types. It does not have a prefix.
|
// file_types. It does not have a prefix.
|
||||||
let hashed_dep_info = dir.join(format!("{}-*.d", crate_name));
|
let hashed_dep_info = dir.join(format!("{}-*.d", crate_name));
|
||||||
let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
|
|
||||||
rm_rf_glob(&hashed_dep_info, config)?;
|
rm_rf_glob(&hashed_dep_info, config)?;
|
||||||
|
let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
|
||||||
rm_rf(&unhashed_dep_info, config)?;
|
rm_rf(&unhashed_dep_info, config)?;
|
||||||
|
// Remove split-debuginfo files generated by rustc.
|
||||||
|
let split_debuginfo_obj = dir.join(format!("{}.*.o", crate_name));
|
||||||
|
rm_rf_glob(&split_debuginfo_obj, config)?;
|
||||||
|
let split_debuginfo_dwo = dir.join(format!("{}.*.dwo", crate_name));
|
||||||
|
rm_rf_glob(&split_debuginfo_dwo, config)?;
|
||||||
|
|
||||||
// Remove the uplifted copy.
|
// Remove the uplifted copy.
|
||||||
if let Some(uplift_dir) = uplift_dir {
|
if let Some(uplift_dir) = uplift_dir {
|
||||||
|
@ -429,12 +429,7 @@ pub fn create_bcx<'a, 'cfg>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let profiles = Profiles::new(
|
let profiles = Profiles::new(ws, build_config.requested_profile)?;
|
||||||
ws.profiles(),
|
|
||||||
config,
|
|
||||||
build_config.requested_profile,
|
|
||||||
ws.unstable_features(),
|
|
||||||
)?;
|
|
||||||
profiles.validate_packages(
|
profiles.validate_packages(
|
||||||
ws.profiles(),
|
ws.profiles(),
|
||||||
&mut config.shell(),
|
&mut config.shell(),
|
||||||
@ -887,19 +882,20 @@ fn generate_targets(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let is_local = pkg.package_id().source_id().is_path();
|
let is_local = pkg.package_id().source_id().is_path();
|
||||||
let profile = profiles.get_profile(
|
|
||||||
pkg.package_id(),
|
|
||||||
ws.is_member(pkg),
|
|
||||||
is_local,
|
|
||||||
unit_for,
|
|
||||||
target_mode,
|
|
||||||
);
|
|
||||||
|
|
||||||
// No need to worry about build-dependencies, roots are never build dependencies.
|
// No need to worry about build-dependencies, roots are never build dependencies.
|
||||||
let features_for = FeaturesFor::from_for_host(target.proc_macro());
|
let features_for = FeaturesFor::from_for_host(target.proc_macro());
|
||||||
let features = resolved_features.activated_features(pkg.package_id(), features_for);
|
let features = resolved_features.activated_features(pkg.package_id(), features_for);
|
||||||
|
|
||||||
for kind in requested_kinds {
|
for kind in requested_kinds {
|
||||||
|
let profile = profiles.get_profile(
|
||||||
|
pkg.package_id(),
|
||||||
|
ws.is_member(pkg),
|
||||||
|
is_local,
|
||||||
|
unit_for,
|
||||||
|
target_mode,
|
||||||
|
kind.for_target(target),
|
||||||
|
);
|
||||||
let unit = interner.intern(
|
let unit = interner.intern(
|
||||||
pkg,
|
pkg,
|
||||||
target,
|
target,
|
||||||
|
@ -432,6 +432,7 @@ pub struct TomlProfile {
|
|||||||
pub lto: Option<StringOrBool>,
|
pub lto: Option<StringOrBool>,
|
||||||
pub codegen_units: Option<u32>,
|
pub codegen_units: Option<u32>,
|
||||||
pub debug: Option<U32OrBool>,
|
pub debug: Option<U32OrBool>,
|
||||||
|
pub split_debuginfo: Option<String>,
|
||||||
pub debug_assertions: Option<bool>,
|
pub debug_assertions: Option<bool>,
|
||||||
pub rpath: Option<bool>,
|
pub rpath: Option<bool>,
|
||||||
pub panic: Option<String>,
|
pub panic: Option<String>,
|
||||||
@ -634,6 +635,10 @@ impl TomlProfile {
|
|||||||
self.debug_assertions = Some(v);
|
self.debug_assertions = Some(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(v) = &profile.split_debuginfo {
|
||||||
|
self.split_debuginfo = Some(v.clone());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(v) = profile.rpath {
|
if let Some(v) = profile.rpath {
|
||||||
self.rpath = Some(v);
|
self.rpath = Some(v);
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,26 @@ The valid options are:
|
|||||||
* `1`: line tables only
|
* `1`: line tables only
|
||||||
* `2` or `true`: full debug info
|
* `2` or `true`: full debug info
|
||||||
|
|
||||||
|
You may wish to also configure the [`split-debuginfo`](#split-debuginfo) option
|
||||||
|
depending on your needs as well.
|
||||||
|
|
||||||
[`-C debuginfo` flag]: ../../rustc/codegen-options/index.html#debuginfo
|
[`-C debuginfo` flag]: ../../rustc/codegen-options/index.html#debuginfo
|
||||||
|
|
||||||
|
#### split-debuginfo
|
||||||
|
|
||||||
|
The `split-debuginfo` setting controls the [`-C split-debuginfo` flag] which
|
||||||
|
controls whether debug information, if generated, is either placed in the
|
||||||
|
executable itself or adjacent to it.
|
||||||
|
|
||||||
|
This option is a string and acceptable values are the same as those the
|
||||||
|
[compiler accepts][`-C split-debuginfo` flag]. This option is currently not
|
||||||
|
passed by default on platforms other than macOS, where it defaults to
|
||||||
|
`unpacked`. The default may change in the future for platforms using DWARF
|
||||||
|
debugging information and ELF executables to `unpacked` as well once it is
|
||||||
|
stabilized in the compiler.
|
||||||
|
|
||||||
|
[`-C split-debuginfo` flag]: ../../rustc/codegen-options/index.html#split-debuginfo
|
||||||
|
|
||||||
#### debug-assertions
|
#### debug-assertions
|
||||||
|
|
||||||
The `debug-assertions` setting controls the [`-C debug-assertions` flag] which
|
The `debug-assertions` setting controls the [`-C debug-assertions` flag] which
|
||||||
|
@ -4444,7 +4444,9 @@ fn uplift_dsym_of_bin_on_mac() {
|
|||||||
.file("tests/d.rs", "fn main() { panic!(); }")
|
.file("tests/d.rs", "fn main() { panic!(); }")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
p.cargo("build --bins --examples --tests").run();
|
p.cargo("build --bins --examples --tests")
|
||||||
|
.enable_mac_dsym()
|
||||||
|
.run();
|
||||||
assert!(p.target_debug_dir().join("foo.dSYM").is_dir());
|
assert!(p.target_debug_dir().join("foo.dSYM").is_dir());
|
||||||
assert!(p.target_debug_dir().join("b.dSYM").is_dir());
|
assert!(p.target_debug_dir().join("b.dSYM").is_dir());
|
||||||
assert!(p.target_debug_dir().join("b.dSYM").is_symlink());
|
assert!(p.target_debug_dir().join("b.dSYM").is_symlink());
|
||||||
@ -4461,7 +4463,7 @@ fn uplift_dsym_of_bin_on_mac_when_broken_link_exists() {
|
|||||||
.build();
|
.build();
|
||||||
let dsym = p.target_debug_dir().join("foo.dSYM");
|
let dsym = p.target_debug_dir().join("foo.dSYM");
|
||||||
|
|
||||||
p.cargo("build").run();
|
p.cargo("build").enable_mac_dsym().run();
|
||||||
assert!(dsym.is_dir());
|
assert!(dsym.is_dir());
|
||||||
|
|
||||||
// Simulate the situation where the underlying dSYM bundle goes missing
|
// Simulate the situation where the underlying dSYM bundle goes missing
|
||||||
@ -4477,7 +4479,7 @@ fn uplift_dsym_of_bin_on_mac_when_broken_link_exists() {
|
|||||||
assert!(dsym.is_symlink());
|
assert!(dsym.is_symlink());
|
||||||
assert!(!dsym.exists());
|
assert!(!dsym.exists());
|
||||||
|
|
||||||
p.cargo("build").run();
|
p.cargo("build").enable_mac_dsym().run();
|
||||||
assert!(dsym.is_dir());
|
assert!(dsym.is_dir());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ fn binary_with_debug() {
|
|||||||
|
|
||||||
p.cargo("build -Z unstable-options --out-dir out")
|
p.cargo("build -Z unstable-options --out-dir out")
|
||||||
.masquerade_as_nightly_cargo()
|
.masquerade_as_nightly_cargo()
|
||||||
|
.enable_mac_dsym()
|
||||||
.run();
|
.run();
|
||||||
check_dir_contents(
|
check_dir_contents(
|
||||||
&p.root().join("out"),
|
&p.root().join("out"),
|
||||||
@ -86,6 +87,7 @@ fn dynamic_library_with_debug() {
|
|||||||
|
|
||||||
p.cargo("build -Z unstable-options --out-dir out")
|
p.cargo("build -Z unstable-options --out-dir out")
|
||||||
.masquerade_as_nightly_cargo()
|
.masquerade_as_nightly_cargo()
|
||||||
|
.enable_mac_dsym()
|
||||||
.run();
|
.run();
|
||||||
check_dir_contents(
|
check_dir_contents(
|
||||||
&p.root().join("out"),
|
&p.root().join("out"),
|
||||||
@ -165,6 +167,7 @@ fn include_only_the_binary_from_the_current_package() {
|
|||||||
|
|
||||||
p.cargo("build -Z unstable-options --bin foo --out-dir out")
|
p.cargo("build -Z unstable-options --bin foo --out-dir out")
|
||||||
.masquerade_as_nightly_cargo()
|
.masquerade_as_nightly_cargo()
|
||||||
|
.enable_mac_dsym()
|
||||||
.run();
|
.run();
|
||||||
check_dir_contents(
|
check_dir_contents(
|
||||||
&p.root().join("out"),
|
&p.root().join("out"),
|
||||||
@ -239,6 +242,7 @@ fn avoid_build_scripts() {
|
|||||||
|
|
||||||
p.cargo("build -Z unstable-options --out-dir out -vv")
|
p.cargo("build -Z unstable-options --out-dir out -vv")
|
||||||
.masquerade_as_nightly_cargo()
|
.masquerade_as_nightly_cargo()
|
||||||
|
.enable_mac_dsym()
|
||||||
.with_stdout_contains("[a 0.0.1] hello-build-a")
|
.with_stdout_contains("[a 0.0.1] hello-build-a")
|
||||||
.with_stdout_contains("[b 0.0.1] hello-build-b")
|
.with_stdout_contains("[b 0.0.1] hello-build-b")
|
||||||
.run();
|
.run();
|
||||||
@ -266,6 +270,7 @@ fn cargo_build_out_dir() {
|
|||||||
|
|
||||||
p.cargo("build -Z unstable-options")
|
p.cargo("build -Z unstable-options")
|
||||||
.masquerade_as_nightly_cargo()
|
.masquerade_as_nightly_cargo()
|
||||||
|
.enable_mac_dsym()
|
||||||
.run();
|
.run();
|
||||||
check_dir_contents(
|
check_dir_contents(
|
||||||
&p.root().join("out"),
|
&p.root().join("out"),
|
||||||
|
@ -233,7 +233,7 @@ fn profile_config_all_options() {
|
|||||||
[RUNNING] `rustc --crate-name foo [..] \
|
[RUNNING] `rustc --crate-name foo [..] \
|
||||||
-C opt-level=1 \
|
-C opt-level=1 \
|
||||||
-C panic=abort \
|
-C panic=abort \
|
||||||
-C lto \
|
-C lto[..]\
|
||||||
-C codegen-units=2 \
|
-C codegen-units=2 \
|
||||||
-C debuginfo=2 \
|
-C debuginfo=2 \
|
||||||
-C debug-assertions=on \
|
-C debug-assertions=on \
|
||||||
@ -342,64 +342,63 @@ fn named_config_profile() {
|
|||||||
// foo -> middle -> bar -> dev
|
// foo -> middle -> bar -> dev
|
||||||
// middle exists in Cargo.toml, the others in .cargo/config
|
// middle exists in Cargo.toml, the others in .cargo/config
|
||||||
use super::config::ConfigBuilder;
|
use super::config::ConfigBuilder;
|
||||||
|
use cargo::core::compiler::CompileKind;
|
||||||
use cargo::core::compiler::CompileMode;
|
use cargo::core::compiler::CompileMode;
|
||||||
use cargo::core::enable_nightly_features;
|
use cargo::core::enable_nightly_features;
|
||||||
use cargo::core::features::Features;
|
|
||||||
use cargo::core::profiles::{Profiles, UnitFor};
|
use cargo::core::profiles::{Profiles, UnitFor};
|
||||||
use cargo::core::PackageId;
|
use cargo::core::{PackageId, Workspace};
|
||||||
use cargo::util::interning::InternedString;
|
use cargo::util::interning::InternedString;
|
||||||
use cargo::util::toml::TomlProfiles;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
enable_nightly_features();
|
enable_nightly_features();
|
||||||
paths::root().join(".cargo").mkdir_p();
|
paths::root().join(".cargo").mkdir_p();
|
||||||
fs::write(
|
fs::write(
|
||||||
paths::root().join(".cargo/config"),
|
paths::root().join(".cargo/config"),
|
||||||
r#"
|
r#"
|
||||||
[profile.foo]
|
[profile.foo]
|
||||||
inherits = "middle"
|
inherits = "middle"
|
||||||
codegen-units = 2
|
codegen-units = 2
|
||||||
[profile.foo.build-override]
|
[profile.foo.build-override]
|
||||||
codegen-units = 6
|
codegen-units = 6
|
||||||
[profile.foo.package.dep]
|
[profile.foo.package.dep]
|
||||||
codegen-units = 7
|
codegen-units = 7
|
||||||
|
|
||||||
[profile.middle]
|
[profile.middle]
|
||||||
inherits = "bar"
|
inherits = "bar"
|
||||||
codegen-units = 3
|
codegen-units = 3
|
||||||
|
|
||||||
[profile.bar]
|
[profile.bar]
|
||||||
inherits = "dev"
|
inherits = "dev"
|
||||||
codegen-units = 4
|
codegen-units = 4
|
||||||
debug = 1
|
debug = 1
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
fs::write(
|
||||||
|
paths::root().join("Cargo.toml"),
|
||||||
|
r#"
|
||||||
|
cargo-features = ['named-profiles']
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
|
||||||
|
[profile.middle]
|
||||||
|
inherits = "bar"
|
||||||
|
codegen-units = 1
|
||||||
|
opt-level = 1
|
||||||
|
[profile.middle.package.dep]
|
||||||
|
overflow-checks = false
|
||||||
|
|
||||||
|
[profile.foo.build-override]
|
||||||
|
codegen-units = 5
|
||||||
|
debug-assertions = false
|
||||||
|
[profile.foo.package.dep]
|
||||||
|
codegen-units = 8
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let config = ConfigBuilder::new().build();
|
let config = ConfigBuilder::new().build();
|
||||||
let mut warnings = Vec::new();
|
|
||||||
let features = Features::new(&["named-profiles".to_string()], &mut warnings).unwrap();
|
|
||||||
assert_eq!(warnings.len(), 0);
|
|
||||||
let profile_name = InternedString::new("foo");
|
let profile_name = InternedString::new("foo");
|
||||||
let toml = r#"
|
let ws = Workspace::new(&paths::root().join("Cargo.toml"), &config).unwrap();
|
||||||
[profile.middle]
|
let profiles = Profiles::new(&ws, profile_name).unwrap();
|
||||||
inherits = "bar"
|
|
||||||
codegen-units = 1
|
|
||||||
opt-level = 1
|
|
||||||
[profile.middle.package.dep]
|
|
||||||
overflow-checks = false
|
|
||||||
|
|
||||||
[profile.foo.build-override]
|
|
||||||
codegen-units = 5
|
|
||||||
debug-assertions = false
|
|
||||||
[profile.foo.package.dep]
|
|
||||||
codegen-units = 8
|
|
||||||
"#;
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
struct TomlManifest {
|
|
||||||
profile: Option<TomlProfiles>,
|
|
||||||
}
|
|
||||||
let manifest: TomlManifest = toml::from_str(toml).unwrap();
|
|
||||||
let profiles =
|
|
||||||
Profiles::new(manifest.profile.as_ref(), &config, profile_name, &features).unwrap();
|
|
||||||
|
|
||||||
let crates_io = cargo::core::source::SourceId::crates_io(&config).unwrap();
|
let crates_io = cargo::core::source::SourceId::crates_io(&config).unwrap();
|
||||||
let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
|
let a_pkg = PackageId::new("a", "0.1.0", crates_io).unwrap();
|
||||||
@ -407,7 +406,14 @@ fn named_config_profile() {
|
|||||||
|
|
||||||
// normal package
|
// normal package
|
||||||
let mode = CompileMode::Build;
|
let mode = CompileMode::Build;
|
||||||
let p = profiles.get_profile(a_pkg, true, true, UnitFor::new_normal(), mode);
|
let p = profiles.get_profile(
|
||||||
|
a_pkg,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
UnitFor::new_normal(),
|
||||||
|
mode,
|
||||||
|
CompileKind::Host,
|
||||||
|
);
|
||||||
assert_eq!(p.name, "foo");
|
assert_eq!(p.name, "foo");
|
||||||
assert_eq!(p.codegen_units, Some(2)); // "foo" from config
|
assert_eq!(p.codegen_units, Some(2)); // "foo" from config
|
||||||
assert_eq!(p.opt_level, "1"); // "middle" from manifest
|
assert_eq!(p.opt_level, "1"); // "middle" from manifest
|
||||||
@ -416,7 +422,14 @@ fn named_config_profile() {
|
|||||||
assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
|
assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override)
|
||||||
|
|
||||||
// build-override
|
// build-override
|
||||||
let bo = profiles.get_profile(a_pkg, true, true, UnitFor::new_host(false), mode);
|
let bo = profiles.get_profile(
|
||||||
|
a_pkg,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
UnitFor::new_host(false),
|
||||||
|
mode,
|
||||||
|
CompileKind::Host,
|
||||||
|
);
|
||||||
assert_eq!(bo.name, "foo");
|
assert_eq!(bo.name, "foo");
|
||||||
assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
|
assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config
|
||||||
assert_eq!(bo.opt_level, "0"); // default to zero
|
assert_eq!(bo.opt_level, "0"); // default to zero
|
||||||
@ -425,7 +438,14 @@ fn named_config_profile() {
|
|||||||
assert_eq!(bo.overflow_checks, true); // SAME as normal
|
assert_eq!(bo.overflow_checks, true); // SAME as normal
|
||||||
|
|
||||||
// package overrides
|
// package overrides
|
||||||
let po = profiles.get_profile(dep_pkg, false, true, UnitFor::new_normal(), mode);
|
let po = profiles.get_profile(
|
||||||
|
dep_pkg,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
UnitFor::new_normal(),
|
||||||
|
mode,
|
||||||
|
CompileKind::Host,
|
||||||
|
);
|
||||||
assert_eq!(po.name, "foo");
|
assert_eq!(po.name, "foo");
|
||||||
assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
|
assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config
|
||||||
assert_eq!(po.opt_level, "1"); // SAME as normal
|
assert_eq!(po.opt_level, "1"); // SAME as normal
|
||||||
|
@ -6,6 +6,11 @@ use std::env;
|
|||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn rustc_info_cache() {
|
fn rustc_info_cache() {
|
||||||
|
// Currently detects a flag only supported on nightly. All other channels
|
||||||
|
// always have a miss.
|
||||||
|
if !cargo_test_support::is_nightly() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let p = project()
|
let p = project()
|
||||||
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
|
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
|
||||||
.build();
|
.build();
|
||||||
|
@ -78,7 +78,8 @@ fn simple() {
|
|||||||
"rpath": false,
|
"rpath": false,
|
||||||
"incremental": false,
|
"incremental": false,
|
||||||
"panic": "unwind",
|
"panic": "unwind",
|
||||||
"strip": "none"
|
"strip": "none",
|
||||||
|
"split_debuginfo": "{...}"
|
||||||
},
|
},
|
||||||
"platform": null,
|
"platform": null,
|
||||||
"mode": "build",
|
"mode": "build",
|
||||||
@ -121,7 +122,8 @@ fn simple() {
|
|||||||
"rpath": false,
|
"rpath": false,
|
||||||
"incremental": false,
|
"incremental": false,
|
||||||
"panic": "unwind",
|
"panic": "unwind",
|
||||||
"strip": "none"
|
"strip": "none",
|
||||||
|
"split_debuginfo": "{...}"
|
||||||
},
|
},
|
||||||
"platform": null,
|
"platform": null,
|
||||||
"mode": "build",
|
"mode": "build",
|
||||||
@ -164,7 +166,8 @@ fn simple() {
|
|||||||
"rpath": false,
|
"rpath": false,
|
||||||
"incremental": false,
|
"incremental": false,
|
||||||
"panic": "unwind",
|
"panic": "unwind",
|
||||||
"strip": "none"
|
"strip": "none",
|
||||||
|
"split_debuginfo": "{...}"
|
||||||
},
|
},
|
||||||
"platform": null,
|
"platform": null,
|
||||||
"mode": "build",
|
"mode": "build",
|
||||||
@ -200,7 +203,8 @@ fn simple() {
|
|||||||
"rpath": false,
|
"rpath": false,
|
||||||
"incremental": false,
|
"incremental": false,
|
||||||
"panic": "unwind",
|
"panic": "unwind",
|
||||||
"strip": "none"
|
"strip": "none",
|
||||||
|
"split_debuginfo": "{...}"
|
||||||
},
|
},
|
||||||
"platform": null,
|
"platform": null,
|
||||||
"mode": "build",
|
"mode": "build",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user