diff --git a/src/cargo/core/compiler/fingerprint/mod.rs b/src/cargo/core/compiler/fingerprint/mod.rs index 379bab0b159..f30bab0ea3f 100644 --- a/src/cargo/core/compiler/fingerprint/mod.rs +++ b/src/cargo/core/compiler/fingerprint/mod.rs @@ -1494,7 +1494,9 @@ fn calculate_normal( // Afterwards calculate our own fingerprint information. let build_root = build_root(build_runner); - let local = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + let is_any_doc_gen = unit.mode.is_doc() || unit.mode.is_doc_scrape(); + let rustdoc_depinfo_enabled = build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo; + let local = if is_any_doc_gen && !rustdoc_depinfo_enabled { // rustdoc does not have dep-info files. let fingerprint = pkg_fingerprint(build_runner.bcx, &unit.pkg).with_context(|| { format!( diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 3ec3b74ba93..7825a30fe1b 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -763,6 +763,19 @@ fn prepare_rustdoc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResu add_error_format_and_color(build_runner, &mut rustdoc); add_allow_features(build_runner, &mut rustdoc); + if build_runner.bcx.gctx.cli_unstable().rustdoc_depinfo { + // invocation-specific is required for keeping the original rustdoc emission + let mut arg = OsString::from("--emit=invocation-specific,dep-info="); + arg.push(rustdoc_dep_info_loc(build_runner, unit)); + rustdoc.arg(arg); + + if build_runner.bcx.gctx.cli_unstable().checksum_freshness { + rustdoc.arg("-Z").arg("checksum-hash-algorithm=blake3"); + } + + rustdoc.arg("-Zunstable-options"); + } + if let Some(trim_paths) = unit.profile.trim_paths.as_ref() { trim_paths_args_rustdoc(&mut rustdoc, build_runner, unit, trim_paths)?; } @@ -838,6 +851,20 @@ fn rustdoc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult, unit: &Unit) -> CargoResult, unit: &Unit) -> CargoResult, unit: &Unit) -> CargoR .outputs(unit) .map(|outputs| outputs[0].path.clone()) } + +/// Gets the dep-info file emitted by rustdoc. +fn rustdoc_dep_info_loc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> PathBuf { + let mut loc = build_runner.files().fingerprint_file_path(unit, ""); + loc.set_extension("d"); + loc +} diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index f5aab9dc60b..152d308d832 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -790,6 +790,7 @@ unstable_cli_options!( public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"), publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"), root_dir: Option = ("Set the root directory relative to which paths are printed (defaults to workspace root)"), + rustdoc_depinfo: bool = ("Use dep-info files in rustdoc rebuild detection"), rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"), rustdoc_scrape_examples: bool = ("Allows Rustdoc to scrape code examples from reverse-dependencies"), sbom: bool = ("Enable the `sbom` option in build config in .cargo/config.toml file"), @@ -1303,6 +1304,7 @@ impl CliUnstable { "trim-paths" => self.trim_paths = parse_empty(k, v)?, "publish-timeout" => self.publish_timeout = parse_empty(k, v)?, "root-dir" => self.root_dir = v.map(|v| v.into()), + "rustdoc-depinfo" => self.rustdoc_depinfo = parse_empty(k, v)?, "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, "rustdoc-scrape-examples" => self.rustdoc_scrape_examples = parse_empty(k, v)?, "sbom" => self.sbom = parse_empty(k, v)?, diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index c527fb63d1f..1d031301992 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -98,6 +98,7 @@ Each new feature described below should explain how to use it. * [rustdoc-map](#rustdoc-map) --- Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/). * [scrape-examples](#scrape-examples) --- Shows examples within documentation. * [output-format](#output-format-for-rustdoc) --- Allows documentation to also be emitted in the experimental [JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). + * [rustdoc-depinfo](#rustdoc-depinfo) --- Use dep-info files in rustdoc rebuild detection. * `Cargo.toml` extensions * [Profile `rustflags` option](#profile-rustflags-option) --- Passed directly to rustc. * [codegen-backend](#codegen-backend) --- Select the codegen backend used by rustc. @@ -1901,6 +1902,14 @@ Requires `-Zunstable-options`. See [`cargo package --message-format`](../commands/cargo-package.md#option-cargo-package---message-format) for more information. +## rustdoc depinfo + +* Tracking Issue: [#00000](https://github.com/rust-lang/cargo/issues/00000) + +The `-Z rustdoc-depinfo` flag leverages rustdoc's dep-info files to determine +whether documentations are required to re-generate. This can be combined with +`-Z checksum-freshness` to detect checksum changes rather than file mtime. + # Stabilized and removed features ## Compile progress diff --git a/tests/testsuite/cargo/z_help/stdout.term.svg b/tests/testsuite/cargo/z_help/stdout.term.svg index c7791176d58..c152f663f20 100644 --- a/tests/testsuite/cargo/z_help/stdout.term.svg +++ b/tests/testsuite/cargo/z_help/stdout.term.svg @@ -1,4 +1,4 @@ - +