Skip to content

Commit f02f61c

Browse files
committed
adjust build action to use SpirvBuilder
1 parent 8b5ea07 commit f02f61c

File tree

5 files changed

+72
-127
lines changed

5 files changed

+72
-127
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ exclude = [
1313
resolver = "2"
1414

1515
[workspace.dependencies]
16-
spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "744c844eb761edf23bcd379b5271d128128d7dfa", default-features = false }
16+
spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "436846c9084920f6ed6840370ec9d694d13ded32", default-features = false }
1717
anyhow = "1.0.94"
1818
clap = { version = "4.5.37", features = ["derive"] }
1919
chrono = { version = "0.4.38", default-features = false, features = ["std"] }

crates/cargo-gpu/src/build.rs

+51-88
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
#![allow(clippy::unwrap_used, reason = "this is basically a test")]
33
//! `cargo gpu build`, analogous to `cargo build`
44
5-
use anyhow::Context as _;
6-
use std::io::Write as _;
7-
85
use crate::args::BuildArgs;
9-
use crate::linkage::{Linkage, ShaderModule};
6+
use crate::linkage::Linkage;
107
use crate::{install::Install, target_spec_dir};
8+
use anyhow::Context as _;
9+
use spirv_builder::ModuleResult;
10+
use std::io::Write as _;
1111

