Lines
87.41 %
Functions
70 %
Branches
100 %
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use wasm_bindgen_cli_support::Bindgen;
fn main() {
let output = Command::new("git")
.args(["rev-parse", "HEAD"])
.output()
.expect("Can't get git revision");
let git_hash = String::from_utf8(output.stdout)
.expect("Can't parse git revision")
.trim()
.to_owned();
println!("cargo:rustc-env=GIT_HASH={git_hash}");
let build_date = chrono::Utc::now().to_rfc3339();
println!("cargo:rustc-env=BUILD_DATE={build_date}");
println!("cargo:rerun-if-changed=frontend/src");
build_wasm_frontend();
println!("cargo:rerun-if-changed=../doc");
build_org_docs();
}
fn export_org_file(org_path: &Path, out_dir: &Path, eval_babel: bool) {
let html_name = org_path.file_stem().unwrap().to_str().unwrap().to_owned() + ".html";
let html_in_place = org_path.with_extension("html");
let html_dest = out_dir.join(&html_name);
if html_dest.exists() {
let org_modified = fs::metadata(org_path)
.and_then(|m| m.modified())
.unwrap_or(std::time::SystemTime::UNIX_EPOCH);
let html_modified = fs::metadata(&html_dest)
if html_modified >= org_modified {
return;
let mut args: Vec<&str> = vec!["-q", "--batch"];
let org_str = org_path.to_str().unwrap();
args.push(org_str);
args.extend_from_slice(&["-l", "ox-html"]);
if eval_babel {
args.extend_from_slice(&[
"--eval",
"(progn (require 'ob-emacs-lisp) (setq org-confirm-babel-evaluate nil))",
]);
args.extend_from_slice(&["--eval", "(org-html-export-to-html)", "-f", "kill-emacs"]);
let status = Command::new("emacs").args(&args).status();
match status {
Ok(s) if s.success() => {
if html_in_place.exists() {
fs::create_dir_all(out_dir).expect("Failed to create doc output dir");
fs::rename(&html_in_place, &html_dest).expect("Failed to move HTML");
Ok(s) => eprintln!(
"Warning: emacs export failed for {} (exit {})",
org_str,
s.code().unwrap_or(-1)
),
Err(_) => eprintln!("Warning: emacs not found, skipping doc generation"),
fn build_org_docs() {
let project_root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
.parent()
.unwrap()
.to_path_buf();
let doc_dir = project_root.join("doc");
let static_doc = PathBuf::from("static/doc");
// doc/disdoc.org → static/doc/
export_org_file(&doc_dir.join("disdoc.org"), &static_doc, false);
// doc/scripts/*.org → static/doc/scripts/
if let Ok(entries) = fs::read_dir(doc_dir.join("scripts")) {
for entry in entries.flatten() {
let path = entry.path();
if path.extension().is_some_and(|e| e == "org") {
export_org_file(&path, &static_doc.join("scripts"), false);
// doc/nomiscript/*.org → static/doc/nomiscript/ (with babel eval)
if let Ok(entries) = fs::read_dir(doc_dir.join("nomiscript")) {
export_org_file(&path, &static_doc.join("nomiscript"), true);
fn build_wasm_frontend() {
let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
let wasm_target_dir = project_root.join("target-wasm");
let wasm_file = wasm_target_dir
.join("wasm32-unknown-unknown")
.join(&profile)
.join("nomisync_frontend.wasm");
let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
let mut cmd = Command::new(&cargo);
cmd.args([
"build",
"-p",
"nomisync-frontend",
"--target",
"wasm32-unknown-unknown",
"--features",
"auto-init",
"-j",
"1",
])
.current_dir(&project_root)
.env("CARGO_TARGET_DIR", &wasm_target_dir)
.env_remove("CARGO_MAKEFLAGS")
.env_remove("MAKEFLAGS")
.env_remove("RUSTC_WRAPPER")
.env_remove("RUSTC_WORKSPACE_WRAPPER")
.env_remove("RUSTFLAGS")
.env_remove("CARGO_ENCODED_RUSTFLAGS");
if profile == "release" {
cmd.arg("--release");
assert!(
cmd.status().expect("Failed to execute cargo").success(),
"Failed to build WASM frontend"
);
wasm_file.exists(),
"WASM file not found: {}",
wasm_file.display()
let out_dir = PathBuf::from("static/wasm");
std::fs::create_dir_all(&out_dir).expect("Failed to create output directory");
let out_wasm = out_dir.join("nomisync_frontend_bg.wasm");
Bindgen::new()
.input_path(&wasm_file)
.web(true)
.expect("Failed to set web mode")
.omit_default_module_path(false)
.typescript(false)
.generate(&out_dir)
.expect("Failed to generate WASM bindings");
let status = Command::new("wasm-opt")
.args(["-Oz", "--output"])
.arg(&out_wasm)
.status();
if let Ok(status) = status {
if !status.success() {
eprintln!("Warning: wasm-opt failed, skipping optimization");
} else {
eprintln!("Warning: wasm-opt not found, skipping optimization");