Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
[workspace]
members = [
"crates/cargo-gpu",
"crates/cargo-gpu-cli",
"crates/xtask",
]

exclude = [
# This currently needs to be excluded because it depends on a version of `rust-gpu` that
# uses a toolchain whose Cargo version doesn't recognise version 4 of `Cargo.lock`.
"crates/shader-crate-template"
# uses a toolchain whose Cargo version doesn't recognize version 4 of `Cargo.lock`.
"crates/shader-crate-template",
]

resolver = "2"

[workspace.package]
version = "0.1.0"
edition = "2021"
repository = "https://github.com/Rust-GPU/cargo-gpu"
keywords = ["gpu", "compiler", "rust-gpu"]
license = "MIT OR Apache-2.0"

[workspace.dependencies]
spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3df836eb9d7b01344f52737bf9a310d1fb5a0c26", default-features = false }
anyhow = "1.0.98"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Command line tool for building Rust shaders using rust-gpu.
To install the tool ensure you have `rustup`. Then run:

```
cargo install --git https://github.com/rust-gpu/cargo-gpu cargo-gpu
cargo install --git https://github.com/rust-gpu/cargo-gpu cargo-gpu-cli
```

After that you can use `cargo gpu` to compile your shader crates with:
Expand Down
24 changes: 24 additions & 0 deletions crates/cargo-gpu-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "cargo-gpu-cli"
description = "Command line tool for building Rust shaders using `rust-gpu`"
version.workspace = true
edition.workspace = true
repository.workspace = true
keywords.workspace = true
license.workspace = true

default-run = "cargo-gpu"

[[bin]]
name = "cargo-gpu"
path = "src/main.rs"

[dependencies]
cargo-gpu = { path = "../cargo-gpu", features = ["watch", "clap"] }
clap.workspace = true
log.workspace = true
env_logger.workspace = true
anyhow.workspace = true

[lints]
workspace = true
File renamed without changes.
27 changes: 15 additions & 12 deletions crates/cargo-gpu/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
[package]
name = "cargo-gpu"
version = "0.1.0"
edition = "2021"
description = "Generates shader .spv files from rust-gpu shader crates"
repository = "https://github.com/Rust-GPU/cargo-gpu"
description = "Generates shader .spv files from `rust-gpu` shader crates"
readme = "../../README.md"
keywords = ["gpu", "compiler", "rust-gpu"]
license = "MIT OR Apache-2.0"
default-run = "cargo-gpu"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
version.workspace = true
edition.workspace = true
repository.workspace = true
keywords.workspace = true
license.workspace = true

[dependencies]
cargo_metadata.workspace = true
anyhow.workspace = true
spirv-builder = { workspace = true, features = ["clap", "watch"] }
spirv-builder.workspace = true
legacy_target_specs.workspace = true
clap.workspace = true
clap = { workspace = true, optional = true }
directories.workspace = true
env_logger.workspace = true
log.workspace = true
relative-path.workspace = true
serde.workspace = true
Expand All @@ -29,7 +26,13 @@ dunce.workspace = true
[dev-dependencies]
test-log.workspace = true
cargo_metadata = { workspace = true, features = ["builder"] }
cargo-util-schemas = "0.8.2"
cargo-util-schemas.workspace = true

[features]
# Rebuilds target shader crate upon changes
watch = ["spirv-builder/watch"]
# Enables `clap` support for public structs
clap = ["dep:clap", "spirv-builder/clap"]

[lints]
workspace = true
79 changes: 54 additions & 25 deletions crates/cargo-gpu/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@
#![allow(clippy::unwrap_used, reason = "this is basically a test")]
//! `cargo gpu build`, analogous to `cargo build`

use crate::install::Install;
use crate::linkage::Linkage;
use crate::lockfile::LockfileMismatchHandler;
use anyhow::Context as _;
use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder};
use std::io::Write as _;
use std::path::PathBuf;

use crate::install::Install;
use crate::linkage::Linkage;
use crate::lockfile::LockfileMismatchHandler;

/// Args for just a build
#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[cfg_attr(feature = "clap", derive(clap::Parser))]
pub struct BuildArgs {
/// Path to the output directory for the compiled shaders.
#[clap(long, short, default_value = "./")]
#[cfg_attr(feature = "clap", clap(long, short, default_value = "./"))]
pub output_dir: PathBuf,

/// Watch the shader crate directory and automatically recompile on changes.
#[clap(long, short, action)]
#[cfg(feature = "watch")]
#[cfg_attr(feature = "clap", clap(long, short, action))]
pub watch: bool,

/// the flattened [`SpirvBuilder`]
#[clap(flatten)]
#[cfg_attr(feature = "clap", clap(flatten))]
#[serde(flatten)]
pub spirv_builder: SpirvBuilder,

///Renames the manifest.json file to the given name
#[clap(long, short, default_value = "manifest.json")]
#[cfg_attr(feature = "clap", clap(long, short, default_value = "manifest.json"))]
pub manifest_file: String,
}