1212
/// `cargo build` subcommands
1313
#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)]
@@ -25,7 +25,16 @@ impl Build {
2525
/// Entrypoint
2626
#[expect(clippy::too_many_lines, reason = "It's not too confusing")]
2727
pub fn run(&mut self) -> anyhow::Result<()> {
28-
self.install.run()?;
28+
let (rustc_codegen_spirv_location, toolchain_channel) = self.install.run()?;
29+
30+
let builder = &mut self.build_args.spirv_builder;
31+
builder.rustc_codegen_spirv_location = Some(rustc_codegen_spirv_location);
32+
builder.toolchain_overwrite = Some(toolchain_channel);
33+
builder.path_to_crate = Some(self.install.spirv_install.shader_crate.clone());
34+
builder.path_to_target_spec = Some(target_spec_dir()?.join(format!(
35+
"{}.json",
36+
builder.target.as_ref().context("expect target to be set")?
37+
)));
2938

3039
// Ensure the shader output dir exists
3140
log::debug!(
@@ -47,96 +56,58 @@ impl Build {
4756
std::env::current_dir()?.display()
4857
);
4958

50-
if !self.build_args.watch {
51-
self.build_args.spirv_builder.target = Some(
52-
target_spec_dir()?
53-
.join(format!(
54-
"{}.json",
55-
self.build_args
56-
.spirv_builder
57-
.target
58-
.as_ref()
59-
.context("expect target to be set")?
60-
))
61-
.display()
62-
.to_string(),
63-
);
64-
}
65-
66-
let args_as_json = serde_json::json!({
67-
"install": self.install.spirv_install,
68-
"build": self.build_args
69-
});
70-
let arg = serde_json::to_string_pretty(&args_as_json)?;
71-
log::info!("using spirv-builder-cli arg: {arg}");
72-
7359
if !self.build_args.watch {
7460
crate::user_output!(
75-
"Running `spirv-builder-cli` to compile shader at {}...\n",
61+
"Compiling shaders at {}...\n",
7662
self.install.spirv_install.shader_crate.display()
7763
);
7864
}
7965

80-
// TODO Call spirv-builder-cli to compile the shaders.
81-
let output = std::process::Command::new("TODO_DUMMY_PLEASE_CHANGE_ME")
82-
.arg(arg)
83-
.stdout(std::process::Stdio::inherit())
84-
.stderr(std::process::Stdio::inherit())
85-
.output()?;
86-
anyhow::ensure!(output.status.success(), "build failed");
87-
88-
let spirv_manifest = self.build_args.output_dir.join("spirv-manifest.json");
89-
if spirv_manifest.is_file() {
90-
log::debug!(
91-
"successfully built shaders, raw manifest is at '{}'",
92-
spirv_manifest.display()
93-
);
94-
} else {
95-
log::error!("missing raw manifest '{}'", spirv_manifest.display());
96-
anyhow::bail!("missing raw manifest");
97-
}
98-
99-
let shaders: Vec<ShaderModule> =
100-
serde_json::from_reader(std::fs::File::open(&spirv_manifest)?)?;
101-
66+
let result = self.build_args.spirv_builder.build()?;
67+
68+
let shaders = match &result.module {
69+
ModuleResult::MultiModule(modules) => {
70+
assert!(!modules.is_empty(), "No shader modules to compile");
71+
modules.iter().collect::<Vec<_>>()
72+
}
73+
ModuleResult::SingleModule(filepath) => result
74+
.entry_points
75+
.iter()
76+
.map(|entry| (entry, filepath))
77+
.collect::<Vec<_>>(),
78+
};
10279
let mut linkage: Vec<Linkage> = shaders
10380
.into_iter()
104-
.map(
105-
|ShaderModule {
106-
entry,
107-
path: filepath,
108-
}|
109-
-> anyhow::Result<Linkage> {
110-
use relative_path::PathExt as _;
111-
let path = self.build_args.output_dir.join(
112-
filepath
113-
.file_name()
114-
.context("Couldn't parse file name from shader module path")?,
115-
);
116-
log::debug!("copying {} to {}", filepath.display(), path.display());
117-
std::fs::copy(&filepath, &path)?;
118-
log::debug!(
119-
"linkage of {} relative to {}",
120-
path.display(),
121-
self.install.spirv_install.shader_crate.display()
122-
);
123-
let spv_path = path
124-
.relative_to(&self.install.spirv_install.shader_crate)
125-
.map_or(path, |path_relative_to_shader_crate| {
126-
path_relative_to_shader_crate.to_path("")
127-
});
128-
Ok(Linkage::new(entry, spv_path))
129-
},
130-
)
81+
.map(|(entry, filepath)| -> anyhow::Result<Linkage> {
82+
use relative_path::PathExt as _;
83+
let path = self.build_args.output_dir.join(
84+
filepath
85+
.file_name()
86+
.context("Couldn't parse file name from shader module path")?,
87+
);
88+
log::debug!("copying {} to {}", filepath.display(), path.display());
89+
std::fs::copy(&filepath, &path)?;
90+
log::debug!(
91+
"linkage of {} relative to {}",
92+
path.display(),
93+
self.install.spirv_install.shader_crate.display()
94+
);
95+
let spv_path = path
96+
.relative_to(&self.install.spirv_install.shader_crate)
97+
.map_or(path, |path_relative_to_shader_crate| {
98+
path_relative_to_shader_crate.to_path("")
99+
});
100+
Ok(Linkage::new(entry, spv_path))
101+
})
131102
.collect::<anyhow::Result<Vec<Linkage>>>()?;
103+
// Sort the contents so the output is deterministic
104+
linkage.sort();
132105

133106
// Write the shader manifest json file
134107
let manifest_path = self
135108
.build_args
136109
.output_dir
137110
.join(&self.build_args.manifest_file);
138-
// Sort the contents so the output is deterministic
139-
linkage.sort();
140111
let json = serde_json::to_string_pretty(&linkage)?;
141112
let mut file = std::fs::File::create(&manifest_path).with_context(|| {
142113
format!(
@@ -152,14 +123,6 @@ impl Build {
152123
})?;
153124

154125
log::info!("wrote manifest to '{}'", manifest_path.display());
155-
156-
if spirv_manifest.is_file() {
157-
log::debug!(
158-
"removing spirv-manifest.json file '{}'",
159-
spirv_manifest.display()
160-
);
161-
std::fs::remove_file(spirv_manifest)?;
162-
}
163126
Ok(())
164127
}
165128
}

crates/cargo-gpu/src/install.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{cache_dir, spirv_source::SpirvSource, target_spec_dir};
88
use anyhow::Context as _;
99
use log::trace;
1010
use std::io::Write as _;
11-
use std::path::Path;
11+
use std::path::{Path, PathBuf};
1212

1313
/// Metadata for the compile targets supported by `rust-gpu`
1414
const TARGET_SPECS: &[(&str, &str)] = &[
@@ -152,8 +152,8 @@ package = "rustc_codegen_spirv"
152152
Ok(())
153153
}
154154

155-
/// Install the binary pair and return the paths, (dylib, cli).
156-
pub fn run(&mut self) -> anyhow::Result<()> {
155+
/// Install the binary pair and return the `(dylib_path, toolchain_channel)`.
156+
pub fn run(&mut self) -> anyhow::Result<(PathBuf, String)> {
157157
// Ensure the cache dir exists
158158
let cache_dir = cache_dir()?;
159159
log::info!("cache directory is '{}'", cache_dir.display());
@@ -191,22 +191,25 @@ package = "rustc_codegen_spirv"
191191
}
192192
}
193193

194-
if !source_is_path
194+
let skip_rebuild = !source_is_path
195195
&& dest_dylib_path.is_file()
196-
&& !self.spirv_install.force_spirv_cli_rebuild
197-
{
196+
&& !self.spirv_install.force_spirv_cli_rebuild;
197+
if skip_rebuild {
198198
log::info!("...and so we are aborting the install step.");
199199
} else {
200200
Self::write_source_files(&source, &checkout).context("writing source files")?;
201+
}
201202

202-
log::debug!("resolving toolchain version to use");
203-
let rustc_codegen_spirv = get_package_from_crate(&checkout, "rustc_codegen_spirv")
204-
.context("get `rustc_codegen_spirv` metadata")?;
205-
let toolchain_channel =
206-
get_channel_from_rustc_codegen_spirv_build_script(&rustc_codegen_spirv)
207-
.context("read toolchain from `rustc_codegen_spirv`'s build.rs")?;
208-
log::info!("selected toolchain channel `{toolchain_channel:?}`");
203+
// TODO cache toolchain channel in a file?
204+
log::debug!("resolving toolchain version to use");
205+
let rustc_codegen_spirv = get_package_from_crate(&checkout, "rustc_codegen_spirv")
206+
.context("get `rustc_codegen_spirv` metadata")?;
207+
let toolchain_channel =
208+
get_channel_from_rustc_codegen_spirv_build_script(&rustc_codegen_spirv)
209+
.context("read toolchain from `rustc_codegen_spirv`'s build.rs")?;
210+
log::info!("selected toolchain channel `{toolchain_channel:?}`");
209211

212+
if !skip_rebuild {
210213
log::debug!("ensure_toolchain_and_components_exist");
211214
crate::install_toolchain::ensure_toolchain_and_components_exist(
212215
&toolchain_channel,
@@ -265,7 +268,7 @@ package = "rustc_codegen_spirv"
265268
.context("writing target spec files")?;
266269
}
267270

268-
self.spirv_install.dylib_path = dest_dylib_path;
269-
Ok(())
271+
self.spirv_install.dylib_path = dest_dylib_path.clone();
272+
Ok((dest_dylib_path, toolchain_channel))
270273
}
271274
}

crates/cargo-gpu/src/linkage.rs

-21
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,3 @@ impl Linkage {
3434
self.entry_point.split("::").last().unwrap()
3535
}
3636
}
37-
38-
/// A built shader entry-point, used in `spirv-builder-cli` to generate
39-
/// a `build-manifest.json` used by `cargo-gpu`.
40-
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
41-
pub struct ShaderModule {
42-
/// Name of the entry point for spirv and vulkan
43-
pub entry: String,
44-
/// File path to the entry point's source file
45-
pub path: std::path::PathBuf,
46-
}
47-
48-
impl ShaderModule {
49-
/// Make a new `ShaderModule` from an entry point and source path
50-
#[expect(clippy::impl_trait_in_params, reason = "just a struct new")]
51-
pub fn new(entry: impl AsRef<str>, path: impl AsRef<std::path::Path>) -> Self {
52-
Self {
53-
entry: entry.as_ref().into(),
54-
path: path.as_ref().into(),
55-
}
56-
}
57-
}

0 commit comments

Comments
 (0)