|
1 | 1 | use std::env;
|
| 2 | +use std::error::Error; |
2 | 3 | use std::fs;
|
3 | 4 | use std::path::{Path, PathBuf};
|
4 | 5 |
|
@@ -92,14 +93,25 @@ impl Build {
|
92 | 93 |
|
93 | 94 | /// Builds the Lua artifacts for the specified version.
|
94 | 95 | pub fn build(&self, version: Version) -> Artifacts {
|
95 |
| - let target = &self.target.as_ref().expect("TARGET is not set")[..]; |
96 |
| - let out_dir = self.out_dir.as_ref().expect("OUT_DIR is not set"); |
| 96 | + match self.try_build(version) { |
| 97 | + Ok(artifacts) => artifacts, |
| 98 | + Err(err) => panic!("{err}"), |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + /// Attempts to build the Lua artifacts for the specified version. |
| 103 | + /// |
| 104 | + /// Returns an error if the build fails. |
| 105 | + pub fn try_build(&self, version: Version) -> Result<Artifacts, Box<dyn Error>> { |
| 106 | + let target = self.target.as_ref().ok_or("TARGET is not set")?; |
| 107 | + let out_dir = self.out_dir.as_ref().ok_or("OUT_DIR is not set")?; |
97 | 108 | let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
|
98 | 109 | let mut source_dir = manifest_dir.join(version.source_dir());
|
99 | 110 | let include_dir = out_dir.join("include");
|
100 | 111 |
|
101 | 112 | if !include_dir.exists() {
|
102 |
| - fs::create_dir_all(&include_dir).unwrap(); |
| 113 | + fs::create_dir_all(&include_dir) |
| 114 | + .context(|| format!("Cannot create '{}'", include_dir.display()))?; |
103 | 115 | }
|
104 | 116 |
|
105 | 117 | let mut config = cc::Build::new();
|
@@ -148,27 +160,33 @@ impl Build {
|
148 | 160 |
|
149 | 161 | let cpp_source_dir = out_dir.join("cpp_source");
|
150 | 162 | if cpp_source_dir.exists() {
|
151 |
| - fs::remove_dir_all(&cpp_source_dir).unwrap(); |
| 163 | + fs::remove_dir_all(&cpp_source_dir) |
| 164 | + .context(|| format!("Cannot remove '{}'", cpp_source_dir.display()))?; |
152 | 165 | }
|
153 |
| - fs::create_dir_all(&cpp_source_dir).unwrap(); |
| 166 | + fs::create_dir_all(&cpp_source_dir) |
| 167 | + .context(|| format!("Cannot create '{}'", cpp_source_dir.display()))?; |
154 | 168 |
|
155 |
| - for file in fs::read_dir(&source_dir).unwrap() { |
156 |
| - let file = file.unwrap(); |
| 169 | + for file in fs::read_dir(&source_dir) |
| 170 | + .context(|| format!("Cannot read '{}'", source_dir.display()))? |
| 171 | + { |
| 172 | + let file = file?; |
157 | 173 | let filename = file.file_name();
|
158 |
| - let filename = filename.to_str().unwrap(); |
| 174 | + let filename = &*filename.to_string_lossy(); |
159 | 175 | let src_file = source_dir.join(file.file_name());
|
160 | 176 | let dst_file = cpp_source_dir.join(file.file_name());
|
161 | 177 |
|
162 |
| - let mut content = fs::read(src_file).unwrap(); |
| 178 | + let mut content = fs::read(&src_file) |
| 179 | + .context(|| format!("Cannot read '{}'", src_file.display()))?; |
163 | 180 | if ["lauxlib.h", "lua.h", "lualib.h"].contains(&filename) {
|
164 | 181 | content.splice(0..0, b"extern \"C\" {\n".to_vec());
|
165 | 182 | content.extend(b"\n}".to_vec())
|
166 | 183 | }
|
167 |
| - fs::write(dst_file, content).unwrap(); |
| 184 | + fs::write(&dst_file, content) |
| 185 | + .context(|| format!("Cannot write to '{}'", dst_file.display()))?; |
168 | 186 | }
|
169 | 187 | source_dir = cpp_source_dir
|
170 | 188 | }
|
171 |
| - _ => panic!("don't know how to build Lua for {target}"), |
| 189 | + _ => Err(format!("don't know how to build Lua for {target}"))?, |
172 | 190 | }
|
173 | 191 |
|
174 | 192 | if let Lua54 = version {
|
@@ -199,19 +217,22 @@ impl Build {
|
199 | 217 | .include(&source_dir)
|
200 | 218 | .flag("-w") // Suppress all warnings
|
201 | 219 | .flag_if_supported("-fno-common") // Compile common globals like normal definitions
|
202 |
| - .add_files_by_ext(&source_dir, "c") |
| 220 | + .add_files_by_ext(&source_dir, "c")? |
203 | 221 | .out_dir(out_dir)
|
204 |
| - .compile(version.lib_name()); |
| 222 | + .try_compile(version.lib_name())?; |
205 | 223 |
|
206 | 224 | for f in &["lauxlib.h", "lua.h", "luaconf.h", "lualib.h"] {
|
207 |
| - fs::copy(source_dir.join(f), include_dir.join(f)).unwrap(); |
| 225 | + let from = source_dir.join(f); |
| 226 | + let to = include_dir.join(f); |
| 227 | + fs::copy(&from, &to) |
| 228 | + .context(|| format!("Cannot copy '{}' to '{}'", from.display(), to.display()))?; |
208 | 229 | }
|
209 | 230 |
|
210 |
| - Artifacts { |
| 231 | + Ok(Artifacts { |
211 | 232 | include_dir,
|
212 | 233 | lib_dir: out_dir.clone(),
|
213 | 234 | libs: vec![version.lib_name().to_string()],
|
214 |
| - } |
| 235 | + }) |
215 | 236 | }
|
216 | 237 | }
|
217 | 238 |
|
@@ -263,19 +284,29 @@ impl Artifacts {
|
263 | 284 | }
|
264 | 285 | }
|
265 | 286 |
|
| 287 | +trait ErrorContext<T> { |
| 288 | + fn context(self, f: impl FnOnce() -> String) -> Result<T, Box<dyn Error>>; |
| 289 | +} |
| 290 | + |
| 291 | +impl<T, E: Error> ErrorContext<T> for Result<T, E> { |
| 292 | + fn context(self, f: impl FnOnce() -> String) -> Result<T, Box<dyn Error>> { |
| 293 | + self.map_err(|e| format!("{}: {e}", f()).into()) |
| 294 | + } |
| 295 | +} |
| 296 | + |
266 | 297 | trait AddFilesByExt {
|
267 |
| - fn add_files_by_ext(&mut self, dir: &Path, ext: &str) -> &mut Self; |
| 298 | + fn add_files_by_ext(&mut self, dir: &Path, ext: &str) -> Result<&mut Self, Box<dyn Error>>; |
268 | 299 | }
|
269 | 300 |
|
270 | 301 | impl AddFilesByExt for cc::Build {
|
271 |
| - fn add_files_by_ext(&mut self, dir: &Path, ext: &str) -> &mut Self { |
| 302 | + fn add_files_by_ext(&mut self, dir: &Path, ext: &str) -> Result<&mut Self, Box<dyn Error>> { |
272 | 303 | for entry in fs::read_dir(dir)
|
273 |
| - .unwrap() |
| 304 | + .context(|| format!("Cannot read '{}'", dir.display()))? |
274 | 305 | .filter_map(|e| e.ok())
|
275 | 306 | .filter(|e| e.path().extension() == Some(ext.as_ref()))
|
276 | 307 | {
|
277 | 308 | self.file(entry.path());
|
278 | 309 | }
|
279 |
| - self |
| 310 | + Ok(self) |
280 | 311 | }
|
281 | 312 | }
|
0 commit comments