Expand All @@ -36,6 +39,7 @@ impl Default for BuildArgs {
fn default() -> Self {
Self {
output_dir: PathBuf::from("./"),
#[cfg(feature = "watch")]
watch: false,
spirv_builder: SpirvBuilder::default(),
manifest_file: String::from("manifest.json"),
Expand All @@ -44,14 +48,15 @@ impl Default for BuildArgs {
}

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

/// CLI args for configuring the build of the shader
#[clap(flatten)]
#[cfg_attr(feature = "clap", clap(flatten))]
pub build: BuildArgs,
}

Expand Down Expand Up @@ -89,30 +94,52 @@ impl Build {
std::env::current_dir()?.display()
);

if self.build.watch {
#[cfg(feature = "watch")]
let watching = self.build.watch;
#[cfg(not(feature = "watch"))]
let watching = false;
if watching {
return self.watch();
}

self.build()
}

/// Builds shader crate using [`SpirvBuilder`].
fn build(&self) -> anyhow::Result<()> {
crate::user_output!(
"Compiling shaders at {}...\n",
self.install.shader_crate.display()
);
let result = self.build.spirv_builder.build()?;
self.parse_compilation_result(&result)?;
Ok(())
}

/// Watches shader crate for changes using [`SpirvBuilder`]
/// or returns an error depending on presence of `watch` feature.
fn watch(&self) -> anyhow::Result<()> {
#[cfg(feature = "watch")]
{
let this = self.clone();
self.build
.spirv_builder
.watch(move |result, accept| {
let result1 = this.parse_compilation_result(&result);
let parse_result = this.parse_compilation_result(&result);
if let Some(accept) = accept {
accept.submit(result1);
accept.submit(parse_result);
}
})?
.context("unreachable")??;
std::thread::park();
} else {
crate::user_output!(
"Compiling shaders at {}...\n",
self.install.shader_crate.display()
);
let result = self.build.spirv_builder.build()?;
self.parse_compilation_result(&result)?;
.context("should always return the first compile result")
.flatten()?;
anyhow::bail!("unexpected end of watch")
}
Ok(())

#[cfg(not(feature = "watch"))]
anyhow::bail!("cannot watch for changes without the `watch` feature")
}

/// Parses compilation result from `SpirvBuilder` and writes it out to a file
/// Parses compilation result from [`SpirvBuilder`] and writes it out to a file
fn parse_compilation_result(&self, result: &CompileResult) -> anyhow::Result<()> {
let shaders = match &result.module {
ModuleResult::MultiModule(modules) => {
Expand Down Expand Up @@ -175,6 +202,8 @@ impl Build {

#[cfg(test)]
mod test {
#![cfg(feature = "clap")]

use clap::Parser as _;

use crate::{Cli, Command};
Expand Down
3 changes: 3 additions & 0 deletions crates/cargo-gpu/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! Manage and merge the various sources of config: shader crate's `Cargo.toml`(s) and CLI args.

#![cfg(feature = "clap")]

use anyhow::Context as _;
use clap::Parser as _;

Expand Down
2 changes: 2 additions & 0 deletions crates/cargo-gpu/src/dump_usage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Convenience function for internal use. Dumps all the CLI usage instructions. Useful for
//! updating the README.

#![cfg(feature = "clap")]

use crate::{user_output, Cli};

/// main dump usage function
Expand Down
20 changes: 12 additions & 8 deletions crates/cargo-gpu/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@ impl InstalledBackend {
clippy::struct_excessive_bools,
reason = "cmdline args have many bools"
)]
#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[cfg_attr(feature = "clap", derive(clap::Parser))]
#[non_exhaustive]
pub struct Install {
/// Directory containing the shader crate to compile.
#[clap(long, alias("package"), short_alias('p'), default_value = "./")]
#[cfg_attr(
feature = "clap",
clap(long, alias("package"), short_alias('p'), default_value = "./")
)]
#[serde(alias = "package")]
pub shader_crate: PathBuf,

Expand All @@ -75,30 +79,30 @@ pub struct Install {
)]
/// Source of `spirv-builder` dependency
/// Eg: "https://github.com/Rust-GPU/rust-gpu"
#[clap(long)]
#[cfg_attr(feature = "clap", clap(long))]
pub spirv_builder_source: Option<String>,

/// Version of `spirv-builder` dependency.
/// * If `--spirv-builder-source` is not set, then this is assumed to be a crates.io semantic
/// version such as "0.9.0".
/// * If `--spirv-builder-source` is set, then this is assumed to be a Git "commitsh", such
/// as a Git commit hash or a Git tag, therefore anything that `git checkout` can resolve.
#[clap(long, verbatim_doc_comment)]
#[cfg_attr(feature = "clap", clap(long, verbatim_doc_comment))]
pub spirv_builder_version: Option<String>,

/// Force `rustc_codegen_spirv` to be rebuilt.
#[clap(long)]
#[cfg_attr(feature = "clap", clap(long))]
pub rebuild_codegen: bool,

/// Assume "yes" to "Install Rust toolchain: [y/n]" prompt.
///
/// Defaults to `false` in cli, `true` in [`Default`]
#[clap(long, action)]
#[cfg_attr(feature = "clap", clap(long, action))]
pub auto_install_rust_toolchain: bool,

/// Clear target dir of `rustc_codegen_spirv` build after a successful build, saves about
/// 200MiB of disk space.
#[clap(long = "no-clear-target", default_value = "true", action = clap::ArgAction::SetFalse)]
#[cfg_attr(feature = "clap", clap(long = "no-clear-target", default_value = "true", action = clap::ArgAction::SetFalse))]
pub clear_target: bool,

/// There is a tricky situation where a shader crate that depends on workspace config can have
Expand All @@ -122,7 +126,7 @@ pub struct Install {
/// way source URLs are encoded. See these PRs for more details:
/// * <https://github.com/rust-lang/cargo/pull/12280>
/// * <https://github.com/rust-lang/cargo/pull/14595>
#[clap(long, action, verbatim_doc_comment)]
#[cfg_attr(feature = "clap", clap(long, action, verbatim_doc_comment))]
pub force_overwrite_lockfiles_v4_to_v3: bool,
}

Expand Down
Loading
Loading