Skip to content

Commit 91cc6a5

Browse files
committed
build: OUT_DIR per-case tree (all.rs aggregates) instead of single file
OUT_DIR/generated/<topic>/<case>.rs (per-case) + all.rs which include!s each. tests/mod.rs does include!(OUT_DIR/generated/all.rs). Nested include! works because inner paths resolve relative to all.rs (which sits next to the <topic>/ dirs). Each per-case fn puts `use crate::TestCtx` inside the fn body so all.rs flat include! does not duplicate the use. Local builds mirror the same tree under tests/generated/; CI (CI=true) and cargo package/publish verify (target/package) skip the mirror. cargo package verify passes (writes only inside OUT_DIR).
1 parent c218583 commit 91cc6a5

2 files changed

Lines changed: 44 additions & 38 deletions

File tree

float-pigment-forest/build.rs

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,27 @@
33
// (create_node / create_text / set_style / append + layout_imperative +
44
// getters).
55
//
6-
// Output strategy:
7-
// - Always: OUT_DIR/html_tests.rs (single file, all #[test] inlined),
8-
// pulled in by tests/mod.rs via `include!`. This is what compiles.
9-
// - Local (non-CI, non-publish-verify) builds ALSO mirror per-case .rs
10-
// files under tests/generated/<topic>/<case>.rs (+ mod tree) for human
11-
// review. CI (CI=true) and `cargo package`/`publish` verify
12-
// (CARGO_MANIFEST_DIR under target/package) skip the mirror — CI doesn't
13-
// need it, and publish verify forbids build.rs from writing outside
14-
// OUT_DIR.
6+
// Output (per-case .rs under <gen_dir>/<topic>/<case>.rs, not one big file):
7+
// - OUT_DIR/generated/<topic>/<case>.rs + OUT_DIR/generated/all.rs
8+
// (all.rs does `include!("topic/case.rs")` for each case — paths resolve
9+
// relative to all.rs, which lives next to the <topic>/ dirs). tests/mod.rs
10+
// pulls all.rs in via `include!(OUT_DIR/generated/all.rs)`. This is what
11+
// compiles.
12+
// - Local (non-CI, non-publish-verify) builds ALSO write the same tree
13+
// under tests/generated/ for human review. CI (CI=true) and cargo
14+
// package/publish verify (CARGO_MANIFEST_DIR under target/package) skip
15+
// the tests/generated mirror — CI doesn't need it, and publish verify
16+
// forbids build.rs from writing outside OUT_DIR.
17+
//
18+
// Each per-case .rs puts `use crate::TestCtx;` *inside* the fn so that
19+
// all.rs's flat include! sequence doesn't trip "duplicate use" — each fn
20+
// brings TestCtx into its own scope.
1521
//
1622
// The translator walks the parsed DOM and emits imperative calls in
1723
// document order. Layout assertions (data-expect-*) are collected during
1824
// the walk and emitted after `ctx.layout_imperative()` so they read back
1925
// computed values.
20-
use std::{fs, path::PathBuf};
26+
use std::{collections::BTreeMap, fs, path::{Path, PathBuf}};
2127

