Auto merge of #131951 - notriddle:notriddle/sha256-compile-time, r=GuillaumeGomez

rustdoc: hash assets at rustdoc build time

Since sha256 is slow enough to show up on small benchmarks, we can save time by embedding the hash in the executable.

Addresses https://github.com/rust-lang/rust/pull/131934#issuecomment-2424213861
This commit is contained in:
bors 2024-10-24 05:48:56 +00:00
commit 8aca4bab08
3 changed files with 58 additions and 14 deletions

View File

@ -2,6 +2,7 @@
name = "rustdoc" name = "rustdoc"
version = "0.0.0" version = "0.0.0"
edition = "2021" edition = "2021"
build = "build.rs"
[lib] [lib]
path = "lib.rs" path = "lib.rs"
@ -24,13 +25,15 @@ tracing = "0.1"
tracing-tree = "0.3.0" tracing-tree = "0.3.0"
threadpool = "1.8.1" threadpool = "1.8.1"
unicode-segmentation = "1.9" unicode-segmentation = "1.9"
sha2 = "0.10.8"
[dependencies.tracing-subscriber] [dependencies.tracing-subscriber]
version = "0.3.3" version = "0.3.3"
default-features = false default-features = false
features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"]
[build-dependencies]
sha2 = "0.10.8"
[dev-dependencies] [dev-dependencies]
expect-test = "1.4.0" expect-test = "1.4.0"

48
src/librustdoc/build.rs Normal file
View File

@ -0,0 +1,48 @@
fn main() {
// generate sha256 files
// this avoids having to perform hashing at runtime
let files = &[
"static/css/rustdoc.css",
"static/css/noscript.css",
"static/css/normalize.css",
"static/js/main.js",
"static/js/search.js",
"static/js/settings.js",
"static/js/src-script.js",
"static/js/storage.js",
"static/js/scrape-examples.js",
"static/COPYRIGHT.txt",
"static/LICENSE-APACHE.txt",
"static/LICENSE-MIT.txt",
"static/images/rust-logo.svg",
"static/images/favicon.svg",
"static/images/favicon-32x32.png",
"static/fonts/FiraSans-Regular.woff2",
"static/fonts/FiraSans-Medium.woff2",
"static/fonts/FiraSans-LICENSE.txt",
"static/fonts/SourceSerif4-Regular.ttf.woff2",
"static/fonts/SourceSerif4-Bold.ttf.woff2",
"static/fonts/SourceSerif4-It.ttf.woff2",
"static/fonts/SourceSerif4-LICENSE.md",
"static/fonts/SourceCodePro-Regular.ttf.woff2",
"static/fonts/SourceCodePro-Semibold.ttf.woff2",
"static/fonts/SourceCodePro-It.ttf.woff2",
"static/fonts/SourceCodePro-LICENSE.txt",
"static/fonts/NanumBarunGothic.ttf.woff2",
"static/fonts/NanumBarunGothic-LICENSE.txt",
];
let out_dir = std::env::var("OUT_DIR").expect("standard Cargo environment variable");
for path in files {
let inpath = format!("html/{path}");
println!("cargo::rerun-if-changed={inpath}");
let bytes = std::fs::read(inpath).expect("static path exists");
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
digest.truncate(9);
let outpath = std::path::PathBuf::from(format!("{out_dir}/{path}.sha256"));
std::fs::create_dir_all(outpath.parent().expect("all file paths are in a directory"))
.expect("should be able to write to out_dir");
std::fs::write(&outpath, digest.as_bytes()).expect("write to out_dir");
}
}

View File

@ -12,8 +12,8 @@ pub(crate) struct StaticFile {
} }
impl StaticFile { impl StaticFile {
fn new(filename: &str, bytes: &'static [u8]) -> StaticFile { fn new(filename: &str, bytes: &'static [u8], sha256: &'static str) -> StaticFile {
Self { filename: static_filename(filename, bytes), bytes } Self { filename: static_filename(filename, sha256), bytes }
} }
pub(crate) fn minified(&self) -> Vec<u8> { pub(crate) fn minified(&self) -> Vec<u8> {
@ -55,17 +55,9 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf {
filename.into() filename.into()
} }
pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf { pub(crate) fn static_filename(filename: &str, sha256: &str) -> PathBuf {
let filename = filename.rsplit('/').next().unwrap(); let filename = filename.rsplit('/').next().unwrap();
suffix_path(filename, &static_suffix(contents)) suffix_path(filename, &sha256)
}
fn static_suffix(bytes: &[u8]) -> String {
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
digest.truncate(9);
digest
} }
macro_rules! static_files { macro_rules! static_files {
@ -74,8 +66,9 @@ pub(crate) struct StaticFiles {
$(pub $field: StaticFile,)+ $(pub $field: StaticFile,)+
} }
// sha256 files are generated in build.rs
pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles { pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
$($field: StaticFile::new($file_path, include_bytes!($file_path)),)+ $($field: StaticFile::new($file_path, include_bytes!($file_path), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
}); });
pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> { pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {