This repository has no description
3.1 kB
86 lines
1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result};
4use jacquard_lexicon::codegen::{CodeGenerator, CodegenMode};
5use jacquard_lexicon::corpus::LexiconCorpus;
6use walkdir::WalkDir;
7
8const LEXICONS_SUBDIR: &str = "lexicons";
9const STAGED_SUBDIR: &str = "lexicons-staged";
10const GENERATED_SUBDIR: &str = "src/_lex";
11const TEMP_SEGMENT: &str = "temp";
12
13fn main() -> Result<()> {
14 let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?);
15 let knot_root = manifest_dir
16 .parent()
17 .and_then(Path::parent)
18 .context("resolve knot root from manifest dir")?
19 .to_path_buf();
20 let workspace_root = knot_root
21 .parent()
22 .context("resolve workspace root from knot root")?
23 .to_path_buf();
24
25 let lexicons_dir = std::env::var("KNOT_LEXICONS_DIR")
26 .map(PathBuf::from)
27 .unwrap_or_else(|_| workspace_root.join(LEXICONS_SUBDIR));
28 let vendored_dir = knot_root.join(LEXICONS_SUBDIR);
29
30 println!("cargo:rerun-if-env-changed=KNOT_LEXICONS_DIR");
31 println!("cargo:rerun-if-changed={}", lexicons_dir.display());
32 println!("cargo:rerun-if-changed={}", vendored_dir.display());
33 println!("cargo:rerun-if-changed=build.rs");
34
35 let out_dir = PathBuf::from(std::env::var("OUT_DIR")?);
36 let staged = out_dir.join(STAGED_SUBDIR);
37 if staged.exists() {
38 std::fs::remove_dir_all(&staged).context("clean staged lexicons")?;
39 }
40 stage_lexicons(&lexicons_dir, &staged)?;
41 stage_lexicons(&vendored_dir, &staged)?;
42
43 let corpus = LexiconCorpus::load_from_dir(&staged)
44 .map_err(|e| anyhow::anyhow!("load lexicon corpus: {e:?}"))?;
45
46 let generated = manifest_dir.join(GENERATED_SUBDIR);
47 if generated.exists() {
48 std::fs::remove_dir_all(&generated).context("clean generated dir")?;
49 }
50 std::fs::create_dir_all(&generated).context("create generated dir")?;
51
52 let codegen = CodeGenerator::with_mode(&corpus, "crate", CodegenMode::Pretty);
53 codegen
54 .write_to_disk(&generated)
55 .map_err(|e| anyhow::anyhow!("write generated code: {e:?}"))?;
56
57 Ok(())
58}
59
60fn stage_lexicons(src: &Path, dst: &Path) -> Result<()> {
61 WalkDir::new(src)
62 .into_iter()
63 .filter_map(std::result::Result::ok)
64 .filter(|entry| entry.file_type().is_file())
65 .filter(|entry| {
66 entry
67 .path()
68 .extension()
69 .is_some_and(|ext| ext.eq_ignore_ascii_case("json"))
70 })
71 .filter(|entry| {
72 !entry
73 .path()
74 .components()
75 .any(|component| component.as_os_str() == TEMP_SEGMENT)
76 })
77 .try_for_each(|entry| -> Result<()> {
78 let rel = entry.path().strip_prefix(src).context("strip src prefix")?;
79 let target = dst.join(rel);
80 if let Some(parent) = target.parent() {
81 std::fs::create_dir_all(parent).context("create staged parent")?;
82 }
83 std::fs::copy(entry.path(), &target).context("copy lexicon file")?;
84 Ok(())
85 })
86}