Skip to content

Commit 5c544f8

Browse files
committed
Refactor out all panics. Use anyhow instead.
1 parent 2395dd7 commit 5c544f8

File tree

12 files changed

+308
-252
lines changed

12 files changed

+308
-252
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ exclude = [
1414
resolver = "2"
1515

1616
[workspace.dependencies]
17+
anyhow = "1.0.94"
1718
clap = { version = "4.4.8", features = ["derive"] }
18-
chrono = { version = "0.4.38", default-features = false }
19+
chrono = { version = "0.4.38", default-features = false, features = ["std"] }
1920
directories = "5.0.1"
2021
env_home = "0.1.0"
2122
env_logger = "0.10"
@@ -51,9 +52,4 @@ pattern_type_mismatch = { level = "allow", priority = 1 }
5152
print_stdout = { level = "allow", priority = 1 }
5253
std_instead_of_alloc = { level = "allow", priority = 1 }
5354

54-
# TODO: Try to not depend on allowing these lints
55-
unwrap_used = { level = "allow", priority = 1 }
56-
get_unwrap = { level = "allow", priority = 1 }
57-
expect_used = { level = "allow", priority = 1 }
58-
panic = { level = "allow", priority = 1 }
5955

clippy.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
allow-unwrap-in-tests = true
2+
allow-panic-in-tests = true

crates/cargo-gpu/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ keywords = ["gpu", "compiler"]
99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

1111
[dependencies]
12+
anyhow.workspace = true
1213
spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false }
1314
clap.workspace = true
1415
directories.workspace = true

crates/cargo-gpu/src/build.rs

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use std::io::Write as _;
44

5+
use anyhow::Context as _;
56
use clap::Parser;
67
use spirv_builder_cli::{Linkage, ShaderModule};
78

@@ -33,45 +34,43 @@ pub struct Build {
3334

3435
impl Build {
3536
/// Entrypoint
36-
pub fn run(&mut self) {
37-
let (dylib_path, spirv_builder_cli_path) = self.install.run();
37+
pub fn run(&mut self) -> anyhow::Result<()> {
38+
let (dylib_path, spirv_builder_cli_path) = self.install.run()?;
3839

3940
// Ensure the shader output dir exists
4041
log::debug!("ensuring output-dir '{}' exists", self.output_dir.display());
41-
std::fs::create_dir_all(&self.output_dir).unwrap();
42-
self.output_dir = self.output_dir.canonicalize().unwrap();
42+
std::fs::create_dir_all(&self.output_dir)?;
43+
self.output_dir = self.output_dir.canonicalize()?;
4344

4445
// Ensure the shader crate exists
45-
self.install.shader_crate = self.install.shader_crate.canonicalize().unwrap();
46-
assert!(
46+
self.install.shader_crate = self.install.shader_crate.canonicalize()?;
47+
anyhow::ensure!(
4748
self.install.shader_crate.exists(),
4849
"shader crate '{}' does not exist. (Current dir is '{}')",
4950
self.install.shader_crate.display(),
50-
std::env::current_dir().unwrap().display()
51+
std::env::current_dir()?.display()
5152
);
5253

5354
let spirv_builder_args = spirv_builder_cli::Args {
5455
dylib_path,
5556
shader_crate: self.install.shader_crate.clone(),
5657
shader_target: self.shader_target.clone(),
57-
path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)),
58+
path_to_target_spec: target_spec_dir()?.join(format!("{}.json", self.shader_target)),
5859
no_default_features: self.no_default_features,
5960
features: self.features.clone(),
6061
output_dir: self.output_dir.clone(),
6162
};
6263

63-
// UNWRAP: safe because we know this always serializes
64-
let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap();
64+
let arg = serde_json::to_string_pretty(&spirv_builder_args)?;
6565
log::info!("using spirv-builder-cli arg: {arg}");
6666

6767
// Call spirv-builder-cli to compile the shaders.
6868
let output = std::process::Command::new(spirv_builder_cli_path)
6969
.arg(arg)
7070
.stdout(std::process::Stdio::inherit())
7171
.stderr(std::process::Stdio::inherit())
72-
.output()
73-
.unwrap();
74-
assert!(output.status.success(), "build failed");
72+
.output()?;
73+
anyhow::ensure!(output.status.success(), "build failed");
7574

7675
let spirv_manifest = self.output_dir.join("spirv-manifest.json");
7776
if spirv_manifest.is_file() {
@@ -81,51 +80,52 @@ impl Build {
8180
);
8281
} else {
8382
log::error!("missing raw manifest '{}'", spirv_manifest.display());
84-
panic!("missing raw manifest");
83+
anyhow::bail!("missing raw manifest");
8584
}
8685

8786
let shaders: Vec<ShaderModule> =
88-
serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap();
87+
serde_json::from_reader(std::fs::File::open(&spirv_manifest)?)?;
8988

90-
let mut linkage: Vec<_> = shaders
89+
let mut linkage: Vec<Linkage> = shaders
9190
.into_iter()
9291
.map(
9392
|ShaderModule {
9493
entry,
9594
path: filepath,
96-
}| {
95+
}|
96+
-> anyhow::Result<Linkage> {
9797
use relative_path::PathExt as _;
98-
let path = self.output_dir.join(filepath.file_name().unwrap());
99-
std::fs::copy(&filepath, &path).unwrap();
100-
let path_relative_to_shader_crate = path
101-
.relative_to(&self.install.shader_crate)
102-
.unwrap()
103-
.to_path("");
104-
Linkage::new(entry, path_relative_to_shader_crate)
98+
let path = self.output_dir.join(
99+
filepath
100+
.file_name()
101+
.context("Couldn't parse file name from shader module path")?,
102+
);
103+
std::fs::copy(&filepath, &path)?;
104+
let path_relative_to_shader_crate =
105+
path.relative_to(&self.install.shader_crate)?.to_path("");
106+
Ok(Linkage::new(entry, path_relative_to_shader_crate))
105107
},
106108
)
107-
.collect();
109+
.collect::<anyhow::Result<Vec<Linkage>>>()?;
108110

109111
// Write the shader manifest json file
110112
let manifest_path = self.output_dir.join("manifest.json");
111113
// Sort the contents so the output is deterministic
112114
linkage.sort();
113115
// UNWRAP: safe because we know this always serializes
114-
let json = serde_json::to_string_pretty(&linkage).unwrap();
115-
let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|error| {
116-
log::error!(
117-
"could not create shader manifest file '{}': {error}",
116+
let json = serde_json::to_string_pretty(&linkage)?;
117+
let mut file = std::fs::File::create(&manifest_path).with_context(|| {
118+
format!(
119+
"could not create shader manifest file '{}'",
118120
manifest_path.display(),
119-
);
120-
panic!("{error}")
121-
});
122-
file.write_all(json.as_bytes()).unwrap_or_else(|error| {
123-
log::error!(
124-
"could not write shader manifest file '{}': {error}",
121+
)
122+
})?;
123+
file.write_all(json.as_bytes()).with_context(|| {
124+
format!(
125+
"could not write shader manifest file '{}'",
125126
manifest_path.display(),
126-
);
127-
panic!("{error}")
128-
});
127+
)
128+
})?;
129129

130130
log::info!("wrote manifest to '{}'", manifest_path.display());
131131

@@ -134,8 +134,10 @@ impl Build {
134134
"removing spirv-manifest.json file '{}'",
135135
spirv_manifest.display()
136136
);
137-
std::fs::remove_file(spirv_manifest).unwrap();
137+
std::fs::remove_file(spirv_manifest)?;
138138
}
139+
140+
Ok(())
139141
}
140142
}
141143

