Skip to content

Commit 78c108f

Browse files
committed
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 <david.calavera@gmail.com>
1 parent 0de91c8 commit 78c108f

File tree

5 files changed

+282
-3
lines changed

5 files changed

+282
-3
lines changed

src/cargo/core/package.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::util::network::http::http_handle_and_timeout;
3131
use crate::util::network::http::HttpTimeout;
3232
use crate::util::network::retry::{Retry, RetryResult};
3333
use crate::util::network::sleep::SleepTracker;
34+
use crate::util::toml::TomlProfiles;
3435
use crate::util::PartialVersion;
3536
use crate::util::{self, internal, Config, Progress, ProgressStyle};
3637

@@ -105,6 +106,8 @@ pub struct SerializedPackage {
105106
metabuild: Option<Vec<String>>,
106107
default_run: Option<String>,
107108
rust_version: Option<PartialVersion>,
109+
#[serde(skip_serializing_if = "Option::is_none")]
110+
profiles: Option<TomlProfiles>,
108111
}
109112

110113
impl Package {
@@ -264,6 +267,7 @@ impl Package {
264267
publish: self.publish().as_ref().cloned(),
265268
default_run: self.manifest().default_run().map(|s| s.to_owned()),
266269
rust_version: self.rust_version(),
270+
profiles: self.manifest().profiles().cloned(),
267271
}
268272
}
269273
}

src/cargo/ops/cargo_output_metadata.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use crate::core::compiler::{CompileKind, RustcTargetData};
33
use crate::core::dependency::DepKind;
44
use crate::core::package::SerializedPackage;
55
use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve};
6-
use crate::core::{Package, PackageId, Workspace};
6+
use crate::core::{MaybePackage, Package, PackageId, Workspace};
77
use crate::ops::{self, Packages};
88
use crate::util::interning::InternedString;
9+
use crate::util::toml::TomlProfiles;
910
use crate::util::CargoResult;
1011
use cargo_platform::Platform;
1112
use serde::Serialize;
@@ -40,6 +41,11 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
4041
(packages, Some(resolve))
4142
};
4243

44+
let workspace_profiles = match ws.root_maybe() {
45+
MaybePackage::Virtual(vm) => vm.profiles().cloned(),
46+
_ => None, // regular packages include the profile information under their package section
47+
};
48+
4349
Ok(ExportInfo {
4450
packages,
4551
workspace_members: ws.members().map(|pkg| pkg.package_id()).collect(),
@@ -49,6 +55,7 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
4955
version: VERSION,
5056
workspace_root: ws.root().to_path_buf(),
5157
metadata: ws.custom_metadata().cloned(),
58+
workspace_profiles,
5259
})
5360
}
5461

@@ -65,6 +72,8 @@ pub struct ExportInfo {
6572
version: u32,
6673
workspace_root: PathBuf,
6774
metadata: Option<toml::Value>,
75+
#[serde(skip_serializing_if = "Option::is_none")]
76+
workspace_profiles: Option<TomlProfiles>,
6877
}
6978

7079
#[derive(Serialize)]

