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.
This commit is contained in:
Michael Howell 2024-10-19 15:27:53 -07:00
parent 8069f8d17a
commit 86abb5439a
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> {