2228
use float_pigment_mlp::{
2329
context::{Context, Parse},
@@ -28,13 +34,10 @@ fn main() {
2834
let manifest = std::env::var("CARGO_MANIFEST_DIR").unwrap();
2935
let cases_dir = PathBuf::from(&manifest).join("tests/cases");
3036
let out = std::env::var("OUT_DIR").unwrap();
31-
let output_file = PathBuf::from(&out).join("html_tests.rs");
37+
let out_gen = PathBuf::from(&out).join("generated");
3238

33-
let mut tests = String::from("// AUTO-GENERATED by build.rs. Do not edit.\n\n");
34-
// topic -> Vec<(case_name, name_ident, body, ignore)>, used to mirror
35-
// per-case .rs files under tests/generated in local builds.
36-
let mut by_topic: std::collections::BTreeMap<String, Vec<(String, String, String, bool)>> =
37-
std::collections::BTreeMap::new();
39+
// topic -> Vec<(case_name, name_ident, body, ignore)>
40+
let mut by_topic: BTreeMap<String, Vec<(String, String, String, bool)>> = BTreeMap::new();
3841

3942
if cases_dir.exists() {
4043
let mut entries = walk(&cases_dir, &cases_dir);
@@ -47,47 +50,44 @@ fn main() {
4750
let mut parts = rel_str.split('/');
4851
let topic = parts.next().unwrap_or("misc").to_string();
4952
let name = parts.collect::<Vec<_>>().join("_");
50-
let topic_ident = topic.replace('-', "_");
5153
let name_ident = name.replace('-', "_");
52-
let fn_name = format!("html_{}_{}", topic_ident, name_ident);
5354
let html = fs::read_to_string(&abs).unwrap_or_default();
5455
let ignore = html.contains("data-ignore=\"true\"");
55-
let ignore_attr = if ignore { "#[ignore]\n" } else { "" };
5656
let body = translate_html(&html);
57-
// OUT_DIR/html_tests.rs — compiled via include! in tests/mod.rs.
58-
tests.push_str(&format!(
59-
"{ignore_attr}#[test]\nfn {fn_name}() {{\n use crate::TestCtx;\n{body}}}\n\n"
60-
));
6157
by_topic
6258
.entry(topic)
6359
.or_default()
6460
.push((name, name_ident, body, ignore));
6561
}
6662
}
6763

68-
fs::write(&output_file, tests).unwrap();
64+
// OUT_DIR/generated: per-case .rs + all.rs (compiled). all.rs is always
65+
// emitted here; mod.rs/ tree is also emitted (harmless, aids browsing).
66+
write_cases_tree(&out_gen, &by_topic, true);
6967

70-
// Local builds also mirror per-case .rs under tests/generated/ for review.
68+
// Local mirror under tests/generated for human review.
7169
let is_ci = std::env::var("CI").is_ok();
7270
let is_publish_verify = manifest.contains("target/package");
7371
if !is_ci && !is_publish_verify {
74-
mirror_to_generated(&manifest, &by_topic);
72+
let gen_dir = PathBuf::from(&manifest).join("tests/generated");
73+
write_cases_tree(&gen_dir, &by_topic, false);
7574
}
7675

7776
println!("cargo:rerun-if-changed=tests/cases");
7877
println!("cargo:rerun-if-changed=build.rs");
7978
}
8079

81-
/// Mirror per-case .rs files (+ nested mod tree) under tests/generated/ for
82-
/// human review. Not compiled (tests/mod.rs uses the OUT_DIR include!), so
83-
/// purely for readability.
84-
fn mirror_to_generated(
85-
manifest: &str,
86-
by_topic: &std::collections::BTreeMap<String, Vec<(String, String, String, bool)>>,
80+
/// Write per-case .rs under `<gen_dir>/<topic>/<case>.rs` plus a nested
81+
/// `mod.rs` tree (browsing aid) and, when `emit_all_rs`, an `all.rs` that
82+
/// `include!`s every case — that all.rs is what tests/mod.rs compiles.
83+
fn write_cases_tree(
84+
gen_dir: &Path,
85+
by_topic: &BTreeMap<String, Vec<(String, String, String, bool)>>,
86+
emit_all_rs: bool,
8787
) {
88-
let gen_dir = PathBuf::from(manifest).join("tests/generated");
89-
let _ = fs::remove_dir_all(&gen_dir);
90-
fs::create_dir_all(&gen_dir).unwrap();
88+
let _ = fs::remove_dir_all(gen_dir);
89+
fs::create_dir_all(gen_dir).unwrap();
90+
let mut all_rs = String::from("// AUTO-GENERATED by build.rs. Do not edit.\n\n");
9191
let mut top_mod = String::from("// AUTO-GENERATED by build.rs. Do not edit.\n\n");
9292
for (topic, cases) in by_topic {
9393
let topic_dir = gen_dir.join(topic);
@@ -98,15 +98,21 @@ fn mirror_to_generated(
9898
let fn_name = format!("html_{}_{}", topic_ident, name_ident);
9999
let ignore_attr = if *ignore { "#[ignore]\n" } else { "" };
100100
let case_rs = format!(
101-
"// AUTO-GENERATED from tests/cases/{topic}/{name}.html. Do not edit.\nuse crate::TestCtx;\n\n{ignore_attr}#[rustfmt::skip]\n#[test]\nfn {fn_name}() {{\n{body}}}\n"
101+
"// AUTO-GENERATED from tests/cases/{topic}/{name}.html. Do not edit.\n\n{ignore_attr}#[rustfmt::skip]\n#[test]\nfn {fn_name}() {{\n use crate::TestCtx;\n{body}}}\n"
102102
);
103-
fs::write(topic_dir.join(format!("{name}.rs")), case_rs).unwrap();
103+
fs::write(topic_dir.join(format!("{name}.rs")), &case_rs).unwrap();
104+
// all.rs includes each case; path is relative to all.rs (gen_dir),
105+
// which sits next to <topic>/, so "<topic>/<case>.rs" resolves.
106+
all_rs.push_str(&format!("include!(\"{topic}/{name}.rs\");\n"));
104107
topic_mod.push_str(&format!("mod {name_ident};\n"));
105108
}
106109
fs::write(topic_dir.join("mod.rs"), topic_mod).unwrap();
107110
top_mod.push_str(&format!("mod {topic_ident};\n"));
108111
}
109112
fs::write(gen_dir.join("mod.rs"), top_mod).unwrap();
113+
if emit_all_rs {
114+
fs::write(gen_dir.join("all.rs"), all_rs).unwrap();
115+
}
110116
}
111117

112118
/// Parse the HTML and emit imperative TestCtx calls.

float-pigment-forest/tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,4 +677,4 @@ fn convert_grid_auto(grid_auto: GridAuto) -> LayoutGridAuto<Len> {
677677
}
678678
}
679679

680-
include!(concat!(env!("OUT_DIR"), "/html_tests.rs"));
680+
include!(concat!(env!("OUT_DIR"), "/generated/all.rs"));

0 commit comments

Comments
 (0)