src/cargo/util/toml/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,25 +499,42 @@ impl Display for TomlDebugInfo {
499499
#[derive(Deserialize, Serialize, Clone, Debug, Default, Eq, PartialEq)]
500500
#[serde(default, rename_all = "kebab-case")]
501501
pub struct TomlProfile {
502+
#[serde(skip_serializing_if = "Option::is_none")]
502503
pub opt_level: Option<TomlOptLevel>,
504+
#[serde(skip_serializing_if = "Option::is_none")]
503505
pub lto: Option<StringOrBool>,
506+
#[serde(skip_serializing_if = "Option::is_none")]
504507
pub codegen_backend: Option<InternedString>,
508+
#[serde(skip_serializing_if = "Option::is_none")]
505509
pub codegen_units: Option<u32>,
510+
#[serde(skip_serializing_if = "Option::is_none")]
506511
pub debug: Option<TomlDebugInfo>,
512+
#[serde(skip_serializing_if = "Option::is_none")]
507513
pub split_debuginfo: Option<String>,
514+
#[serde(skip_serializing_if = "Option::is_none")]
508515
pub debug_assertions: Option<bool>,
516+
#[serde(skip_serializing_if = "Option::is_none")]
509517
pub rpath: Option<bool>,
518+
#[serde(skip_serializing_if = "Option::is_none")]
510519
pub panic: Option<String>,
520+
#[serde(skip_serializing_if = "Option::is_none")]
511521
pub overflow_checks: Option<bool>,
522+
#[serde(skip_serializing_if = "Option::is_none")]
512523
pub incremental: Option<bool>,
524+
#[serde(skip_serializing_if = "Option::is_none")]
513525
pub dir_name: Option<InternedString>,
526+
#[serde(skip_serializing_if = "Option::is_none")]
514527
pub inherits: Option<InternedString>,
528+
#[serde(skip_serializing_if = "Option::is_none")]
515529
pub strip: Option<StringOrBool>,
516530
// Note that `rustflags` is used for the cargo-feature `profile_rustflags`
531+
#[serde(skip_serializing_if = "Option::is_none")]
517532
pub rustflags: Option<Vec<InternedString>>,
518533
// These two fields must be last because they are sub-tables, and TOML
519534
// requires all non-tables to be listed first.
535+
#[serde(skip_serializing_if = "Option::is_none")]
520536
pub package: Option<BTreeMap<ProfilePackageSpec, TomlProfile>>,
537+
#[serde(skip_serializing_if = "Option::is_none")]
521538
pub build_override: Option<Box<TomlProfile>>,
522539
}
523540

tests/testsuite/metadata.rs

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4257,3 +4257,242 @@ fn workspace_metadata_with_dependencies_no_deps_artifact() {
42574257
)
42584258
.run();
42594259
}
4260+
4261+
#[cargo_test]
4262+
fn library_metadata_with_profiles() {
4263+
let p = project()
4264+
.file("src/lib.rs", "")
4265+
.file(
4266+
"Cargo.toml",
4267+
r#"
4268+
[package]
4269+
name = "foo"
4270+
version = "0.5.0"
4271+
4272+
[profile.release]
4273+
strip = "symbols"
4274+
4275+
[profile.custom-lto]
4276+
lto = "thin"
4277+
"#,
4278+
)
4279+
.build();
4280+
4281+
p.cargo("metadata")
4282+
.with_json(
4283+
r#"
4284+
{
4285+
"packages": [
4286+
{
4287+
"authors": [],
4288+
"categories": [],
4289+
"default_run": null,
4290+
"name": "foo",
4291+
"readme": null,
4292+
"repository": null,
4293+
"homepage": null,
4294+
"documentation": null,
4295+
"version": "0.5.0",
4296+
"rust_version": null,
4297+
"id": "foo[..]",
4298+
"keywords": [],
4299+
"source": null,
4300+
"dependencies": [],
4301+
"edition": "2015",
4302+
"license": null,
4303+
"license_file": null,
4304+
"links": null,
4305+
"description": null,
4306+
"targets": [
4307+
{
4308+
"kind": [
4309+
"lib"
4310+
],
4311+
"crate_types": [
4312+
"lib"
4313+
],
4314+
"doc": true,
4315+
"doctest": true,
4316+
"test": true,
4317+
"edition": "2015",
4318+
"name": "foo",
4319+
"src_path": "[..]/foo/src/lib.rs"
4320+
}
4321+
],
4322+
"features": {},
4323+
"manifest_path": "[..]Cargo.toml",
4324+
"metadata": null,
4325+
"publish": null,
4326+
"profiles": {
4327+
"custom-lto": {
4328+
"lto": "thin"
4329+
},
4330+
"release": {
4331+
"strip": "symbols"
4332+
}
4333+
}
4334+
}
4335+
],
4336+
"workspace_members": ["foo 0.5.0 (path+file:[..]foo)"],
4337+
"workspace_default_members": ["foo 0.5.0 (path+file:[..]foo)"],
4338+
"resolve": {
4339+
"nodes": [
4340+
{
4341+
"dependencies": [],
4342+
"deps": [],
4343+
"features": [],
4344+
"id": "foo 0.5.0 (path+file:[..]foo)"
4345+
}
4346+
],
4347+
"root": "foo 0.5.0 (path+file:[..]foo)"
4348+
},
4349+
"target_directory": "[..]foo/target",
4350+
"version": 1,
4351+
"workspace_root": "[..]/foo",
4352+
"metadata": null
4353+
}"#,
4354+
)
4355+
.run();
4356+
}
4357+
4358+
#[cargo_test]
4359+
fn workspace_metadata_with_profiles() {
4360+
let p = project()
4361+
.file(
4362+
"Cargo.toml",
4363+
r#"
4364+
[workspace]
4365+
members = ["bar", "baz"]
4366+
4367+
[profile.release]
4368+
strip = "symbols"
4369+
4370+
[profile.custom-lto]
4371+
lto = "thin"
4372+
"#,
4373+
)
4374+
.file("bar/Cargo.toml", &basic_lib_manifest("bar"))
4375+
.file("bar/src/lib.rs", "")
4376+
.file("baz/Cargo.toml", &basic_lib_manifest("baz"))
4377+
.file("baz/src/lib.rs", "")
4378+
.build();
4379+
4380+
p.cargo("metadata")
4381+
.with_json(
4382+
r#"
4383+
{
4384+
"packages": [
4385+
{
4386+
"authors": [
4387+
"wycats@example.com"
4388+
],
4389+
"categories": [],
4390+
"default_run": null,
4391+
"name": "bar",
4392+
"version": "0.5.0",
4393+
"id": "bar[..]",
4394+
"readme": null,
4395+
"repository": null,
4396+
"rust_version": null,
4397+
"homepage": null,
4398+
"documentation": null,
4399+
"keywords": [],
4400+
"source": null,
4401+
"dependencies": [],
4402+
"license": null,
4403+
"license_file": null,
4404+
"links": null,
4405+
"description": null,
4406+
"edition": "2015",
4407+
"targets": [
4408+
{
4409+
"kind": [ "lib" ],
4410+
"crate_types": [ "lib" ],
4411+
"doc": true,
4412+
"doctest": true,
4413+
"test": true,
4414+
"edition": "2015",
4415+
"name": "bar",
4416+
"src_path": "[..]bar/src/lib.rs"
4417+
}
4418+
],
4419+
"features": {},
4420+
"manifest_path": "[..]bar/Cargo.toml",
4421+
"metadata": null,
4422+
"publish": null
4423+
},
4424+
{
4425+
"authors": [
4426+
"wycats@example.com"
4427+
],
4428+
"categories": [],
4429+
"default_run": null,
4430+
"name": "baz",
4431+
"readme": null,
4432+
"repository": null,
4433+
"rust_version": null,
4434+
"homepage": null,
4435+
"documentation": null,
4436+
"version": "0.5.0",
4437+
"id": "baz[..]",
4438+
"keywords": [],
4439+
"source": null,
4440+
"dependencies": [],
4441+
"license": null,
4442+
"license_file": null,
4443+
"links": null,
4444+
"description": null,
4445+
"edition": "2015",
4446+
"targets": [
4447+
{
4448+
"kind": [ "lib" ],
4449+
"crate_types": [ "lib" ],
4450+
"doc": true,
4451+
"doctest": true,
4452+
"test": true,
4453+
"edition": "2015",
4454+
"name": "baz",
4455+
"src_path": "[..]baz/src/lib.rs"
4456+
}
4457+
],
4458+
"features": {},
4459+
"manifest_path": "[..]baz/Cargo.toml",
4460+
"metadata": null,
4461+
"publish": null
4462+
}
4463+
],
4464+
"workspace_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"],
4465+
"workspace_default_members": ["bar 0.5.0 (path+file:[..]bar)", "baz 0.5.0 (path+file:[..]baz)"],
4466+
"resolve": {
4467+
"nodes": [
4468+
{
4469+
"dependencies": [],
4470+
"deps": [],
4471+
"features": [],
4472+
"id": "bar 0.5.0 (path+file:[..]bar)"
4473+
},
4474+
{
4475+
"dependencies": [],
4476+
"deps": [],
4477+
"features": [],
4478+
"id": "baz 0.5.0 (path+file:[..]baz)"
4479+
}
4480+
],
4481+
"root": null
4482+
},
4483+
"target_directory": "[..]foo/target",
4484+
"version": 1,
4485+
"workspace_root": "[..]/foo",
4486+
"metadata": null,
4487+
"workspace_profiles": {
4488+
"custom-lto": {
4489+
"lto": "thin"
4490+
},
4491+
"release": {
4492+
"strip": "symbols"
4493+
}
4494+
}
4495+
}"#,
4496+
)
4497+
.run();
4498+
}

tests/testsuite/script.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,12 @@ fn cmd_metadata_with_embedded() {
10611061
"features": {},
10621062
"manifest_path": "[..]script.rs",
10631063
"metadata": null,
1064-
"publish": []
1064+
"publish": [],
1065+
"profiles": {
1066+
"release": {
1067+
"strip": true
1068+
}
1069+
}
10651070
}
10661071
],
10671072
"workspace_members": ["script 0.0.0 (path+file:[..]foo)"],
@@ -1136,7 +1141,12 @@ fn cmd_read_manifest_with_embedded() {
11361141
"features":{},
11371142
"manifest_path":"[..]script.rs",
11381143
"metadata": null,
1139-
"publish": []
1144+
"publish": [],
1145+
"profiles": {
1146+
"release": {
1147+
"strip": true
1148+
}
1149+
}
11401150
}"#,
11411151
)
11421152
.with_stderr(

0 commit comments

Comments
 (0)