Skip to content

bootstrap: Enable rustdoc mergeable CCI for std and internal docs - #160098

Open
camelid wants to merge 5 commits into
rust-lang:mainfrom
camelid:bootstrap-doc-mergeable
Open

bootstrap: Enable rustdoc mergeable CCI for std and internal docs#160098
camelid wants to merge 5 commits into
rust-lang:mainfrom
camelid:bootstrap-doc-mergeable

Conversation

@camelid

@camelid camelid commented Jul 28, 2026

Copy link
Copy Markdown
Member

View all comments

This feature is unstable but will be stabilized soon, and this is a good way of dogfooding it to make sure it works properly. It should have no effect on the generated docs, but it provides a significant speedup. For example, I measure a 3x speedup locally (3m 11s -> 1m 1s) for x doc src/tools -- note that this is with the latest rustdoc perf improvements (#159854).

r? @Kobzol

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Jul 28, 2026
@rustbot

rustbot commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Kobzol is not on the review rotation at the moment.
They may take a while to respond.

@rustbot

This comment has been minimized.

@Kobzol

Kobzol commented Jul 28, 2026

Copy link
Copy Markdown
Member

Let's try the main x64 Linux dist job, I will compare the docs build time before/after.

Btw, it would be nice to add a comment on top of the added argument, which explains why is it there.

@bors try jobs=dist-x86_64-linux

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 28, 2026
bootstrap: Enable rustdoc mergeable CCI for std and internal docs


try-job: dist-x86_64-linux
@camelid
camelid force-pushed the bootstrap-doc-mergeable branch 2 times, most recently from 1696dc7 to 23a03ba Compare July 28, 2026 18:28
@rust-log-analyzer

This comment has been minimized.

@camelid

camelid commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

@GuillaumeGomez @notriddle do you think this failure is due to a bug in mergeable CCI? It's a little weird because it seems to pass on LLVM 22.2 but not 22.1 -- so could be spurious? But it's suspicious that it's related to the search index.

@Kobzol

Kobzol commented Jul 28, 2026

Copy link
Copy Markdown
Member

I kinda doubt it is spurious. However, bootstrap does a lot of weird crimes related to the created and removal of various doc things being built in the build directory, could be caused by that. I'll take a look at it tomorrow.

@camelid

camelid commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Yes, I suspect it's a bug in rustdoc. It looks like the LLVM 22.2 CI disables js-std tests.

@camelid

camelid commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Looks like it's actually a cargo bug, where cargo isn't passing the --resource-suffix to the final merge step. Actually cargo isn't passing the RUSTDOCFLAGS at all. We should probably pass the same flags to the final merge invocation as to each crate's rustdoc invocation. This conflates two somewhat different things, but we already share the same flags across all crates so sharing it with the merge makes sense I think. Working with @weihanglo on a fix in cargo.

@rust-bors rust-bors Bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 28, 2026
@rust-bors

rust-bors Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

💔 Test for bf99269 failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@camelid

camelid commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

cc rust-lang/cargo#17269

@Kobzol

Kobzol commented Jul 28, 2026

Copy link
Copy Markdown
Member

The try build failure looks like it might be some different error, maybe related to some cursedness when documenting the standard library?

##[group]Documenting stage1 library{alloc, compiler_builtins, core, panic_abort, panic_unwind, proc_macro, profiler_builtins, rustc-std-workspace-core, std, std_detect, sysroot, test, unwind} in JSON format (stage1 -> stage1, x86_64-unknown-linux-gnu)
warning: output filename collision at /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/dist/build/alloc/4e4894d7dbb95523/out/alloc.json
  |
  = note: the lib target `alloc` in package `alloc v0.0.0 (/checkout/library/alloc)` has the same output filename as the lib target `alloc` in package `alloc v0.0.0 (/checkout/library/alloc)`
  = note: this is a known bug where multiple crates with the same name use the same path; see <https://github.com/rust-lang/cargo/issues/6313>

@weihanglo

Copy link
Copy Markdown
Member

Looks like it's actually a cargo bug, where cargo isn't passing the --resource-suffix to the final merge step. Actually cargo isn't passing the RUSTDOCFLAGS at all.

This is an unresolved question. See rust-lang/cargo#17269 (comment)

@camelid

camelid commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Came across another issue. Currently, when building compiler/tool docs, we do separate cargo invocations but have them all end up in the same output directory. So that rustc, rustdoc, cargo, clippy, etc. all share one docs site (/nightly/nightly-rustc). This works out of the box with legacy shared CCI because rustdoc updates the finalized artifacts with each build. However, with shared CCI, we run one finalize per docs target (i.e. one for rustc, one for rustdoc, one for clippy, etc.), which causes the CCI (crates.js, search-index, etc.) to be overwritten.

I'm not sure what the best fix for this is. Ideally, we would probably have bootstrap tell Cargo to not run finalize for the intermediate targets and just do one finalize at the end. It also suggests that enabling mergeable CCI by default in Cargo is a moderately breaking change for workflows that depend on separate cargo doc invocations working well together.

@camelid

camelid commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@notriddle @weihanglo do you have any thoughts about the above issue?

@weihanglo weihanglo Jul 29, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@camelid #160098 (comment)

Came across another issue. Currently, when building compiler/tool docs, we do separate cargo invocations but have them all end up in the same output directory. So that rustc, rustdoc, cargo, clippy, etc. all share one docs site (/nightly/nightly-rustc). This works out of the box with legacy shared CCI because rustdoc updates the finalized artifacts with each build. However, with shared CCI, we run one finalize per docs target (i.e. one for rustc, one for rustdoc, one for clippy, etc.), which causes the CCI (crates.js, search-index, etc.) to be overwritten.

I'm not sure what the best fix for this is. Ideally, we would probably have bootstrap tell Cargo to not run finalize for the intermediate targets and just do one finalize at the end. It also suggests that enabling mergeable CCI by default in Cargo is a moderately breaking change for workflows that depend on separate cargo doc invocations working well together.

Haven't checked how bootstrap builds docs, though I think it should just work, as cargo doc is additive (in order to follow how rustdoc works and keep backward-compat): https://github.com/rust-lang/cargo/blob/9c930d9f8d5ec08afd4bd69dbdcba2a336fbefe3/tests/testsuite/doc.rs#L3773-L3913

It might be possible that bootstrap is using -Zskip-rustdoc-fingerprint. See also rust-lang/cargo#9404

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bootstrap is in fact using -Zskip-rustdoc-fingerprint. However, I think the issue is more fundamental than that because rustdoc assumes that finalize is always run exactly once per doc site. If you run finalize for rustc and then for a tool, it will just overwrite the shared files for rustc with ones specific to the tool.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. I thought the feature was additive hence the test in Cargo (it ran cargo doc -p foo then -p dep and then -p bar sequentially).

If it were not they Cargo probably can't ship it as a default for backward compatibility reasons.

What are those shared files being overwritten? Were they safe-from-overwrite previously without -Zrustdoc-mergeable-info?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cargo test doesn't actually check the contents of the shared files as far as I can tell. Rustdoc is still additive for the crate docs (e.g. foo/struct.Bar.html will not be overwritten). But with mergeable CCI, sequential cargo doc invocations will clobber the shared files like the search index.

The shared files were deserialized, updated, and reserialized on every single rustdoc invocation before. With mergeable CCI, each crate's contribution to the CCI is serialized separately and the merge step combines them all into the final shared files. One possible fix for this backcompat issue is that the merge step could check for any existing shared files in the output directory and use those as the basis for its merge step. It would be nice to avoid that if we can though and have the merge be authoritative rather than being invoked any number of times.

@notriddle

notriddle commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

However, with shared CCI, we run one finalize per docs target (i.e. one for rustc, one for rustdoc, one for clippy, etc.), which causes the CCI (crates.js, search-index, etc.) to be overwritten.

As long as the same Cargo build directory is used for all three of these builds, that isn’t supposed to be a problem. The feature implements --doc-meta-dir as a directory specifically so that this can still work.

Did you try the feature and have it not work?

@camelid

camelid commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Yes, I tried this branch locally with e.g. x doc src/tools/rustdoc, and the crates.js file and search index are both broken. Crate documentation exists for all the rustc crates, but they are not in the crates.js file or search index.

@camelid

camelid commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

The specific problem is that merging assumes it is given all meta-dir inputs and does not import existing finalized outputs. Since bootstrap invokes cargo doc on rustc separately from each of the tools, we run the merge step for each one, without providing meta-dir inputs from the other invocations.

@weihanglo

Copy link
Copy Markdown
Member

Yes, I tried this branch locally with e.g. x doc src/tools/rustdoc, and the crates.js file and search index are both broken. Crate documentation exists for all the rustc crates, but they are not in the crates.js file or search index.

That may be due to skipping rustdoc-fingeprint. The fingerprint file tracks previous rustdoc run in order to collect all mergeable info across multiple cargo doc invocations.

@camelid

camelid commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Hmm, so what is in rustdoc-fingerprint? Does it include all the meta dirs that were generated along the way?

@camelid

camelid commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

@weihanglo the index.html, settings.html, and some other root pages were not generated when doc merge finalize was run as a separate step. So that PR fixes it.

This feature is unstable but will be stabilized soon, and this is a good
way of dogfooding it to make sure it works properly. It should have no
effect on the generated docs, but it provides a significant speedup. For
example, I measure a 3x speedup locally (3m 11s -> 1m 1s) for
`x doc src/tools` -- note that this is with the latest rustdoc perf
improvements (PR 159854).
@camelid
camelid force-pushed the bootstrap-doc-mergeable branch from 23a03ba to a34d83a Compare August 6, 2026 15:24
@rustbot

rustbot commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@camelid

camelid commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

Will start a try job once CI passes. Or if you get to it before me, please run @bors try jobs=dist-x86_64-linux.

@Kobzol

Kobzol commented Aug 6, 2026

Copy link
Copy Markdown
Member

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 6, 2026
bootstrap: Enable rustdoc mergeable CCI for std and internal docs
@camelid

camelid commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

@Kobzol isn't that the wrong try job?

@Kobzol

Kobzol commented Aug 6, 2026

Copy link
Copy Markdown
Member

It is 😆 Thanks.

@bors try jobs=dist-x86_64-linux

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 6, 2026
bootstrap: Enable rustdoc mergeable CCI for std and internal docs


try-job: dist-x86_64-linux
@rust-bors

rust-bors Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

💔 Test for 7d8ef04 failed: CI. Failed job:

@camelid

camelid commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

Good ol' GitHub Actions... seems like there's some 500s.

@rust-log-analyzer

This comment has been minimized.

@camelid

camelid commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

Oh, wait, I guess we still need to fix the issue caused by bootstrap's weird symlinking of different doc directories. @notriddle is working on a patch.

@camelid

camelid commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-x86_64-linux

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 7, 2026
bootstrap: Enable rustdoc mergeable CCI for std and internal docs


try-job: dist-x86_64-linux
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

💔 Test for 661fd6f failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@camelid

camelid commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

I wonder if it makes sense to split off another PR that enables the feature just for std -- that way we can start dogfooding it before the whole bootstrap mess is fixed?

@GuillaumeGomez

Copy link
Copy Markdown
Member

I tend to prefer incremental over "all at once" but up to you.

I know that this change causes `doc` to build compiler stuff before
building docs for bootstrap. This just reduces the combinatorics that we
have to deal with.
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
##[endgroup]
Doc path: /checkout/obj/build/aarch64-unknown-linux-gnu/doc/alloc/index.html
[TIMING:end] doc::Std { build_compiler: Compiler { stage: 2, host: aarch64-unknown-linux-gnu, forced_compiler: false }, target: aarch64-unknown-linux-gnu, format: Html, crates: [] } -- 59.222
##[group]Testing stage2 rustdoc-js-std (aarch64-unknown-linux-gnu)
Error: ENOENT: no such file or directory, open '/checkout/obj/build/aarch64-unknown-linux-gnu/doc/search.index/root1.99.0.js'
    at Object.readFileSync (node:fs:449:20)
    at readFile (/checkout/src/tools/rustdoc-js/tester.js:30:15)
    at Object.loadRoot (/checkout/src/tools/rustdoc-js/tester.js:468:32)
    at /checkout/obj/build/aarch64-unknown-linux-gnu/doc/static.files/stringdex-b5109af9.js:2:24000
    at new Promise (<anonymous>)
    at Object.loadDatabase (/checkout/obj/build/aarch64-unknown-linux-gnu/doc/static.files/stringdex-b5109af9.js:2:23870)
    at Object.initSearch (/checkout/obj/build/aarch64-unknown-linux-gnu/doc/static.files/search-cf4fc35e.js:5:12018)
    at loadSearchJS (/checkout/src/tools/rustdoc-js/tester.js:458:57)
    at main (/checkout/src/tools/rustdoc-js/tester.js:628:34)
    at Object.<anonymous> (/checkout/src/tools/rustdoc-js/tester.js:656:1) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/checkout/obj/build/aarch64-unknown-linux-gnu/doc/search.index/root1.99.0.js'
}
Bootstrap failed while executing `--stage 2 test --skip tidy --skip intrinsic-test --skip compiler --skip src`
Currently active steps:
test::RustdocJSStd { build_compiler: Compiler { stage: 2, host: aarch64-unknown-linux-gnu, forced_compiler: false }, target: aarch64-unknown-linux-gnu } at src/bootstrap/src/core/build_steps/test.rs:1332
Command `/usr/bin/node /checkout/src/tools/rustdoc-js/tester.js --crate-name std --resource-suffix 1.99.0 --doc-folder /checkout/obj/build/aarch64-unknown-linux-gnu/doc --test-folder /checkout/tests/rustdoc-js-std` failed with exit code 1
Created at: src/bootstrap/src/core/build_steps/test.rs:1341:27
Executed at: src/bootstrap/src/core/build_steps/test.rs:1382:17

Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:43:58
  local time: Sat Aug  8 00:27:09 UTC 2026
  network time: Sat, 08 Aug 2026 00:27:09 GMT
##[error]Process completed with exit code 1.
##[group]Run echo "disk usage:"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants