From 18c4f9865447f622eb3f81c796b6619f94c3926e Mon Sep 17 00:00:00 2001 From: David Calavera Date: Sun, 9 Jul 2023 12:46:38 -0700 Subject: [PATCH] feat(metadata): Add profiles information to `cargo metadata` This change adds profile information to the output of `cargo metadata`. I opted for serializing this information only when there is information present to minimize changes in the output. Signed-off-by: David Calavera --- src/cargo/core/package.rs | 4 + src/cargo/ops/cargo_output_metadata.rs | 11 +- src/cargo/util/toml/mod.rs | 17 ++ tests/testsuite/metadata.rs | 239 +++++++++++++++++++++++++ tests/testsuite/script.rs | 14 +- 5 files changed, 282 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 093c64d72d30..6ca94aaa5ca3 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -31,6 +31,7 @@ use crate::util::network::http::http_handle_and_timeout; use crate::util::network::http::HttpTimeout; use crate::util::network::retry::{Retry, RetryResult}; use crate::util::network::sleep::SleepTracker; +use crate::util::toml::TomlProfiles; use crate::util::{self, internal, Config, Progress, ProgressStyle}; pub const MANIFEST_PREAMBLE: &str = "\ @@ -104,6 +105,8 @@ pub struct SerializedPackage { metabuild: Option>, default_run: Option, rust_version: Option, + #[serde(skip_serializing_if = "Option::is_none")] + profiles: Option, } impl Package { @@ -263,6 +266,7 @@ impl Package { publish: self.publish().as_ref().cloned(), default_run: self.manifest().default_run().map(|s| s.to_owned()), rust_version: self.rust_version().map(|s| s.to_owned()), + profiles: self.manifest().profiles().cloned(), } } } diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index c0a63aa75a2c..9ef49af03b24 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -3,9 +3,10 @@ use crate::core::compiler::{CompileKind, RustcTargetData}; use crate::core::dependency::DepKind; use crate::core::package::SerializedPackage; use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve}; -use crate::core::{Package, PackageId, Workspace}; +use crate::core::{MaybePackage, 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; @@ -40,6 +41,11 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo (packages, Some(resolve)) }; + let workspace_profiles = match ws.root_maybe() { + MaybePackage::Virtual(vm) => vm.profiles().cloned(), + _ => None, // regular packages include the profile information under their package section + }; + Ok(ExportInfo { packages, workspace_members: ws.members().map(|pkg| pkg.package_id()).collect(), @@ -49,6 +55,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo version: VERSION, workspace_root: ws.root().to_path_buf(), metadata: ws.custom_metadata().cloned(), + workspace_profiles, }) } @@ -65,6 +72,8 @@ pub struct ExportInfo { version: u32, workspace_root: PathBuf, metadata: Option, + #[serde(skip_serializing_if = "Option::is_none")] + workspace_profiles: Option, } #[derive(Serialize)] diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 284c5dd35d15..013067934c73 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -564,25 +564,42 @@ impl Display for TomlDebugInfo { #[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)] #[serde(default, rename_all = "kebab-case")] pub struct TomlProfile { + #[serde(skip_serializing_if = "Option::is_none")] pub opt_level: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub lto: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub codegen_backend: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub codegen_units: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub debug: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub split_debuginfo: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub debug_assertions: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub rpath: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub panic: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub overflow_checks: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub incremental: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub dir_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub inherits: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub strip: Option, // Note that `rustflags` is used for the cargo-feature `profile_rustflags` + #[serde(skip_serializing_if = "Option::is_none")] pub rustflags: Option>, // These two fields must be last because they are sub-tables, and TOML // requires all non-tables to be listed first. + #[serde(skip_serializing_if = "Option::is_none")] pub package: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub build_override: Option>, } diff --git a/tests/testsuite/metadata.rs b/tests/testsuite/metadata.rs index ac2cec39661e..e38fbfb1f956 100644 --- a/tests/testsuite/metadata.rs +++ b/tests/testsuite/metadata.rs @@ -4248,3 +4248,242 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() { ) .run(); } + +#[cargo_test] +fn library_metadata_with_profiles() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.5.0" + +[profile.release] +strip = "symbols" + +[profile.custom-lto] +lto = "thin" + "#, + ) + .build(); + + p.cargo("metadata") + .with_json( + r#" + { + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "name": "foo", + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "version": "0.5.0", + "rust_version": null, + "id": "foo[..]", + "keywords": [], + "source": null, + "dependencies": [], + "edition": "2015", + "license": null, + "license_file": null, + "links": null, + "description": null, + "targets": [ + { + "kind": [ + "lib" + ], + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "test": true, + "edition": "2015", + "name": "foo", + "src_path": "[..]/foo/src/lib.rs" + } + ], + "features": {}, + "manifest_path": "[..]Cargo.toml", + "metadata": null, + "publish": null, + "profiles": { + "custom-lto": { + "lto": "thin" + }, + "release": { + "strip": "symbols" + } + } + } + ], + "workspace_members": ["foo 0.5.0 (path+file:[..]foo)"], + "workspace_default_members": ["foo 0.5.0 (path+file:[..]foo)"], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "foo 0.5.0 (path+file:[..]foo)" + } + ], + "root": "foo 0.5.0 (path+file:[..]foo)" + }, + "target_directory": "[..]foo/target", + "version": 1, + "workspace_root": "[..]/foo", + "metadata": null + }"#, + ) + .run(); +} + +#[cargo_test] +fn workspace_metadata_with_profiles() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + + [profile.release] + strip = "symbols" + + [profile.custom-lto] + lto = "thin" + "#, + ) + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_json( + r#" + { + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "name": "bar", + "version": "0.5.0", + "id": "bar[..]", + "readme": null, + "repository": null, + "rust_version": null, + "homepage": null, + "documentation": null, + "keywords": [], + "source": null, + "dependencies": [], + "license": null, + "license_file": null, + "links": null, + "description": null, + "edition": "2015", + "targets": [ + { + "kind": [ "lib" ], + "crate_types": [ "lib" ], + "doc": true, + "doctest": true, + "test": true, + "edition": "2015", + "name": "bar", + "src_path": "[..]bar/src/lib.rs" + } + ], + "features": {}, + "manifest_path": "[..]bar/Cargo.toml", + "metadata": null, + "publish": null + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "name": "baz", + "readme": null, + "repository": null, + "rust_version": null, + "homepage": null, + "documentation": null, + "version": "0.5.0", + "id": "baz[..]", + "keywords": [], + "source": null, + "dependencies": [], + "license": null, + "license_file": null, + "links": null, + "description": null, + "edition": "2015", + "targets": [ + { + "kind": [ "lib" ], + "crate_types": [ "lib" ], + "doc": true, + "doctest": true, + "test": true, + "edition": "2015", + "name": "baz", + "src_path": "[..]baz/src/lib.rs" + } + ], + "features": {}, + "manifest_path": "[..]baz/Cargo.toml", + "metadata": null, + "publish": null + } + ], + "workspace_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"], + "workspace_default_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "bar 0.5.0 (path+file:[..]bar)" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "baz 0.5.0 (path+file:[..]baz)" + } + ], + "root": null + }, + "target_directory": "[..]foo/target", + "version": 1, + "workspace_root": "[..]/foo", + "metadata": null, + "workspace_profiles": { + "custom-lto": { + "lto": "thin" + }, + "release": { + "strip": "symbols" + } + } + }"#, + ) + .run(); +} diff --git a/tests/testsuite/script.rs b/tests/testsuite/script.rs index 0c0441d625af..663f5c3b72ae 100644 --- a/tests/testsuite/script.rs +++ b/tests/testsuite/script.rs @@ -1061,7 +1061,12 @@ fn cmd_metadata_with_embedded() { "features": {}, "manifest_path": "[..]script.rs", "metadata": null, - "publish": [] + "publish": [], + "profiles": { + "release": { + "strip": true + } + } } ], "workspace_members": ["script 0.0.0 (path+file:[..]foo)"], @@ -1136,7 +1141,12 @@ fn cmd_read_manifest_with_embedded() { "features":{}, "manifest_path":"[..]script.rs", "metadata": null, - "publish": [] + "publish": [], + "profiles": { + "release": { + "strip": true + } + } }"#, ) .with_stderr(