Files
ElyOffice/crates/ely-pdf-engine/build.rs
T

142 lines
5.8 KiB
Rust

//! Builds the MuPDF shim into the worker binary only.
use std::path::PathBuf;
fn main() {
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").expect("set by cargo")).join("../..");
let mupdf = std::env::var_os("ELY_MUPDF_DIR").map_or_else(|| root.join("engines/mupdf-build"), PathBuf::from);
// One stamp for client and worker; stale workers refused.
let mut stamp: u64 = 0xcbf2_9ce4_8422_2325;
for source in [
"shim/ely_mupdf.c",
"shim/ely_pages.c",
"shim/ely_insert.c",
"shim/ely_text.c",
"shim/ely_write.c",
"shim/ely_pen.c",
"shim/ely_place.c",
"shim/ely_annot.c",
"shim/ely_form.c",
"shim/ely_ocr.c",
"shim/ely_outline.c",
"shim/ely_meta.c",
"shim/ely_redact.c",
"shim/ely_alt.c",
"shim/ely_clean.c",
"shim/ely_secure.c",
"shim/ely_sign.c",
"shim/ely_output.c",
"shim/ely_story.c",
"shim/ely_shim.h",
"src/proto.rs",
"src/bin/ely-pdf-worker/main.rs",
"src/bin/ely-pdf-worker/ffi.rs",
"src/bin/ely-pdf-worker/edit.rs",
"src/bin/ely-pdf-worker/content.rs",
"src/edit.rs",
"src/content.rs",
"src/marks.rs",
"src/bin/ely-pdf-worker/marks.rs",
"src/bin/ely-pdf-worker/ocr.rs",
"src/bin/ely-pdf-worker/structure.rs",
"src/bin/ely-pdf-worker/redact.rs",
"src/redact.rs",
"src/structure.rs",
"src/ocr.rs",
"src/bin/ely-pdf-worker/secure.rs",
"src/secure.rs",
"src/bin/ely-pdf-worker/sign.rs",
"src/sign.rs",
"src/bin/ely-pdf-worker/output.rs",
"src/output.rs",
"../ely-ipc/src/lib.rs",
] {
println!("cargo:rerun-if-changed={source}");
for byte in std::fs::read(source).expect("a source file") {
stamp = (stamp ^ u64::from(byte)).wrapping_mul(0x100_0000_01b3);
}
}
println!("cargo:rustc-env=ELY_PDF_BUILD={stamp:016x}");
println!("cargo:rerun-if-env-changed=ELY_MUPDF_DIR");
let windows = std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows");
// MSVC's libmupdf.lib holds its third parties and PKCS#7.
let libs: &[&str] =
if windows { &["libmupdf.lib"] } else { &["libmupdf-pkcs7.a", "libmupdf.a", "libmupdf-third.a"] };
for lib in libs {
println!("cargo:rerun-if-changed={}", mupdf.join(lib).display());
if !mupdf.join(lib).is_file() {
panic!("no {lib} in {} (run scripts/build-mupdf.sh or set ELY_MUPDF_DIR)", mupdf.display());
}
}
cc::Build::new()
.file("shim/ely_mupdf.c")
.file("shim/ely_pages.c")
.file("shim/ely_insert.c")
.file("shim/ely_text.c")
.file("shim/ely_write.c")
.file("shim/ely_pen.c")
.file("shim/ely_place.c")
.file("shim/ely_annot.c")
.file("shim/ely_form.c")
.file("shim/ely_ocr.c")
.file("shim/ely_outline.c")
.file("shim/ely_meta.c")
.file("shim/ely_redact.c")
.file("shim/ely_alt.c")
.file("shim/ely_clean.c")
.file("shim/ely_secure.c")
.file("shim/ely_sign.c")
.file("shim/ely_output.c")
.file("shim/ely_story.c")
.include(root.join("reference/mupdf/include"))
.include(openssl(&root, "includedir"))
.warnings(true)
.cargo_metadata(false)
.compile("ely_mupdf");
let out = PathBuf::from(std::env::var("OUT_DIR").expect("set by cargo"));
let bin = "ely-pdf-worker";
let shim = if windows { "ely_mupdf.lib" } else { "libely_mupdf.a" };
println!("cargo:rustc-link-arg-bin={bin}={}", out.join(shim).display());
for lib in libs {
println!("cargo:rustc-link-arg-bin={bin}={}", mupdf.join(lib).display());
}
// Signing and checking need OpenSSL, linked in whole.
let crypto = if windows { "libcrypto.lib" } else { "libcrypto.a" };
println!("cargo:rustc-link-arg-bin={bin}={}", PathBuf::from(openssl(&root, "libdir")).join(crypto).display());
if windows {
for lib in ["crypt32.lib", "ws2_32.lib", "advapi32.lib", "user32.lib"] {
println!("cargo:rustc-link-arg-bin={bin}={lib}");
}
return;
}
// What a static libcrypto needs, as its pkg-config says.
let needs = std::process::Command::new("pkg-config")
.args(["--static", "--libs-only-l", "libcrypto"])
.output()
.expect("pkg-config, to find OpenSSL");
assert!(needs.status.success(), "pkg-config knows no static libcrypto");
for lib in String::from_utf8(needs.stdout).expect("UTF-8 flags").split_whitespace().filter(|lib| *lib != "-lcrypto") {
println!("cargo:rustc-link-arg-bin={bin}={lib}");
}
println!("cargo:rustc-link-arg-bin={bin}=-lm");
// Tesseract inside MuPDF is C++.
let cxx = if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") { "-lc++" } else { "-lstdc++" };
println!("cargo:rustc-link-arg-bin={bin}={cxx}");
}
/// An OpenSSL directory: vcpkg's static build on Windows, else pkg-config's.
fn openssl(root: &std::path::Path, variable: &str) -> String {
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
let dir = root.join("engines/vcpkg/installed/x64-windows-static");
let sub = if variable == "includedir" { "include" } else { "lib" };
assert!(dir.join("lib/libcrypto.lib").is_file(), "no static OpenSSL in {}", dir.display());
return dir.join(sub).display().to_string();
}
let out = std::process::Command::new("pkg-config")
.args([&format!("--variable={variable}"), "libcrypto"])
.output()
.expect("pkg-config, to find OpenSSL");
assert!(out.status.success(), "pkg-config knows no libcrypto");
String::from_utf8(out.stdout).expect("a UTF-8 path").trim().to_string()
}