crates/cargo-gpu/src/install.rs

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it.
22
use std::io::Write as _;
33

4+
use anyhow::Context as _;
5+
46
use crate::{cache_dir, spirv_cli::SpirvCli, spirv_source::SpirvSource, target_spec_dir};
57

68
/// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create.
@@ -120,7 +122,7 @@ pub struct Install {
120122

121123
impl Install {
122124
/// Returns a [`SpirvCLI`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate.
123-
fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> SpirvCli {
125+
fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> anyhow::Result<SpirvCli> {
124126
SpirvCli::new(
125127
shader_crate_path,
126128
self.spirv_builder_source.clone(),
@@ -130,20 +132,21 @@ impl Install {
130132
}
131133

132134
/// Create the `spirv-builder-cli` crate.
133-
fn write_source_files(&self) {
134-
let spirv_cli = self.spirv_cli(&self.shader_crate);
135-
let checkout = spirv_cli.cached_checkout_path();
136-
std::fs::create_dir_all(checkout.join("src")).unwrap();
135+
fn write_source_files(&self) -> anyhow::Result<()> {
136+
let spirv_cli = self.spirv_cli(&self.shader_crate)?;
137+
let checkout = spirv_cli.cached_checkout_path()?;
138+
std::fs::create_dir_all(checkout.join("src"))?;
137139
for (filename, contents) in SPIRV_BUILDER_FILES {
138140
log::debug!("writing {filename}");
139141
let path = checkout.join(filename);
140-
let mut file = std::fs::File::create(&path).unwrap();
142+
let mut file = std::fs::File::create(&path)?;
141143
let mut replaced_contents = contents.replace("${CHANNEL}", &spirv_cli.channel);
142144
if filename == &"Cargo.toml" {
143145
replaced_contents = Self::update_cargo_toml(&replaced_contents, &spirv_cli.source);
144146
}
145-
file.write_all(replaced_contents.as_bytes()).unwrap();
147+
file.write_all(replaced_contents.as_bytes())?;
146148
}
149+
Ok(())
147150
}
148151

149152
/// Update the `Cargo.toml` file in the `spirv-builder-cli` crate so that it contains
@@ -176,33 +179,30 @@ impl Install {
176179
}
177180

178181
/// Add the target spec files to the crate.
179-
fn write_target_spec_files(&self) {
182+
fn write_target_spec_files(&self) -> anyhow::Result<()> {
180183
for (filename, contents) in TARGET_SPECS {
181-
let path = target_spec_dir().join(filename);
184+
let path = target_spec_dir()?.join(filename);
182185
if !path.is_file() || self.force_spirv_cli_rebuild {
183-
let mut file = std::fs::File::create(&path).unwrap();
184-
file.write_all(contents.as_bytes()).unwrap();
186+
let mut file = std::fs::File::create(&path)?;
187+
file.write_all(contents.as_bytes())?;
185188
}
186189
}
190+
Ok(())
187191
}
188192

189193
/// Install the binary pair and return the paths, (dylib, cli).
190-
pub fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) {
194+
pub fn run(&self) -> anyhow::Result<(std::path::PathBuf, std::path::PathBuf)> {
191195
// Ensure the cache dir exists
192-
let cache_dir = cache_dir();
196+
let cache_dir = cache_dir()?;
193197
log::info!("cache directory is '{}'", cache_dir.display());
194-
std::fs::create_dir_all(&cache_dir).unwrap_or_else(|error| {
195-
log::error!(
196-
"could not create cache directory '{}': {error}",
197-
cache_dir.display()
198-
);
199-
panic!("could not create cache dir");
200-
});
198+
std::fs::create_dir_all(&cache_dir).with_context(|| {
199+
format!("could not create cache directory '{}'", cache_dir.display())
200+
})?;
201201

202-
let spirv_version = self.spirv_cli(&self.shader_crate);
203-
spirv_version.ensure_toolchain_and_components_exist();
202+
let spirv_version = self.spirv_cli(&self.shader_crate)?;
203+
spirv_version.ensure_toolchain_and_components_exist()?;
204204

205-
let checkout = spirv_version.cached_checkout_path();
205+
let checkout = spirv_version.cached_checkout_path()?;
206206
let release = checkout.join("target").join("release");
207207

208208
let dylib_filename = format!(
@@ -227,8 +227,8 @@ impl Install {
227227
"writing spirv-builder-cli source files into '{}'",
228228
checkout.display()
229229
);
230-
self.write_source_files();
231-
self.write_target_spec_files();
230+
self.write_source_files()?;
231+
self.write_target_spec_files()?;
232232

233233
let mut command = std::process::Command::new("cargo");
234234
command
@@ -239,24 +239,23 @@ impl Install {
239239

240240
command.args([
241241
"--features",
242-
&Self::get_required_spirv_builder_version(spirv_version.date),
242+
&Self::get_required_spirv_builder_version(spirv_version.date)?,
243243
]);
244244

245245
log::debug!("building artifacts with `{:?}`", command);
246246

247247
let output = command
248248
.stdout(std::process::Stdio::inherit())
249249
.stderr(std::process::Stdio::inherit())
250-
.output()
251-
.unwrap();
252-
assert!(output.status.success(), "...build error!");
250+
.output()?;
251+
anyhow::ensure!(output.status.success(), "...build error!");
253252

254253
if dylib_path.is_file() {
255254
log::info!("successfully built {}", dylib_path.display());
256-
std::fs::rename(&dylib_path, &dest_dylib_path).unwrap();
255+
std::fs::rename(&dylib_path, &dest_dylib_path)?;
257256
} else {
258257
log::error!("could not find {}", dylib_path.display());
259-
panic!("spirv-builder-cli build failed");
258+
anyhow::bail!("spirv-builder-cli build failed");
260259
}
261260

262261
let cli_path = if cfg!(target_os = "windows") {
@@ -266,18 +265,18 @@ impl Install {
266265
};
267266
if cli_path.is_file() {
268267
log::info!("successfully built {}", cli_path.display());
269-
std::fs::rename(&cli_path, &dest_cli_path).unwrap();
268+
std::fs::rename(&cli_path, &dest_cli_path)?;
270269
} else {
271270
log::error!("could not find {}", cli_path.display());
272271
log::debug!("contents of '{}':", release.display());
273-
for maybe_entry in std::fs::read_dir(&release).unwrap() {
274-
let entry = maybe_entry.unwrap();
272+
for maybe_entry in std::fs::read_dir(&release)? {
273+
let entry = maybe_entry?;
275274
log::debug!("{}", entry.file_name().to_string_lossy());
276275
}
277-
panic!("spirv-builder-cli build failed");
276+
anyhow::bail!("spirv-builder-cli build failed");
278277
}
279278
}
280-
(dest_dylib_path, dest_cli_path)
279+
Ok((dest_dylib_path, dest_cli_path))
281280
}
282281

283282
/// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to
@@ -287,15 +286,15 @@ impl Install {
287286
/// TODO:
288287
/// * Warn the user that certain `cargo-gpu` features aren't available when building with
289288
/// older versions of `spirv-builder`, eg setting the target spec.
290-
fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> String {
289+
fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> anyhow::Result<String> {
291290
let parse_date = chrono::NaiveDate::parse_from_str;
292-
let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap();
291+
let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d")?;
293292

294-
if date < pre_cli_date {
293+
Ok(if date < pre_cli_date {
295294
"spirv-builder-pre-cli"
296295
} else {
297296
"spirv-builder-0_10"
298297
}
299-
.into()
298+
.into())
300299
}
301300
}

0 commit comments

Comments
 (0)