-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Closed
Labels
A-rebuild-detectionArea: rebuild detection and fingerprintingArea: rebuild detection and fingerprintingC-bugCategory: bugCategory: bugCommand-doc
Description
Rustdoc can fail if you build documentation with different versions of rustdoc. Rustdoc has some persistent files (like search-index.js
) which are not internally versioned. If the format of these changes, this can cause things to break. Example:
In a project with at least one dependency:
cargo +1.40.0 doc
cargo +1.41.0 doc --no-deps --open
The result will have javascript errors in the console, and the sidebar and search will be broken.
To fix this, Cargo should retain a fingerprint somewhere that tracks the rustc version used when building documentation. Changes to that should cause Cargo to delete the doc
directory.
Metadata
Metadata
Assignees
Labels
A-rebuild-detectionArea: rebuild detection and fingerprintingArea: rebuild detection and fingerprintingC-bugCategory: bugCategory: bugCommand-doc
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
CPerezz commentedon Jul 25, 2020
Hi @ehuss I'd like to work on that.
I've been checking the code and looks like we could apply this check and delete the
doc/
folder here:cargo/src/cargo/ops/cargo_doc.rs
Line 38 in d3360ad
What I'm not sure about is the fingerprint and where/how it should be set.
Is there any cache or file we can attach the latest rustc version used to build the docs?
ehuss commentedon Jul 25, 2020
I don't think there is anything existing. I'm thinking there could probably just be a file stored in the
.fingerprint
directory that would be just for thedoc
output. I'm thinking maybe just a JSON file. I can only think of one field for now ("rustc"
), and maybe a version field (set to 1? not sure if that's necessary). There are some other bugs with rustdoc fingerprinting, so it would be good to keep it flexible so that those can be more easily fixed in the future.I'm not sure how much you know about the cargo codebase. Information about fingerprinting can be found in https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint.rs. Unfortunately I don't think that can be used in this case because those fingerprints are unit-oriented, but this fingerprint needs to be triggered globally (otherwise, if two units are building docs concurrently, there would need to be some messy coordination).
There is a cache of rustc information at https://github.com/rust-lang/cargo/blob/master/src/cargo/util/rustc.rs, stored in the
RustcTargetData
which is stored inBuildContext
.CPerezz commentedon Jul 26, 2020
Thanks for the info. I don't know much about the Cargo codebase as you'll probably witness.. hahah.
The JSON file looks like a good solution. Indeed we already have one in the package directory, inside of
target/
folder which could maybe be used for this. It already contains the latest toolchain used to compile the lib/bin:Therefore, we could simply take this version if
target/
exists (otherways we directly build the docs) and if it exists, we check whether the version stated in the.rustc_info.json
is the same as the one we're using now.If it is we just let it follow the same logic it has now, if it is older, we delete the whole
doc/
folder and we let cargo compile the docs again.Does it make sense? Or you'll create a specific file for docs fingerprinting?
ehuss commentedon Jul 27, 2020
I don't think the
.rustc_info.json
file should be used for fingerprinting. It is just a cache for version information from the compiler. If other commands are run, it will get rebuilt, deleting any information. I think it would probably be best to use a dedicated fingerprint.CPerezz commentedon Jul 28, 2020
Makes sense. Therefore, as you mentioned, a JSON file under
target/
sounds reasonable to you?Then the logic would be something like:
doc
is triggeredtarget/
exists in the target directory.2a. If it doesn't, compile normally.
2b. If it does, check fingerprint file and check latest
cargo version
used to compile the docs.2ba. If it is the same as the actual one, compile normally.
2bb. If it's older than the actual
cargo version
, delete thedoc/
folder and compile normally.What does it seem to you @ehuss ?
ehuss commentedon Jul 28, 2020
Yea, generally seems correct. To be a little more precise:
There probably isn't a need to specifically check for the directory. It can just try to open the fingerprint file, and if it doesn't exist, it can proceed as usual.
It will probably be sufficient to check the version of
rustc
and assume rustdoc is the same.Rustc.verbose_version
provides the version info, which can be found inRustcTargetData
.Implement Rustdoc versioning checks
Auto merge of #8640 - CPerezz:doc_versioning, r=ehuss
jyn514 commentedon Apr 5, 2021
This was kind of a heavy hammer (and caused rustbuild trouble: rust-lang/rust#83530). What do you think about passing a
--resource-suffix
with the name of the toolchain instead? Then you won't need to remove the whole doc directory.