-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathbuild.rs
More file actions
147 lines (130 loc) · 4.34 KB
/
build.rs
File metadata and controls
147 lines (130 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR not set"));
let web_dir = PathBuf::from("web");
if !web_dir.exists() {
panic!("missing `web/` directory; web assets are required for builds");
}
emit_rerun_for_paths(&[
PathBuf::from("pnpm-workspace.yaml"),
PathBuf::from("pnpm-lock.yaml"),
PathBuf::from("package.json"),
web_dir.join("src"),
web_dir.join("public"),
web_dir.join("index.html"),
web_dir.join("package.json"),
web_dir.join("components.json"),
web_dir.join("postcss.config.js"),
web_dir.join("vite.config.ts"),
web_dir.join("tsconfig.json"),
web_dir.join("tsconfig.node.json"),
]);
// Build inside OUT_DIR so that node_modules and dist are not created in
// the source tree. This is required for `cargo publish` which rejects
// build scripts that modify the source directory.
let build_root = out_dir.join("web-build");
copy_dir(&web_dir, &build_root.join("web"));
for file in &["pnpm-workspace.yaml", "pnpm-lock.yaml", "package.json"] {
let src = PathBuf::from(file);
if src.exists() {
fs::copy(&src, build_root.join(file)).unwrap_or_else(|err| {
panic!("failed to copy {file} to OUT_DIR: {err}");
});
}
}
run_pnpm(
&build_root,
&["install", "--frozen-lockfile", "--filter", "./web..."],
);
run_pnpm(&build_root, &["--filter", "./web", "build"]);
}
fn emit_rerun_for_paths(paths: &[PathBuf]) {
for path in paths {
if path.is_dir() {
emit_rerun_for_dir(path);
} else {
println!("cargo:rerun-if-changed={}", path.display());
}
}
}
fn emit_rerun_for_dir(dir: &Path) {
println!("cargo:rerun-if-changed={}", dir.display());
let mut stack = vec![dir.to_path_buf()];
while let Some(next) = stack.pop() {
let entries = match fs::read_dir(&next) {
Ok(entries) => entries,
Err(_) => continue,
};
for entry in entries.flatten() {
let path = entry.path();
if should_skip_path(&path) {
continue;
}
if path.is_dir() {
stack.push(path.clone());
}
println!("cargo:rerun-if-changed={}", path.display());
}
}
}
fn should_skip_path(path: &Path) -> bool {
path.file_name()
.and_then(OsStr::to_str)
.map(|name| matches!(name, "node_modules" | "dist"))
.unwrap_or(false)
}
fn copy_dir(src: &Path, dst: &Path) {
fs::create_dir_all(dst).unwrap_or_else(|err| {
panic!("failed to create {}: {err}", dst.display());
});
let mut stack = vec![(src.to_path_buf(), dst.to_path_buf())];
while let Some((s, d)) = stack.pop() {
let entries = match fs::read_dir(&s) {
Ok(entries) => entries,
Err(_) => continue,
};
for entry in entries.flatten() {
let path = entry.path();
let dest = d.join(entry.file_name());
if should_skip_path(&path) {
continue;
}
if path.is_dir() {
fs::create_dir_all(&dest).unwrap_or_else(|err| {
panic!("failed to create {}: {err}", dest.display());
});
stack.push((path, dest));
} else {
fs::copy(&path, &dest).unwrap_or_else(|err| {
panic!(
"failed to copy {} -> {}: {err}",
path.display(),
dest.display()
);
});
}
}
}
}
fn run_pnpm(cwd: &Path, args: &[&str]) {
let status = Command::new("pnpm")
.env("CI", "true")
.current_dir(cwd)
.args(args)
.status()
.unwrap_or_else(|err| {
panic!(
"failed to run `pnpm {}`: {err}. Install Node.js + pnpm to build Earl web assets.",
args.join(" ")
)
});
if !status.success() {
panic!(
"`pnpm {}` failed with status {status}. Fix the web build before running cargo commands.",
args.join(" ")
);
}
}