Skip to content

Commit e04e0b6

Browse files
authored
feat(unstable): add -Zbuild-analysis unstable feature (#15845)
### What does this PR try to resolve? Part of #15844 Set up `-Zbuild-analysis` flag and `build.analysis` configuration table to lay the ground work. when `build.analysis.enabled = true`, enables HTML timing output to pretend we are persisting timing data for now. This will change when the storage part is implemented. ### How to test and review this PR?
2 parents a22a25b + 4373786 commit e04e0b6

File tree

7 files changed

+130
-42
lines changed

7 files changed

+130
-42
lines changed

src/cargo/core/compiler/build_config.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ impl BuildConfig {
115115
(None, _) => false,
116116
};
117117

118+
let timing_outputs = match (cfg.analysis.as_ref(), gctx.cli_unstable().build_analysis) {
119+
// Enable HTML output to pretend we are persisting timing data for now.
120+
(Some(analysis), true) if analysis.enabled => vec![TimingOutput::Html],
121+
(Some(_), false) => {
122+
gctx.shell().warn(
123+
"ignoring 'build.analysis' config, pass `-Zbuild-analysis` to enable it",
124+
)?;
125+
Vec::new()
126+
}
127+
_ => Vec::new(),
128+
};
129+
118130
Ok(BuildConfig {
119131
requested_kinds,
120132
jobs,
@@ -130,7 +142,7 @@ impl BuildConfig {
130142
rustfix_diagnostic_server: Rc::new(RefCell::new(None)),
131143
export_dir: None,
132144
future_incompat_report: false,
133-
timing_outputs: Vec::new(),
145+
timing_outputs,
134146
sbom,
135147
compile_time_deps_only: false,
136148
})

src/cargo/core/features.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ unstable_cli_options!(
844844
avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"),
845845
binary_dep_depinfo: bool = ("Track changes to dependency artifacts"),
846846
bindeps: bool = ("Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates"),
847+
build_analysis: bool = ("Record and persist build metrics across runs, with commands to query past builds."),
847848
#[serde(deserialize_with = "deserialize_comma_separated_list")]
848849
build_std: Option<Vec<String>> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"),
849850
#[serde(deserialize_with = "deserialize_comma_separated_list")]
@@ -1363,6 +1364,7 @@ impl CliUnstable {
13631364
"avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?,
13641365
"binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?,
13651366
"bindeps" => self.bindeps = parse_empty(k, v)?,
1367+
"build-analysis" => self.build_analysis = parse_empty(k, v)?,
13661368
"build-std" => self.build_std = Some(parse_list(v)),
13671369
"build-std-features" => self.build_std_features = Some(parse_list(v)),
13681370
"cargo-lints" => self.cargo_lints = parse_empty(k, v)?,

src/cargo/util/context/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,6 +2768,15 @@ pub struct CargoBuildConfig {
27682768
pub warnings: Option<WarningHandling>,
27692769
/// Unstable feature `-Zsbom`.
27702770
pub sbom: Option<bool>,
2771+
/// Unstable feature `-Zbuild-analysis`.
2772+
pub analysis: Option<CargoBuildAnalysis>,
2773+
}
2774+
2775+
/// Metrics collection for build analysis.
2776+
#[derive(Debug, Deserialize, Default)]
2777+
#[serde(rename_all = "kebab-case")]
2778+
pub struct CargoBuildAnalysis {
2779+
pub enabled: bool,
27712780
}
27722781

27732782
/// Whether warnings should warn, be allowed, or cause an error.

src/doc/src/reference/unstable.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ Each new feature described below should explain how to use it.
113113
* [Build-plan](#build-plan) --- Emits JSON information on which commands will be run.
114114
* [unit-graph](#unit-graph) --- Emits JSON for Cargo's internal graph structure.
115115
* [`cargo rustc --print`](#rustc---print) --- Calls rustc with `--print` to display information from rustc.
116+
* [Build analysis](#build-analysis) --- Record and persist detailed build metrics across runs, with new commands to query past builds.
116117
* Configuration
117118
* [config-include](#config-include) --- Adds the ability for config files to include other files.
118119
* [`cargo config`](#cargo-config) --- Adds a new subcommand for viewing config files.
@@ -1922,6 +1923,22 @@ HTML/JSON output.
19221923
cargo +nightly -Zsection-timings build --timings
19231924
```
19241925

1926+
## Build analysis
1927+
1928+
* Original Issue: [rust-lang/rust-project-goals#332](https://github.com/rust-lang/rust-project-goals/pull/332)
1929+
* Tracking Issue: [#15844](https://github.com/rust-lang/cargo/issues/15844)
1930+
1931+
The `-Zbuild-analysis` feature records and persists detailed build metrics
1932+
(timings, rebuild reasons, etc.) across runs, with new commands to query past builds.
1933+
1934+
```toml
1935+
# Example config.toml file.
1936+
1937+
# Enable the build metric collection
1938+
[build.analysis]
1939+
enabled = true
1940+
```
1941+
19251942
# Stabilized and removed features
19261943

19271944
## Compile progress

tests/testsuite/build_analysis.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//! Tests for `-Zbuild-analysis`.
2+
3+
use crate::prelude::*;
4+
5+
use cargo_test_support::basic_manifest;
6+
use cargo_test_support::project;
7+
use cargo_test_support::str;
8+
9+
#[cargo_test]
10+
fn gated() {
11+
let p = project()
12+
.file("Cargo.toml", &basic_manifest("foo", "0.0.0"))
13+
.file("src/lib.rs", "")
14+
.build();
15+
16+
p.cargo("check")
17+
.env("CARGO_BUILD_ANALYSIS_ENABLED", "true")
18+
.masquerade_as_nightly_cargo(&["build-analysis"])
19+
.with_stderr_data(str![[r#"
20+
[WARNING] ignoring 'build.analysis' config, pass `-Zbuild-analysis` to enable it
21+
[CHECKING] foo v0.0.0 ([ROOT]/foo)
22+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
23+
24+
"#]])
25+
.run();
26+
}
27+
28+
#[cargo_test]
29+
fn simple() {
30+
let p = project()
31+
.file("Cargo.toml", &basic_manifest("foo", "0.0.0"))
32+
.file("src/lib.rs", "")
33+
.build();
34+
35+
p.cargo("check -Zbuild-analysis")
36+
.env("CARGO_BUILD_ANALYSIS_ENABLED", "true")
37+
.masquerade_as_nightly_cargo(&["build-analysis"])
38+
.with_stderr_data(str![[r#"
39+
[CHECKING] foo v0.0.0 ([ROOT]/foo)
40+
Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..].html
41+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
42+
43+
"#]])
44+
.run();
45+
}

tests/testsuite/cargo/z_help/stdout.term.svg

Lines changed: 43 additions & 41 deletions
Loading

tests/testsuite/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod bad_manifest_path;
1111
mod bench;
1212
mod binary_name;
1313
mod build;
14+
mod build_analysis;
1415
mod build_dir;
1516
mod build_plan;
1617
mod build_script;

0 commit comments

Comments
 (0)