pdftract/crates/pdftract-cli/build.rs
jedarden 8abf01cea3 feat(pdftract-4q8cq): implement 14 environment checks for pdftract doctor
Implement all 14 environment checks for the `pdftract doctor` subcommand.
Each check returns a CheckResult with status (OK/WARN/FAIL/NotApplicable)
and a human-readable detail message.

Checks implemented:
- pdftract binary (version, git SHA, compiled features)
- tesseract install (version check: >=5 OK, ==4 WARN, <=3 FAIL)
- tesseract languages (eng + requested langs present)
- leptonica install (>=1.79 OK, older WARN, not found FAIL)
- libtiff (pkg-config check with ldconfig fallback)
- libopenjp2 (pkg-config check with ldconfig fallback)
- pdfium native lib (version >=6555 OK, older WARN, not found FAIL)
- network reachability (HEAD example.com with 5s timeout)
- cache directory (writable, free space >=1 GiB, layout version)
- profile search path (YAML parse, PROFILE_SECRETS_FORBIDDEN detection)
- ulimit -n (>=1024 OK, 512-1024 WARN, <512 FAIL)
- available RAM (>=256 MiB OK, 128-256 WARN, <128 FAIL)
- system locale (UTF-8 OK, non-UTF-8 WARN, unset FAIL)
- temp dir writable (writable + free space >=100 MiB)

Core module with Check trait, CheckResult, CheckStatus, DoctorCtx,
DoctorFeatures, and panic-safe run_check_safe wrapper.

Build script injects GIT_SHA and COMPILED_FEATURES at compile time.

All checks feature-gated appropriately (ocr, full-render, remote, profiles).

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-05-23 06:47:07 -04:00

58 lines
2.2 KiB
Rust

use std::env;
use std::process::Command;
fn main() {
// Capture git SHA for version reporting
let git_sha = Command::new("git")
.args(["rev-parse", "HEAD"])
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.trim().to_string())
.unwrap_or_else(|| "unknown".to_string());
println!("cargo:rustc-env=GIT_SHA={}", git_sha);
// Emit compile-time feature list
// These are the cargo features that affect doctor output
let features = [
("OCR", cfg!(feature = "ocr")),
("FULL_RENDER", cfg!(feature = "full-render")),
("REMOTE", cfg!(feature = "remote")),
("PROFILES", cfg!(feature = "profiles")),
("SERVE", cfg!(feature = "serve")),
("MCP", cfg!(feature = "mcp")),
("INSPECT", cfg!(feature = "inspect")),
("GREP", cfg!(feature = "grep")),
("CACHE", cfg!(feature = "cache")),
("RECEIPTS", cfg!(feature = "receipts")),
("MARKDOWN", cfg!(feature = "markdown")),
];
let enabled: Vec<&str> = features.iter()
.filter(|(_, enabled)| *enabled)
.map(|(name, _)| *name)
.collect();
let feature_list = if enabled.is_empty() {
"default".to_string()
} else {
enabled.join(",")
};
println!("cargo:rustc-env=COMPILED_FEATURES={}", feature_list);
// Rebuild if git HEAD changes (for accurate GIT_SHA in dev builds)
println!("cargo:rerun-if-changed=.git/HEAD");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_OCR");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_FULL_RENDER");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_REMOTE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_PROFILES");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_SERVE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MCP");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_INSPECT");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_GREP");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_CACHE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_RECEIPTS");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_MARKDOWN");
}