From 5960ae145066e3ae291d180fe4ba9ce3ac6fb72f Mon Sep 17 00:00:00 2001 From: David Calavera Date: Sun, 24 Sep 2023 17:54:29 -0700 Subject: [PATCH] Expose all profiles in the workspace. Implement a new method Profiles::all that returns all profiles in the workspace, including the root and predefined profiles. This new method follows Cargo resolution rules to resolve profile inheritance and ordering. Signed-off-by: David Calavera --- src/cargo/core/profiles.rs | 437 +++++++++++++++---------- src/cargo/ops/cargo_output_metadata.rs | 9 +- tests/testsuite/alt_registry.rs | 26 +- tests/testsuite/features_namespaced.rs | 10 +- tests/testsuite/git.rs | 6 +- tests/testsuite/metadata.rs | 346 +++++++++++++++----- tests/testsuite/script.rs | 56 +++- tests/testsuite/unit_graph.rs | 24 +- tests/testsuite/update.rs | 10 +- 9 files changed, 614 insertions(+), 310 deletions(-) diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 5c7d3e2488e3..406bb00a3c21 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -31,6 +31,7 @@ use crate::util::toml::{ }; use crate::util::{closest_msg, config, CargoResult, Config}; use anyhow::{bail, Context as _}; +use std::collections::btree_map::Entry; use std::collections::{BTreeMap, HashMap, HashSet}; use std::hash::Hash; use std::{cmp, fmt, hash}; @@ -62,196 +63,84 @@ pub struct Profiles { } impl Profiles { + /// Returns all the profiles defined in a workspace, including root and predefined profiles. + /// This function resolves inheritances between profiles. + pub fn all(ws: &Workspace<'_>) -> CargoResult> { + let mut definitions = merge_config_profiles(ws, None)?; + + merge_predefined_profiles(&mut definitions); + + let mut makers = HashMap::new(); + for (name, profile) in root_profiles(&definitions) { + makers.insert(name, profile); + } + + for (name, profile) in &definitions { + let name = *name; + if let Some(maker) = create_profile_maker(name, profile, &makers, &definitions)? { + makers.insert(name, maker); + } + } + + for (name, profile) in &definitions { + let name = *name; + if let Some(maker) = create_profile_maker(name, profile, &makers, &definitions)? { + makers.insert(name, maker); + } + } + + let mut profiles = HashMap::new(); + for (name, maker) in makers { + profiles.insert(name, maker.get_profile(name, None, true, false)); + } + + Ok(profiles) + } + + /// Returns all the profiles defined in a workspace, verifying that + /// the requested profile exists in the workspace. pub fn new(ws: &Workspace<'_>, requested_profile: InternedString) -> CargoResult { let config = ws.config(); let incremental = match config.get_env_os("CARGO_INCREMENTAL") { Some(v) => Some(v == "1"), None => config.build_config()?.incremental, }; - let mut profiles = merge_config_profiles(ws, requested_profile)?; + let mut profiles = merge_config_profiles(ws, Some(requested_profile))?; let rustc_host = ws.config().load_global_rustc(Some(ws))?.host; let mut profile_makers = Profiles { incremental, - dir_names: Self::predefined_dir_names(), + dir_names: predefined_dir_names(), by_name: HashMap::new(), original_profiles: profiles.clone(), requested_profile, rustc_host, }; - Self::add_root_profiles(&mut profile_makers, &profiles); - - // Merge with predefined profiles. - use std::collections::btree_map::Entry; - for (predef_name, mut predef_prof) in Self::predefined_profiles().into_iter() { - match profiles.entry(InternedString::new(predef_name)) { - Entry::Vacant(vac) => { - vac.insert(predef_prof); - } - Entry::Occupied(mut oc) => { - // Override predefined with the user-provided Toml. - let r = oc.get_mut(); - predef_prof.merge(r); - *r = predef_prof; - } - } + for (name, profile) in root_profiles(&profiles) { + profile_makers.by_name.insert(name, profile); } + merge_predefined_profiles(&mut profiles); + for (name, profile) in &profiles { - profile_makers.add_maker(*name, profile, &profiles)?; + let name = *name; + if let Some(dir_name) = profile.dir_name { + profile_makers.dir_names.insert(name, dir_name.to_owned()); + } + if let Some(maker) = + create_profile_maker(name, profile, &profile_makers.by_name, &profiles)? + { + profile_makers.by_name.insert(name, maker); + } } // Verify that the requested profile is defined *somewhere*. // This simplifies the API (no need for CargoResult), and enforces // assumptions about how config profiles are loaded. - profile_makers.get_profile_maker(requested_profile)?; + get_profile_maker(&profile_makers.by_name, requested_profile)?; Ok(profile_makers) } - /// Returns the hard-coded directory names for built-in profiles. - fn predefined_dir_names() -> HashMap { - [ - (InternedString::new("dev"), InternedString::new("debug")), - (InternedString::new("test"), InternedString::new("debug")), - (InternedString::new("bench"), InternedString::new("release")), - ] - .into() - } - - /// Initialize `by_name` with the two "root" profiles, `dev`, and - /// `release` given the user's definition. - fn add_root_profiles( - profile_makers: &mut Profiles, - profiles: &BTreeMap, - ) { - profile_makers.by_name.insert( - InternedString::new("dev"), - ProfileMaker::new(Profile::default_dev(), profiles.get("dev").cloned()), - ); - - profile_makers.by_name.insert( - InternedString::new("release"), - ProfileMaker::new(Profile::default_release(), profiles.get("release").cloned()), - ); - } - - /// Returns the built-in profiles (not including dev/release, which are - /// "root" profiles). - fn predefined_profiles() -> Vec<(&'static str, TomlProfile)> { - vec![ - ( - "bench", - TomlProfile { - inherits: Some(InternedString::new("release")), - ..TomlProfile::default() - }, - ), - ( - "test", - TomlProfile { - inherits: Some(InternedString::new("dev")), - ..TomlProfile::default() - }, - ), - ( - "doc", - TomlProfile { - inherits: Some(InternedString::new("dev")), - ..TomlProfile::default() - }, - ), - ] - } - - /// Creates a `ProfileMaker`, and inserts it into `self.by_name`. - fn add_maker( - &mut self, - name: InternedString, - profile: &TomlProfile, - profiles: &BTreeMap, - ) -> CargoResult<()> { - match &profile.dir_name { - None => {} - Some(dir_name) => { - self.dir_names.insert(name, dir_name.to_owned()); - } - } - - // dev/release are "roots" and don't inherit. - if name == "dev" || name == "release" { - if profile.inherits.is_some() { - bail!( - "`inherits` must not be specified in root profile `{}`", - name - ); - } - // Already inserted from `add_root_profiles`, no need to do anything. - return Ok(()); - } - - // Keep track for inherits cycles. - let mut set = HashSet::new(); - set.insert(name); - let maker = self.process_chain(name, profile, &mut set, profiles)?; - self.by_name.insert(name, maker); - Ok(()) - } - - /// Build a `ProfileMaker` by recursively following the `inherits` setting. - /// - /// * `name`: The name of the profile being processed. - /// * `profile`: The TOML profile being processed. - /// * `set`: Set of profiles that have been visited, used to detect cycles. - /// * `profiles`: Map of all TOML profiles. - /// - /// Returns a `ProfileMaker` to be used for the given named profile. - fn process_chain( - &mut self, - name: InternedString, - profile: &TomlProfile, - set: &mut HashSet, - profiles: &BTreeMap, - ) -> CargoResult { - let mut maker = match profile.inherits { - Some(inherits_name) if inherits_name == "dev" || inherits_name == "release" => { - // These are the root profiles added in `add_root_profiles`. - self.get_profile_maker(inherits_name).unwrap().clone() - } - Some(inherits_name) => { - if !set.insert(inherits_name) { - bail!( - "profile inheritance loop detected with profile `{}` inheriting `{}`", - name, - inherits_name - ); - } - - match profiles.get(&inherits_name) { - None => { - bail!( - "profile `{}` inherits from `{}`, but that profile is not defined", - name, - inherits_name - ); - } - Some(parent) => self.process_chain(inherits_name, parent, set, profiles)?, - } - } - None => { - bail!( - "profile `{}` is missing an `inherits` directive \ - (`inherits` is required for all profiles except `dev` or `release`)", - name - ); - } - }; - match &mut maker.toml { - Some(toml) => toml.merge(profile), - None => maker.toml = Some(profile.clone()), - }; - Ok(maker) - } - /// Retrieves the profile for a target. /// `is_member` is whether or not this package is a member of the /// workspace. @@ -263,8 +152,13 @@ impl Profiles { unit_for: UnitFor, kind: CompileKind, ) -> Profile { - let maker = self.get_profile_maker(self.requested_profile).unwrap(); - let mut profile = maker.get_profile(Some(pkg_id), is_member, unit_for.is_for_host()); + let maker = get_profile_maker(&self.by_name, self.requested_profile).unwrap(); + let mut profile = maker.get_profile( + self.requested_profile, + Some(pkg_id), + is_member, + unit_for.is_for_host(), + ); // Dealing with `panic=abort` and `panic=unwind` requires some special // treatment. Be sure to process all the various options here. @@ -302,7 +196,6 @@ impl Profiles { if !is_local { profile.incremental = false; } - profile.name = self.requested_profile; profile } @@ -325,8 +218,13 @@ impl Profiles { /// select for the package that was actually built. pub fn base_profile(&self) -> Profile { let profile_name = self.requested_profile; - let maker = self.get_profile_maker(profile_name).unwrap(); - maker.get_profile(None, /*is_member*/ true, /*is_for_host*/ false) + let maker = get_profile_maker(&self.by_name, profile_name).unwrap(); + maker.get_profile( + profile_name, + None, + /*is_member*/ true, + /*is_for_host*/ false, + ) } /// Gets the directory name for a profile, like `debug` or `release`. @@ -370,13 +268,170 @@ impl Profiles { } Ok(()) } +} + +/// Returns the hard-coded directory names for built-in profiles. +fn predefined_dir_names() -> HashMap { + [ + (InternedString::new("dev"), InternedString::new("debug")), + (InternedString::new("test"), InternedString::new("debug")), + (InternedString::new("bench"), InternedString::new("release")), + ] + .into() +} + +/// Returns the "root" profiles (dev/release) +fn root_profiles( + profiles: &BTreeMap, +) -> Vec<(InternedString, ProfileMaker)> { + vec![ + ( + InternedString::new("dev"), + ProfileMaker::new(Profile::default_dev(), profiles.get("dev").cloned()), + ), + ( + InternedString::new("release"), + ProfileMaker::new(Profile::default_release(), profiles.get("release").cloned()), + ), + ] +} + +/// Returns the built-in profiles (not including dev/release, which are +/// "root" profiles). +fn predefined_profiles() -> Vec<(&'static str, TomlProfile)> { + vec![ + ( + "bench", + TomlProfile { + inherits: Some(InternedString::new("release")), + ..TomlProfile::default() + }, + ), + ( + "test", + TomlProfile { + inherits: Some(InternedString::new("dev")), + ..TomlProfile::default() + }, + ), + ( + "doc", + TomlProfile { + inherits: Some(InternedString::new("dev")), + ..TomlProfile::default() + }, + ), + ] +} + +/// Merge a list of TOML profile definitions with the predefined list from Cargo. +fn merge_predefined_profiles(definitions: &mut BTreeMap) { + for (predef_name, mut predef_prof) in predefined_profiles().into_iter() { + match definitions.entry(InternedString::new(predef_name)) { + Entry::Vacant(vac) => { + vac.insert(predef_prof); + } + Entry::Occupied(mut oc) => { + // Override predefined with the user-provided Toml. + let r = oc.get_mut(); + predef_prof.merge(r); + *r = predef_prof; + } + } + } +} - /// Returns the profile maker for the given profile name. - fn get_profile_maker(&self, name: InternedString) -> CargoResult<&ProfileMaker> { - self.by_name - .get(&name) - .ok_or_else(|| anyhow::format_err!("profile `{}` is not defined", name)) +/// Creates a `ProfileMaker`. +fn create_profile_maker( + name: InternedString, + profile: &TomlProfile, + makers: &HashMap, + definitions: &BTreeMap, +) -> CargoResult> { + // dev/release are "roots" and don't inherit. + if name == "dev" || name == "release" { + if profile.inherits.is_some() { + bail!( + "`inherits` must not be specified in root profile `{}`", + name + ); + } + // Already inserted from `add_root_profiles`, no need to do anything. + return Ok(None); } + + // Keep track for inherits cycles. + let mut set = HashSet::new(); + set.insert(name); + let maker = process_chain(name, profile, &mut set, makers, definitions)?; + Ok(Some(maker)) +} + +/// Build a `ProfileMaker` by recursively following the `inherits` setting. +/// +/// * `name`: The name of the profile being processed. +/// * `profile`: The TOML profile being processed. +/// * `set`: Set of profiles that have been visited, used to detect cycles. +/// * `makers`: Map of all `ProfileMaker` already defined in the workspace. +/// * `definitions`: Map of all TOML profiles. +/// +/// Returns a `ProfileMaker` to be used for the given named profile. +fn process_chain( + name: InternedString, + profile: &TomlProfile, + set: &mut HashSet, + makers: &HashMap, + definitions: &BTreeMap, +) -> CargoResult { + let mut maker = match profile.inherits { + Some(inherits_name) if inherits_name == "dev" || inherits_name == "release" => { + // These are the root profiles. They must exist in the list of makers + // before calling `process_chain`. + get_profile_maker(makers, inherits_name)?.clone() + } + Some(inherits_name) => { + if !set.insert(inherits_name) { + bail!( + "profile inheritance loop detected with profile `{}` inheriting `{}`", + name, + inherits_name + ); + } + + match definitions.get(&inherits_name) { + None => { + bail!( + "profile `{}` inherits from `{}`, but that profile is not defined", + name, + inherits_name + ); + } + Some(parent) => process_chain(inherits_name, parent, set, makers, definitions)?, + } + } + None => { + bail!( + "profile `{}` is missing an `inherits` directive \ + (`inherits` is required for all profiles except `dev` or `release`)", + name + ); + } + }; + match &mut maker.toml { + Some(toml) => toml.merge(profile), + None => maker.toml = Some(profile.clone()), + }; + Ok(maker) +} + +/// Returns the profile maker for the given profile name. +fn get_profile_maker( + profiles: &HashMap, + name: InternedString, +) -> CargoResult<&ProfileMaker> { + profiles + .get(&name) + .ok_or_else(|| anyhow::format_err!("profile `{}` is not defined", name)) } /// An object used for handling the profile hierarchy. @@ -413,6 +468,7 @@ impl ProfileMaker { /// Generates a new `Profile`. fn get_profile( &self, + name: InternedString, pkg_id: Option, is_member: bool, is_for_host: bool, @@ -457,6 +513,7 @@ impl ProfileMaker { if let Some(toml) = &self.toml { merge_toml_overrides(pkg_id, is_member, is_for_host, &mut profile, toml); } + profile.name = name; profile } } @@ -584,16 +641,20 @@ pub struct Profile { pub root: ProfileRoot, pub lto: Lto, // `None` means use rustc default. + #[serde(skip_serializing_if = "Option::is_none")] pub codegen_backend: Option, // `None` means use rustc default. + #[serde(skip_serializing_if = "Option::is_none")] pub codegen_units: Option, pub debuginfo: DebugInfo, + #[serde(skip_serializing_if = "Option::is_none")] pub split_debuginfo: Option, pub debug_assertions: bool, pub overflow_checks: bool, pub rpath: bool, pub incremental: bool, pub panic: PanicStrategy, + #[serde(skip_serializing_if = "Strip::is_none")] pub strip: Strip, #[serde(skip_serializing_if = "Vec::is_empty")] // remove when `rustflags` is stablized // Note that `rustflags` is used for the cargo-feature `profile_rustflags` @@ -849,9 +910,7 @@ impl fmt::Display for PanicStrategy { } /// The setting for choosing which symbols to strip -#[derive( - Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, -)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord, serde::Deserialize)] #[serde(rename_all = "lowercase")] pub enum Strip { /// Don't remove any symbols @@ -860,6 +919,12 @@ pub enum Strip { Named(InternedString), } +impl Strip { + fn is_none(&self) -> bool { + matches!(self, Strip::None) + } +} + impl fmt::Display for Strip { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -870,6 +935,18 @@ impl fmt::Display for Strip { } } +impl serde::ser::Serialize for Strip { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + match self { + Strip::None => "none".serialize(s), + Strip::Named(n) => n.serialize(s), + } + } +} + /// Flags used in creating `Unit`s to indicate the purpose for the target, and /// to ensure the target's dependencies have the correct settings. /// @@ -1159,7 +1236,7 @@ impl UnitFor { /// Returns a new copy of the profile map with all the mergers complete. fn merge_config_profiles( ws: &Workspace<'_>, - requested_profile: InternedString, + requested_profile: Option, ) -> CargoResult> { let mut profiles = match ws.profiles() { Some(profiles) => profiles.get_all().clone(), @@ -1167,7 +1244,9 @@ fn merge_config_profiles( }; // Set of profile names to check if defined in config only. let mut check_to_add = HashSet::new(); - check_to_add.insert(requested_profile); + if let Some(requested_profile) = requested_profile { + check_to_add.insert(requested_profile); + } // Merge config onto manifest profiles. for (name, profile) in &mut profiles { if let Some(config_profile) = get_config_profile(ws, name)? { diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index 5002c9fadaae..9d2adab3e456 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -2,15 +2,15 @@ use crate::core::compiler::artifact::match_artifacts_kind_with_targets; use crate::core::compiler::{CompileKind, RustcTargetData}; use crate::core::dependency::DepKind; use crate::core::package::SerializedPackage; +use crate::core::profiles::{Profile, Profiles}; use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve}; use crate::core::{Package, PackageId, Workspace}; use crate::ops::{self, Packages}; use crate::util::interning::InternedString; -use crate::util::toml::TomlProfiles; use crate::util::CargoResult; use cargo_platform::Platform; use serde::Serialize; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::path::PathBuf; const VERSION: u32 = 1; @@ -50,7 +50,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo version: VERSION, workspace_root: ws.root().to_path_buf(), metadata: ws.custom_metadata().cloned(), - profiles: ws.profiles().cloned(), + profiles: Profiles::all(ws)?, }) } @@ -67,8 +67,7 @@ pub struct ExportInfo { version: u32, workspace_root: PathBuf, metadata: Option, - #[serde(skip_serializing_if = "Option::is_none")] - profiles: Option, + profiles: HashMap, } #[derive(Serialize)] diff --git a/tests/testsuite/alt_registry.rs b/tests/testsuite/alt_registry.rs index 91157cd5327c..d419be82996c 100644 --- a/tests/testsuite/alt_registry.rs +++ b/tests/testsuite/alt_registry.rs @@ -6,6 +6,8 @@ use cargo_test_support::registry::{self, Package, RegistryBuilder}; use cargo_test_support::{basic_manifest, paths, project}; use std::fs; +use crate::metadata::DEFAULT_PROFILES; + #[cargo_test] fn depend_on_alt_registry() { registry::alt_init(); @@ -844,7 +846,7 @@ fn alt_reg_metadata() { // iodep -> altdep2: alternative-registry p.cargo("metadata --format-version=1 --no-deps") .with_json( - r#" + &r#" { "packages": [ { @@ -909,15 +911,17 @@ fn alt_reg_metadata() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); // --no-deps uses a different code path, make sure both work. p.cargo("metadata --format-version=1") .with_json( - r#" + &r#" { "packages": [ { @@ -1112,8 +1116,10 @@ fn alt_reg_metadata() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -1160,7 +1166,7 @@ fn unknown_registry() { // bar -> baz registry = alternate p.cargo("metadata --format-version=1") .with_json( - r#" + &r#" { "packages": [ { @@ -1278,9 +1284,11 @@ fn unknown_registry() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } diff --git a/tests/testsuite/features_namespaced.rs b/tests/testsuite/features_namespaced.rs index f24186c1591e..299bada38001 100644 --- a/tests/testsuite/features_namespaced.rs +++ b/tests/testsuite/features_namespaced.rs @@ -1,5 +1,7 @@ //! Tests for namespaced features. +use crate::metadata::DEFAULT_PROFILES; + use super::features2::switch_to_resolver_2; use cargo_test_support::registry::{Dependency, Package, RegistryBuilder}; use cargo_test_support::{project, publish}; @@ -576,7 +578,7 @@ fn json_exposed() { p.cargo("metadata --no-deps") .with_json( - r#" + &r#" { "packages": [ { @@ -614,9 +616,11 @@ fn json_exposed() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index 7ed9b546cdeb..d285f87ef81e 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -15,6 +15,8 @@ use cargo_test_support::registry::Package; use cargo_test_support::{basic_lib_manifest, basic_manifest, git, main_file, path2url, project}; use cargo_test_support::{sleep_ms, t, Project}; +use crate::metadata::DEFAULT_PROFILES; + #[cargo_test] fn cargo_compile_simple_git_dep() { let project = project(); @@ -3370,11 +3372,13 @@ fn metadata_master_consistency() { "target_directory": "[..]", "version": 1, "workspace_root": "[..]", - "metadata": null + "metadata": null, + "profiles": $PROFILES } "# .replace("__BAR_SOURCE__", bar_source) .replace("__BAR_HASH__", &bar_hash) + .replace("$PROFILES", DEFAULT_PROFILES) }; let bar_source = format!("git+{}?branch=master", git_project.url()); diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index 9b9b2f0263a4..5194ba86c2a2 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -6,6 +6,64 @@ use cargo_test_support::registry::Package; use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, main_file, project, rustc_host}; use serde_json::json; +pub(crate) const DEFAULT_PROFILES: &str = r#"{ + "bench": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "bench", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false + }, + "dev": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, + "doc": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "doc", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, + "release": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "release", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false + }, + "test": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "test", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + } +}"#; + #[cargo_test] fn cargo_metadata_simple() { let p = project() @@ -15,7 +73,7 @@ fn cargo_metadata_simple() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -80,8 +138,10 @@ fn cargo_metadata_simple() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -117,7 +177,7 @@ crate-type = ["lib", "staticlib"] p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -180,8 +240,10 @@ crate-type = ["lib", "staticlib"] "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -207,7 +269,7 @@ optional_feat = [] p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -277,8 +339,10 @@ optional_feat = [] "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -313,7 +377,7 @@ fn cargo_metadata_with_deps_and_version() { p.cargo("metadata -q --format-version 1") .with_json( - r#" + &r#" { "packages": [ { @@ -594,8 +658,10 @@ fn cargo_metadata_with_deps_and_version() { "foo 0.5.0 (path+file:[..]foo)" ], "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -620,7 +686,7 @@ name = "ex" p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -691,8 +757,10 @@ name = "ex" "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -718,7 +786,7 @@ crate-type = ["rlib", "dylib"] p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -789,8 +857,10 @@ crate-type = ["rlib", "dylib"] "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -821,7 +891,7 @@ fn workspace_metadata() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -931,8 +1001,10 @@ fn workspace_metadata() { "foo": { "bar": 3 } - } - }"#, + }, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -972,7 +1044,7 @@ fn workspace_metadata_with_dependencies_no_deps() { p.cargo("metadata --no-deps -Z bindeps") .masquerade_as_nightly_cargo(&["bindeps"]) .with_json( - r#" + &r#" { "packages": [ { @@ -1145,8 +1217,10 @@ fn workspace_metadata_with_dependencies_no_deps() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -1240,7 +1314,7 @@ fn workspace_metadata_with_dependencies_and_resolve() { p.cargo("metadata -Z bindeps") .masquerade_as_nightly_cargo(&["bindeps"]) .with_json( - r#" + &r#" { "metadata": null, "packages": [ @@ -1779,9 +1853,11 @@ fn workspace_metadata_with_dependencies_and_resolve() { "bin-only-artifact 0.5.0 (path+file://[..]/foo/bin-only-artifact)", "non-artifact 0.5.0 (path+file://[..]/foo/non-artifact)" ], - "workspace_root": "[..]/foo" + "workspace_root": "[..]/foo", + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -1991,7 +2067,8 @@ const MANIFEST_OUTPUT: &str = r#" "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES }"#; #[cargo_test] @@ -2003,7 +2080,7 @@ fn cargo_metadata_no_deps_path_to_cargo_toml_relative() { p.cargo("metadata --no-deps --manifest-path foo/Cargo.toml") .cwd(p.root().parent().unwrap()) - .with_json(MANIFEST_OUTPUT) + .with_json(&MANIFEST_OUTPUT.replace("$PROFILES", DEFAULT_PROFILES)) .run(); } @@ -2017,7 +2094,7 @@ fn cargo_metadata_no_deps_path_to_cargo_toml_absolute() { p.cargo("metadata --no-deps --manifest-path") .arg(p.root().join("Cargo.toml")) .cwd(p.root().parent().unwrap()) - .with_json(MANIFEST_OUTPUT) + .with_json(&MANIFEST_OUTPUT.replace("$PROFILES", DEFAULT_PROFILES)) .run(); } @@ -2064,7 +2141,7 @@ fn cargo_metadata_no_deps_cwd() { .build(); p.cargo("metadata --no-deps") - .with_json(MANIFEST_OUTPUT) + .with_json(&MANIFEST_OUTPUT.replace("$PROFILES", DEFAULT_PROFILES)) .run(); } @@ -2135,7 +2212,7 @@ fn package_metadata() { p.cargo("metadata --no-deps") .with_json( - r#" + &r#" { "packages": [ { @@ -2186,8 +2263,10 @@ fn package_metadata() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2215,7 +2294,7 @@ fn package_publish() { p.cargo("metadata --no-deps") .with_json( - r#" + &r#" { "packages": [ { @@ -2262,8 +2341,10 @@ fn package_publish() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null - }"#, + "metadata": null, + "profiles": $PROFILES + }"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2290,7 +2371,7 @@ fn cargo_metadata_path_to_cargo_toml_project() { p.cargo("metadata --manifest-path") .arg(p.root().join("target/package/bar-0.5.0/Cargo.toml")) .with_json( - r#" + &r#" { "packages": [ { @@ -2357,9 +2438,11 @@ fn cargo_metadata_path_to_cargo_toml_project() { "bar 0.5.0 (path+file:[..])" ], "workspace_root": "[..]", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2381,7 +2464,7 @@ fn package_edition_2018() { .build(); p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -2448,9 +2531,11 @@ fn package_edition_2018() { "foo 0.1.0 (path+file:[..])" ], "workspace_root": "[..]", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2518,7 +2603,7 @@ fn target_edition_2018() { .build(); p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -2599,9 +2684,11 @@ fn target_edition_2018() { "foo 0.1.0 (path+file:[..])" ], "workspace_root": "[..]", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2630,7 +2717,7 @@ fn rename_dependency() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -2838,8 +2925,10 @@ fn rename_dependency() { "foo 0.0.1[..]" ], "workspace_root": "[..]", - "metadata": null -}"#, + "metadata": null, + "profiles": $PROFILES +}"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -2862,7 +2951,7 @@ fn metadata_links() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -2941,9 +3030,11 @@ fn metadata_links() { "foo 0.5.0 [..]" ], "workspace_root": "[..]/foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run() } @@ -2968,7 +3059,7 @@ fn deps_with_bin_only() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -3047,9 +3138,11 @@ fn deps_with_bin_only() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -3499,7 +3592,8 @@ fn filter_platform() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } "# .replace("$ALT_TRIPLE", alt_target) @@ -3508,7 +3602,8 @@ fn filter_platform() { .replace("$CFG_DEP", cfg_dep) .replace("$HOST_DEP", host_dep) .replace("$NORMAL_DEP", normal_dep) - .replace("$FOO", &foo), + .replace("$FOO", &foo) + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); clear(); @@ -3585,13 +3680,15 @@ fn filter_platform() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } "# .replace("$ALT_TRIPLE", alt_target) .replace("$ALT_DEP", alt_dep) .replace("$NORMAL_DEP", normal_dep) - .replace("$FOO", &foo), + .replace("$FOO", &foo) + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); clear(); @@ -3667,13 +3764,15 @@ fn filter_platform() { "target_directory": "[..]foo/target", "version": 1, "workspace_root": "[..]foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } "# .replace("$HOST_TRIPLE", host_target) .replace("$HOST_DEP", host_dep) .replace("$NORMAL_DEP", normal_dep) - .replace("$FOO", &foo), + .replace("$FOO", &foo) + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); clear(); @@ -3769,14 +3868,16 @@ fn filter_platform() { "target_directory": "[..]/foo/target", "version": 1, "workspace_root": "[..]/foo", - "metadata": null + "metadata": null, + "profiles": $PROFILES } "# .replace("$HOST_TRIPLE", host_target) .replace("$CFG_DEP", cfg_dep) .replace("$HOST_DEP", host_dep) .replace("$NORMAL_DEP", normal_dep) - .replace("$FOO", &foo), + .replace("$FOO", &foo) + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -3812,7 +3913,7 @@ fn dep_kinds() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": "{...}", "workspace_members": "{...}", @@ -3821,6 +3922,7 @@ fn dep_kinds() { "version": 1, "workspace_root": "{...}", "metadata": null, + "profiles": $PROFILES, "resolve": { "nodes": [ { @@ -3877,7 +3979,8 @@ fn dep_kinds() { "root": "foo 0.1.0 [..]" } } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -3928,7 +4031,7 @@ fn dep_kinds_workspace() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": "{...}", "workspace_members": "{...}", @@ -3937,6 +4040,7 @@ fn dep_kinds_workspace() { "version": 1, "workspace_root": "[..]/foo", "metadata": null, + "profiles": $PROFILES, "resolve": { "nodes": [ { @@ -3989,7 +4093,8 @@ fn dep_kinds_workspace() { "root": "foo 0.1.0 (path+file://[..]/foo)" } } - "#, + "# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } @@ -4057,9 +4162,10 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() { p.cargo("metadata --no-deps -Z bindeps") .masquerade_as_nightly_cargo(&["bindeps"]) .with_json( - r#" + &r#" { "metadata": null, + "profiles": $PROFILES, "packages": [ { "authors": [ @@ -4253,11 +4359,84 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() { ], "workspace_root": "[..]/foo" } -"#, +"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run(); } +const CUSTOM_PROFILES: &str = r#"{ + "bench": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "bench", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false, + "strip": "symbols" + }, + "custom-lto": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "thin", + "name": "custom-lto", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false, + "strip": "symbols" + }, + "dev": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, + "doc": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "doc", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, + "release": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "release", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false, + "strip": "symbols" + }, + "test": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "test", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + } +}"#; + #[cargo_test] fn library_metadata_with_profiles() { let p = project() @@ -4273,6 +4452,7 @@ version = "0.5.0" strip = "symbols" [profile.custom-lto] +inherits = "release" lto = "thin" "#, ) @@ -4280,7 +4460,7 @@ lto = "thin" p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -4342,15 +4522,9 @@ lto = "thin" "version": 1, "workspace_root": "[..]/foo", "metadata": null, - "profiles": { - "custom-lto": { - "lto": "thin" - }, - "release": { - "strip": "symbols" - } - } - }"#, + "profiles": $PROFILES + }"# + .replace("$PROFILES", CUSTOM_PROFILES), ) .run(); } @@ -4368,6 +4542,7 @@ fn workspace_metadata_with_profiles() { strip = "symbols" [profile.custom-lto] + inherits = "release" lto = "thin" "#, ) @@ -4379,7 +4554,7 @@ fn workspace_metadata_with_profiles() { p.cargo("metadata") .with_json( - r#" + &r#" { "packages": [ { @@ -4484,15 +4659,8 @@ fn workspace_metadata_with_profiles() { "version": 1, "workspace_root": "[..]/foo", "metadata": null, - "profiles": { - "custom-lto": { - "lto": "thin" - }, - "release": { - "strip": "symbols" - } - } - }"#, + "profiles": $PROFILES + }"#.replace("$PROFILES", CUSTOM_PROFILES) ) .run(); } diff --git a/tests/testsuite/script.rs b/tests/testsuite/script.rs index ce4013f9a37c..7d2b1e94c610 100644 --- a/tests/testsuite/script.rs +++ b/tests/testsuite/script.rs @@ -1082,8 +1082,62 @@ fn cmd_metadata_with_embedded() { "workspace_root": "[..]/foo", "metadata": null, "profiles": { + "bench": { + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "bench", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false, + "strip": "symbols" + }, + "dev": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, + "doc": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "doc", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false + }, "release": { - "strip": true + "debug_assertions": false, + "debuginfo": 0, + "incremental": false, + "lto": "false", + "name": "release", + "opt_level": "3", + "overflow_checks": false, + "panic": "unwind", + "rpath": false, + "strip": "symbols" + }, + "test": { + "debug_assertions": true, + "debuginfo": 2, + "incremental": true, + "lto": "false", + "name": "test", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false } } }"#, diff --git a/tests/testsuite/unit_graph.rs b/tests/testsuite/unit_graph.rs index 91451177a516..8d1d5be03ba8 100644 --- a/tests/testsuite/unit_graph.rs +++ b/tests/testsuite/unit_graph.rs @@ -69,8 +69,6 @@ fn simple() { "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "platform": null, "profile": { - "codegen_backend": null, - "codegen_units": null, "debug_assertions": true, "debuginfo": 2, "incremental": false, @@ -79,9 +77,7 @@ fn simple() { "opt_level": "0", "overflow_checks": true, "panic": "unwind", - "rpath": false, - "split_debuginfo": "{...}", - "strip": "none" + "rpath": false }, "target": { "crate_types": [ @@ -114,8 +110,6 @@ fn simple() { "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "platform": null, "profile": { - "codegen_backend": null, - "codegen_units": null, "debug_assertions": true, "debuginfo": 2, "incremental": false, @@ -124,9 +118,7 @@ fn simple() { "opt_level": "0", "overflow_checks": true, "panic": "unwind", - "rpath": false, - "split_debuginfo": "{...}", - "strip": "none" + "rpath": false }, "target": { "crate_types": [ @@ -152,8 +144,6 @@ fn simple() { "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "platform": null, "profile": { - "codegen_backend": null, - "codegen_units": null, "debug_assertions": true, "debuginfo": 2, "incremental": false, @@ -162,9 +152,7 @@ fn simple() { "opt_level": "0", "overflow_checks": true, "panic": "unwind", - "rpath": false, - "split_debuginfo": "{...}", - "strip": "none" + "rpath": false }, "target": { "crate_types": [ @@ -195,8 +183,6 @@ fn simple() { "pkg_id": "foo 0.1.0 (path+file://[..]/foo)", "platform": null, "profile": { - "codegen_backend": null, - "codegen_units": null, "debug_assertions": true, "debuginfo": 2, "incremental": false, @@ -205,9 +191,7 @@ fn simple() { "opt_level": "0", "overflow_checks": true, "panic": "unwind", - "rpath": false, - "split_debuginfo": "{...}", - "strip": "none" + "rpath": false }, "target": { "crate_types": [ diff --git a/tests/testsuite/update.rs b/tests/testsuite/update.rs index 807072eaf6da..75bd7f706ba3 100644 --- a/tests/testsuite/update.rs +++ b/tests/testsuite/update.rs @@ -3,6 +3,8 @@ use cargo_test_support::registry::Package; use cargo_test_support::{basic_manifest, project}; +use crate::metadata::DEFAULT_PROFILES; + #[cargo_test] fn minor_update_two_places() { Package::new("log", "0.1.0").publish(); @@ -577,7 +579,7 @@ fn update_precise_first_run() { // Assert `cargo metadata` shows serde 0.2.0 p.cargo("metadata") .with_json( - r#"{ + &r#"{ "packages": [ { "authors": [], @@ -714,8 +716,10 @@ fn update_precise_first_run() { "bar 0.0.1 (path+file://[..]/foo)" ], "workspace_root": "[..]/foo", - "metadata": null -}"#, + "metadata": null, + "profiles": $PROFILES +}"# + .replace("$PROFILES", DEFAULT_PROFILES), ) .run();