Skip to content

Commit 10bce9f

Browse files
committed
Move binary-specific code into its library
1 parent 8954b47 commit 10bce9f

File tree

21 files changed

+184
-201
lines changed

21 files changed

+184
-201
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ flamegraph.svg
2121
# Compiled shader assets from running tests
2222
crates/shader-crate-template/shaders
2323

24-
# Build artefacts used by CI tests
24+
# Build artifacts used by CI tests
2525
tmp/*
2626
crates/shader-crate-template/manifest.json
2727
crates/shader-crate-template/rust_gpu_shader_crate_template.spv

Cargo.lock

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

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
members = [
33
"crates/rustc_codegen_spirv-cache",
44
"crates/cargo-gpu-test-utils",
5-
"crates/cargo-gpu-cache",
5+
"crates/cargo-gpu-build",
66
"crates/cargo-gpu",
77
"crates/xtask",
88
]
@@ -23,6 +23,9 @@ keywords = ["gpu", "compiler", "rust-gpu"]
2323
license = "MIT OR Apache-2.0"
2424

2525
[workspace.dependencies]
26+
cargo-gpu-build = { path = "crates/cargo-gpu-build", default-features = false }
27+
cargo-gpu-test-utils = { path = "crates/cargo-gpu-test-utils", default-features = false }
28+
rustc_codegen_spirv-cache = { path = "crates/rustc_codegen_spirv-cache", default-features = false }
2629
spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3a897aa96c83b7caede692cbf8da7e58d7014ec8", default-features = false }
2730
anyhow = "1.0.98"
2831
thiserror = "2.0.12"

crates/cargo-gpu-build/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "cargo-gpu-build"
3+
description = "Builder of `rust-gpu` shader crates"
4+
version.workspace = true
5+
edition.workspace = true
6+
repository.workspace = true
7+
keywords.workspace = true
8+
license.workspace = true
9+
10+
[dependencies]
11+
rustc_codegen_spirv-cache.workspace = true
12+
thiserror.workspace = true
13+
14+
[lints]
15+
workspace = true

crates/cargo-gpu-build/src/lib.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#![expect(clippy::pub_use, reason = "pub use for build scripts")]
2+
3+
//! Rust GPU shader crate builder.
4+
//!
5+
//! This library allows you to easily compile your rust-gpu shaders,
6+
//! without requiring you to fix your entire project to a specific toolchain.
7+
//!
8+
//! # How it works
9+
//!
10+
//! This library manages installations of `rustc_codegen_spirv`
11+
//! using rust-gpu's [`rustc_codegen_spirv-cache`](cache) crate.
12+
//!
13+
//! Then we continue to use rust-gpu's [`spirv-builder`](cache::spirv_builder) crate
14+
//! to pass the many additional parameters required to configure rustc and our codegen backend,
15+
//! but provide you with a toolchain agnostic version that you may use from stable rustc.
16+
//! And a `cargo gpu` command line utility to simplify shader building even more.
17+
//!
18+
//! ## How we build the backend
19+
//!
20+
//! * retrieve the version of rust-gpu you want to use based on the version of the
21+
//! `spirv-std` dependency in your shader crate.
22+
//! * create a dummy project at `<cache_dir>/codegen/<version>/` that depends on
23+
//! `rustc_codegen_spirv`
24+
//! * use `cargo metadata` to `cargo update` the dummy project, which downloads the
25+
//! `rustc_codegen_spirv` crate into cargo's cache, and retrieve the path to the
26+
//! download location.
27+
//! * search for the required toolchain in `build.rs` of `rustc_codegen_spirv`
28+
//! * build it with the required toolchain version
29+
//! * copy out the binary and clean the target dir
30+
//!
31+
//! ## Building shader crates
32+
//!
33+
//! `cargo-gpu` takes a path to a shader crate to build, as well as a path to a directory
34+
//! to put the compiled `spv` source files. It also takes a path to an output manifest
35+
//! file where all shader entry points will be mapped to their `spv` source files. This
36+
//! manifest file can be used by build scripts (`build.rs` files) to generate linkage or
37+
//! conduct other post-processing, like converting the `spv` files into `wgsl` files,
38+
//! for example.
39+
40+
pub use rustc_codegen_spirv_cache as cache;
41+
42+
// TODO build script API without shader crate path repetitions

crates/cargo-gpu-cache/Cargo.toml

Lines changed: 0 additions & 38 deletions
This file was deleted.

crates/cargo-gpu/Cargo.toml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,27 @@ license.workspace = true
1010
default-run = "cargo-gpu"
1111

1212
[dependencies]
13-
cargo-gpu-cache = { path = "../cargo-gpu-cache", features = ["watch", "clap"] }
13+
cargo-gpu-build.workspace = true
14+
rustc_codegen_spirv-cache = { workspace = true, features = ["clap"] }
15+
spirv-builder = { workspace = true, features = ["clap", "watch"] }
16+
cargo_metadata.workspace = true
17+
anyhow.workspace = true
18+
thiserror.workspace = true
1419
clap.workspace = true
1520
log.workspace = true
1621
env_logger.workspace = true
17-
anyhow.workspace = true
22+
relative-path.workspace = true
23+
serde.workspace = true
24+
serde_json.workspace = true
25+
crossterm.workspace = true
26+
semver.workspace = true
27+
dunce.workspace = true
28+
29+
[dev-dependencies]
30+
cargo-gpu-test-utils.workspace = true
31+
test-log.workspace = true
32+
cargo_metadata = { workspace = true, features = ["builder"] }
33+
cargo-util-schemas.workspace = true
1834

1935
[lints]
2036
workspace = true
File renamed without changes.

crates/cargo-gpu-cache/src/build.rs renamed to crates/cargo-gpu/src/build.rs

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
1+
//! `cargo gpu build`, analogous to `cargo build`
2+
13
#![allow(clippy::shadow_reuse, reason = "let's not be silly")]
24
#![allow(clippy::unwrap_used, reason = "this is basically a test")]
3-
//! `cargo gpu build`, analogous to `cargo build`
45

5-
use anyhow::Context as _;
6-
use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder};
76
use std::io::{self, Write as _};
87
use std::path::PathBuf;
98

10-
use crate::user_consent::ask_for_user_consent;
11-
use crate::Install;
9+
use anyhow::Context as _;
10+
use rustc_codegen_spirv_cache::install::Install;
11+
use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder};
1212

1313
use crate::linkage::Linkage;
1414
use crate::lockfile::LockfileMismatchHandler;
15+
use crate::user_consent::ask_for_user_consent;
1516

1617
/// Args for just a build
17-
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
18-
#[cfg_attr(feature = "clap", derive(clap::Parser))]
18+
#[derive(Debug, Clone, clap::Parser, serde::Deserialize, serde::Serialize)]
19+
#[non_exhaustive]
20+
#[expect(clippy::module_name_repetitions, reason = "it is intended")]
1921
pub struct BuildArgs {
2022
/// Path to the output directory for the compiled shaders.
21-
#[cfg_attr(feature = "clap", clap(long, short, default_value = "./"))]
23+
#[clap(long, short, default_value = "./")]
2224
pub output_dir: PathBuf,
2325

2426
/// Watch the shader crate directory and automatically recompile on changes.
25-
#[cfg(feature = "watch")]
26-
#[cfg_attr(feature = "clap", clap(long, short, action))]
27+
#[clap(long, short, action)]
2728
pub watch: bool,
2829

29-
/// the flattened [`SpirvBuilder`]
30-
#[cfg_attr(feature = "clap", clap(flatten))]
30+
/// The flattened [`SpirvBuilder`]
31+
#[clap(flatten)]
3132
#[serde(flatten)]
3233
pub spirv_builder: SpirvBuilder,
3334

34-
///Renames the manifest.json file to the given name
35-
#[cfg_attr(feature = "clap", clap(long, short, default_value = "manifest.json"))]
35+
/// Renames the manifest.json file to the given name
36+
#[clap(long, short, default_value = "manifest.json")]
3637
pub manifest_file: String,
3738
}
3839

@@ -41,7 +42,6 @@ impl Default for BuildArgs {
4142
fn default() -> Self {
4243
Self {
4344
output_dir: PathBuf::from("./"),
44-
#[cfg(feature = "watch")]
4545
watch: false,
4646
spirv_builder: SpirvBuilder::default(),
4747
manifest_file: String::from("manifest.json"),
@@ -50,20 +50,25 @@ impl Default for BuildArgs {
5050
}
5151

5252
/// `cargo build` subcommands
53-
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
54-
#[cfg_attr(feature = "clap", derive(clap::Parser))]
53+
#[derive(Clone, Debug, clap::Parser, serde::Deserialize, serde::Serialize)]
54+
#[non_exhaustive]
5555
pub struct Build {
5656
/// CLI args for install the `rust-gpu` compiler and components
57-
#[cfg_attr(feature = "clap", clap(flatten))]
57+
#[clap(flatten)]
5858
pub install: Install,
5959

6060
/// CLI args for configuring the build of the shader
61-
#[cfg_attr(feature = "clap", clap(flatten))]
61+
#[clap(flatten)]
6262
pub build: BuildArgs,
6363
}
6464

6565
impl Build {
66-
/// Entrypoint
66+
/// Builds the shader crate.
67+
///
68+
/// # Errors
69+
///
70+
/// Returns an error if the build process fails somehow.
71+
#[inline]
6772
pub fn run(&mut self) -> anyhow::Result<()> {
6873
let skip_consent = self.install.auto_install_rust_toolchain;
6974
let halt_installation = ask_for_user_consent(skip_consent);
@@ -98,14 +103,9 @@ impl Build {
98103
std::env::current_dir()?.display()
99104
);
100105

101-
#[cfg(feature = "watch")]
102-
let watching = self.build.watch;
103-
#[cfg(not(feature = "watch"))]
104-
let watching = false;
105-
if watching {
106+
if self.build.watch {
106107
return self.watch();
107108
}
108-
109109
self.build()
110110
}
111111

@@ -123,24 +123,18 @@ impl Build {
123123
/// Watches shader crate for changes using [`SpirvBuilder`]
124124
/// or returns an error depending on presence of `watch` feature.
125125
fn watch(&self) -> anyhow::Result<()> {
126-
#[cfg(feature = "watch")]
127-
{
128-
let this = self.clone();
129-
self.build
130-
.spirv_builder
131-
.watch(move |result, accept| {
132-
let parse_result = this.parse_compilation_result(&result);
133-
if let Some(accept) = accept {
134-
accept.submit(parse_result);
135-
}
136-
})?
137-
.context("should always return the first compile result")
138-
.flatten()?;
139-
anyhow::bail!("unexpected end of watch")
140-
}
141-
142-
#[cfg(not(feature = "watch"))]
143-
anyhow::bail!("cannot watch for changes without the `watch` feature")
126+
let this = self.clone();
127+
self.build
128+
.spirv_builder
129+
.watch(move |result, accept| {
130+
let parse_result = this.parse_compilation_result(&result);
131+
if let Some(accept) = accept {
132+
accept.submit(parse_result);
133+
}
134+
})?
135+
.context("should always return the first compile result")
136+
.flatten()?;
137+
anyhow::bail!("unexpected end of watch")
144138
}
145139

146140
/// Parses compilation result from [`SpirvBuilder`] and writes it out to a file
@@ -206,8 +200,6 @@ impl Build {
206200

207201
#[cfg(test)]
208202
mod test {
209-
#![cfg(feature = "clap")]
210-
211203
use cargo_gpu_test_utils::{shader_crate_template_path, tests_teardown};
212204
use clap::Parser as _;
213205

crates/cargo-gpu-cache/src/config.rs renamed to crates/cargo-gpu/src/config.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//! Manage and merge the various sources of config: shader crate's `Cargo.toml`(s) and CLI args.
22
3-
#![cfg(feature = "clap")]
4-
53
use anyhow::Context as _;
64
use clap::Parser as _;
75

0 commit comments

Comments
 (0)