Skip to content

Commit c218583

Browse files
committed
fix(build): OUT_DIR for compile/publish, tests/generated mirror for local review
cargo publish verify forbids build.rs from writing outside OUT_DIR. build.rs always writes OUT_DIR/html_tests.rs (compiled via include! in tests/mod.rs); local (non-CI, non-target/package) builds additionally mirror per-case .rs under tests/generated/ for human review. CI (CI=true) and cargo package/publish verify (target/package) skip the mirror, so publish verification no longer sees source-tree modification.
1 parent 2f42ada commit c218583

2 files changed

Lines changed: 52 additions & 20 deletions

File tree

float-pigment-forest/build.rs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
// HTML -> imperative Rust translator: each tests/cases/<topic>/<case>.html
22
// is translated into a `#[test]` that exercises the TestCtx high-level API
33
// (create_node / create_text / set_style / append + layout_imperative +
4-
// getters). Output goes to tests/generated/<topic>/<case>.rs plus a nested
5-
// mod tree (tests/generated/mod.rs → <topic>/mod.rs → <case>.rs), which
6-
// tests/mod.rs pulls in via `mod generated;`.
4+
// getters).
5+
//
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.
715
//
816
// The translator walks the parsed DOM and emits imperative calls in
917
// document order. Layout assertions (data-expect-*) are collected during
@@ -19,13 +27,13 @@ use float_pigment_mlp::{
1927
fn main() {
2028
let manifest = std::env::var("CARGO_MANIFEST_DIR").unwrap();
2129
let cases_dir = PathBuf::from(&manifest).join("tests/cases");
22-
let gen_dir = PathBuf::from(&manifest).join("tests/generated");
23-
// 清空旧生成(删整个 generated 再重建,避免残留)
24-
let _ = fs::remove_dir_all(&gen_dir);
25-
fs::create_dir_all(&gen_dir).unwrap();
30+
let out = std::env::var("OUT_DIR").unwrap();
31+
let output_file = PathBuf::from(&out).join("html_tests.rs");
2632

27-
// topic -> Vec<(case_name, body, ignore)>
28-
let mut by_topic: std::collections::BTreeMap<String, Vec<(String, String, bool)>> =
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)>> =
2937
std::collections::BTreeMap::new();
3038

3139
if cases_dir.exists() {
@@ -39,28 +47,54 @@ fn main() {
3947
let mut parts = rel_str.split('/');
4048
let topic = parts.next().unwrap_or("misc").to_string();
4149
let name = parts.collect::<Vec<_>>().join("_");
50+
let topic_ident = topic.replace('-', "_");
51+
let name_ident = name.replace('-', "_");
52+
let fn_name = format!("html_{}_{}", topic_ident, name_ident);
4253
let html = fs::read_to_string(&abs).unwrap_or_default();
4354
let ignore = html.contains("data-ignore=\"true\"");
55+
let ignore_attr = if ignore { "#[ignore]\n" } else { "" };
4456
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+
));
4561
by_topic
4662
.entry(topic)
4763
.or_default()
48-
.push((name, body, ignore));
64+
.push((name, name_ident, body, ignore));
4965
}
5066
}
5167

52-
// 生成每 topic 目录 + mod.rs + 各 case .rs。
53-
// topic/name 原样用作目录名/文件名(文件系统允许 `-`),但需 sanitize
54-
// 为合法 Rust 标识符(`-` 非法)用于 mod 名与 fn 名。当前 cases 无 `-`,
55-
// 此 sanitize 为防御性 —— 与旧 build.rs `replace(['/', '\\', '-', ' '], "_")` 一致。
68+
fs::write(&output_file, tests).unwrap();
69+
70+
// Local builds also mirror per-case .rs under tests/generated/ for review.
71+
let is_ci = std::env::var("CI").is_ok();
72+
let is_publish_verify = manifest.contains("target/package");
73+
if !is_ci && !is_publish_verify {
74+
mirror_to_generated(&manifest, &by_topic);
75+
}
76+
77+
println!("cargo:rerun-if-changed=tests/cases");
78+
println!("cargo:rerun-if-changed=build.rs");
79+
}
80+
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)>>,
87+
) {
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();
5691
let mut top_mod = String::from("// AUTO-GENERATED by build.rs. Do not edit.\n\n");
57-
for (topic, cases) in &by_topic {
92+
for (topic, cases) in by_topic {
5893
let topic_dir = gen_dir.join(topic);
5994
fs::create_dir_all(&topic_dir).unwrap();
6095
let topic_ident = topic.replace('-', "_");
6196
let mut topic_mod = String::from("// AUTO-GENERATED. Do not edit.\n\n");
62-
for (name, body, ignore) in cases {
63-
let name_ident = name.replace('-', "_");
97+
for (name, name_ident, body, ignore) in cases {
6498
let fn_name = format!("html_{}_{}", topic_ident, name_ident);
6599
let ignore_attr = if *ignore { "#[ignore]\n" } else { "" };
66100
let case_rs = format!(
@@ -73,8 +107,6 @@ fn main() {
73107
top_mod.push_str(&format!("mod {topic_ident};\n"));
74108
}
75109
fs::write(gen_dir.join("mod.rs"), top_mod).unwrap();
76-
println!("cargo:rerun-if-changed=tests/cases");
77-
println!("cargo:rerun-if-changed=build.rs");
78110
}
79111

80112
/// 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-
mod generated;
680+
include!(concat!(env!("OUT_DIR"), "/html_tests.rs"));

0 commit comments

Comments
 (0)