From 9030ede7951c3e1470d1658dd2c39e32842ced10 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 19 Oct 2024 08:25:40 +1300 Subject: [PATCH 001/162] Initial commit --- .gitignore | 21 +++++++++++++++++++++ LICENSE | 21 +++++++++++++++++++++ README.md | 2 ++ 3 files changed, 44 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..d01bd1a990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..a0a8cb4ae5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Rust GPU + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000000..b157ea98f6 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# cargo-gpu +Command line tool for building Rust shaders using rust-gpu From 81fad9a741ff59b8017fad1d8e948c94890023f0 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 3 Nov 2024 21:21:29 +1300 Subject: [PATCH 002/162] init --- .gitignore | 23 +- Cargo.lock | 939 ++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 30 ++ rust-toolchain.toml | 12 + src/linkage.rs | 57 +++ src/main.rs | 189 +++++++++ 6 files changed, 1238 insertions(+), 12 deletions(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 rust-toolchain.toml create mode 100644 src/linkage.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index d01bd1a990..aab88c292e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,20 @@ -# Generated by Cargo +# macOS +*.DS_Store # will have compiled files and executables -debug/ -target/ +/target/ +shaders/target +shaders/shader-crate/target # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock +# Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb +*~undo-tree~ -# RustRover -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file +test_output +cmy_triangle_renderer.svg +.aider* +flamegraph.svg diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000000..e911f1306c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,939 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "ar" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bit-set" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cargo-gpu" +version = "0.1.0" +dependencies = [ + "clap", + "env_logger", + "log", + "naga", + "quote", + "spirv-builder", +] + +[[package]] +name = "cc" +version = "1.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.87", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elsa" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +dependencies = [ + "indexmap 2.6.0", + "stable_deref_trait", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "internal-iterator" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "longest-increasing-subsequence" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "naga" +version = "22.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.6.0", + "cfg_aliases", + "codespan-reporting", + "hexf-parse", + "indexmap 2.6.0", + "log", + "petgraph", + "rustc-hash", + "spirv 0.3.0+sdk-1.3.268.0", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.6.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "raw-string" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rspirv" +version = "0.11.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba" +dependencies = [ + "fxhash", + "num-traits", + "spirv 0.2.0+1.5.4", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_codegen_spirv" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" +dependencies = [ + "ar", + "either", + "hashbrown 0.11.2", + "indexmap 1.9.3", + "itertools", + "lazy_static", + "libc", + "num-traits", + "once_cell", + "regex", + "rspirv", + "rustc-demangle", + "rustc_codegen_spirv-types", + "sanitize-filename", + "smallvec", + "spirt", + "spirv-tools", + "syn 1.0.109", +] + +[[package]] +name = "rustc_codegen_spirv-types" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" +dependencies = [ + "rspirv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "sanitize-filename" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "spirt" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d5968bd2a36466468aac637b355776f080edfb0c6f769b2b99b9708260c42a" +dependencies = [ + "arrayvec", + "bytemuck", + "derive_more", + "elsa", + "indexmap 2.6.0", + "internal-iterator", + "itertools", + "lazy_static", + "longest-increasing-subsequence", + "rustc-hash", + "serde", + "serde_json", + "smallvec", +] + +[[package]] +name = "spirv" +version = "0.2.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +dependencies = [ + "bitflags 1.3.2", + "num-traits", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "spirv-builder" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" +dependencies = [ + "memchr", + "raw-string", + "rustc_codegen_spirv", + "rustc_codegen_spirv-types", + "serde", + "serde_json", +] + +[[package]] +name = "spirv-tools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcb3b0832881834994b7ec82b709ec5491043ceb4bf8101e27da6b5234b24261" +dependencies = [ + "spirv-tools-sys", +] + +[[package]] +name = "spirv-tools-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e68b55a97aa6856e010a6f2477425875a97873e147bb0232160e73c45bdae7" +dependencies = [ + "cc", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000000..a3e36fd033 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "cargo-gpu" +version = "0.1.0" +edition = "2021" +description = "Generates shader .spv files from rust-gpu shader crates" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.4.8", features = ["derive"] } +env_logger = "0.10" +log = "0.4" +naga = { version = "22.0", features = ["spv-in", "wgsl-out", "wgsl-in", "msl-out"] } +quote = "1.0" +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } + +# Enable incremental by default in release mode. +[profile.release] +incremental = true +# HACK(eddyb) this is the default but without explicitly specifying it, Cargo +# will treat the identical settings in `[profile.release.build-override]` below +# as different sets of `rustc` flags and will not reuse artifacts between them. +codegen-units = 256 + +# Compile build-dependencies in release mode with the same settings +# as regular dependencies (including the incremental enabled above). +[profile.release.build-override] +opt-level = 3 +incremental = true +codegen-units = 256 diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000000..92ae501066 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,12 @@ +# If you see this, run `rustup self update` to get rustup 1.23 or newer. + +# NOTE: above comment is for older `rustup` (before TOML support was added), +# which will treat the first line as the toolchain name, and therefore show it +# to the user in the error, instead of "error: invalid channel name '[toolchain]'". + +[toolchain] +channel = "nightly-2024-04-24" +components = ["rust-src", "rustc-dev", "llvm-tools"] + +# Whenever changing the nightly channel, update the commit hash above, and make +# sure to change REQUIRED_TOOLCHAIN in crates/rustc_codegen_spirv/src/build.rs also. diff --git a/src/linkage.rs b/src/linkage.rs new file mode 100644 index 0000000000..07b8be18b6 --- /dev/null +++ b/src/linkage.rs @@ -0,0 +1,57 @@ +//! A shader source and entry point that can be used to create renderling +//! shader linkage. +use super::ShaderLang; +use quote::quote; + +pub struct Linkage { + pub source_path: std::path::PathBuf, + pub entry_point: String, +} + +impl Linkage { + pub fn fn_name(&self) -> &str { + self.entry_point.split("::").last().unwrap() + } + + pub fn to_string(&self, lang: ShaderLang) -> String { + let original_source_path = match lang { + ShaderLang::Spv => self.source_path.clone(), + ShaderLang::Wgsl => self.source_path.with_extension("wgsl"), + }; + + let source_path = original_source_path.file_name().unwrap().to_str().unwrap(); + let entry_point = self.entry_point.clone(); + + let wgsl_entry_point = entry_point.replace("::", ""); + let entry_point = match lang { + ShaderLang::Spv => entry_point, + ShaderLang::Wgsl => entry_point.replace("::", ""), + }; + + let entry_point_quote = quote! { + #[cfg(not(target_arch = "wasm32"))] + pub const ENTRY_POINT: &str = #entry_point; + #[cfg(target_arch = "wasm32")] + pub const ENTRY_POINT: &str = #wgsl_entry_point; + }; + let bytes_quote = quote! { + pub const BYTES: &'static [u8] = include_bytes!(#source_path); + }; + format!( + r#"#![allow(dead_code)] + //! Automatically generated with `cargo-gpu`. + //! + //! Provides the shader linkage for `{entry_point}`. + //! + //! **source path**: `{original_source_path}` + + /// Shader entry point. + {entry_point_quote} + + /// Shader bytes. + {bytes_quote} + "#, + original_source_path = original_source_path.display() + ) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000000..ec1b4f4725 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,189 @@ +//! This program builds rust-gpu shader crates and writes generated spv files +//! into the main source repo. +use clap::Parser; +use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; + +mod linkage; + +#[derive(Clone, Copy, Default)] +pub enum ShaderLang { + #[default] + Spv, + Wgsl, +} + +impl core::str::FromStr for ShaderLang { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "spv" => Ok(ShaderLang::Spv), + "wgsl" => Ok(ShaderLang::Wgsl), + s => Err(format!("not a valid option '{s}'")), + } + } +} + +#[derive(Parser)] +#[clap(author, version, about)] +struct Cli { + /// Directory containing the shader crate to compile. + #[clap(long, short, default_value = "renderling")] + shader_crate: std::path::PathBuf, + + /// Whether to write the spv or wgsl + #[clap(long, default_value = "spv")] + shader_lang: ShaderLang, + + /// Shader target. + #[clap(long, default_value = "spirv-unknown-vulkan1.2")] + shader_target: String, + + /// Set cargo default-features. + #[clap(long)] + no_default_features: bool, + + /// Set cargo features. + #[clap(long)] + features: Vec, + + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "../crates/renderling/src/linkage")] + output_dir: std::path::PathBuf, + + /// If set the shaders will be compiled but not put into place. + #[clap(long, short)] + dry_run: bool, +} + +fn wgsl(spv_filepath: impl AsRef, destination: impl AsRef) { + let bytes = std::fs::read(spv_filepath).unwrap(); + let opts = naga::front::spv::Options::default(); + let module = naga::front::spv::parse_u8_slice(&bytes, &opts).unwrap(); + let mut validator = + naga::valid::Validator::new(Default::default(), naga::valid::Capabilities::empty()); + let info = validator.validate(&module).unwrap(); + let wgsl = + naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::empty()) + .unwrap(); + let destination = destination.as_ref().with_extension("wgsl"); + std::fs::write(destination, wgsl).unwrap(); +} + +fn main() -> Result<(), Box> { + env_logger::builder().init(); + + log::info!("args: {:#?}", std::env::args()); + + let Cli { + shader_crate, + shader_lang, + shader_target, + no_default_features, + features, + output_dir, + dry_run, + } = Cli::parse(); + + std::fs::create_dir_all(&output_dir).unwrap(); + + assert!( + shader_crate.exists(), + "shader crate '{}' does not exist. (Current dir is '{}')", + shader_crate.display(), + std::env::current_dir().unwrap().display() + ); + + let start = std::time::Instant::now(); + + let CompileResult { + entry_points, + module, + } = { + let mut builder = SpirvBuilder::new(shader_crate, &shader_target) + //.shader_panic_strategy(spirv_builder::ShaderPanicStrategy::UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable) + .print_metadata(MetadataPrintout::None) + .multimodule(true); + + if no_default_features { + log::info!("setting cargo --no-default-features"); + builder = builder.shader_crate_default_features(false); + } + if !features.is_empty() { + log::info!("setting --features {features:?}"); + builder = builder.shader_crate_features(features); + } + + builder.build()? + }; + + let dir = output_dir; + let mut shaders = vec![]; + match module { + ModuleResult::MultiModule(modules) => { + assert!(!modules.is_empty(), "No shader modules to compile"); + for (entry, filepath) in modules.into_iter() { + let path = dir.join(filepath.file_name().unwrap()); + if !dry_run { + match shader_lang { + ShaderLang::Spv => { + std::fs::copy(filepath, &path).unwrap(); + } + ShaderLang::Wgsl => { + wgsl(filepath, &path); + } + } + } + shaders.push(linkage::Linkage { + entry_point: entry, + source_path: path, + }); + } + } + ModuleResult::SingleModule(filepath) => { + let path = dir.join(filepath.file_name().unwrap()); + if !dry_run { + std::fs::copy(filepath, &path).unwrap(); + } + for entry in entry_points { + shaders.push(linkage::Linkage { + entry_point: entry, + source_path: path.clone(), + }); + } + } + } + + if dry_run { + println!("\nNot writing shaders.rs because --dry-run was set.\n"); + } else { + println!("\nWriting shaders..."); + }; + + let mut set = std::collections::HashSet::<&str>::default(); + + for linkage in shaders.iter() { + let fn_name = linkage.fn_name(); + + if set.contains(fn_name) { + panic!("Shader name '{fn_name}' is used for two or more shaders, aborting!"); + } + set.insert(fn_name); + + let filepath = dir.join(fn_name).with_extension("rs"); + let contents = linkage.to_string(shader_lang); + if !dry_run { + std::fs::write(&filepath, contents).unwrap(); + std::process::Command::new("rustfmt") + .args([&format!("{}", filepath.display())]) + .output() + .expect("could not format generated code"); + println!(" {}", filepath.display()); + } + } + + let end = std::time::Instant::now(); + println!("Finished in {:?}", (end - start)); + + Ok(()) +} From 4550f7cac8e098d0f804eebc6bf1fdba1278a78d Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 4 Nov 2024 12:38:34 +1300 Subject: [PATCH 003/162] works for the happy path --- Cargo.lock | 60 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 5 ++++ src/build.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 src/build.rs diff --git a/Cargo.lock b/Cargo.lock index e911f1306c..d6bb7943c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,11 +133,13 @@ name = "cargo-gpu" version = "0.1.0" dependencies = [ "clap", + "env_home", "env_logger", "log", "naga", "quote", "spirv-builder", + "toml", ] [[package]] @@ -254,6 +256,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "env_logger" version = "0.10.2" @@ -662,6 +670,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "shlex" version = "1.3.0" @@ -811,6 +828,40 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.13" @@ -937,3 +988,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index a3e36fd033..6eacbdc920 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,14 @@ name = "cargo-gpu" version = "0.1.0" edition = "2021" description = "Generates shader .spv files from rust-gpu shader crates" +build = "src/build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[build-dependencies] +env_home = "0.1.0" +toml = "0.8.19" + [dependencies] clap = { version = "4.4.8", features = ["derive"] } env_logger = "0.10" diff --git a/src/build.rs b/src/build.rs new file mode 100644 index 0000000000..3fede43bad --- /dev/null +++ b/src/build.rs @@ -0,0 +1,68 @@ +//! Build script that copies the built `librustc_codegen_spirv.dylib` into +//! a known location. + +//const DYLIB_FILENAME: &str = "librustc_codegen_spirv.dylib"; + +use std::str::FromStr; + +fn dylib_filename() -> String { + format!( + "{}rustc_codegen_spirv{}", + std::env::consts::DLL_PREFIX, + std::env::consts::DLL_SUFFIX + ) +} + +fn find_file(dir: &std::path::Path, filename: &str) -> std::path::PathBuf { + let mut path = dir.join(filename); + while !path.exists() { + if let Some(parent) = path.parent().and_then(|p| p.parent()) { + path = parent.join(filename); + } else { + break; + } + } + + if !path.exists() { + panic!("could not find file '{filename}'"); + } + path +} + +fn main() { + let out_dir = std::path::PathBuf::from( + std::env::var("OUT_DIR").expect("Environment variable OUT_DIR was not set"), + ); + let built_dylib_path = find_file(&out_dir, &dylib_filename()); + + let dest_dir = std::env::home_dir() + .expect("home directory is not set") + .join(".rust-gpu"); + std::fs::create_dir_all(&dest_dir).expect("could not create ~/.rust-gpu directory"); + let dest_path = dest_dir.join(dylib_filename()); + + std::fs::copy(&built_dylib_path, &dest_path).unwrap_or_else(|e| { + panic!( + "failed to copy dylib '{}' to destination '{}': {e}", + built_dylib_path.display(), + dest_path.display() + ) + }); + + println!("cargo:rustc-env=DYLIB_PATH={}", dest_path.display()); + + let rust_toolchain_toml_path = find_file(&out_dir, "rust-toolchain.toml"); + let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path) + .unwrap_or_else(|e| panic!("could not read rust-toolchain.toml: {e}")); + let table = toml::Table::from_str(&rust_toolchain_toml) + .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); + let toolchain = table + .get("toolchain") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) + .as_table() + .unwrap(); + let channel = toolchain + .get("channel") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")); + println!("cargo:rustc-env=RUSTC_NIGHTLY_CHANNEL={channel}"); +} diff --git a/src/main.rs b/src/main.rs index ec1b4f4725..380f5c47fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,51 @@ use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder} mod linkage; +const RUSTC_CODEGEN_SPIRV_PATH: &str = std::env!("DYLIB_PATH"); + +fn dylib_path_envvar() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_FALLBACK_LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + +fn dylib_path() -> Vec { + match std::env::var_os(dylib_path_envvar()) { + Some(var) => std::env::split_paths(&var).collect(), + None => Vec::new(), + } +} + +fn set_rustc_codegen_spirv_path() { + let var = dylib_path_envvar(); + let mut paths = dylib_path(); + paths.push( + std::path::PathBuf::from(RUSTC_CODEGEN_SPIRV_PATH) + .parent() + .unwrap() + .to_path_buf(), + ); + std::env::set_var( + var, + std::env::join_paths(paths).expect("could not join paths"), + ); + log::trace!("library search paths: {:#?}", dylib_path()); +} + +const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); + +fn set_rustup_toolchain() { + log::trace!( + "setting RUSTUP_TOOLCHAIN = '{}'", + RUSTC_NIGHTLY_CHANNEL.trim_matches('"') + ); + std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); +} + #[derive(Clone, Copy, Default)] pub enum ShaderLang { #[default] @@ -28,7 +73,7 @@ impl core::str::FromStr for ShaderLang { #[clap(author, version, about)] struct Cli { /// Directory containing the shader crate to compile. - #[clap(long, short, default_value = "renderling")] + #[clap(long, short, default_value = "./")] shader_crate: std::path::PathBuf, /// Whether to write the spv or wgsl @@ -48,7 +93,7 @@ struct Cli { features: Vec, /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "../crates/renderling/src/linkage")] + #[clap(long, short, default_value = "./")] output_dir: std::path::PathBuf, /// If set the shaders will be compiled but not put into place. @@ -73,7 +118,8 @@ fn wgsl(spv_filepath: impl AsRef, destination: impl AsRef Result<(), Box> { env_logger::builder().init(); - log::info!("args: {:#?}", std::env::args()); + set_rustc_codegen_spirv_path(); + set_rustup_toolchain(); let Cli { shader_crate, @@ -83,7 +129,11 @@ fn main() -> Result<(), Box> { features, output_dir, dry_run, - } = Cli::parse(); + } = Cli::parse_from(std::env::args().filter(|p| { + // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" + // as the first parameter, which we want to ignore. + p != "gpu" + })); std::fs::create_dir_all(&output_dir).unwrap(); From f266d8b04dde9d12fd12a08717957e464b1bfc2c Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 4 Nov 2024 13:05:18 +1300 Subject: [PATCH 004/162] don't use std::env::home --- Cargo.toml | 1 + README.md | 16 +++++++++++++++- src/build.rs | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6eacbdc920..1f89439890 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ build = "src/build.rs" [build-dependencies] env_home = "0.1.0" toml = "0.8.19" +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } [dependencies] clap = { version = "4.4.8", features = ["derive"] } diff --git a/README.md b/README.md index b157ea98f6..0c60b96308 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,16 @@ # cargo-gpu -Command line tool for building Rust shaders using rust-gpu +Command line tool for building Rust shaders using rust-gpu. + +## Getting Started + +### installation +To install the tool ensure you have `rustup`. Then run: + +``` +cargo install --git https://github.com/rust-gpu/cargo-gpu +``` + +After that you can use `cargo gpu` to compile your shader crates. + +### Next Steps + diff --git a/src/build.rs b/src/build.rs index 3fede43bad..15542b53a3 100644 --- a/src/build.rs +++ b/src/build.rs @@ -35,7 +35,7 @@ fn main() { ); let built_dylib_path = find_file(&out_dir, &dylib_filename()); - let dest_dir = std::env::home_dir() + let dest_dir = env_home::env_home_dir() .expect("home directory is not set") .join(".rust-gpu"); std::fs::create_dir_all(&dest_dir).expect("could not create ~/.rust-gpu directory"); From 53cf5571b6508f023dad55c0598e13b044f4dd54 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 4 Nov 2024 13:41:08 +1300 Subject: [PATCH 005/162] include rust-toolchain.toml --- src/build.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/build.rs b/src/build.rs index 15542b53a3..738b2f061e 100644 --- a/src/build.rs +++ b/src/build.rs @@ -51,9 +51,7 @@ fn main() { println!("cargo:rustc-env=DYLIB_PATH={}", dest_path.display()); - let rust_toolchain_toml_path = find_file(&out_dir, "rust-toolchain.toml"); - let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path) - .unwrap_or_else(|e| panic!("could not read rust-toolchain.toml: {e}")); + let rust_toolchain_toml = include_str!("../rust-toolchain.toml"); let table = toml::Table::from_str(&rust_toolchain_toml) .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); let toolchain = table From cc437bf688b3781a9d70b1150bc27d97c5d34395 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 4 Nov 2024 14:54:41 +1300 Subject: [PATCH 006/162] readme --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0c60b96308..c26c81c852 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,20 @@ 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 +nightly-2024-04-24 install --git https://github.com/rust-gpu/cargo-gpu ``` -After that you can use `cargo gpu` to compile your shader crates. +After that you can use `cargo gpu` to compile your shader crates with: + +``` +cargo gpu +``` + +This plain invocation will compile the crate in the current directory and +place the compiled shaders in the current directory. + +Use `cargo gpu --help` to see other options :) ### Next Steps +TODO(schell) - finish up the cargo-generate template repo and explain it here. From 0213bb342e545c95ef7a1b3840a5543c6e947a45 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 6 Nov 2024 08:51:09 +1300 Subject: [PATCH 007/162] write shader manifest, remove naga --- Cargo.lock | 139 ++-------------------------------- Cargo.toml | 14 +++- src/build.rs | 2 +- src/lib.rs | 3 + src/linkage.rs | 57 +++----------- src/main.rs | 198 +++++++++++++++++++------------------------------ 6 files changed, 107 insertions(+), 306 deletions(-) create mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d6bb7943c3..df5fa713bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,33 +89,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "bit-set" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - [[package]] name = "bytemuck" version = "1.19.0" @@ -136,8 +115,8 @@ dependencies = [ "env_home", "env_logger", "log", - "naga", - "quote", + "serde", + "serde_json", "spirv-builder", "toml", ] @@ -159,12 +138,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "clap" version = "4.5.20" @@ -205,16 +178,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "colorchoice" version = "1.0.3" @@ -281,12 +244,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "fxhash" version = "0.2.1" @@ -340,12 +297,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - [[package]] name = "humantime" version = "2.1.0" @@ -449,28 +400,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "naga" -version = "22.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.6.0", - "cfg_aliases", - "codespan-reporting", - "hexf-parse", - "indexmap 2.6.0", - "log", - "petgraph", - "rustc-hash", - "spirv 0.3.0+sdk-1.3.268.0", - "termcolor", - "thiserror", - "unicode-xid", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -486,16 +415,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset", - "indexmap 2.6.0", -] - [[package]] name = "proc-macro2" version = "1.0.89" @@ -557,7 +476,7 @@ checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba" dependencies = [ "fxhash", "num-traits", - "spirv 0.2.0+1.5.4", + "spirv", ] [[package]] @@ -575,7 +494,6 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" dependencies = [ "ar", "either", @@ -600,7 +518,6 @@ dependencies = [ [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" dependencies = [ "rspirv", "serde", @@ -696,15 +613,15 @@ dependencies = [ [[package]] name = "spirt" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d5968bd2a36466468aac637b355776f080edfb0c6f769b2b99b9708260c42a" +checksum = "64e1f7903720ff818d6da824edf2c4082c6e7a029a99317fd10c39dd7c40c7ff" dependencies = [ "arrayvec", "bytemuck", "derive_more", "elsa", - "indexmap 2.6.0", + "indexmap 1.9.3", "internal-iterator", "itertools", "lazy_static", @@ -721,23 +638,13 @@ version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ - "bitflags 1.3.2", + "bitflags", "num-traits", ] -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.6.0", -] - [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#61f7e7a8078bfc41e206caa019b79eb9f55560c6" dependencies = [ "memchr", "raw-string", @@ -808,26 +715,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "thiserror" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "toml" version = "0.8.19" @@ -868,18 +755,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index 1f89439890..4211081f97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,18 +7,24 @@ build = "src/build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "cargo-gpu" + +[lib] +name = "cargo_gpu" + [build-dependencies] env_home = "0.1.0" toml = "0.8.19" -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } +spirv-builder = { path = "../rust-gpu/crates/spirv-builder" } [dependencies] clap = { version = "4.4.8", features = ["derive"] } env_logger = "0.10" log = "0.4" -naga = { version = "22.0", features = ["spv-in", "wgsl-out", "wgsl-in", "msl-out"] } -quote = "1.0" -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } +serde = "1.0.214" +serde_json = "1.0.132" +spirv-builder = { path = "../rust-gpu/crates/spirv-builder" } # Enable incremental by default in release mode. [profile.release] diff --git a/src/build.rs b/src/build.rs index 738b2f061e..c2dfc89236 100644 --- a/src/build.rs +++ b/src/build.rs @@ -52,7 +52,7 @@ fn main() { println!("cargo:rustc-env=DYLIB_PATH={}", dest_path.display()); let rust_toolchain_toml = include_str!("../rust-toolchain.toml"); - let table = toml::Table::from_str(&rust_toolchain_toml) + let table = toml::Table::from_str(rust_toolchain_toml) .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); let toolchain = table .get("toolchain") diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000000..5be42f12b8 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +//! Helps compiling rust-gpu shaders. + +pub mod linkage; diff --git a/src/linkage.rs b/src/linkage.rs index 07b8be18b6..92603944e0 100644 --- a/src/linkage.rs +++ b/src/linkage.rs @@ -1,57 +1,22 @@ -//! A shader source and entry point that can be used to create renderling -//! shader linkage. -use super::ShaderLang; -use quote::quote; +//! A shader source and entry point that can be used to create shader linkage. +#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Linkage { pub source_path: std::path::PathBuf, pub entry_point: String, + pub wgsl_entry_point: String, } impl Linkage { - pub fn fn_name(&self) -> &str { - self.entry_point.split("::").last().unwrap() + pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { + Self { + source_path: source_path.as_ref().to_path_buf(), + wgsl_entry_point: entry_point.as_ref().replace("::", ""), + entry_point: entry_point.as_ref().to_string(), + } } - pub fn to_string(&self, lang: ShaderLang) -> String { - let original_source_path = match lang { - ShaderLang::Spv => self.source_path.clone(), - ShaderLang::Wgsl => self.source_path.with_extension("wgsl"), - }; - - let source_path = original_source_path.file_name().unwrap().to_str().unwrap(); - let entry_point = self.entry_point.clone(); - - let wgsl_entry_point = entry_point.replace("::", ""); - let entry_point = match lang { - ShaderLang::Spv => entry_point, - ShaderLang::Wgsl => entry_point.replace("::", ""), - }; - - let entry_point_quote = quote! { - #[cfg(not(target_arch = "wasm32"))] - pub const ENTRY_POINT: &str = #entry_point; - #[cfg(target_arch = "wasm32")] - pub const ENTRY_POINT: &str = #wgsl_entry_point; - }; - let bytes_quote = quote! { - pub const BYTES: &'static [u8] = include_bytes!(#source_path); - }; - format!( - r#"#![allow(dead_code)] - //! Automatically generated with `cargo-gpu`. - //! - //! Provides the shader linkage for `{entry_point}`. - //! - //! **source path**: `{original_source_path}` - - /// Shader entry point. - {entry_point_quote} - - /// Shader bytes. - {bytes_quote} - "#, - original_source_path = original_source_path.display() - ) + pub fn fn_name(&self) -> &str { + self.entry_point.split("::").last().unwrap() } } diff --git a/src/main.rs b/src/main.rs index 380f5c47fa..9d92b75e24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,44 +1,46 @@ //! This program builds rust-gpu shader crates and writes generated spv files //! into the main source repo. +use std::io::Write; + use clap::Parser; use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; -mod linkage; +use cargo_gpu::linkage; const RUSTC_CODEGEN_SPIRV_PATH: &str = std::env!("DYLIB_PATH"); -fn dylib_path_envvar() -> &'static str { - if cfg!(windows) { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_FALLBACK_LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } -} - -fn dylib_path() -> Vec { - match std::env::var_os(dylib_path_envvar()) { - Some(var) => std::env::split_paths(&var).collect(), - None => Vec::new(), - } -} - -fn set_rustc_codegen_spirv_path() { - let var = dylib_path_envvar(); - let mut paths = dylib_path(); - paths.push( - std::path::PathBuf::from(RUSTC_CODEGEN_SPIRV_PATH) - .parent() - .unwrap() - .to_path_buf(), - ); - std::env::set_var( - var, - std::env::join_paths(paths).expect("could not join paths"), - ); - log::trace!("library search paths: {:#?}", dylib_path()); -} +// fn dylib_path_envvar() -> &'static str { +// if cfg!(windows) { +// "PATH" +// } else if cfg!(target_os = "macos") { +// "DYLD_FALLBACK_LIBRARY_PATH" +// } else { +// "LD_LIBRARY_PATH" +// } +// } + +// fn dylib_path() -> Vec { +// match std::env::var_os(dylib_path_envvar()) { +// Some(var) => std::env::split_paths(&var).collect(), +// None => Vec::new(), +// } +// } + +// fn set_rustc_codegen_spirv_path() { +// let var = dylib_path_envvar(); +// let mut paths = dylib_path(); +// paths.push( +// std::path::PathBuf::from(RUSTC_CODEGEN_SPIRV_PATH) +// .parent() +// .unwrap() +// .to_path_buf(), +// ); +// std::env::set_var( +// var, +// std::env::join_paths(paths).expect("could not join paths"), +// ); +// log::trace!("library search paths: {:#?}", dylib_path()); +// } const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); @@ -50,84 +52,51 @@ fn set_rustup_toolchain() { std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); } -#[derive(Clone, Copy, Default)] -pub enum ShaderLang { - #[default] - Spv, - Wgsl, -} - -impl core::str::FromStr for ShaderLang { - type Err = String; - - fn from_str(s: &str) -> Result { - match s { - "spv" => Ok(ShaderLang::Spv), - "wgsl" => Ok(ShaderLang::Wgsl), - s => Err(format!("not a valid option '{s}'")), - } - } -} - #[derive(Parser)] #[clap(author, version, about)] -struct Cli { +pub struct Cli { /// Directory containing the shader crate to compile. - #[clap(long, short, default_value = "./")] - shader_crate: std::path::PathBuf, - - /// Whether to write the spv or wgsl - #[clap(long, default_value = "spv")] - shader_lang: ShaderLang, + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, /// Shader target. #[clap(long, default_value = "spirv-unknown-vulkan1.2")] - shader_target: String, + pub shader_target: String, + + /// Path to the output JSON manifest file where the paths to .spv files + /// and the names of their entry points will be saved. + #[clap(long)] + pub shader_manifest: Option, /// Set cargo default-features. #[clap(long)] - no_default_features: bool, + pub no_default_features: bool, /// Set cargo features. #[clap(long)] - features: Vec, + pub features: Vec, /// Path to the output directory for the compiled shaders. #[clap(long, short, default_value = "./")] - output_dir: std::path::PathBuf, + pub output_dir: std::path::PathBuf, /// If set the shaders will be compiled but not put into place. #[clap(long, short)] - dry_run: bool, -} - -fn wgsl(spv_filepath: impl AsRef, destination: impl AsRef) { - let bytes = std::fs::read(spv_filepath).unwrap(); - let opts = naga::front::spv::Options::default(); - let module = naga::front::spv::parse_u8_slice(&bytes, &opts).unwrap(); - let mut validator = - naga::valid::Validator::new(Default::default(), naga::valid::Capabilities::empty()); - let info = validator.validate(&module).unwrap(); - let wgsl = - naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::empty()) - .unwrap(); - let destination = destination.as_ref().with_extension("wgsl"); - std::fs::write(destination, wgsl).unwrap(); + pub dry_run: bool, } fn main() -> Result<(), Box> { env_logger::builder().init(); - set_rustc_codegen_spirv_path(); set_rustup_toolchain(); let Cli { shader_crate, - shader_lang, shader_target, no_default_features, features, output_dir, + shader_manifest: output_manifest, dry_run, } = Cli::parse_from(std::env::args().filter(|p| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" @@ -151,7 +120,7 @@ fn main() -> Result<(), Box> { module, } = { let mut builder = SpirvBuilder::new(shader_crate, &shader_target) - //.shader_panic_strategy(spirv_builder::ShaderPanicStrategy::UNSOUND_DO_NOT_USE_UndefinedBehaviorViaUnreachable) + .rustc_codegen_spirv_location(RUSTC_CODEGEN_SPIRV_PATH) .print_metadata(MetadataPrintout::None) .multimodule(true); @@ -175,19 +144,9 @@ fn main() -> Result<(), Box> { for (entry, filepath) in modules.into_iter() { let path = dir.join(filepath.file_name().unwrap()); if !dry_run { - match shader_lang { - ShaderLang::Spv => { - std::fs::copy(filepath, &path).unwrap(); - } - ShaderLang::Wgsl => { - wgsl(filepath, &path); - } - } + std::fs::copy(filepath, &path).unwrap(); } - shaders.push(linkage::Linkage { - entry_point: entry, - source_path: path, - }); + shaders.push(linkage::Linkage::new(entry, path)); } } ModuleResult::SingleModule(filepath) => { @@ -196,44 +155,37 @@ fn main() -> Result<(), Box> { std::fs::copy(filepath, &path).unwrap(); } for entry in entry_points { - shaders.push(linkage::Linkage { - entry_point: entry, - source_path: path.clone(), - }); + shaders.push(linkage::Linkage::new(entry, path.clone())); } } } - if dry_run { - println!("\nNot writing shaders.rs because --dry-run was set.\n"); - } else { - println!("\nWriting shaders..."); - }; - - let mut set = std::collections::HashSet::<&str>::default(); - - for linkage in shaders.iter() { - let fn_name = linkage.fn_name(); - - if set.contains(fn_name) { - panic!("Shader name '{fn_name}' is used for two or more shaders, aborting!"); - } - set.insert(fn_name); - - let filepath = dir.join(fn_name).with_extension("rs"); - let contents = linkage.to_string(shader_lang); - if !dry_run { - std::fs::write(&filepath, contents).unwrap(); - std::process::Command::new("rustfmt") - .args([&format!("{}", filepath.display())]) - .output() - .expect("could not format generated code"); - println!(" {}", filepath.display()); + // Write the shader manifest json file + if !dry_run { + if let Some(manifest_path) = output_manifest { + // Sort the contents so the output is deterministic + shaders.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&shaders).unwrap(); + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); } } let end = std::time::Instant::now(); - println!("Finished in {:?}", (end - start)); + log::debug!("finished in {:?}", (end - start)); Ok(()) } From 1fb24d90870189d40d966a49f89485a87f6547aa Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 6 Nov 2024 09:14:27 +1300 Subject: [PATCH 008/162] reference rust-gpu git --- Cargo.lock | 3 +++ Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df5fa713bc..8607213092 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv" version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" dependencies = [ "ar", "either", @@ -518,6 +519,7 @@ dependencies = [ [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" dependencies = [ "rspirv", "serde", @@ -645,6 +647,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" dependencies = [ "memchr", "raw-string", diff --git a/Cargo.toml b/Cargo.toml index 4211081f97..adc1ae70f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ name = "cargo_gpu" [build-dependencies] env_home = "0.1.0" toml = "0.8.19" -spirv-builder = { path = "../rust-gpu/crates/spirv-builder" } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", branch = "feature/spirv-builder-rustc-codegen-spirv-location" } [dependencies] clap = { version = "4.4.8", features = ["derive"] } @@ -24,7 +24,7 @@ env_logger = "0.10" log = "0.4" serde = "1.0.214" serde_json = "1.0.132" -spirv-builder = { path = "../rust-gpu/crates/spirv-builder" } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", branch = "feature/spirv-builder-rustc-codegen-spirv-location" } # Enable incremental by default in release mode. [profile.release] From 2309b0d3ccb29334d0643d244345bed9ad4f82ef Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 8 Nov 2024 14:52:27 +1300 Subject: [PATCH 009/162] remove extraneous commented-out code --- src/build.rs | 3 +-- src/main.rs | 33 --------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/build.rs b/src/build.rs index c2dfc89236..273895a31b 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,7 +1,6 @@ //! Build script that copies the built `librustc_codegen_spirv.dylib` into //! a known location. - -//const DYLIB_FILENAME: &str = "librustc_codegen_spirv.dylib"; +// TODO: remove the dependency on spirv-builder and subsequently rustc_codegen_spirv. use std::str::FromStr; diff --git a/src/main.rs b/src/main.rs index 9d92b75e24..1fed9cb7b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,39 +9,6 @@ use cargo_gpu::linkage; const RUSTC_CODEGEN_SPIRV_PATH: &str = std::env!("DYLIB_PATH"); -// fn dylib_path_envvar() -> &'static str { -// if cfg!(windows) { -// "PATH" -// } else if cfg!(target_os = "macos") { -// "DYLD_FALLBACK_LIBRARY_PATH" -// } else { -// "LD_LIBRARY_PATH" -// } -// } - -// fn dylib_path() -> Vec { -// match std::env::var_os(dylib_path_envvar()) { -// Some(var) => std::env::split_paths(&var).collect(), -// None => Vec::new(), -// } -// } - -// fn set_rustc_codegen_spirv_path() { -// let var = dylib_path_envvar(); -// let mut paths = dylib_path(); -// paths.push( -// std::path::PathBuf::from(RUSTC_CODEGEN_SPIRV_PATH) -// .parent() -// .unwrap() -// .to_path_buf(), -// ); -// std::env::set_var( -// var, -// std::env::join_paths(paths).expect("could not join paths"), -// ); -// log::trace!("library search paths: {:#?}", dylib_path()); -// } - const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); fn set_rustup_toolchain() { From 85e18fbff330a1a9142616ec01e16d8d1c3797f5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 9 Nov 2024 11:48:07 +1300 Subject: [PATCH 010/162] decoupled spirv-builder from cargo-gpu --- .gitignore | 3 +- Cargo.lock | 496 ++++-------- Cargo.toml | 48 +- crates/cargo-gpu-wire-types/Cargo.toml | 8 + crates/cargo-gpu-wire-types/src/lib.rs | 72 ++ crates/cargo-gpu/Cargo.toml | 36 + README.md => crates/cargo-gpu/README.md | 0 crates/cargo-gpu/src/main.rs | 334 ++++++++ crates/spirv-builder-cli/Cargo.lock | 748 ++++++++++++++++++ crates/spirv-builder-cli/Cargo.toml | 13 + .../spirv-builder-cli/rust-toolchain.toml | 0 crates/spirv-builder-cli/src/main.rs | 74 ++ src/build.rs | 65 -- src/lib.rs | 3 - src/linkage.rs | 22 - src/main.rs | 158 ---- 16 files changed, 1439 insertions(+), 641 deletions(-) create mode 100644 crates/cargo-gpu-wire-types/Cargo.toml create mode 100644 crates/cargo-gpu-wire-types/src/lib.rs create mode 100644 crates/cargo-gpu/Cargo.toml rename README.md => crates/cargo-gpu/README.md (100%) create mode 100644 crates/cargo-gpu/src/main.rs create mode 100644 crates/spirv-builder-cli/Cargo.lock create mode 100644 crates/spirv-builder-cli/Cargo.toml rename rust-toolchain.toml => crates/spirv-builder-cli/rust-toolchain.toml (100%) create mode 100644 crates/spirv-builder-cli/src/main.rs delete mode 100644 src/build.rs delete mode 100644 src/lib.rs delete mode 100644 src/linkage.rs delete mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index aab88c292e..99d4b406dd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,7 @@ *.DS_Store # will have compiled files and executables /target/ -shaders/target -shaders/shader-crate/target +**/target # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html diff --git a/Cargo.lock b/Cargo.lock index 8607213092..7533ec21b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" version = "1.1.3" @@ -71,65 +60,33 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "ar" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bytemuck" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" - -[[package]] -name = "byteorder" -version = "1.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "cargo-gpu" version = "0.1.0" dependencies = [ + "cargo-gpu-wire-types", "clap", + "directories", "env_home", "env_logger", "log", "serde", "serde_json", - "spirv-builder", "toml", ] [[package]] -name = "cc" -version = "1.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +name = "cargo-gpu-wire-types" +version = "0.1.0" dependencies = [ - "jobserver", - "libc", - "shlex", + "serde", + "serde_json", ] [[package]] @@ -169,7 +126,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn", ] [[package]] @@ -185,38 +142,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "derive_more" -version = "0.99.18" +name = "directories" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.87", + "dirs-sys", ] [[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elsa" -version = "1.10.0" +name = "dirs-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ - "indexmap 2.6.0", - "stable_deref_trait", + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", ] [[package]] @@ -244,15 +187,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -264,21 +198,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.15.0" @@ -303,16 +222,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.6.0" @@ -320,15 +229,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown", ] -[[package]] -name = "internal-iterator" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" - [[package]] name = "is-terminal" version = "0.4.13" @@ -346,36 +249,12 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libc" version = "0.2.161" @@ -383,16 +262,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] -name = "log" -version = "0.4.22" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] [[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -401,19 +284,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.20.2" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" @@ -434,10 +308,15 @@ dependencies = [ ] [[package]] -name = "raw-string" -version = "0.3.5" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] [[package]] name = "regex" @@ -468,95 +347,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" -[[package]] -name = "rspirv" -version = "0.11.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba" -dependencies = [ - "fxhash", - "num-traits", - "spirv", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_codegen_spirv" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" -dependencies = [ - "ar", - "either", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "itertools", - "lazy_static", - "libc", - "num-traits", - "once_cell", - "regex", - "rspirv", - "rustc-demangle", - "rustc_codegen_spirv-types", - "sanitize-filename", - "smallvec", - "spirt", - "spirv-tools", - "syn 1.0.109", -] - -[[package]] -name = "rustc_codegen_spirv-types" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" -dependencies = [ - "rspirv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "sanitize-filename" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - [[package]] name = "serde" version = "1.0.214" @@ -574,7 +370,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn", ] [[package]] @@ -598,106 +394,12 @@ dependencies = [ "serde", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -dependencies = [ - "serde", -] - -[[package]] -name = "spirt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e1f7903720ff818d6da824edf2c4082c6e7a029a99317fd10c39dd7c40c7ff" -dependencies = [ - "arrayvec", - "bytemuck", - "derive_more", - "elsa", - "indexmap 1.9.3", - "internal-iterator", - "itertools", - "lazy_static", - "longest-increasing-subsequence", - "rustc-hash", - "serde", - "serde_json", - "smallvec", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "spirv-builder" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?branch=feature/spirv-builder-rustc-codegen-spirv-location#ce00c8b3a2d1046566d26da4c9d25092b051156c" -dependencies = [ - "memchr", - "raw-string", - "rustc_codegen_spirv", - "rustc_codegen_spirv-types", - "serde", - "serde_json", -] - -[[package]] -name = "spirv-tools" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb3b0832881834994b7ec82b709ec5491043ceb4bf8101e27da6b5234b24261" -dependencies = [ - "spirv-tools-sys", -] - -[[package]] -name = "spirv-tools-sys" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e68b55a97aa6856e010a6f2477425875a97873e147bb0232160e73c45bdae7" -dependencies = [ - "cc", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.87" @@ -718,6 +420,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "toml" version = "0.8.19" @@ -745,7 +467,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -764,12 +486,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -785,13 +501,22 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -800,7 +525,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -809,28 +549,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -843,24 +601,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index adc1ae70f8..463deb38ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,42 +1,22 @@ -[package] -name = "cargo-gpu" -version = "0.1.0" -edition = "2021" -description = "Generates shader .spv files from rust-gpu shader crates" -build = "src/build.rs" +[workspace] +members = [ + "crates/cargo-gpu", + "crates/cargo-gpu-wire-types", +] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +exclude = [ + "crates/spirv-builder-cli" +] -[[bin]] -name = "cargo-gpu" +resolver = "2" -[lib] -name = "cargo_gpu" - -[build-dependencies] -env_home = "0.1.0" -toml = "0.8.19" -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", branch = "feature/spirv-builder-rustc-codegen-spirv-location" } - -[dependencies] +[workspace.dependencies] clap = { version = "4.4.8", features = ["derive"] } +directories = "5.0.1" +env_home = "0.1.0" env_logger = "0.10" log = "0.4" -serde = "1.0.214" +serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", branch = "feature/spirv-builder-rustc-codegen-spirv-location" } - -# Enable incremental by default in release mode. -[profile.release] -incremental = true -# HACK(eddyb) this is the default but without explicitly specifying it, Cargo -# will treat the identical settings in `[profile.release.build-override]` below -# as different sets of `rustc` flags and will not reuse artifacts between them. -codegen-units = 256 +toml = "0.8.19" -# Compile build-dependencies in release mode with the same settings -# as regular dependencies (including the incremental enabled above). -[profile.release.build-override] -opt-level = 3 -incremental = true -codegen-units = 256 diff --git a/crates/cargo-gpu-wire-types/Cargo.toml b/crates/cargo-gpu-wire-types/Cargo.toml new file mode 100644 index 0000000000..42d22b0822 --- /dev/null +++ b/crates/cargo-gpu-wire-types/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cargo-gpu-wire-types" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde.workspace = true +serde_json.workspace = true diff --git a/crates/cargo-gpu-wire-types/src/lib.rs b/crates/cargo-gpu-wire-types/src/lib.rs new file mode 100644 index 0000000000..144348b51b --- /dev/null +++ b/crates/cargo-gpu-wire-types/src/lib.rs @@ -0,0 +1,72 @@ +//! Wire types for `cargo-gpu` and `spirv-builder-cli`. + +/// A built shader entry-point, assumed to be still in the build tree. +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ShaderModule { + pub entry: String, + pub path: std::path::PathBuf, +} + +impl ShaderModule { + pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { + Self { + entry: entry.as_ref().into(), + path: path.as_ref().into(), + } + } +} + +/// Shader source and entry point that can be used to create shader linkage. +#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Linkage { + pub source_path: std::path::PathBuf, + pub entry_point: String, + pub wgsl_entry_point: String, +} + +impl Linkage { + pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { + Self { + source_path: source_path.as_ref().to_path_buf(), + wgsl_entry_point: entry_point.as_ref().replace("::", ""), + entry_point: entry_point.as_ref().to_string(), + } + } + + pub fn fn_name(&self) -> &str { + self.entry_point.split("::").last().unwrap() + } +} + +pub mod spirv_builder_cli { + //! `spirv-builder-cli` interface types. + //! + //! This module is exposed here to keep `spirv-build-cli`'s source + //! as small as possible. It is not expected to be used by any + //! user-facing code. + + /// `spirv-builder-cli` command line interface. + #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] + pub struct Args { + /// Path to rustc_codegen_spirv dylib. + pub dylib_path: std::path::PathBuf, + + /// Directory containing the shader crate to compile. + pub shader_crate: std::path::PathBuf, + + /// Shader target. + pub shader_target: String, + + /// Set cargo default-features. + pub no_default_features: bool, + + /// Set cargo features. + pub features: Vec, + + /// Path to the output directory for the compiled shaders. + pub output_dir: std::path::PathBuf, + + /// Dry run or not + pub dry_run: bool, + } +} diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml new file mode 100644 index 0000000000..159f09dd7e --- /dev/null +++ b/crates/cargo-gpu/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "cargo-gpu" +version = "0.1.0" +edition = "2021" +description = "Generates shader .spv files from rust-gpu shader crates" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +env_home.workspace = true +toml.workspace = true + +[dependencies] +cargo-gpu-wire-types = { version = "0.1", path = "../cargo-gpu-wire-types" } +clap.workspace = true +directories.workspace = true +env_logger.workspace = true +log.workspace = true +serde.workspace = true +serde_json.workspace = true +toml.workspace = true + +# Enable incremental by default in release mode. +[profile.release] +incremental = true +# HACK(eddyb) this is the default but without explicitly specifying it, Cargo +# will treat the identical settings in `[profile.release.build-override]` below +# as different sets of `rustc` flags and will not reuse artifacts between them. +codegen-units = 256 + +# Compile build-dependencies in release mode with the same settings +# as regular dependencies (including the incremental enabled above). +[profile.release.build-override] +opt-level = 3 +incremental = true +codegen-units = 256 diff --git a/README.md b/crates/cargo-gpu/README.md similarity index 100% rename from README.md rename to crates/cargo-gpu/README.md diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs new file mode 100644 index 0000000000..5f6ae51178 --- /dev/null +++ b/crates/cargo-gpu/src/main.rs @@ -0,0 +1,334 @@ +//! Rust GPU shader crate builder. +//! +//! This program manages installations of `spirv-builder-cli` and `rustc_codegen_spirv`. +//! It uses these tools to compile Rust code into SPIR-V. +use std::{io::Write, str::FromStr}; + +use cargo_gpu_wire_types::{Linkage, ShaderModule}; +use clap::Parser; + +#[derive(Debug, Clone)] +enum SpirvVersion { + LocalPath(std::path::PathBuf), +} + +impl FromStr for SpirvVersion { + type Err = String; + + fn from_str(s: &str) -> Result { + let local_path = std::path::PathBuf::from(s); + if local_path.is_dir() { + Ok(SpirvVersion::LocalPath(local_path)) + } else { + Err(format!("local path '{s}' is not a directory")) + } + } +} + +impl core::fmt::Display for SpirvVersion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SpirvVersion::LocalPath(path) => path.display().fmt(f), + } + } +} + +impl SpirvVersion { + fn to_dirname(&self) -> String { + match self { + SpirvVersion::LocalPath(path) => path + .canonicalize() + .unwrap() + .display() + .to_string() + .replace(std::path::MAIN_SEPARATOR, "_"), + } + } + + fn checkout(&self) -> std::path::PathBuf { + let checkout_dir = cache_dir().join(self.to_dirname()); + std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { + log::error!( + "could not create checkout dir '{}': {e}", + checkout_dir.display() + ); + panic!("could not create checkout dir"); + }); + checkout_dir + } + + fn cargo_build_params(&self) -> Vec { + let checkout = self.checkout(); + match self { + SpirvVersion::LocalPath(path) => vec![ + "build".into(), + "--release".into(), + "--manifest-path".into(), + path.join("Cargo.toml").display().to_string(), + "--target-dir".into(), + checkout.join("target").display().to_string(), + ], + } + } + + fn toolchain(&self) -> String { + match self { + SpirvVersion::LocalPath(path) => { + let rust_toolchain_toml_path = path.join("rust-toolchain.toml"); + let rust_toolchain_toml = + std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); + let table = toml::Table::from_str(&rust_toolchain_toml) + .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); + let toolchain = table + .get("toolchain") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) + .as_table() + .unwrap(); + toolchain + .get("channel") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) + .as_str() + .unwrap() + .into() + } + } + } + + fn build(&self, force: bool) -> (std::path::PathBuf, std::path::PathBuf) { + let checkout = self.checkout(); + let release = checkout.join("target").join("release"); + + let dylib_filename = format!( + "{}rustc_codegen_spirv{}", + std::env::consts::DLL_PREFIX, + std::env::consts::DLL_SUFFIX + ); + let dylib_path = release.join(&dylib_filename); + let dest_dylib_path = checkout.join(&dylib_filename); + + let dest_cli_path = checkout.join("spirv-builder-cli"); + + let toolchain = self.toolchain(); + std::env::set_var("RUSTC_NIGHTLY_CHANNEL", &toolchain); + + if dest_dylib_path.is_file() && dest_cli_path.is_file() { + log::info!("artifacts are already built"); + } + + if dest_dylib_path.is_file() && dest_cli_path.is_file() && !force { + log::info!("...and so we are aborting the build step."); + } else { + let args = { + let mut args = vec![format!("+{toolchain}")]; + args.extend(self.cargo_build_params()); + args + }; + log::debug!("running cargo {}", args.join(" ")); + let output = std::process::Command::new("cargo") + .args(args) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + if output.status.success() { + log::info!("installation succeeded"); + } + + if dylib_path.is_file() { + log::info!("successfully built {}", dylib_path.display()); + std::fs::rename(&dylib_path, &dest_dylib_path).unwrap(); + } else { + log::error!("could not build {}", dylib_path.display()); + panic!("spirv-builder-cli build failed"); + } + + let cli_path = release.join("spirv-builder-cli"); + if cli_path.is_file() { + log::info!("successfully built {}", cli_path.display()); + std::fs::rename(&cli_path, &dest_cli_path).unwrap(); + } else { + log::error!("could not build {}", cli_path.display()); + panic!("spirv-builder-cli build failed"); + } + } + (dest_dylib_path, dest_cli_path) + } +} + +#[derive(Parser)] +#[clap(author, version, about)] +struct Cli { + /// Version of `spirv-std` used to compile shaders. + #[clap(default_value = "crates/spirv-builder-cli")] + spirv_version: SpirvVersion, + + /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + force_spirv_cli_rebuild: bool, + + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + shader_crate: std::path::PathBuf, + + /// Shader target. + #[clap(long, default_value = "spirv-unknown-vulkan1.2")] + shader_target: String, + + /// Path to the output JSON manifest file where the paths to .spv files + /// and the names of their entry points will be saved. + #[clap(long)] + shader_manifest: Option, + + /// Set cargo default-features. + #[clap(long)] + no_default_features: bool, + + /// Set cargo features. + #[clap(long)] + features: Vec, + + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "./")] + output_dir: std::path::PathBuf, + + /// If set the shaders will be compiled but not put into place. + #[clap(long, short)] + dry_run: bool, +} + +fn cache_dir() -> std::path::PathBuf { + directories::BaseDirs::new() + .unwrap_or_else(|| { + log::error!("could not find the user home directory"); + panic!("cache_dir failed"); + }) + .cache_dir() + .join("rust-gpu") +} + +fn main() -> Result<(), Box> { + env_logger::builder().init(); + + let Cli { + spirv_version, + force_spirv_cli_rebuild, + shader_crate, + shader_target, + no_default_features, + features, + output_dir, + shader_manifest: output_manifest, + dry_run, + } = Cli::parse_from(std::env::args().filter(|p| { + // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" + // as the first parameter, which we want to ignore. + p != "gpu" + })); + log::info!("using spirv-std version '{spirv_version}'"); + + // Ensure the cache dir exists + let cache_dir = cache_dir(); + std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { + log::error!( + "could not create cache directory '{}': {e}", + cache_dir.display() + ); + panic!("could not create cache dir"); + }); + + // Check out the spirv-builder-cli source into the cache dir with a prefix and build it. + let (dylib_path, spirv_builder_cli_path) = spirv_version.build(force_spirv_cli_rebuild); + + // Ensure the shader output dir exists + std::fs::create_dir_all(&output_dir).unwrap(); + + assert!( + shader_crate.exists(), + "shader crate '{}' does not exist. (Current dir is '{}')", + shader_crate.display(), + std::env::current_dir().unwrap().display() + ); + + let spirv_builder_args = cargo_gpu_wire_types::spirv_builder_cli::Args { + dylib_path, + shader_crate, + shader_target, + no_default_features, + features, + output_dir: output_dir.clone(), + dry_run, + }; + + // let mut file = std::fs::File::create(dir.join("build-manifest.json")).unwrap(); + // file.write_all(&serde_json::to_vec(&shaders).unwrap()); + // UNWRAP: safe because we know this always serializes + let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); + log::info!("using spirv-builder-cli arg: {arg}"); + + // Call spirv-builder-cli to compile the shaders. + let output = std::process::Command::new(&spirv_builder_cli_path) + .arg(arg) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "build failed"); + + let spirv_manifest = output_dir.join("spirv-manifest.json"); + if spirv_manifest.is_file() { + log::debug!( + "successfully built shaders, raw manifest is at '{}'", + spirv_manifest.display() + ); + } else { + log::error!("missing raw manifest '{}'", spirv_manifest.display()); + panic!("missing raw manifest"); + } + + let shaders: Vec = + serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); + + let mut linkage: Vec<_> = shaders + .into_iter() + .map( + |ShaderModule { + entry, + path: filepath, + }| { + let path = output_dir.join(filepath.file_name().unwrap()); + if !dry_run { + std::fs::copy(filepath, &path).unwrap(); + } + Linkage::new(entry, path) + }, + ) + .collect(); + + // Write the shader manifest json file + if !dry_run { + if let Some(manifest_path) = output_manifest { + // Sort the contents so the output is deterministic + linkage.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&linkage).unwrap(); + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + + log::info!("wrote manifest to '{}'", manifest_path.display()); + } + } + + Ok(()) +} diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock new file mode 100644 index 0000000000..817e515b87 --- /dev/null +++ b/crates/spirv-builder-cli/Cargo.lock @@ -0,0 +1,748 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "ar" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + +[[package]] +name = "cargo-gpu-wire-types" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "cc" +version = "1.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.87", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elsa" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +dependencies = [ + "indexmap 2.6.0", + "stable_deref_trait", +] + +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.1", +] + +[[package]] +name = "internal-iterator" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "longest-increasing-subsequence" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "raw-string" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rspirv" +version = "0.12.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" +dependencies = [ + "rustc-hash", + "spirv", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_codegen_spirv" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +dependencies = [ + "ar", + "either", + "hashbrown 0.11.2", + "indexmap 1.9.3", + "itertools", + "lazy_static", + "libc", + "num-traits", + "once_cell", + "regex", + "rspirv", + "rustc-demangle", + "rustc_codegen_spirv-types", + "sanitize-filename", + "smallvec", + "spirt", + "spirv-tools", + "syn 1.0.109", +] + +[[package]] +name = "rustc_codegen_spirv-types" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +dependencies = [ + "rspirv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "sanitize-filename" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.214" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "spirt" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d5968bd2a36466468aac637b355776f080edfb0c6f769b2b99b9708260c42a" +dependencies = [ + "arrayvec", + "bytemuck", + "derive_more", + "elsa", + "indexmap 2.6.0", + "internal-iterator", + "itertools", + "lazy_static", + "longest-increasing-subsequence", + "rustc-hash", + "serde", + "serde_json", + "smallvec", +] + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags", +] + +[[package]] +name = "spirv-builder" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +dependencies = [ + "memchr", + "raw-string", + "rustc_codegen_spirv", + "rustc_codegen_spirv-types", + "serde", + "serde_json", +] + +[[package]] +name = "spirv-builder-cli" +version = "0.1.0" +dependencies = [ + "cargo-gpu-wire-types", + "env_home", + "env_logger", + "log", + "serde_json", + "spirv-builder", + "toml", +] + +[[package]] +name = "spirv-tools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcb3b0832881834994b7ec82b709ec5491043ceb4bf8101e27da6b5234b24261" +dependencies = [ + "spirv-tools-sys", +] + +[[package]] +name = "spirv-tools-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e68b55a97aa6856e010a6f2477425875a97873e147bb0232160e73c45bdae7" +dependencies = [ + "cc", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml new file mode 100644 index 0000000000..7f6a0747b5 --- /dev/null +++ b/crates/spirv-builder-cli/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "spirv-builder-cli" +version = "0.1.0" +edition = "2021" + +[dependencies] +cargo-gpu-wire-types = { version = "0.1", path = "../cargo-gpu-wire-types" } +env_home = "0.1.0" +env_logger = "0.10" +log = "0.4" +serde_json = "1.0.132" +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } +toml = "0.8.19" diff --git a/rust-toolchain.toml b/crates/spirv-builder-cli/rust-toolchain.toml similarity index 100% rename from rust-toolchain.toml rename to crates/spirv-builder-cli/rust-toolchain.toml diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs new file mode 100644 index 0000000000..5cbcbbe6a6 --- /dev/null +++ b/crates/spirv-builder-cli/src/main.rs @@ -0,0 +1,74 @@ +//! This program builds rust-gpu shader crates and writes generated spv files +//! into the main source repo. +use cargo_gpu_wire_types::{spirv_builder_cli::Args, ShaderModule}; +use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; + +const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); + +fn set_rustup_toolchain() { + log::trace!( + "setting RUSTUP_TOOLCHAIN = '{}'", + RUSTC_NIGHTLY_CHANNEL.trim_matches('"') + ); + std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); +} + +fn main() { + env_logger::builder().init(); + + set_rustup_toolchain(); + + let mut args = std::env::args().collect::>(); + + let Args { + dylib_path, + shader_crate, + shader_target, + no_default_features, + features, + output_dir, + dry_run: _, + } = serde_json::from_str(&args[1]).unwrap(); + + let CompileResult { + entry_points, + module, + } = { + let mut builder = SpirvBuilder::new(shader_crate, &shader_target) + .rustc_codegen_spirv_location(dylib_path) + .print_metadata(MetadataPrintout::None) + .multimodule(true); + + if no_default_features { + log::info!("setting cargo --no-default-features"); + builder = builder.shader_crate_default_features(false); + } + if !features.is_empty() { + log::info!("setting --features {features:?}"); + builder = builder.shader_crate_features(features); + } + + builder.build().unwrap() + }; + + let dir = output_dir; + let mut shaders = vec![]; + match module { + ModuleResult::MultiModule(modules) => { + assert!(!modules.is_empty(), "No shader modules to compile"); + for (entry, filepath) in modules.into_iter() { + shaders.push(ShaderModule::new(entry, filepath)); + } + } + ModuleResult::SingleModule(filepath) => { + for entry in entry_points { + shaders.push(ShaderModule::new(entry, filepath.clone())); + } + } + } + + use std::io::Write; + let mut file = std::fs::File::create(dir.join("spirv-manifest.json")).unwrap(); + file.write_all(&serde_json::to_vec(&shaders).unwrap()) + .unwrap(); +} diff --git a/src/build.rs b/src/build.rs deleted file mode 100644 index 273895a31b..0000000000 --- a/src/build.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Build script that copies the built `librustc_codegen_spirv.dylib` into -//! a known location. -// TODO: remove the dependency on spirv-builder and subsequently rustc_codegen_spirv. - -use std::str::FromStr; - -fn dylib_filename() -> String { - format!( - "{}rustc_codegen_spirv{}", - std::env::consts::DLL_PREFIX, - std::env::consts::DLL_SUFFIX - ) -} - -fn find_file(dir: &std::path::Path, filename: &str) -> std::path::PathBuf { - let mut path = dir.join(filename); - while !path.exists() { - if let Some(parent) = path.parent().and_then(|p| p.parent()) { - path = parent.join(filename); - } else { - break; - } - } - - if !path.exists() { - panic!("could not find file '{filename}'"); - } - path -} - -fn main() { - let out_dir = std::path::PathBuf::from( - std::env::var("OUT_DIR").expect("Environment variable OUT_DIR was not set"), - ); - let built_dylib_path = find_file(&out_dir, &dylib_filename()); - - let dest_dir = env_home::env_home_dir() - .expect("home directory is not set") - .join(".rust-gpu"); - std::fs::create_dir_all(&dest_dir).expect("could not create ~/.rust-gpu directory"); - let dest_path = dest_dir.join(dylib_filename()); - - std::fs::copy(&built_dylib_path, &dest_path).unwrap_or_else(|e| { - panic!( - "failed to copy dylib '{}' to destination '{}': {e}", - built_dylib_path.display(), - dest_path.display() - ) - }); - - println!("cargo:rustc-env=DYLIB_PATH={}", dest_path.display()); - - let rust_toolchain_toml = include_str!("../rust-toolchain.toml"); - let table = toml::Table::from_str(rust_toolchain_toml) - .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); - let toolchain = table - .get("toolchain") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) - .as_table() - .unwrap(); - let channel = toolchain - .get("channel") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")); - println!("cargo:rustc-env=RUSTC_NIGHTLY_CHANNEL={channel}"); -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 5be42f12b8..0000000000 --- a/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Helps compiling rust-gpu shaders. - -pub mod linkage; diff --git a/src/linkage.rs b/src/linkage.rs deleted file mode 100644 index 92603944e0..0000000000 --- a/src/linkage.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! A shader source and entry point that can be used to create shader linkage. - -#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Linkage { - pub source_path: std::path::PathBuf, - pub entry_point: String, - pub wgsl_entry_point: String, -} - -impl Linkage { - pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { - Self { - source_path: source_path.as_ref().to_path_buf(), - wgsl_entry_point: entry_point.as_ref().replace("::", ""), - entry_point: entry_point.as_ref().to_string(), - } - } - - pub fn fn_name(&self) -> &str { - self.entry_point.split("::").last().unwrap() - } -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 1fed9cb7b9..0000000000 --- a/src/main.rs +++ /dev/null @@ -1,158 +0,0 @@ -//! This program builds rust-gpu shader crates and writes generated spv files -//! into the main source repo. -use std::io::Write; - -use clap::Parser; -use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; - -use cargo_gpu::linkage; - -const RUSTC_CODEGEN_SPIRV_PATH: &str = std::env!("DYLIB_PATH"); - -const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); - -fn set_rustup_toolchain() { - log::trace!( - "setting RUSTUP_TOOLCHAIN = '{}'", - RUSTC_NIGHTLY_CHANNEL.trim_matches('"') - ); - std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); -} - -#[derive(Parser)] -#[clap(author, version, about)] -pub struct Cli { - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - pub shader_crate: std::path::PathBuf, - - /// Shader target. - #[clap(long, default_value = "spirv-unknown-vulkan1.2")] - pub shader_target: String, - - /// Path to the output JSON manifest file where the paths to .spv files - /// and the names of their entry points will be saved. - #[clap(long)] - pub shader_manifest: Option, - - /// Set cargo default-features. - #[clap(long)] - pub no_default_features: bool, - - /// Set cargo features. - #[clap(long)] - pub features: Vec, - - /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "./")] - pub output_dir: std::path::PathBuf, - - /// If set the shaders will be compiled but not put into place. - #[clap(long, short)] - pub dry_run: bool, -} - -fn main() -> Result<(), Box> { - env_logger::builder().init(); - - set_rustup_toolchain(); - - let Cli { - shader_crate, - shader_target, - no_default_features, - features, - output_dir, - shader_manifest: output_manifest, - dry_run, - } = Cli::parse_from(std::env::args().filter(|p| { - // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" - // as the first parameter, which we want to ignore. - p != "gpu" - })); - - std::fs::create_dir_all(&output_dir).unwrap(); - - assert!( - shader_crate.exists(), - "shader crate '{}' does not exist. (Current dir is '{}')", - shader_crate.display(), - std::env::current_dir().unwrap().display() - ); - - let start = std::time::Instant::now(); - - let CompileResult { - entry_points, - module, - } = { - let mut builder = SpirvBuilder::new(shader_crate, &shader_target) - .rustc_codegen_spirv_location(RUSTC_CODEGEN_SPIRV_PATH) - .print_metadata(MetadataPrintout::None) - .multimodule(true); - - if no_default_features { - log::info!("setting cargo --no-default-features"); - builder = builder.shader_crate_default_features(false); - } - if !features.is_empty() { - log::info!("setting --features {features:?}"); - builder = builder.shader_crate_features(features); - } - - builder.build()? - }; - - let dir = output_dir; - let mut shaders = vec![]; - match module { - ModuleResult::MultiModule(modules) => { - assert!(!modules.is_empty(), "No shader modules to compile"); - for (entry, filepath) in modules.into_iter() { - let path = dir.join(filepath.file_name().unwrap()); - if !dry_run { - std::fs::copy(filepath, &path).unwrap(); - } - shaders.push(linkage::Linkage::new(entry, path)); - } - } - ModuleResult::SingleModule(filepath) => { - let path = dir.join(filepath.file_name().unwrap()); - if !dry_run { - std::fs::copy(filepath, &path).unwrap(); - } - for entry in entry_points { - shaders.push(linkage::Linkage::new(entry, path.clone())); - } - } - } - - // Write the shader manifest json file - if !dry_run { - if let Some(manifest_path) = output_manifest { - // Sort the contents so the output is deterministic - shaders.sort(); - // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&shaders).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { - log::error!( - "could not create shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { - log::error!( - "could not write shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - } - } - - let end = std::time::Instant::now(); - log::debug!("finished in {:?}", (end - start)); - - Ok(()) -} From d199d0614f0e52c294d9089cfd0b8180043f130c Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 9 Nov 2024 11:49:21 +1300 Subject: [PATCH 011/162] spirvversion todo --- crates/cargo-gpu/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 5f6ae51178..10dcd4b17c 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -7,6 +7,7 @@ use std::{io::Write, str::FromStr}; use cargo_gpu_wire_types::{Linkage, ShaderModule}; use clap::Parser; +// TODO: expand the sources of spirv versions #[derive(Debug, Clone)] enum SpirvVersion { LocalPath(std::path::PathBuf), From b1c2b51fb6dae14292dcef84f2e9d5aba7e04c56 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 9 Nov 2024 15:40:26 +1300 Subject: [PATCH 012/162] move ShaderModule --- crates/cargo-gpu-wire-types/src/lib.rs | 33 +++++++++++++------------- crates/cargo-gpu/src/main.rs | 2 +- crates/spirv-builder-cli/src/main.rs | 3 +-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/cargo-gpu-wire-types/src/lib.rs b/crates/cargo-gpu-wire-types/src/lib.rs index 144348b51b..75b4f84c31 100644 --- a/crates/cargo-gpu-wire-types/src/lib.rs +++ b/crates/cargo-gpu-wire-types/src/lib.rs @@ -1,21 +1,5 @@ //! Wire types for `cargo-gpu` and `spirv-builder-cli`. -/// A built shader entry-point, assumed to be still in the build tree. -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct ShaderModule { - pub entry: String, - pub path: std::path::PathBuf, -} - -impl ShaderModule { - pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { - Self { - entry: entry.as_ref().into(), - path: path.as_ref().into(), - } - } -} - /// Shader source and entry point that can be used to create shader linkage. #[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Linkage { @@ -69,4 +53,21 @@ pub mod spirv_builder_cli { /// Dry run or not pub dry_run: bool, } + + /// A built shader entry-point, used in `spirv-builder-cli` to generate + /// a `build-manifest.json` used by `cargo-gpu`. + #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] + pub struct ShaderModule { + pub entry: String, + pub path: std::path::PathBuf, + } + + impl ShaderModule { + pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { + Self { + entry: entry.as_ref().into(), + path: path.as_ref().into(), + } + } + } } diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 10dcd4b17c..7d8494da89 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -4,7 +4,7 @@ //! It uses these tools to compile Rust code into SPIR-V. use std::{io::Write, str::FromStr}; -use cargo_gpu_wire_types::{Linkage, ShaderModule}; +use cargo_gpu_wire_types::{spirv_builder_cli::ShaderModule, Linkage}; use clap::Parser; // TODO: expand the sources of spirv versions diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 5cbcbbe6a6..d549e94fb2 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -18,8 +18,7 @@ fn main() { set_rustup_toolchain(); - let mut args = std::env::args().collect::>(); - + let args = std::env::args().collect::>(); let Args { dylib_path, shader_crate, From 59906a71fa6eee5759457fa543be6132b991e4e7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 10 Nov 2024 09:33:19 +1300 Subject: [PATCH 013/162] can use git checkout of `cargo-gpu` for `spirv-builder-cli` source --- Cargo.lock | 85 +++++++++++++++++ crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/main.rs | 177 +++++++++++++++++++++++++---------- 3 files changed, 212 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7533ec21b1..3a373b019a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,6 +78,7 @@ dependencies = [ "log", "serde", "serde_json", + "tempdir", "toml", ] @@ -187,6 +188,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "getrandom" version = "0.2.15" @@ -307,6 +314,43 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_users" version = "0.4.6" @@ -347,6 +391,15 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "ryu" version = "1.0.18" @@ -411,6 +464,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -492,6 +555,22 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -501,6 +580,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 159f09dd7e..8ccdc89b47 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -18,6 +18,7 @@ env_logger.workspace = true log.workspace = true serde.workspace = true serde_json.workspace = true +tempdir = "0.3.7" toml.workspace = true # Enable incremental by default in release mode. diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 7d8494da89..5f5a7f9578 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -7,46 +7,58 @@ use std::{io::Write, str::FromStr}; use cargo_gpu_wire_types::{spirv_builder_cli::ShaderModule, Linkage}; use clap::Parser; -// TODO: expand the sources of spirv versions +/// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. #[derive(Debug, Clone)] -enum SpirvVersion { +enum SpirvCli { + Git(String), LocalPath(std::path::PathBuf), } -impl FromStr for SpirvVersion { +impl FromStr for SpirvCli { type Err = String; fn from_str(s: &str) -> Result { - let local_path = std::path::PathBuf::from(s); - if local_path.is_dir() { - Ok(SpirvVersion::LocalPath(local_path)) + if s.starts_with("https://") || s.starts_with("ssh://") || s.starts_with("git@") { + Ok(SpirvCli::Git(s.to_string())) } else { - Err(format!("local path '{s}' is not a directory")) + let local_path = std::path::PathBuf::from(s); + if local_path.is_dir() { + Ok(SpirvCli::LocalPath(local_path)) + } else { + Err(format!("local path '{s}' is not a directory")) + } } } } -impl core::fmt::Display for SpirvVersion { +impl core::fmt::Display for SpirvCli { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - SpirvVersion::LocalPath(path) => path.display().fmt(f), + SpirvCli::Git(url) => url.fmt(f), + SpirvCli::LocalPath(path) => path.display().fmt(f), } } } -impl SpirvVersion { +impl SpirvCli { fn to_dirname(&self) -> String { match self { - SpirvVersion::LocalPath(path) => path - .canonicalize() - .unwrap() - .display() - .to_string() - .replace(std::path::MAIN_SEPARATOR, "_"), + SpirvCli::Git(url) => url.clone(), + SpirvCli::LocalPath(path) => path.canonicalize().unwrap().display().to_string(), } + .replace([std::path::MAIN_SEPARATOR, '.', ':', '@'], "_") + .to_string() + } + + fn cached_rust_toolchain_toml_path(&self) -> std::path::PathBuf { + let checkout_dir = cache_dir().join(self.to_dirname()); + checkout_dir + .join("crates") + .join("spirv-builder-cli") + .join("rust-toolchain.toml") } - fn checkout(&self) -> std::path::PathBuf { + fn cached_checkout_path(&self) -> std::path::PathBuf { let checkout_dir = cache_dir().join(self.to_dirname()); std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { log::error!( @@ -55,48 +67,105 @@ impl SpirvVersion { ); panic!("could not create checkout dir"); }); + checkout_dir } fn cargo_build_params(&self) -> Vec { - let checkout = self.checkout(); - match self { - SpirvVersion::LocalPath(path) => vec![ - "build".into(), - "--release".into(), - "--manifest-path".into(), - path.join("Cargo.toml").display().to_string(), - "--target-dir".into(), - checkout.join("target").display().to_string(), - ], - } + let checkout = self.cached_checkout_path(); + let cargo_gpu_path = match self { + SpirvCli::Git(_) => &checkout, + SpirvCli::LocalPath(path) => path, + }; + let manifest_path = cargo_gpu_path + .join("crates") + .join("spirv-builder-cli") + .join("Cargo.toml") + .display() + .to_string(); + vec![ + "build".into(), + "--release".into(), + "--manifest-path".into(), + manifest_path, + "--target-dir".into(), + checkout.join("target").display().to_string(), + ] } - fn toolchain(&self) -> String { - match self { - SpirvVersion::LocalPath(path) => { - let rust_toolchain_toml_path = path.join("rust-toolchain.toml"); - let rust_toolchain_toml = - std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); - let table = toml::Table::from_str(&rust_toolchain_toml) - .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); - let toolchain = table - .get("toolchain") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) - .as_table() + fn perform_checkout(&self, refresh_git_source: bool) { + if let SpirvCli::Git(url) = self { + let checkout_path = self.cached_checkout_path(); + let git_path = checkout_path.join(".git"); + if git_path.exists() { + log::info!("found existing .git dir in '{}'", git_path.display()); + if refresh_git_source { + log::info!("refreshing existing checkout"); + let output = std::process::Command::new("git") + .current_dir(&checkout_path) + .args(["pull", "origin"]) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "could not refresh git source"); + } else { + log::info!("...and argument `--refresh-spirv-cli` was not passed, so skipping the refresh"); + } + } else { + log::info!("checking out source '{}'", checkout_path.display()); + let output = std::process::Command::new("git") + .args(["clone", "--depth=1", "--no-tags"]) + .arg(url) + .arg(&checkout_path) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() .unwrap(); - toolchain - .get("channel") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) - .as_str() - .unwrap() - .into() + assert!(output.status.success(), "could not checkout git source"); } + log::info!("...checkout done."); + } + } + + fn toolchain(&self) -> String { + /// Determine the toolchain given a path to `cargo-gpu` source directory + fn toolchain_from_path(path: &std::path::Path) -> String { + let rust_toolchain_toml_path = path + .join("crates") + .join("spirv-builder-cli") + .join("rust-toolchain.toml"); + let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); + let table = toml::Table::from_str(&rust_toolchain_toml) + .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); + let toolchain = table + .get("toolchain") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) + .as_table() + .unwrap(); + toolchain + .get("channel") + .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) + .as_str() + .unwrap() + .into() } + + let path = match self { + SpirvCli::Git(_) => self.cached_checkout_path(), + SpirvCli::LocalPath(path) => path.clone(), + }; + toolchain_from_path(&path) } - fn build(&self, force: bool) -> (std::path::PathBuf, std::path::PathBuf) { - let checkout = self.checkout(); + fn build( + &self, + force: bool, + refresh_git_source: bool, + ) -> (std::path::PathBuf, std::path::PathBuf) { + self.perform_checkout(refresh_git_source); + + let checkout = self.cached_checkout_path(); let release = checkout.join("target").join("release"); let dylib_filename = format!( @@ -160,13 +229,17 @@ impl SpirvVersion { #[clap(author, version, about)] struct Cli { /// Version of `spirv-std` used to compile shaders. - #[clap(default_value = "crates/spirv-builder-cli")] - spirv_version: SpirvVersion, + #[clap(default_value = "./")] + spirv_version: SpirvCli, /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. #[clap(long)] force_spirv_cli_rebuild: bool, + /// Refresh the source of `spirv-builder-cli`. Only applies to a git spirv_version. + #[clap(long)] + refresh_spirv_cli: bool, + /// Directory containing the shader crate to compile. #[clap(long, default_value = "./")] shader_crate: std::path::PathBuf, @@ -213,6 +286,7 @@ fn main() -> Result<(), Box> { let Cli { spirv_version, force_spirv_cli_rebuild, + refresh_spirv_cli, shader_crate, shader_target, no_default_features, @@ -238,7 +312,8 @@ fn main() -> Result<(), Box> { }); // Check out the spirv-builder-cli source into the cache dir with a prefix and build it. - let (dylib_path, spirv_builder_cli_path) = spirv_version.build(force_spirv_cli_rebuild); + let (dylib_path, spirv_builder_cli_path) = + spirv_version.build(force_spirv_cli_rebuild, refresh_spirv_cli); // Ensure the shader output dir exists std::fs::create_dir_all(&output_dir).unwrap(); From f007fd91fb45c35383076802658d884863b88998 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 10 Nov 2024 10:51:31 +1300 Subject: [PATCH 014/162] can checkout spirv-builder-cli from a branch --- crates/cargo-gpu/src/main.rs | 112 ++++++++++++++++++++++++----------- 1 file changed, 79 insertions(+), 33 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 5f5a7f9578..8283abea8c 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -7,34 +7,40 @@ use std::{io::Write, str::FromStr}; use cargo_gpu_wire_types::{spirv_builder_cli::ShaderModule, Linkage}; use clap::Parser; -/// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. #[derive(Debug, Clone)] -enum SpirvCli { - Git(String), - LocalPath(std::path::PathBuf), +enum GitSource { + Branch(String), + Rev(String), + Tag(String), } -impl FromStr for SpirvCli { - type Err = String; +impl Default for GitSource { + fn default() -> Self { + GitSource::Branch("main".into()) + } +} - fn from_str(s: &str) -> Result { - if s.starts_with("https://") || s.starts_with("ssh://") || s.starts_with("git@") { - Ok(SpirvCli::Git(s.to_string())) - } else { - let local_path = std::path::PathBuf::from(s); - if local_path.is_dir() { - Ok(SpirvCli::LocalPath(local_path)) - } else { - Err(format!("local path '{s}' is not a directory")) - } +impl core::fmt::Display for GitSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + GitSource::Branch(b) => b.fmt(f), + GitSource::Rev(r) => r.fmt(f), + GitSource::Tag(t) => t.fmt(f), } } } +/// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. +#[derive(Debug, Clone)] +enum SpirvCli { + Git { url: String, source: GitSource }, + LocalPath(std::path::PathBuf), +} + impl core::fmt::Display for SpirvCli { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - SpirvCli::Git(url) => url.fmt(f), + SpirvCli::Git { url, source } => format!("{url}#{source}").fmt(f), SpirvCli::LocalPath(path) => path.display().fmt(f), } } @@ -43,21 +49,13 @@ impl core::fmt::Display for SpirvCli { impl SpirvCli { fn to_dirname(&self) -> String { match self { - SpirvCli::Git(url) => url.clone(), + SpirvCli::Git { url, source } => format!("{url}#{source}"), SpirvCli::LocalPath(path) => path.canonicalize().unwrap().display().to_string(), } .replace([std::path::MAIN_SEPARATOR, '.', ':', '@'], "_") .to_string() } - fn cached_rust_toolchain_toml_path(&self) -> std::path::PathBuf { - let checkout_dir = cache_dir().join(self.to_dirname()); - checkout_dir - .join("crates") - .join("spirv-builder-cli") - .join("rust-toolchain.toml") - } - fn cached_checkout_path(&self) -> std::path::PathBuf { let checkout_dir = cache_dir().join(self.to_dirname()); std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { @@ -74,8 +72,8 @@ impl SpirvCli { fn cargo_build_params(&self) -> Vec { let checkout = self.cached_checkout_path(); let cargo_gpu_path = match self { - SpirvCli::Git(_) => &checkout, SpirvCli::LocalPath(path) => path, + _ => &checkout, }; let manifest_path = cargo_gpu_path .join("crates") @@ -94,7 +92,7 @@ impl SpirvCli { } fn perform_checkout(&self, refresh_git_source: bool) { - if let SpirvCli::Git(url) = self { + if let SpirvCli::Git { url, source } = self { let checkout_path = self.cached_checkout_path(); let git_path = checkout_path.join(".git"); if git_path.exists() { @@ -123,6 +121,16 @@ impl SpirvCli { .output() .unwrap(); assert!(output.status.success(), "could not checkout git source"); + + let output = std::process::Command::new("git") + .current_dir(&checkout_path) + .arg("checkout") + .arg(source.to_string()) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "could not checkout {source}"); } log::info!("...checkout done."); } @@ -152,8 +160,8 @@ impl SpirvCli { } let path = match self { - SpirvCli::Git(_) => self.cached_checkout_path(), SpirvCli::LocalPath(path) => path.clone(), + _ => self.cached_checkout_path(), }; toolchain_from_path(&path) } @@ -228,9 +236,28 @@ impl SpirvCli { #[derive(Parser)] #[clap(author, version, about)] struct Cli { - /// Version of `spirv-std` used to compile shaders. - #[clap(default_value = "./")] - spirv_version: SpirvCli, + // /// Version of `spirv-builder-cli` used to compile shaders. + // #[clap(long)] + // spirv_cli_version: Option, + /// Git URL of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. + #[clap(long)] + spirv_cli_git: Option, + + /// Tag of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. + #[clap(long)] + spirv_cli_tag: Option, + + /// Branch of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. + #[clap(long)] + spirv_cli_branch: Option, + + /// Revision (sha) of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. + #[clap(long)] + spirv_cli_rev: Option, + + /// Path of a local repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. + #[clap(long)] + spirv_cli_path: Option, /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. #[clap(long)] @@ -284,7 +311,6 @@ fn main() -> Result<(), Box> { env_logger::builder().init(); let Cli { - spirv_version, force_spirv_cli_rebuild, refresh_spirv_cli, shader_crate, @@ -294,11 +320,31 @@ fn main() -> Result<(), Box> { output_dir, shader_manifest: output_manifest, dry_run, + // spirv_cli_version, + spirv_cli_git, + spirv_cli_tag, + spirv_cli_branch, + spirv_cli_rev, + spirv_cli_path, } = Cli::parse_from(std::env::args().filter(|p| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" // as the first parameter, which we want to ignore. p != "gpu" })); + let cli_git = spirv_cli_git.map(|url| { + let tag = spirv_cli_tag.map(GitSource::Tag); + let rev = spirv_cli_rev.map(GitSource::Rev); + let branch = spirv_cli_branch.map(GitSource::Branch); + SpirvCli::Git { + url, + source: tag.or(rev).or(branch).unwrap_or_default(), + } + }); + let cli_path = spirv_cli_path.map(|p| SpirvCli::LocalPath(p.into())); + // Temporarily require git or path + let spirv_version = cli_git.or(cli_path).unwrap_or_else(|| { + panic!("must supply --spirv-cli-git or --spirv-cli-path"); + }); log::info!("using spirv-std version '{spirv_version}'"); // Ensure the cache dir exists From 722e63abd4cd0236827f6c02b366816aaeb4f11d Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 10 Nov 2024 11:23:31 +1300 Subject: [PATCH 015/162] correct imports --- crates/cargo-gpu/src/main.rs | 5 +++-- crates/spirv-builder-cli/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 8283abea8c..2c89be21f8 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -113,7 +113,7 @@ impl SpirvCli { } else { log::info!("checking out source '{}'", checkout_path.display()); let output = std::process::Command::new("git") - .args(["clone", "--depth=1", "--no-tags"]) + .arg("clone") .arg(url) .arg(&checkout_path) .stdout(std::process::Stdio::inherit()) @@ -122,9 +122,10 @@ impl SpirvCli { .unwrap(); assert!(output.status.success(), "could not checkout git source"); + log::info!("checking out source '{}'", checkout_path.display()); let output = std::process::Command::new("git") .current_dir(&checkout_path) - .arg("checkout") + .arg("switch") .arg(source.to_string()) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index d549e94fb2..24478e4e12 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -1,6 +1,6 @@ //! This program builds rust-gpu shader crates and writes generated spv files //! into the main source repo. -use cargo_gpu_wire_types::{spirv_builder_cli::Args, ShaderModule}; +use cargo_gpu_wire_types::spirv_builder_cli::{Args, ShaderModule}; use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); From d1f23d97bc9708ceb376a250ddd3d36b852ababf Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 07:09:28 +1300 Subject: [PATCH 016/162] use spirv-builder dep+channel strategy --- Cargo.lock | 9 - Cargo.toml | 1 - crates/cargo-gpu/Cargo.toml | 4 +- .../src/lib.rs | 2 + crates/cargo-gpu/src/main.rs | 348 +++++++----------- crates/spirv-builder-cli/Cargo.toml | 6 +- crates/spirv-builder-cli/rust-toolchain.toml | 2 +- crates/spirv-builder-cli/src/main.rs | 5 +- 8 files changed, 155 insertions(+), 222 deletions(-) rename crates/{cargo-gpu-wire-types => cargo-gpu}/src/lib.rs (96%) diff --git a/Cargo.lock b/Cargo.lock index 3a373b019a..33f4c7b72e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,7 +70,6 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" name = "cargo-gpu" version = "0.1.0" dependencies = [ - "cargo-gpu-wire-types", "clap", "directories", "env_home", @@ -82,14 +81,6 @@ dependencies = [ "toml", ] -[[package]] -name = "cargo-gpu-wire-types" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "cfg-if" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 463deb38ca..2a8dd9981a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "crates/cargo-gpu", - "crates/cargo-gpu-wire-types", ] exclude = [ diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 8ccdc89b47..0b090f8ccd 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -5,13 +5,15 @@ edition = "2021" description = "Generates shader .spv files from rust-gpu shader crates" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "cargo_gpu" [build-dependencies] env_home.workspace = true toml.workspace = true [dependencies] -cargo-gpu-wire-types = { version = "0.1", path = "../cargo-gpu-wire-types" } clap.workspace = true directories.workspace = true env_logger.workspace = true diff --git a/crates/cargo-gpu-wire-types/src/lib.rs b/crates/cargo-gpu/src/lib.rs similarity index 96% rename from crates/cargo-gpu-wire-types/src/lib.rs rename to crates/cargo-gpu/src/lib.rs index 75b4f84c31..15facc35f0 100644 --- a/crates/cargo-gpu-wire-types/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -1,4 +1,6 @@ //! Wire types for `cargo-gpu` and `spirv-builder-cli`. +//! +//! This file is copied by `cargo-gpu` into the build tree of `spirv-builder-cli`. /// Shader source and entry point that can be used to create shader linkage. #[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 2c89be21f8..4a26b7d0a0 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -4,56 +4,39 @@ //! It uses these tools to compile Rust code into SPIR-V. use std::{io::Write, str::FromStr}; -use cargo_gpu_wire_types::{spirv_builder_cli::ShaderModule, Linkage}; +use cargo_gpu::{spirv_builder_cli::ShaderModule, Linkage}; use clap::Parser; -#[derive(Debug, Clone)] -enum GitSource { - Branch(String), - Rev(String), - Tag(String), -} - -impl Default for GitSource { - fn default() -> Self { - GitSource::Branch("main".into()) - } -} - -impl core::fmt::Display for GitSource { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - GitSource::Branch(b) => b.fmt(f), - GitSource::Rev(r) => r.fmt(f), - GitSource::Tag(t) => t.fmt(f), - } - } -} +const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); +const SPIRV_BUILDER_CLI_RUST_TOOLCHAIN_TOML: &str = + include_str!("../../spirv-builder-cli/rust-toolchain.toml"); +const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); +const SPIRV_BUILDER_CLI_LIB: &str = include_str!("lib.rs"); +const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ + ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), + ("rust-toolchain.toml", SPIRV_BUILDER_CLI_RUST_TOOLCHAIN_TOML), + ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), + ("src/lib.rs", SPIRV_BUILDER_CLI_LIB), +]; /// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. #[derive(Debug, Clone)] -enum SpirvCli { - Git { url: String, source: GitSource }, - LocalPath(std::path::PathBuf), +struct SpirvCli { + dep: String, + channel: String, } impl core::fmt::Display for SpirvCli { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - SpirvCli::Git { url, source } => format!("{url}#{source}").fmt(f), - SpirvCli::LocalPath(path) => path.display().fmt(f), - } + format!("{}+{}", self.dep, self.channel).fmt(f) } } impl SpirvCli { fn to_dirname(&self) -> String { - match self { - SpirvCli::Git { url, source } => format!("{url}#{source}"), - SpirvCli::LocalPath(path) => path.canonicalize().unwrap().display().to_string(), - } - .replace([std::path::MAIN_SEPARATOR, '.', ':', '@'], "_") - .to_string() + self.to_string() + .replace([std::path::MAIN_SEPARATOR, '.', ':', '@'], "_") + .to_string() } fn cached_checkout_path(&self) -> std::path::PathBuf { @@ -69,111 +52,96 @@ impl SpirvCli { checkout_dir } - fn cargo_build_params(&self) -> Vec { + // fn perform_checkout(&self, refresh_git_source: bool) { + // if let SpirvCli::Git { url, source } = self { + // let checkout_path = self.cached_checkout_path(); + // let git_path = checkout_path.join(".git"); + // if git_path.exists() { + // log::info!("found existing .git dir in '{}'", git_path.display()); + // if refresh_git_source { + // log::info!("refreshing existing checkout"); + // let output = std::process::Command::new("git") + // .current_dir(&checkout_path) + // .args(["pull", "origin"]) + // .stdout(std::process::Stdio::inherit()) + // .stderr(std::process::Stdio::inherit()) + // .output() + // .unwrap(); + // assert!(output.status.success(), "could not refresh git source"); + // } else { + // log::info!("...and argument `--refresh-spirv-cli` was not passed, so skipping the refresh"); + // } + // } else { + // log::info!("checking out source '{}'", checkout_path.display()); + // let output = std::process::Command::new("git") + // .arg("clone") + // .arg(url) + // .arg(&checkout_path) + // .stdout(std::process::Stdio::inherit()) + // .stderr(std::process::Stdio::inherit()) + // .output() + // .unwrap(); + // assert!(output.status.success(), "could not checkout git source"); + + // log::info!("checking out source '{}'", checkout_path.display()); + // let output = std::process::Command::new("git") + // .current_dir(&checkout_path) + // .arg("switch") + // .arg(source.to_string()) + // .stdout(std::process::Stdio::inherit()) + // .stderr(std::process::Stdio::inherit()) + // .output() + // .unwrap(); + // assert!(output.status.success(), "could not checkout {source}"); + // } + // log::info!("...checkout done."); + // } + // } + + // fn toolchain(&self) -> String { + // /// Determine the toolchain given a path to `cargo-gpu` source directory + // fn toolchain_from_path(path: &std::path::Path) -> String { + // let rust_toolchain_toml_path = path + // .join("crates") + // .join("spirv-builder-cli") + // .join("rust-toolchain.toml"); + // let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); + // let table = toml::Table::from_str(&rust_toolchain_toml) + // .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); + // let toolchain = table + // .get("toolchain") + // .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) + // .as_table() + // .unwrap(); + // toolchain + // .get("channel") + // .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) + // .as_str() + // .unwrap() + // .into() + // } + + // let path = match self { + // SpirvCli::LocalPath(path) => path.clone(), + // _ => self.cached_checkout_path(), + // }; + // toolchain_from_path(&path) + // } + + fn write_source_files(&self) { let checkout = self.cached_checkout_path(); - let cargo_gpu_path = match self { - SpirvCli::LocalPath(path) => path, - _ => &checkout, - }; - let manifest_path = cargo_gpu_path - .join("crates") - .join("spirv-builder-cli") - .join("Cargo.toml") - .display() - .to_string(); - vec![ - "build".into(), - "--release".into(), - "--manifest-path".into(), - manifest_path, - "--target-dir".into(), - checkout.join("target").display().to_string(), - ] - } - - fn perform_checkout(&self, refresh_git_source: bool) { - if let SpirvCli::Git { url, source } = self { - let checkout_path = self.cached_checkout_path(); - let git_path = checkout_path.join(".git"); - if git_path.exists() { - log::info!("found existing .git dir in '{}'", git_path.display()); - if refresh_git_source { - log::info!("refreshing existing checkout"); - let output = std::process::Command::new("git") - .current_dir(&checkout_path) - .args(["pull", "origin"]) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "could not refresh git source"); - } else { - log::info!("...and argument `--refresh-spirv-cli` was not passed, so skipping the refresh"); - } - } else { - log::info!("checking out source '{}'", checkout_path.display()); - let output = std::process::Command::new("git") - .arg("clone") - .arg(url) - .arg(&checkout_path) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "could not checkout git source"); - - log::info!("checking out source '{}'", checkout_path.display()); - let output = std::process::Command::new("git") - .current_dir(&checkout_path) - .arg("switch") - .arg(source.to_string()) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "could not checkout {source}"); - } - log::info!("...checkout done."); + std::fs::create_dir_all(checkout.join("src")).unwrap(); + for (filename, contents) in SPIRV_BUILDER_FILES.iter() { + let path = checkout.join(filename); + let mut file = std::fs::File::create(&path).unwrap(); + let replaced_contents = contents + .replace("${SPIRV_BUILDER_SOURCE}", &self.dep) + .replace("${CHANNEL}", &self.channel); + file.write_all(replaced_contents.as_bytes()).unwrap(); } } - fn toolchain(&self) -> String { - /// Determine the toolchain given a path to `cargo-gpu` source directory - fn toolchain_from_path(path: &std::path::Path) -> String { - let rust_toolchain_toml_path = path - .join("crates") - .join("spirv-builder-cli") - .join("rust-toolchain.toml"); - let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); - let table = toml::Table::from_str(&rust_toolchain_toml) - .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); - let toolchain = table - .get("toolchain") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) - .as_table() - .unwrap(); - toolchain - .get("channel") - .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) - .as_str() - .unwrap() - .into() - } - - let path = match self { - SpirvCli::LocalPath(path) => path.clone(), - _ => self.cached_checkout_path(), - }; - toolchain_from_path(&path) - } - - fn build( - &self, - force: bool, - refresh_git_source: bool, - ) -> (std::path::PathBuf, std::path::PathBuf) { - self.perform_checkout(refresh_git_source); - + fn build(&self, force: bool) -> (std::path::PathBuf, std::path::PathBuf) { let checkout = self.cached_checkout_path(); let release = checkout.join("target").join("release"); @@ -184,40 +152,35 @@ impl SpirvCli { ); let dylib_path = release.join(&dylib_filename); let dest_dylib_path = checkout.join(&dylib_filename); - let dest_cli_path = checkout.join("spirv-builder-cli"); - - let toolchain = self.toolchain(); - std::env::set_var("RUSTC_NIGHTLY_CHANNEL", &toolchain); - if dest_dylib_path.is_file() && dest_cli_path.is_file() { - log::info!("artifacts are already built"); + log::info!("cargo-gpu artifacts are already installed"); } if dest_dylib_path.is_file() && dest_cli_path.is_file() && !force { - log::info!("...and so we are aborting the build step."); + log::info!("...and so we are aborting the install step."); } else { - let args = { - let mut args = vec![format!("+{toolchain}")]; - args.extend(self.cargo_build_params()); - args - }; - log::debug!("running cargo {}", args.join(" ")); + log::debug!( + "writing spirv-builder-cli source files into '{}'", + checkout.display() + ); + self.write_source_files(); + + log::debug!("building artifacts"); let output = std::process::Command::new("cargo") - .args(args) + .current_dir(&checkout) + .args(["build", "--release"]) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) .output() .unwrap(); - if output.status.success() { - log::info!("installation succeeded"); - } + assert!(output.status.success(), "...build error!"); if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); std::fs::rename(&dylib_path, &dest_dylib_path).unwrap(); } else { - log::error!("could not build {}", dylib_path.display()); + log::error!("could not find {}", dylib_path.display()); panic!("spirv-builder-cli build failed"); } @@ -226,7 +189,7 @@ impl SpirvCli { log::info!("successfully built {}", cli_path.display()); std::fs::rename(&cli_path, &dest_cli_path).unwrap(); } else { - log::error!("could not build {}", cli_path.display()); + log::error!("could not find {}", cli_path.display()); panic!("spirv-builder-cli build failed"); } } @@ -237,37 +200,23 @@ impl SpirvCli { #[derive(Parser)] #[clap(author, version, about)] struct Cli { - // /// Version of `spirv-builder-cli` used to compile shaders. - // #[clap(long)] - // spirv_cli_version: Option, - /// Git URL of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. - #[clap(long)] - spirv_cli_git: Option, - - /// Tag of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. - #[clap(long)] - spirv_cli_tag: Option, - - /// Branch of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. - #[clap(long)] - spirv_cli_branch: Option, - - /// Revision (sha) of Git repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. - #[clap(long)] - spirv_cli_rev: Option, - - /// Path of a local repo of `cargo-gpu` containing `spirv-builder-cli` used to compile shaders. - #[clap(long)] - spirv_cli_path: Option, + /// spirv-builder dependency, written just like in a Cargo.toml file. + #[clap( + long, + default_value = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"# + )] + spirv_builder: String, + + /// Rust toolchain channel to use to build `spirv-builder`. + /// + /// This must match the `spirv_builder` argument. + #[clap(long, default_value = "nightly-2024-04-24")] + rust_toolchain: String, /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. #[clap(long)] force_spirv_cli_rebuild: bool, - /// Refresh the source of `spirv-builder-cli`. Only applies to a git spirv_version. - #[clap(long)] - refresh_spirv_cli: bool, - /// Directory containing the shader crate to compile. #[clap(long, default_value = "./")] shader_crate: std::path::PathBuf, @@ -312,8 +261,9 @@ fn main() -> Result<(), Box> { env_logger::builder().init(); let Cli { + spirv_builder, + rust_toolchain, force_spirv_cli_rebuild, - refresh_spirv_cli, shader_crate, shader_target, no_default_features, @@ -321,32 +271,13 @@ fn main() -> Result<(), Box> { output_dir, shader_manifest: output_manifest, dry_run, - // spirv_cli_version, - spirv_cli_git, - spirv_cli_tag, - spirv_cli_branch, - spirv_cli_rev, - spirv_cli_path, } = Cli::parse_from(std::env::args().filter(|p| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" // as the first parameter, which we want to ignore. p != "gpu" })); - let cli_git = spirv_cli_git.map(|url| { - let tag = spirv_cli_tag.map(GitSource::Tag); - let rev = spirv_cli_rev.map(GitSource::Rev); - let branch = spirv_cli_branch.map(GitSource::Branch); - SpirvCli::Git { - url, - source: tag.or(rev).or(branch).unwrap_or_default(), - } - }); - let cli_path = spirv_cli_path.map(|p| SpirvCli::LocalPath(p.into())); - // Temporarily require git or path - let spirv_version = cli_git.or(cli_path).unwrap_or_else(|| { - panic!("must supply --spirv-cli-git or --spirv-cli-path"); - }); - log::info!("using spirv-std version '{spirv_version}'"); + + log::info!("using spirv-std version 'spirv-builder = {spirv_builder}'"); // Ensure the cache dir exists let cache_dir = cache_dir(); @@ -359,8 +290,11 @@ fn main() -> Result<(), Box> { }); // Check out the spirv-builder-cli source into the cache dir with a prefix and build it. - let (dylib_path, spirv_builder_cli_path) = - spirv_version.build(force_spirv_cli_rebuild, refresh_spirv_cli); + let spirv_version = SpirvCli { + dep: spirv_builder, + channel: rust_toolchain, + }; + let (dylib_path, spirv_builder_cli_path) = spirv_version.build(force_spirv_cli_rebuild); // Ensure the shader output dir exists std::fs::create_dir_all(&output_dir).unwrap(); @@ -372,7 +306,7 @@ fn main() -> Result<(), Box> { std::env::current_dir().unwrap().display() ); - let spirv_builder_args = cargo_gpu_wire_types::spirv_builder_cli::Args { + let spirv_builder_args = cargo_gpu::spirv_builder_cli::Args { dylib_path, shader_crate, shader_target, diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 7f6a0747b5..2e5ba79513 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -3,11 +3,13 @@ name = "spirv-builder-cli" version = "0.1.0" edition = "2021" +[lib] +name = "spirv_builder_cli" + [dependencies] -cargo-gpu-wire-types = { version = "0.1", path = "../cargo-gpu-wire-types" } env_home = "0.1.0" env_logger = "0.10" log = "0.4" serde_json = "1.0.132" -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu" } +spirv-builder = ${SPIRV_BUILDER_SOURCE} toml = "0.8.19" diff --git a/crates/spirv-builder-cli/rust-toolchain.toml b/crates/spirv-builder-cli/rust-toolchain.toml index 92ae501066..bfe382e8d9 100644 --- a/crates/spirv-builder-cli/rust-toolchain.toml +++ b/crates/spirv-builder-cli/rust-toolchain.toml @@ -5,7 +5,7 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "nightly-2024-04-24" +channel = "${CHANNEL}" components = ["rust-src", "rustc-dev", "llvm-tools"] # Whenever changing the nightly channel, update the commit hash above, and make diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 24478e4e12..b57c4c6ced 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -3,7 +3,10 @@ use cargo_gpu_wire_types::spirv_builder_cli::{Args, ShaderModule}; use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; -const RUSTC_NIGHTLY_CHANNEL: &str = std::env!("RUSTC_NIGHTLY_CHANNEL"); +mod interface; +use interface::{Args, ShaderModule}; + +const RUSTC_NIGHTLY_CHANNEL: &str = "${CHANNEL}"; fn set_rustup_toolchain() { log::trace!( From ec4ad55142854960251f2243798d4d0130b90b4a Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 07:58:44 +1300 Subject: [PATCH 017/162] better cache dir --- crates/cargo-gpu/src/main.rs | 112 +++++-------------- crates/spirv-builder-cli/Cargo.toml | 1 + crates/spirv-builder-cli/rust-toolchain.toml | 12 -- crates/spirv-builder-cli/src/main.rs | 4 +- 4 files changed, 27 insertions(+), 102 deletions(-) delete mode 100644 crates/spirv-builder-cli/rust-toolchain.toml diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 4a26b7d0a0..848b02b171 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -2,23 +2,22 @@ //! //! This program manages installations of `spirv-builder-cli` and `rustc_codegen_spirv`. //! It uses these tools to compile Rust code into SPIR-V. -use std::{io::Write, str::FromStr}; +use std::io::Write; use cargo_gpu::{spirv_builder_cli::ShaderModule, Linkage}; use clap::Parser; const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); -const SPIRV_BUILDER_CLI_RUST_TOOLCHAIN_TOML: &str = - include_str!("../../spirv-builder-cli/rust-toolchain.toml"); const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); const SPIRV_BUILDER_CLI_LIB: &str = include_str!("lib.rs"); const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), - ("rust-toolchain.toml", SPIRV_BUILDER_CLI_RUST_TOOLCHAIN_TOML), ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), ("src/lib.rs", SPIRV_BUILDER_CLI_LIB), ]; +const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; + /// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. #[derive(Debug, Clone)] struct SpirvCli { @@ -33,10 +32,15 @@ impl core::fmt::Display for SpirvCli { } impl SpirvCli { + /// Returns a string suitable to use as a directory. + /// + /// Created from the spirv-builder source dep and the rustc channel. fn to_dirname(&self) -> String { self.to_string() - .replace([std::path::MAIN_SEPARATOR, '.', ':', '@'], "_") - .to_string() + .replace([std::path::MAIN_SEPARATOR, '.', ':', '@', '='], "_") + .split(['{', '}', ' ', '\n', '"', '\'']) + .collect::>() + .concat() } fn cached_checkout_path(&self) -> std::path::PathBuf { @@ -52,86 +56,11 @@ impl SpirvCli { checkout_dir } - // fn perform_checkout(&self, refresh_git_source: bool) { - // if let SpirvCli::Git { url, source } = self { - // let checkout_path = self.cached_checkout_path(); - // let git_path = checkout_path.join(".git"); - // if git_path.exists() { - // log::info!("found existing .git dir in '{}'", git_path.display()); - // if refresh_git_source { - // log::info!("refreshing existing checkout"); - // let output = std::process::Command::new("git") - // .current_dir(&checkout_path) - // .args(["pull", "origin"]) - // .stdout(std::process::Stdio::inherit()) - // .stderr(std::process::Stdio::inherit()) - // .output() - // .unwrap(); - // assert!(output.status.success(), "could not refresh git source"); - // } else { - // log::info!("...and argument `--refresh-spirv-cli` was not passed, so skipping the refresh"); - // } - // } else { - // log::info!("checking out source '{}'", checkout_path.display()); - // let output = std::process::Command::new("git") - // .arg("clone") - // .arg(url) - // .arg(&checkout_path) - // .stdout(std::process::Stdio::inherit()) - // .stderr(std::process::Stdio::inherit()) - // .output() - // .unwrap(); - // assert!(output.status.success(), "could not checkout git source"); - - // log::info!("checking out source '{}'", checkout_path.display()); - // let output = std::process::Command::new("git") - // .current_dir(&checkout_path) - // .arg("switch") - // .arg(source.to_string()) - // .stdout(std::process::Stdio::inherit()) - // .stderr(std::process::Stdio::inherit()) - // .output() - // .unwrap(); - // assert!(output.status.success(), "could not checkout {source}"); - // } - // log::info!("...checkout done."); - // } - // } - - // fn toolchain(&self) -> String { - // /// Determine the toolchain given a path to `cargo-gpu` source directory - // fn toolchain_from_path(path: &std::path::Path) -> String { - // let rust_toolchain_toml_path = path - // .join("crates") - // .join("spirv-builder-cli") - // .join("rust-toolchain.toml"); - // let rust_toolchain_toml = std::fs::read_to_string(rust_toolchain_toml_path).unwrap(); - // let table = toml::Table::from_str(&rust_toolchain_toml) - // .unwrap_or_else(|e| panic!("could not parse rust-toolchain.toml: {e}")); - // let toolchain = table - // .get("toolchain") - // .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'toolchain'")) - // .as_table() - // .unwrap(); - // toolchain - // .get("channel") - // .unwrap_or_else(|| panic!("rust-toolchain.toml is missing 'channel'")) - // .as_str() - // .unwrap() - // .into() - // } - - // let path = match self { - // SpirvCli::LocalPath(path) => path.clone(), - // _ => self.cached_checkout_path(), - // }; - // toolchain_from_path(&path) - // } - fn write_source_files(&self) { let checkout = self.cached_checkout_path(); std::fs::create_dir_all(checkout.join("src")).unwrap(); for (filename, contents) in SPIRV_BUILDER_FILES.iter() { + log::debug!("writing {filename}"); let path = checkout.join(filename); let mut file = std::fs::File::create(&path).unwrap(); let replaced_contents = contents @@ -141,6 +70,14 @@ impl SpirvCli { } } + fn ensure_version_channel_compatibility(&self) { + for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { + if version.starts_with(&self.dep) && channel != &self.channel { + panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); + } + } + } + fn build(&self, force: bool) -> (std::path::PathBuf, std::path::PathBuf) { let checkout = self.cached_checkout_path(); let release = checkout.join("target").join("release"); @@ -154,7 +91,10 @@ impl SpirvCli { let dest_dylib_path = checkout.join(&dylib_filename); let dest_cli_path = checkout.join("spirv-builder-cli"); if dest_dylib_path.is_file() && dest_cli_path.is_file() { - log::info!("cargo-gpu artifacts are already installed"); + log::info!( + "cargo-gpu artifacts are already installed in '{}'", + checkout.display() + ); } if dest_dylib_path.is_file() && dest_cli_path.is_file() && !force { @@ -169,6 +109,7 @@ impl SpirvCli { log::debug!("building artifacts"); let output = std::process::Command::new("cargo") .current_dir(&checkout) + .arg(format!("+{}", self.channel)) .args(["build", "--release"]) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) @@ -277,8 +218,6 @@ fn main() -> Result<(), Box> { p != "gpu" })); - log::info!("using spirv-std version 'spirv-builder = {spirv_builder}'"); - // Ensure the cache dir exists let cache_dir = cache_dir(); std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { @@ -294,6 +233,7 @@ fn main() -> Result<(), Box> { dep: spirv_builder, channel: rust_toolchain, }; + spirv_version.ensure_version_channel_compatibility(); let (dylib_path, spirv_builder_cli_path) = spirv_version.build(force_spirv_cli_rebuild); // Ensure the shader output dir exists @@ -316,8 +256,6 @@ fn main() -> Result<(), Box> { dry_run, }; - // let mut file = std::fs::File::create(dir.join("build-manifest.json")).unwrap(); - // file.write_all(&serde_json::to_vec(&shaders).unwrap()); // UNWRAP: safe because we know this always serializes let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); log::info!("using spirv-builder-cli arg: {arg}"); diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 2e5ba79513..e9a6cc0aff 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -10,6 +10,7 @@ name = "spirv_builder_cli" env_home = "0.1.0" env_logger = "0.10" log = "0.4" +serde = "1.0.214" serde_json = "1.0.132" spirv-builder = ${SPIRV_BUILDER_SOURCE} toml = "0.8.19" diff --git a/crates/spirv-builder-cli/rust-toolchain.toml b/crates/spirv-builder-cli/rust-toolchain.toml deleted file mode 100644 index bfe382e8d9..0000000000 --- a/crates/spirv-builder-cli/rust-toolchain.toml +++ /dev/null @@ -1,12 +0,0 @@ -# If you see this, run `rustup self update` to get rustup 1.23 or newer. - -# NOTE: above comment is for older `rustup` (before TOML support was added), -# which will treat the first line as the toolchain name, and therefore show it -# to the user in the error, instead of "error: invalid channel name '[toolchain]'". - -[toolchain] -channel = "${CHANNEL}" -components = ["rust-src", "rustc-dev", "llvm-tools"] - -# Whenever changing the nightly channel, update the commit hash above, and make -# sure to change REQUIRED_TOOLCHAIN in crates/rustc_codegen_spirv/src/build.rs also. diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index b57c4c6ced..9a03173e7b 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -1,10 +1,8 @@ //! This program builds rust-gpu shader crates and writes generated spv files //! into the main source repo. -use cargo_gpu_wire_types::spirv_builder_cli::{Args, ShaderModule}; use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; -mod interface; -use interface::{Args, ShaderModule}; +use spirv_builder_cli::spirv_builder_cli::{Args, ShaderModule}; const RUSTC_NIGHTLY_CHANNEL: &str = "${CHANNEL}"; From d5f98cf935955d8f8576e0be689bb15cfc3a0416 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 08:04:43 +1300 Subject: [PATCH 018/162] remove extraneous files --- crates/cargo-gpu-wire-types/Cargo.toml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 crates/cargo-gpu-wire-types/Cargo.toml diff --git a/crates/cargo-gpu-wire-types/Cargo.toml b/crates/cargo-gpu-wire-types/Cargo.toml deleted file mode 100644 index 42d22b0822..0000000000 --- a/crates/cargo-gpu-wire-types/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "cargo-gpu-wire-types" -version = "0.1.0" -edition = "2021" - -[dependencies] -serde.workspace = true -serde_json.workspace = true From 117a355b2ccf5ad9f982f2ec9bc51971b88e6cd7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 09:04:36 +1300 Subject: [PATCH 019/162] readme, separate install and build commands --- crates/cargo-gpu/README.md => README.md | 0 crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/main.rs | 379 ++++++++++++++---------- 3 files changed, 228 insertions(+), 152 deletions(-) rename crates/cargo-gpu/README.md => README.md (100%) diff --git a/crates/cargo-gpu/README.md b/README.md similarity index 100% rename from crates/cargo-gpu/README.md rename to README.md diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 0b090f8ccd..cce8fdd914 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -3,6 +3,7 @@ name = "cargo-gpu" version = "0.1.0" edition = "2021" description = "Generates shader .spv files from rust-gpu shader crates" +readme = "../../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 848b02b171..91c84bb2e7 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -2,10 +2,57 @@ //! //! This program manages installations of `spirv-builder-cli` and `rustc_codegen_spirv`. //! It uses these tools to compile Rust code into SPIR-V. +//! +//! # How it works +//! +//! In order to build shader crates, we must invoke cargo/rustc with a special backend +//! that performs the SPIR-V code generation. This backend is a dynamic library known +//! by its project name `rustc_codegen_spirv`. The name of the artifact itself is +//! OS-dependent. +//! +//! There are a lot of special flags to wrangle and so we use a command line program +//! that wraps `cargo` to perform the building of shader crates. This cli program is +//! called `spirv-builder-cli`, which itself is a cli wrapper around the `spirv-builder` +//! library. +//! +//! ## Where the binaries are +//! +//! `cargo-gpu` maintains different versions `spirv-builder-cli` and `rustc_codegen_spirv` +//! in a cache dir. The location is OS-dependent, for example on macOS it's in +//! `~/Library/Caches/rust-gpu`. Specific versions live inside the cache dir, prefixed +//! by their `spirv-builder` cargo dependency and rust toolchain pair. +//! +//! Building a specific "binary pair" of `spirv-builder-cli` and `rustc_codegen_spirv` +//! happens when there is no existing pair that matches the computed prefix, or if +//! a force rebuild is specified on the command line. +//! +//! ## Building the "binary pairs" +//! +//! The source of `spirv-builder-cli` lives alongside this source file, in crate that +//! is not included in the workspace. That same source code is also included statically +//! in **this** source file. +//! +//! When `spirv-builder-cli` needs to be built, a new directory is created in the cache +//! where the source to `spirv-builder-cli` is copied into, containing the specific cargo +//! dependency for `spirv-builder` and the matching rust toolchain channel. +//! +//! Then `cargo` is invoked in that cache directory to build the pair of artifacts, which +//! are then put into the top level of that cache directory. +//! +//! This pair of artifacts is then used to build shader crates. +//! +//! ## Building shader crates +//! +//! `cargo-gpu` takes a path to a shader crate to build, as well as a path to a directory +//! to put the compiled `spv` source files. It also takes a path to an output mainifest +//! file where all shader entry points will be mapped to their `spv` source files. This +//! manifest file can be used by build scripts (`build.rs` files) to generate linkage or +//! conduct other post-processing, like converting the `spv` files into `wgsl` files, +//! for example. use std::io::Write; use cargo_gpu::{spirv_builder_cli::ShaderModule, Linkage}; -use clap::Parser; +use clap::{Parser, Subcommand}; const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); @@ -56,30 +103,74 @@ impl SpirvCli { checkout_dir } + fn ensure_version_channel_compatibility(&self) { + for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { + if version.starts_with(&self.dep) && channel != &self.channel { + panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); + } + } + } +} + +#[derive(Parser)] +struct Install { + /// spirv-builder dependency, written just like in a Cargo.toml file. + #[clap( + long, + default_value = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"# + )] + spirv_builder: String, + + /// Rust toolchain channel to use to build `spirv-builder`. + /// + /// This must match the `spirv_builder` argument. + #[clap(long, default_value = "nightly-2024-04-24")] + rust_toolchain: String, + + /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + force_spirv_cli_rebuild: bool, +} + +impl Install { + fn spirv_cli(&self) -> SpirvCli { + SpirvCli { + dep: self.spirv_builder.clone(), + channel: self.rust_toolchain.clone(), + } + } + fn write_source_files(&self) { - let checkout = self.cached_checkout_path(); + let cli = self.spirv_cli(); + let checkout = cli.cached_checkout_path(); std::fs::create_dir_all(checkout.join("src")).unwrap(); for (filename, contents) in SPIRV_BUILDER_FILES.iter() { log::debug!("writing {filename}"); let path = checkout.join(filename); let mut file = std::fs::File::create(&path).unwrap(); let replaced_contents = contents - .replace("${SPIRV_BUILDER_SOURCE}", &self.dep) - .replace("${CHANNEL}", &self.channel); + .replace("${SPIRV_BUILDER_SOURCE}", &cli.dep) + .replace("${CHANNEL}", &cli.channel); file.write_all(replaced_contents.as_bytes()).unwrap(); } } - fn ensure_version_channel_compatibility(&self) { - for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { - if version.starts_with(&self.dep) && channel != &self.channel { - panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); - } - } - } + // Install the binary pair and return the paths, (dylib, cli). + fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { + // Ensure the cache dir exists + let cache_dir = cache_dir(); + std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { + log::error!( + "could not create cache directory '{}': {e}", + cache_dir.display() + ); + panic!("could not create cache dir"); + }); + + let spirv_version = self.spirv_cli(); + spirv_version.ensure_version_channel_compatibility(); - fn build(&self, force: bool) -> (std::path::PathBuf, std::path::PathBuf) { - let checkout = self.cached_checkout_path(); + let checkout = spirv_version.cached_checkout_path(); let release = checkout.join("target").join("release"); let dylib_filename = format!( @@ -97,7 +188,7 @@ impl SpirvCli { ); } - if dest_dylib_path.is_file() && dest_cli_path.is_file() && !force { + if dest_dylib_path.is_file() && dest_cli_path.is_file() && !self.force_spirv_cli_rebuild { log::info!("...and so we are aborting the install step."); } else { log::debug!( @@ -109,7 +200,7 @@ impl SpirvCli { log::debug!("building artifacts"); let output = std::process::Command::new("cargo") .current_dir(&checkout) - .arg(format!("+{}", self.channel)) + .arg(format!("+{}", spirv_version.channel)) .args(["build", "--release"]) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) @@ -139,24 +230,9 @@ impl SpirvCli { } #[derive(Parser)] -#[clap(author, version, about)] -struct Cli { - /// spirv-builder dependency, written just like in a Cargo.toml file. - #[clap( - long, - default_value = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"# - )] - spirv_builder: String, - - /// Rust toolchain channel to use to build `spirv-builder`. - /// - /// This must match the `spirv_builder` argument. - #[clap(long, default_value = "nightly-2024-04-24")] - rust_toolchain: String, - - /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. - #[clap(long)] - force_spirv_cli_rebuild: bool, +struct Build { + #[clap(flatten)] + install: Install, /// Directory containing the shader crate to compile. #[clap(long, default_value = "./")] @@ -188,6 +264,118 @@ struct Cli { dry_run: bool, } +impl Build { + fn run(&self) { + let (dylib_path, spirv_builder_cli_path) = self.install.run(); + + // Ensure the shader output dir exists + std::fs::create_dir_all(&self.output_dir).unwrap(); + + assert!( + self.shader_crate.exists(), + "shader crate '{}' does not exist. (Current dir is '{}')", + self.shader_crate.display(), + std::env::current_dir().unwrap().display() + ); + + let spirv_builder_args = cargo_gpu::spirv_builder_cli::Args { + dylib_path, + shader_crate: self.shader_crate.clone(), + shader_target: self.shader_target.clone(), + no_default_features: self.no_default_features, + features: self.features.clone(), + output_dir: self.output_dir.clone(), + dry_run: self.dry_run, + }; + + // UNWRAP: safe because we know this always serializes + let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); + log::info!("using spirv-builder-cli arg: {arg}"); + + // Call spirv-builder-cli to compile the shaders. + let output = std::process::Command::new(&spirv_builder_cli_path) + .arg(arg) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "build failed"); + + let spirv_manifest = self.output_dir.join("spirv-manifest.json"); + if spirv_manifest.is_file() { + log::debug!( + "successfully built shaders, raw manifest is at '{}'", + spirv_manifest.display() + ); + } else { + log::error!("missing raw manifest '{}'", spirv_manifest.display()); + panic!("missing raw manifest"); + } + + let shaders: Vec = + serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); + + let mut linkage: Vec<_> = shaders + .into_iter() + .map( + |ShaderModule { + entry, + path: filepath, + }| { + let path = self.output_dir.join(filepath.file_name().unwrap()); + if !self.dry_run { + std::fs::copy(filepath, &path).unwrap(); + } + Linkage::new(entry, path) + }, + ) + .collect(); + + // Write the shader manifest json file + if !self.dry_run { + if let Some(manifest_path) = &self.shader_manifest { + // Sort the contents so the output is deterministic + linkage.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&linkage).unwrap(); + let mut file = std::fs::File::create(manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + + log::info!("wrote manifest to '{}'", manifest_path.display()); + } + } + } +} + +#[derive(Subcommand)] +enum Command { + /// Install rust-gpu compiler artifacts. + Install(Install), + + /// Compile a shader crate to SPIR-V. + Build(Build), +} + +#[derive(Parser)] +#[clap(author, version, about, subcommand_required = true)] +struct Cli { + /// The command to run. + #[clap(subcommand)] + command: Command, +} + fn cache_dir() -> std::path::PathBuf { directories::BaseDirs::new() .unwrap_or_else(|| { @@ -198,132 +386,19 @@ fn cache_dir() -> std::path::PathBuf { .join("rust-gpu") } -fn main() -> Result<(), Box> { +fn main() { env_logger::builder().init(); - let Cli { - spirv_builder, - rust_toolchain, - force_spirv_cli_rebuild, - shader_crate, - shader_target, - no_default_features, - features, - output_dir, - shader_manifest: output_manifest, - dry_run, - } = Cli::parse_from(std::env::args().filter(|p| { + let cli = Cli::parse_from(std::env::args().filter(|p| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" // as the first parameter, which we want to ignore. p != "gpu" })); - // Ensure the cache dir exists - let cache_dir = cache_dir(); - std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { - log::error!( - "could not create cache directory '{}': {e}", - cache_dir.display() - ); - panic!("could not create cache dir"); - }); - - // Check out the spirv-builder-cli source into the cache dir with a prefix and build it. - let spirv_version = SpirvCli { - dep: spirv_builder, - channel: rust_toolchain, - }; - spirv_version.ensure_version_channel_compatibility(); - let (dylib_path, spirv_builder_cli_path) = spirv_version.build(force_spirv_cli_rebuild); - - // Ensure the shader output dir exists - std::fs::create_dir_all(&output_dir).unwrap(); - - assert!( - shader_crate.exists(), - "shader crate '{}' does not exist. (Current dir is '{}')", - shader_crate.display(), - std::env::current_dir().unwrap().display() - ); - - let spirv_builder_args = cargo_gpu::spirv_builder_cli::Args { - dylib_path, - shader_crate, - shader_target, - no_default_features, - features, - output_dir: output_dir.clone(), - dry_run, - }; - - // UNWRAP: safe because we know this always serializes - let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); - log::info!("using spirv-builder-cli arg: {arg}"); - - // Call spirv-builder-cli to compile the shaders. - let output = std::process::Command::new(&spirv_builder_cli_path) - .arg(arg) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "build failed"); - - let spirv_manifest = output_dir.join("spirv-manifest.json"); - if spirv_manifest.is_file() { - log::debug!( - "successfully built shaders, raw manifest is at '{}'", - spirv_manifest.display() - ); - } else { - log::error!("missing raw manifest '{}'", spirv_manifest.display()); - panic!("missing raw manifest"); - } - - let shaders: Vec = - serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); - - let mut linkage: Vec<_> = shaders - .into_iter() - .map( - |ShaderModule { - entry, - path: filepath, - }| { - let path = output_dir.join(filepath.file_name().unwrap()); - if !dry_run { - std::fs::copy(filepath, &path).unwrap(); - } - Linkage::new(entry, path) - }, - ) - .collect(); - - // Write the shader manifest json file - if !dry_run { - if let Some(manifest_path) = output_manifest { - // Sort the contents so the output is deterministic - linkage.sort(); - // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { - log::error!( - "could not create shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { - log::error!( - "could not write shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - - log::info!("wrote manifest to '{}'", manifest_path.display()); + match cli.command { + Command::Install(install) => { + let _ = install.run(); } + Command::Build(build) => build.run(), } - - Ok(()) } From cd2f2972bafc58816303207a52212b57073b9712 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 09:09:03 +1300 Subject: [PATCH 020/162] Readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c26c81c852..67124010b3 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,19 @@ Command line tool for building Rust shaders using rust-gpu. To install the tool ensure you have `rustup`. Then run: ``` -cargo +nightly-2024-04-24 install --git https://github.com/rust-gpu/cargo-gpu +cargo install --git https://github.com/rust-gpu/cargo-gpu ``` After that you can use `cargo gpu` to compile your shader crates with: ``` -cargo gpu +cargo gpu build ``` This plain invocation will compile the crate in the current directory and place the compiled shaders in the current directory. -Use `cargo gpu --help` to see other options :) +Use `cargo gpu help` to see other options :) ### Next Steps From 1398e304b6725188d9a2eeca79e74606dd8728d0 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 09:16:59 +1300 Subject: [PATCH 021/162] spirv version rename --- crates/cargo-gpu/src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 91c84bb2e7..f3a2995aca 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -65,20 +65,20 @@ const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; -/// Location of `cargo-gpu` source, which contains `crates/spirv-builder-cli`. +/// Cargo dependency for `spirv-builder` and the rust toolchain channel. #[derive(Debug, Clone)] -struct SpirvCli { +struct Spirv { dep: String, channel: String, } -impl core::fmt::Display for SpirvCli { +impl core::fmt::Display for Spirv { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { format!("{}+{}", self.dep, self.channel).fmt(f) } } -impl SpirvCli { +impl Spirv { /// Returns a string suitable to use as a directory. /// /// Created from the spirv-builder source dep and the rustc channel. @@ -133,8 +133,8 @@ struct Install { } impl Install { - fn spirv_cli(&self) -> SpirvCli { - SpirvCli { + fn spirv_cli(&self) -> Spirv { + Spirv { dep: self.spirv_builder.clone(), channel: self.rust_toolchain.clone(), } From 42171f1481070dd7912bf87de46569f156793185 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 09:38:37 +1300 Subject: [PATCH 022/162] Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 67124010b3..5c8e3e9bc0 100644 --- a/README.md +++ b/README.md @@ -23,4 +23,12 @@ Use `cargo gpu help` to see other options :) ### Next Steps -TODO(schell) - finish up the cargo-generate template repo and explain it here. +You can try this out using the example repo at . +Keep in mind is _not_ yet a cargo generate template, +it's just a normal repo. + +``` +git clone https://github.com/rust-GPU/shader-crate-template +cd shader-crate-template +cargo gpu build +``` From 181d1c81b7bd7a5b4bf3a55ced923552493e7ea9 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 11 Nov 2024 10:50:07 +1300 Subject: [PATCH 023/162] remove unused deps --- Cargo.lock | 167 ------------------------------------ Cargo.toml | 2 - crates/cargo-gpu/Cargo.toml | 6 -- 3 files changed, 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 33f4c7b72e..94e828ebd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,13 +72,10 @@ version = "0.1.0" dependencies = [ "clap", "directories", - "env_home", "env_logger", "log", "serde", "serde_json", - "tempdir", - "toml", ] [[package]] @@ -154,12 +151,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "env_logger" version = "0.10.2" @@ -173,18 +164,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "getrandom" version = "0.2.15" @@ -196,12 +175,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - [[package]] name = "heck" version = "0.5.0" @@ -220,16 +193,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "indexmap" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "is-terminal" version = "0.4.13" @@ -305,43 +268,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_users" version = "0.4.6" @@ -382,15 +308,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "ryu" version = "1.0.18" @@ -429,15 +346,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "strsim" version = "0.11.1" @@ -455,16 +363,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand", - "remove_dir_all", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -494,40 +392,6 @@ dependencies = [ "syn", ] -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - [[package]] name = "unicode-ident" version = "1.0.13" @@ -546,22 +410,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -571,12 +419,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.48.0" @@ -724,12 +566,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] diff --git a/Cargo.toml b/Cargo.toml index 2a8dd9981a..cfba204901 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,5 +17,3 @@ env_logger = "0.10" log = "0.4" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" -toml = "0.8.19" - diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index cce8fdd914..ffab9b1882 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -10,10 +10,6 @@ readme = "../../README.md" [lib] name = "cargo_gpu" -[build-dependencies] -env_home.workspace = true -toml.workspace = true - [dependencies] clap.workspace = true directories.workspace = true @@ -21,8 +17,6 @@ env_logger.workspace = true log.workspace = true serde.workspace = true serde_json.workspace = true -tempdir = "0.3.7" -toml.workspace = true # Enable incremental by default in release mode. [profile.release] From 1c14e24b287d72a08a333ce85a49f06ea88924b7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 12 Nov 2024 11:46:55 +1300 Subject: [PATCH 024/162] feat: use rustup to install toolchain and components --- crates/cargo-gpu/src/main.rs | 75 ++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index f3a2995aca..ad31a84c65 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -110,6 +110,80 @@ impl Spirv { } } } + + /// Use `rustup` to install the toolchain and components, if not already installed. + /// + /// Pretty much runs: + /// + /// * rustup toolchain add nightly-2024-04-24 + /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools + fn ensure_toolchain_and_components_exist(&self) { + // Check for the required toolchain + let output = std::process::Command::new("rustup") + .args(["toolchain", "list"]) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not list installed toolchains" + ); + let stdout = String::from_utf8_lossy(&output.stdout); + if stdout + .split_whitespace() + .any(|toolchain| toolchain.starts_with(&self.channel)) + { + log::debug!("toolchain {} is already installed", self.channel); + } else { + let output = std::process::Command::new("rustup") + .args(["toolchain", "add"]) + .arg(&self.channel) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not install required toolchain" + ); + } + + // Check for the required components + let output = std::process::Command::new("rustup") + .args(["component", "list", "--toolchain"]) + .arg(&self.channel) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not list installed components" + ); + let stdout = String::from_utf8_lossy(&output.stdout); + let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; + let installed_components = stdout.lines().collect::>(); + let all_components_installed = required_components.iter().all(|component| { + installed_components.iter().any(|installed_component| { + let is_component = installed_component.starts_with(component); + let is_installed = installed_component.ends_with("(installed)"); + is_component && is_installed + }) + }); + if all_components_installed { + log::debug!("all required components are installed"); + } else { + let output = std::process::Command::new("rustup") + .args(["component", "add", "--toolchain"]) + .arg(&self.channel) + .args(["rust-src", "rustc-dev", "llvm-tools"]) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not install required components" + ); + } + } } #[derive(Parser)] @@ -169,6 +243,7 @@ impl Install { let spirv_version = self.spirv_cli(); spirv_version.ensure_version_channel_compatibility(); + spirv_version.ensure_toolchain_and_components_exist(); let checkout = spirv_version.cached_checkout_path(); let release = checkout.join("target").join("release"); From 525e2e3608471064999c58f76ecb9bb5bd707765 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 13 Nov 2024 16:32:23 +1300 Subject: [PATCH 025/162] fix: provide spirv-builder with a path to a specific target-spec file, fixes #10 --- crates/cargo-gpu/src/lib.rs | 3 + crates/cargo-gpu/src/main.rs | 79 +++++++++++++++++++ .../target-specs/spirv-unknown-opengl4.0.json | 26 ++++++ .../target-specs/spirv-unknown-opengl4.1.json | 26 ++++++ .../target-specs/spirv-unknown-opengl4.2.json | 26 ++++++ .../target-specs/spirv-unknown-opengl4.3.json | 26 ++++++ .../target-specs/spirv-unknown-opengl4.5.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.0.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.1.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.2.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.3.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.4.json | 26 ++++++ .../target-specs/spirv-unknown-spv1.5.json | 26 ++++++ .../target-specs/spirv-unknown-vulkan1.0.json | 26 ++++++ .../target-specs/spirv-unknown-vulkan1.1.json | 26 ++++++ .../spirv-unknown-vulkan1.1spv1.4.json | 26 ++++++ .../target-specs/spirv-unknown-vulkan1.2.json | 26 ++++++ crates/spirv-builder-cli/src/main.rs | 2 + 18 files changed, 474 insertions(+) create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json create mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 15facc35f0..5311651809 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -43,6 +43,9 @@ pub mod spirv_builder_cli { /// Shader target. pub shader_target: String, + /// Path to target spec file. + pub path_to_target_spec: std::path::PathBuf, + /// Set cargo default-features. pub no_default_features: bool, diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index ad31a84c65..2637730869 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -65,6 +65,69 @@ const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; +const TARGET_SPECS: &[(&str, &str)] = &[ + ( + "spirv-unknown-opengl4.0.json", + include_str!("../target-specs/spirv-unknown-opengl4.0.json"), + ), + ( + "spirv-unknown-opengl4.1.json", + include_str!("../target-specs/spirv-unknown-opengl4.1.json"), + ), + ( + "spirv-unknown-opengl4.2.json", + include_str!("../target-specs/spirv-unknown-opengl4.2.json"), + ), + ( + "spirv-unknown-opengl4.3.json", + include_str!("../target-specs/spirv-unknown-opengl4.3.json"), + ), + ( + "spirv-unknown-opengl4.5.json", + include_str!("../target-specs/spirv-unknown-opengl4.5.json"), + ), + ( + "spirv-unknown-spv1.0.json", + include_str!("../target-specs/spirv-unknown-spv1.0.json"), + ), + ( + "spirv-unknown-spv1.1.json", + include_str!("../target-specs/spirv-unknown-spv1.1.json"), + ), + ( + "spirv-unknown-spv1.2.json", + include_str!("../target-specs/spirv-unknown-spv1.2.json"), + ), + ( + "spirv-unknown-spv1.3.json", + include_str!("../target-specs/spirv-unknown-spv1.3.json"), + ), + ( + "spirv-unknown-spv1.4.json", + include_str!("../target-specs/spirv-unknown-spv1.4.json"), + ), + ( + "spirv-unknown-spv1.5.json", + include_str!("../target-specs/spirv-unknown-spv1.5.json"), + ), + ( + "spirv-unknown-vulkan1.0.json", + include_str!("../target-specs/spirv-unknown-vulkan1.0.json"), + ), + ( + "spirv-unknown-vulkan1.1.json", + include_str!("../target-specs/spirv-unknown-vulkan1.1.json"), + ), + ( + "spirv-unknown-vulkan1.1spv1.4.json", + include_str!("../target-specs/spirv-unknown-vulkan1.1spv1.4.json"), + ), + ( + "spirv-unknown-vulkan1.2.json", + include_str!("../target-specs/spirv-unknown-vulkan1.2.json"), + ), +]; + /// Cargo dependency for `spirv-builder` and the rust toolchain channel. #[derive(Debug, Clone)] struct Spirv { @@ -229,6 +292,16 @@ impl Install { } } + fn write_target_spec_files(&self) { + let cli = self.spirv_cli(); + let checkout = cli.cached_checkout_path(); + for (filename, contents) in TARGET_SPECS.iter() { + let path = checkout.join(filename); + let mut file = std::fs::File::create(&path).unwrap(); + file.write_all(contents.as_bytes()).unwrap(); + } + } + // Install the binary pair and return the paths, (dylib, cli). fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { // Ensure the cache dir exists @@ -271,6 +344,7 @@ impl Install { checkout.display() ); self.write_source_files(); + self.write_target_spec_files(); log::debug!("building artifacts"); let output = std::process::Command::new("cargo") @@ -357,6 +431,11 @@ impl Build { dylib_path, shader_crate: self.shader_crate.clone(), shader_target: self.shader_target.clone(), + path_to_target_spec: self + .install + .spirv_cli() + .cached_checkout_path() + .join(format!("{}.json", self.shader_target)), no_default_features: self.no_default_features, features: self.features.clone(), output_dir: self.output_dir.clone(), diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json new file mode 100644 index 0000000000..9fa58d8558 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "opengl4.0", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-opengl4.0", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json new file mode 100644 index 0000000000..13d687233c --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "opengl4.1", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-opengl4.1", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json new file mode 100644 index 0000000000..d1312620a2 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "opengl4.2", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-opengl4.2", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json new file mode 100644 index 0000000000..7a52159432 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "opengl4.3", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-opengl4.3", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json new file mode 100644 index 0000000000..ba509ed6dd --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "opengl4.5", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-opengl4.5", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json new file mode 100644 index 0000000000..d9e2166f5c --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.0", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.0", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json new file mode 100644 index 0000000000..8fc1bcaf38 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.1", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.1", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json new file mode 100644 index 0000000000..0037561bee --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.2", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.2", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json new file mode 100644 index 0000000000..645848caf5 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.3", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.3", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json new file mode 100644 index 0000000000..43ab248a65 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.4", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.4", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json new file mode 100644 index 0000000000..e339e11535 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "spv1.5", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-spv1.5", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json new file mode 100644 index 0000000000..a15b45b6c6 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "vulkan1.0", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-vulkan1.0", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json new file mode 100644 index 0000000000..b71dd7b2fd --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "vulkan1.1", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-vulkan1.1", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json new file mode 100644 index 0000000000..82634e6b85 --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "vulkan1.1spv1.4", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-vulkan1.1spv1.4", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json new file mode 100644 index 0000000000..7952baed9d --- /dev/null +++ b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json @@ -0,0 +1,26 @@ +{ + "allows-weak-linkage": false, + "arch": "spirv", + "crt-objects-fallback": "false", + "crt-static-allows-dylibs": true, + "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", + "dll-prefix": "", + "dll-suffix": ".spv.json", + "dynamic-linking": true, + "emit-debug-gdb-scripts": false, + "env": "vulkan1.2", + "linker-flavor": "unix", + "linker-is-gnu": false, + "llvm-target": "spirv-unknown-vulkan1.2", + "main-needs-argc-argv": false, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "os": "unknown", + "panic-strategy": "abort", + "simd-types-indirect": false, + "target-pointer-width": "32" +} diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 9a03173e7b..d99800aa1f 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -24,6 +24,7 @@ fn main() { dylib_path, shader_crate, shader_target, + path_to_target_spec, no_default_features, features, output_dir, @@ -36,6 +37,7 @@ fn main() { } = { let mut builder = SpirvBuilder::new(shader_crate, &shader_target) .rustc_codegen_spirv_location(dylib_path) + .target_spec(path_to_target_spec) .print_metadata(MetadataPrintout::None) .multimodule(true); From 87bc94912961cbda4f50438bbeefee1fe2ae10f7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 13 Nov 2024 16:47:59 +1300 Subject: [PATCH 026/162] write target spec files into top-level of cache dir --- crates/cargo-gpu/src/main.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 2637730869..422403b76c 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -249,6 +249,12 @@ impl Spirv { } } +fn target_spec_dir() -> std::path::PathBuf { + let dir = cache_dir().join("target-specs"); + std::fs::create_dir_all(&dir).unwrap(); + dir +} + #[derive(Parser)] struct Install { /// spirv-builder dependency, written just like in a Cargo.toml file. @@ -293,12 +299,12 @@ impl Install { } fn write_target_spec_files(&self) { - let cli = self.spirv_cli(); - let checkout = cli.cached_checkout_path(); for (filename, contents) in TARGET_SPECS.iter() { - let path = checkout.join(filename); - let mut file = std::fs::File::create(&path).unwrap(); - file.write_all(contents.as_bytes()).unwrap(); + let path = target_spec_dir().join(filename); + if !path.is_file() || self.force_spirv_cli_rebuild { + let mut file = std::fs::File::create(&path).unwrap(); + file.write_all(contents.as_bytes()).unwrap(); + } } } @@ -431,11 +437,7 @@ impl Build { dylib_path, shader_crate: self.shader_crate.clone(), shader_target: self.shader_target.clone(), - path_to_target_spec: self - .install - .spirv_cli() - .cached_checkout_path() - .join(format!("{}.json", self.shader_target)), + path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)), no_default_features: self.no_default_features, features: self.features.clone(), output_dir: self.output_dir.clone(), From ea632e9f41708488e3300f498f31ae5cead9f6e8 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 14 Nov 2024 20:33:25 +1300 Subject: [PATCH 027/162] feat: use cargo.toml metadata table for build paramaters --- Cargo.lock | 75 ++++++++++++++++++++++++++ Cargo.toml | 1 + crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/main.rs | 101 +++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 94e828ebd8..36976374bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,6 +76,7 @@ dependencies = [ "log", "serde", "serde_json", + "toml", ] [[package]] @@ -164,6 +165,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "getrandom" version = "0.2.15" @@ -175,6 +182,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.5.0" @@ -193,6 +206,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "is-terminal" version = "0.4.13" @@ -346,6 +369,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + [[package]] name = "strsim" version = "0.11.1" @@ -392,6 +424,40 @@ dependencies = [ "syn", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.13" @@ -566,3 +632,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index cfba204901..e82ea78177 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ env_logger = "0.10" log = "0.4" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" +toml = "0.8.19" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index ffab9b1882..594babbe41 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -17,6 +17,7 @@ env_logger.workspace = true log.workspace = true serde.workspace = true serde_json.workspace = true +toml.workspace = true # Enable incremental by default in release mode. [profile.release] diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 422403b76c..25ab4f8725 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -515,6 +515,102 @@ impl Build { } } +#[derive(Parser)] +struct Toml { + /// Path to the toml file. + /// + /// Must include a [package.metadata.rust-gpu.build] section where + /// arguments to `cargo gpu build` are listed. + #[clap(default_value = "./Cargo.toml")] + path: std::path::PathBuf, +} + +impl Toml { + fn run(&self) { + // Find the path to the toml file to use + let path = if self.path.is_file() && self.path.ends_with(".toml") { + self.path.clone() + } else { + let path = self.path.join("Cargo.toml"); + if path.is_file() { + path + } else { + log::error!("toml file '{}' is not a file", self.path.display()); + panic!("toml file '{}' is not a file", self.path.display()); + } + }; + + log::info!("using toml file '{}'", path.display()); + + // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml + let contents = std::fs::read_to_string(&path).unwrap(); + let toml: toml::Table = toml::from_str(&contents).unwrap(); + + fn get_metadata_rustgpu_table<'a>( + toml: &'a toml::Table, + toml_type: &'static str, + ) -> Option<&'a toml::Table> { + let workspace = toml.get(toml_type)?.as_table()?; + let metadata = workspace.get("metadata")?.as_table()?; + metadata.get("rust-gpu")?.as_table() + } + + let (toml_type, table) = if toml.contains_key("workspace") { + let table = get_metadata_rustgpu_table(&toml, "workspace") + .unwrap_or_else(|| { + panic!( + "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", + path.display() + ); + }) + .clone(); + ("workspace", table) + } else if toml.contains_key("package") { + let mut table = get_metadata_rustgpu_table(&toml, "package") + .unwrap_or_else(|| { + panic!( + "toml file '{}' is missing a [package.metadata.rust-gpu] table", + path.display() + ); + }) + .clone(); + // Ensure the package name is included as the shader-crate parameter + if !table.contains_key("shader-crate") { + table.insert( + "shader-crate".to_string(), + format!("{}", path.parent().unwrap().display()).into(), + ); + } + ("package", table) + } else { + panic!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); + }; + log::info!( + "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", + path.display() + ); + + let parameters = table + .get("build") + .unwrap_or_else(|| panic!("toml is missing the 'build' table")) + .as_table() + .unwrap_or_else(|| { + panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") + }) + .into_iter() + .map(|(k, v)| { + let mut value = String::new(); + let ser = toml::ser::ValueSerializer::new(&mut value); + serde::Serialize::serialize(v, ser).unwrap(); + format!("--{k}={value}") + }) + .collect::>(); + log::debug!("build parameters: {parameters:#?}"); + let build = Build::parse_from(parameters); + build.run(); + } +} + #[derive(Subcommand)] enum Command { /// Install rust-gpu compiler artifacts. @@ -522,6 +618,10 @@ enum Command { /// Compile a shader crate to SPIR-V. Build(Build), + + /// Compile a shader crate according to the `cargo gpu build` parameters + /// found in the given toml file. + Toml(Toml), } #[derive(Parser)] @@ -556,5 +656,6 @@ fn main() { let _ = install.run(); } Command::Build(build) => build.run(), + Command::Toml(toml) => toml.run(), } } From 6d3a5f6d1ce9b8edb449cc5a473ab95af77f9ea1 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 15 Nov 2024 07:41:20 +1300 Subject: [PATCH 028/162] fix: toml subcommand issues cargo commands relative to provided Cargo.toml, cli help --- crates/cargo-gpu/src/main.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 25ab4f8725..0d3e9fba97 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -517,11 +517,30 @@ impl Build { #[derive(Parser)] struct Toml { - /// Path to the toml file. + /// Path to a workspace or package Cargo.toml file. /// - /// Must include a [package.metadata.rust-gpu.build] section where + /// Must include a [[workspace | package].metadata.rust-gpu.build] section where /// arguments to `cargo gpu build` are listed. - #[clap(default_value = "./Cargo.toml")] + /// + /// Path arguments like `output-dir` and `shader-manifest` must be relative to + /// the location of the Cargo.toml file. + /// + /// Example: + /// + /// ```toml + /// [package.metadata.rust-gpu.build.spirv-builder] + /// git = "https://github.com/Rust-GPU/rust-gpu.git" + /// rev = "0da80f8" + /// + /// [package.metadata.rust-gpu.build] + /// output-dir = "shaders" + /// shader-manifest = "shaders/manifest.json" + /// ``` + /// + /// Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that + /// contains the example above would compile the crate and place the compiled + /// `.spv` files and manifest in a directory "shaders". + #[clap(default_value = "./Cargo.toml", verbatim_doc_comment)] path: std::path::PathBuf, } @@ -605,6 +624,14 @@ impl Toml { format!("--{k}={value}") }) .collect::>(); + + let working_directory = path.parent().unwrap(); + log::info!( + "Issuing cargo commands from the working directory '{}'", + working_directory.display() + ); + std::env::set_current_dir(working_directory).unwrap(); + log::debug!("build parameters: {parameters:#?}"); let build = Build::parse_from(parameters); build.run(); From 12010db3a8bce73e6f62457708b2b5f32adda0c5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 16 Nov 2024 08:21:14 +1300 Subject: [PATCH 029/162] fix: properly use toml file table as build parameters --- crates/cargo-gpu/src/main.rs | 134 ++++++++++++++++++--------- crates/spirv-builder-cli/src/main.rs | 8 +- 2 files changed, 96 insertions(+), 46 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 0d3e9fba97..ac9a3fc13d 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -255,7 +255,7 @@ fn target_spec_dir() -> std::path::PathBuf { dir } -#[derive(Parser)] +#[derive(Parser, Debug)] struct Install { /// spirv-builder dependency, written just like in a Cargo.toml file. #[clap( @@ -384,7 +384,7 @@ impl Install { } } -#[derive(Parser)] +#[derive(Parser, Debug)] struct Build { #[clap(flatten)] install: Install, @@ -397,11 +397,6 @@ struct Build { #[clap(long, default_value = "spirv-unknown-vulkan1.2")] shader_target: String, - /// Path to the output JSON manifest file where the paths to .spv files - /// and the names of their entry points will be saved. - #[clap(long)] - shader_manifest: Option, - /// Set cargo default-features. #[clap(long)] no_default_features: bool, @@ -420,12 +415,16 @@ struct Build { } impl Build { - fn run(&self) { + fn run(&mut self) { let (dylib_path, spirv_builder_cli_path) = self.install.run(); // Ensure the shader output dir exists + log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); std::fs::create_dir_all(&self.output_dir).unwrap(); + self.output_dir = self.output_dir.canonicalize().unwrap(); + // Ensure the shader crate exists + self.shader_crate = self.shader_crate.canonicalize().unwrap(); assert!( self.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", @@ -449,7 +448,7 @@ impl Build { log::info!("using spirv-builder-cli arg: {arg}"); // Call spirv-builder-cli to compile the shaders. - let output = std::process::Command::new(&spirv_builder_cli_path) + let output = std::process::Command::new(spirv_builder_cli_path) .arg(arg) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) @@ -489,28 +488,27 @@ impl Build { // Write the shader manifest json file if !self.dry_run { - if let Some(manifest_path) = &self.shader_manifest { - // Sort the contents so the output is deterministic - linkage.sort(); - // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(manifest_path).unwrap_or_else(|e| { - log::error!( - "could not create shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { - log::error!( - "could not write shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); + let manifest_path = self.output_dir.join("manifest.json"); + // Sort the contents so the output is deterministic + linkage.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&linkage).unwrap(); + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); - log::info!("wrote manifest to '{}'", manifest_path.display()); - } + log::info!("wrote manifest to '{}'", manifest_path.display()); } } } @@ -608,8 +606,9 @@ impl Toml { "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", path.display() ); + log::debug!("table: {table:#?}"); - let parameters = table + let mut parameters = table .get("build") .unwrap_or_else(|| panic!("toml is missing the 'build' table")) .as_table() @@ -617,24 +616,37 @@ impl Toml { panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") }) .into_iter() - .map(|(k, v)| { - let mut value = String::new(); - let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(v, ser).unwrap(); - format!("--{k}={value}") + .flat_map(|(k, v)| match v { + toml::Value::String(s) => [format!("--{k}"), s.clone()], + _ => { + let mut value = String::new(); + let ser = toml::ser::ValueSerializer::new(&mut value); + serde::Serialize::serialize(v, ser).unwrap(); + [format!("--{k}"), value] + } }) .collect::>(); + parameters.insert(0, "cargo-gpu".to_string()); + parameters.insert(1, "build".to_string()); let working_directory = path.parent().unwrap(); log::info!( - "Issuing cargo commands from the working directory '{}'", + "issuing cargo commands from the working directory '{}'", working_directory.display() ); std::env::set_current_dir(working_directory).unwrap(); log::debug!("build parameters: {parameters:#?}"); - let build = Build::parse_from(parameters); - build.run(); + if let Cli { + command: Command::Build(mut build), + } = Cli::parse_from(parameters) + { + log::debug!("build: {build:?}"); + build.run(); + } else { + log::error!("parameters found in [{toml_type}.metadata.rust-gpu.build] were not parameters to `cargo gpu build`"); + panic!("could not determin build command"); + } } } @@ -672,17 +684,49 @@ fn cache_dir() -> std::path::PathBuf { fn main() { env_logger::builder().init(); - let cli = Cli::parse_from(std::env::args().filter(|p| { - // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" - // as the first parameter, which we want to ignore. - p != "gpu" - })); + let args = std::env::args() + .filter(|p| { + // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" + // as the first parameter, which we want to ignore. + p != "gpu" + }) + .collect::>(); + log::trace!("args: {args:?}"); + let cli = Cli::parse_from(args); match cli.command { Command::Install(install) => { let _ = install.run(); } - Command::Build(build) => build.run(), + Command::Build(mut build) => build.run(), Command::Toml(toml) => toml.run(), } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn builder_from_params() { + let shader_crate = std::path::PathBuf::from("../shader-crate-template"); + let output_dir = std::path::PathBuf::from("../shader-crate-template/shaders"); + let args = [ + "target/debug/cargo-gpu", + "build", + "--shader-crate", + &format!("{}", shader_crate.display()), + "--output-dir", + &format!("{}", output_dir.display()), + ]; + if let Cli { + command: Command::Build(build), + } = Cli::parse_from(args) + { + assert_eq!(shader_crate, build.shader_crate); + assert_eq!(output_dir, build.output_dir); + } else { + panic!("was not a build command"); + } + } +} diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index d99800aa1f..16a6d5d657 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -20,6 +20,12 @@ fn main() { set_rustup_toolchain(); let args = std::env::args().collect::>(); + log::debug!( + "running spirv-builder-cli from '{}'", + std::env::current_dir().unwrap().display() + ); + let args = serde_json::from_str(&args[1]).unwrap(); + log::debug!("compiling with args: {args:#?}"); let Args { dylib_path, shader_crate, @@ -29,7 +35,7 @@ fn main() { features, output_dir, dry_run: _, - } = serde_json::from_str(&args[1]).unwrap(); + } = args; let CompileResult { entry_points, From 4ec33b1101acc163d9b619ae4c33848398d2095f Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 16 Nov 2024 08:38:08 +1300 Subject: [PATCH 030/162] remove unused dry-run arg --- crates/cargo-gpu/src/lib.rs | 3 -- crates/cargo-gpu/src/main.rs | 57 ++++++++++++++-------------- crates/spirv-builder-cli/src/main.rs | 1 - 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 5311651809..68ede7a34a 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -54,9 +54,6 @@ pub mod spirv_builder_cli { /// Path to the output directory for the compiled shaders. pub output_dir: std::path::PathBuf, - - /// Dry run or not - pub dry_run: bool, } /// A built shader entry-point, used in `spirv-builder-cli` to generate diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index ac9a3fc13d..6a5b9b92c6 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -408,10 +408,6 @@ struct Build { /// Path to the output directory for the compiled shaders. #[clap(long, short, default_value = "./")] output_dir: std::path::PathBuf, - - /// If set the shaders will be compiled but not put into place. - #[clap(long, short)] - dry_run: bool, } impl Build { @@ -440,7 +436,6 @@ impl Build { no_default_features: self.no_default_features, features: self.features.clone(), output_dir: self.output_dir.clone(), - dry_run: self.dry_run, }; // UNWRAP: safe because we know this always serializes @@ -478,37 +473,41 @@ impl Build { path: filepath, }| { let path = self.output_dir.join(filepath.file_name().unwrap()); - if !self.dry_run { - std::fs::copy(filepath, &path).unwrap(); - } + std::fs::copy(filepath, &path).unwrap(); Linkage::new(entry, path) }, ) .collect(); // Write the shader manifest json file - if !self.dry_run { - let manifest_path = self.output_dir.join("manifest.json"); - // Sort the contents so the output is deterministic - linkage.sort(); - // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { - log::error!( - "could not create shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { - log::error!( - "could not write shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); + let manifest_path = self.output_dir.join("manifest.json"); + // Sort the contents so the output is deterministic + linkage.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&linkage).unwrap(); + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); - log::info!("wrote manifest to '{}'", manifest_path.display()); + log::info!("wrote manifest to '{}'", manifest_path.display()); + + if spirv_manifest.is_file() { + log::debug!( + "removing spirv-manifest.json file '{}'", + spirv_manifest.display() + ); + std::fs::remove_file(spirv_manifest).unwrap(); } } } diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 16a6d5d657..ab66d1ace0 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -34,7 +34,6 @@ fn main() { no_default_features, features, output_dir, - dry_run: _, } = args; let CompileResult { From 4623ccb10e90d77f54cb87c6eebebcd96eb6a1f4 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 16 Nov 2024 11:43:09 +1300 Subject: [PATCH 031/162] shader paths in generated manifest.json are relative to the shader crate --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/main.rs | 7 +++++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36976374bf..7318e041ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,6 +74,7 @@ dependencies = [ "directories", "env_logger", "log", + "relative-path", "serde", "serde_json", "toml", @@ -331,6 +332,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "ryu" version = "1.0.18" diff --git a/Cargo.toml b/Cargo.toml index e82ea78177..04249efaaa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ directories = "5.0.1" env_home = "0.1.0" env_logger = "0.10" log = "0.4" +relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" toml = "0.8.19" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 594babbe41..1de55cae87 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -15,6 +15,7 @@ clap.workspace = true directories.workspace = true env_logger.workspace = true log.workspace = true +relative-path.workspace = true serde.workspace = true serde_json.workspace = true toml.workspace = true diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 6a5b9b92c6..419b7d4b7e 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -472,9 +472,12 @@ impl Build { entry, path: filepath, }| { + use relative_path::PathExt; let path = self.output_dir.join(filepath.file_name().unwrap()); - std::fs::copy(filepath, &path).unwrap(); - Linkage::new(entry, path) + std::fs::copy(&filepath, &path).unwrap(); + let path_relative_to_shader_crate = + path.relative_to(&self.shader_crate).unwrap().to_path(""); + Linkage::new(entry, path_relative_to_shader_crate) }, ) .collect(); From f0b0da756c80cd6d8a2058c3683e8a636dc2dadf Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Fri, 29 Nov 2024 16:21:25 +0100 Subject: [PATCH 032/162] Features to allow `spirv-builder` backwards compat Fixes #19 Previously we couldn't compile shaders dependent on pre-`cargo-gpu` versions of `spirv-builder`, because of incompatible `SpirvBuilder` interfaces. Here we introduce some Cargo features on the `spirv-builder-cli` crate that gate calls to `SpirvBuilder` depending on the required version of `spirv-builder`. Notable changes: * `spirv-builder-cli` should be buildable on its own now. This is mainly for development, as it should help with getting better in-editor feedback from LSP etc. But it also made it possible to move `cargo-gpu`'s `lib.rs` to `spirv-builder` because `spirv-builder` is now a "real" crate that can be compiled to a library. * Related to the previous point, a `rust-toolchain.toml` has been added to the root of `spirv-builder-cli`, again this is purely for development. Because of the new feature gates its not even needed to compile it to a library. Its merely a convenience to get a working crate that lends itself to direct development rather than always watching for log output in `cargo gpu` runs. TODO: - [ ] Download the actual `rust-gpu` repo as pinned in the shader's `Cargo.lock` and get the `spirv-builder` version from there. - [ ] Warn the user that certain `cargo-gpu` features aren't available when building with older versions of `spirv-builder`, eg setting the target spec. - [ ] An integration test. --- Cargo.lock | 44 ++++++ Cargo.toml | 1 + crates/cargo-gpu/Cargo.toml | 5 +- crates/cargo-gpu/src/lib.rs | 75 ---------- crates/cargo-gpu/src/main.rs | 42 +++++- crates/spirv-builder-cli/Cargo.lock | 143 ++++++++++++++++--- crates/spirv-builder-cli/Cargo.toml | 22 ++- crates/spirv-builder-cli/README.md | 7 + crates/spirv-builder-cli/rust-toolchain.toml | 5 + crates/spirv-builder-cli/src/lib.rs | 65 +++++++++ crates/spirv-builder-cli/src/main.rs | 53 +++++-- 11 files changed, 349 insertions(+), 113 deletions(-) delete mode 100644 crates/cargo-gpu/src/lib.rs create mode 100644 crates/spirv-builder-cli/README.md create mode 100644 crates/spirv-builder-cli/rust-toolchain.toml create mode 100644 crates/spirv-builder-cli/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 7318e041ba..501e23e429 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bitflags" version = "2.6.0" @@ -70,6 +76,7 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" name = "cargo-gpu" version = "0.1.0" dependencies = [ + "chrono", "clap", "directories", "env_logger", @@ -77,6 +84,7 @@ dependencies = [ "relative-path", "serde", "serde_json", + "spirv-builder-cli", "toml", ] @@ -86,6 +94,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", +] + [[package]] name = "clap" version = "4.5.20" @@ -153,6 +170,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "env_logger" version = "0.10.2" @@ -268,6 +291,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -385,6 +417,18 @@ dependencies = [ "serde", ] +[[package]] +name = "spirv-builder-cli" +version = "0.1.0" +dependencies = [ + "env_home", + "env_logger", + "log", + "serde", + "serde_json", + "toml", +] + [[package]] name = "strsim" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 04249efaaa..2c5db4bade 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ resolver = "2" [workspace.dependencies] clap = { version = "4.4.8", features = ["derive"] } +chrono = { version = "0.4.38", default-features = false } directories = "5.0.1" env_home = "0.1.0" env_logger = "0.10" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 1de55cae87..0bdd10f174 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -6,11 +6,9 @@ description = "Generates shader .spv files from rust-gpu shader crates" readme = "../../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -name = "cargo_gpu" [dependencies] +spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false } clap.workspace = true directories.workspace = true env_logger.workspace = true @@ -19,6 +17,7 @@ relative-path.workspace = true serde.workspace = true serde_json.workspace = true toml.workspace = true +chrono.workspace = true # Enable incremental by default in release mode. [profile.release] diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs deleted file mode 100644 index 68ede7a34a..0000000000 --- a/crates/cargo-gpu/src/lib.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Wire types for `cargo-gpu` and `spirv-builder-cli`. -//! -//! This file is copied by `cargo-gpu` into the build tree of `spirv-builder-cli`. - -/// Shader source and entry point that can be used to create shader linkage. -#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Linkage { - pub source_path: std::path::PathBuf, - pub entry_point: String, - pub wgsl_entry_point: String, -} - -impl Linkage { - pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { - Self { - source_path: source_path.as_ref().to_path_buf(), - wgsl_entry_point: entry_point.as_ref().replace("::", ""), - entry_point: entry_point.as_ref().to_string(), - } - } - - pub fn fn_name(&self) -> &str { - self.entry_point.split("::").last().unwrap() - } -} - -pub mod spirv_builder_cli { - //! `spirv-builder-cli` interface types. - //! - //! This module is exposed here to keep `spirv-build-cli`'s source - //! as small as possible. It is not expected to be used by any - //! user-facing code. - - /// `spirv-builder-cli` command line interface. - #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] - pub struct Args { - /// Path to rustc_codegen_spirv dylib. - pub dylib_path: std::path::PathBuf, - - /// Directory containing the shader crate to compile. - pub shader_crate: std::path::PathBuf, - - /// Shader target. - pub shader_target: String, - - /// Path to target spec file. - pub path_to_target_spec: std::path::PathBuf, - - /// Set cargo default-features. - pub no_default_features: bool, - - /// Set cargo features. - pub features: Vec, - - /// Path to the output directory for the compiled shaders. - pub output_dir: std::path::PathBuf, - } - - /// A built shader entry-point, used in `spirv-builder-cli` to generate - /// a `build-manifest.json` used by `cargo-gpu`. - #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] - pub struct ShaderModule { - pub entry: String, - pub path: std::path::PathBuf, - } - - impl ShaderModule { - pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { - Self { - entry: entry.as_ref().into(), - path: path.as_ref().into(), - } - } - } -} diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 419b7d4b7e..3b152be689 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -51,12 +51,12 @@ //! for example. use std::io::Write; -use cargo_gpu::{spirv_builder_cli::ShaderModule, Linkage}; use clap::{Parser, Subcommand}; +use spirv_builder_cli::{Linkage, ShaderModule}; const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); -const SPIRV_BUILDER_CLI_LIB: &str = include_str!("lib.rs"); +const SPIRV_BUILDER_CLI_LIB: &str = include_str!("../../spirv-builder-cli/src/lib.rs"); const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), @@ -352,11 +352,21 @@ impl Install { self.write_source_files(); self.write_target_spec_files(); - log::debug!("building artifacts"); - let output = std::process::Command::new("cargo") + let mut command = std::process::Command::new("cargo"); + command .current_dir(&checkout) .arg(format!("+{}", spirv_version.channel)) .args(["build", "--release"]) + .args(["--no-default-features"]); + + command.args([ + "--features", + &Self::get_required_spirv_builder_version(spirv_version.channel), + ]); + + log::debug!("building artifacts with `{:?}`", command); + + let output = command .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) .output() @@ -382,6 +392,28 @@ impl Install { } (dest_dylib_path, dest_cli_path) } + + /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to + /// interact with `cargo-gpu`. Older versions don't have the same `SpirvBuilder` interface. So + /// here we choose the right Cargo feature to enable/disable code in `spirv-builder-cli`. + /// + /// TODO: + /// * Download the actual `rust-gpu` repo as pinned in the shader's `Cargo.lock` and get the + /// `spirv-builder` version from there. + /// * Warn the user that certain `cargo-gpu` features aren't available when building with + /// older versions of `spirv-builder`, eg setting the target spec. + fn get_required_spirv_builder_version(toolchain_channel: String) -> String { + let parse_date = chrono::NaiveDate::parse_from_str; + let datetime = parse_date(&toolchain_channel, "nightly-%Y-%m-%d").unwrap(); + let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); + + if datetime < pre_cli_date { + "spirv-builder-pre-cli" + } else { + "spirv-builder-0_10" + } + .into() + } } #[derive(Parser, Debug)] @@ -428,7 +460,7 @@ impl Build { std::env::current_dir().unwrap().display() ); - let spirv_builder_args = cargo_gpu::spirv_builder_cli::Args { + let spirv_builder_args = spirv_builder_cli::Args { dylib_path, shader_crate: self.shader_crate.clone(), shader_target: self.shader_target.clone(), diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index 817e515b87..683b299663 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -40,6 +40,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.6.0" @@ -53,12 +59,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] -name = "cargo-gpu-wire-types" -version = "0.1.0" -dependencies = [ - "serde", - "serde_json", -] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" @@ -137,6 +141,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -340,6 +353,17 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rspirv" +version = "0.11.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba" +dependencies = [ + "fxhash", + "num-traits", + "spirv 0.2.0+1.5.4", +] + [[package]] name = "rspirv" version = "0.12.0+sdk-1.3.268.0" @@ -347,7 +371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" dependencies = [ "rustc-hash", - "spirv", + "spirv 0.3.0+sdk-1.3.268.0", ] [[package]] @@ -365,7 +389,34 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" +dependencies = [ + "ar", + "either", + "hashbrown 0.11.2", + "indexmap 1.9.3", + "itertools", + "lazy_static", + "libc", + "num-traits", + "once_cell", + "regex", + "rspirv 0.11.0+1.5.4", + "rustc-demangle", + "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", + "sanitize-filename", + "serde", + "serde_json", + "smallvec", + "spirt 0.3.0", + "spirv-tools", + "syn 1.0.109", +] + +[[package]] +name = "rustc_codegen_spirv" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" dependencies = [ "ar", "either", @@ -377,12 +428,12 @@ dependencies = [ "num-traits", "once_cell", "regex", - "rspirv", + "rspirv 0.12.0+sdk-1.3.268.0", "rustc-demangle", - "rustc_codegen_spirv-types", + "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", "sanitize-filename", "smallvec", - "spirt", + "spirt 0.4.0", "spirv-tools", "syn 1.0.109", ] @@ -390,9 +441,18 @@ dependencies = [ [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" +dependencies = [ + "rspirv 0.11.0+1.5.4", + "serde", +] + +[[package]] +name = "rustc_codegen_spirv-types" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" dependencies = [ - "rspirv", + "rspirv 0.12.0+sdk-1.3.268.0", "serde", "serde_json", ] @@ -484,6 +544,27 @@ dependencies = [ "serde", ] +[[package]] +name = "spirt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e1f7903720ff818d6da824edf2c4082c6e7a029a99317fd10c39dd7c40c7ff" +dependencies = [ + "arrayvec", + "bytemuck", + "derive_more", + "elsa", + "indexmap 1.9.3", + "internal-iterator", + "itertools", + "lazy_static", + "longest-increasing-subsequence", + "rustc-hash", + "serde", + "serde_json", + "smallvec", +] + [[package]] name = "spirt" version = "0.4.0" @@ -505,24 +586,47 @@ dependencies = [ "smallvec", ] +[[package]] +name = "spirv" +version = "0.2.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +dependencies = [ + "bitflags 1.3.2", + "num-traits", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu#ed32960e5a174a6a74171d580601a2105a8e6d32" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" dependencies = [ "memchr", "raw-string", - "rustc_codegen_spirv", - "rustc_codegen_spirv-types", + "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", + "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", + "serde", + "serde_json", +] + +[[package]] +name = "spirv-builder" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" +dependencies = [ + "memchr", + "raw-string", + "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", + "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", "serde", "serde_json", ] @@ -531,12 +635,13 @@ dependencies = [ name = "spirv-builder-cli" version = "0.1.0" dependencies = [ - "cargo-gpu-wire-types", "env_home", "env_logger", "log", + "serde", "serde_json", - "spirv-builder", + "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", + "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", "toml", ] diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index e9a6cc0aff..67f9ee82ca 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" [lib] -name = "spirv_builder_cli" [dependencies] env_home = "0.1.0" @@ -12,5 +11,24 @@ env_logger = "0.10" log = "0.4" serde = "1.0.214" serde_json = "1.0.132" -spirv-builder = ${SPIRV_BUILDER_SOURCE} toml = "0.8.19" + +[dependencies.spirv-builder-pre-cli] +package = "spirv-builder" +optional = true +git = "https://github.com/Rust-GPU/rust-gpu" +rev = "4c633aec" + +[dependencies.spirv-builder-0_10] +package = "spirv-builder" +optional = true +git = "https://github.com/Rust-GPU/rust-gpu" +rev = "60dcb82" + +[features] +default = ["spirv-builder-0_10"] +# The `spirv-builder` before `cargo gpu` existed. It has an incompatible `SpirvBuilder` interface. +spirv-builder-pre-cli = ["dep:spirv-builder-pre-cli"] +# The first version that introduced `cargo gpu`. It has some extra `.builder()` args that make +# dynamically changing build dependencies easier. +spirv-builder-0_10 = ["dep:spirv-builder-0_10"] diff --git a/crates/spirv-builder-cli/README.md b/crates/spirv-builder-cli/README.md new file mode 100644 index 0000000000..ad609e9134 --- /dev/null +++ b/crates/spirv-builder-cli/README.md @@ -0,0 +1,7 @@ +# SPIR-V Builder CLI Template + +> [!CAUTION] +> This may look like a typical crate, but it is in fact more like a crate _template_. +> It is intended to be primarily called by `cargo gpu`, which has these files embedded +> into its binary and so can copy and edit them to automatically compile end-user +> shaders. diff --git a/crates/spirv-builder-cli/rust-toolchain.toml b/crates/spirv-builder-cli/rust-toolchain.toml new file mode 100644 index 0000000000..6148ea9e63 --- /dev/null +++ b/crates/spirv-builder-cli/rust-toolchain.toml @@ -0,0 +1,5 @@ +# This is just a placeholder for development. In actual usage the toolchain +# is set dynamically. +[toolchain] +channel = "nightly-2024-04-24" +components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/crates/spirv-builder-cli/src/lib.rs b/crates/spirv-builder-cli/src/lib.rs new file mode 100644 index 0000000000..8f9aea4e21 --- /dev/null +++ b/crates/spirv-builder-cli/src/lib.rs @@ -0,0 +1,65 @@ +//! Wire types for `cargo-gpu` and `spirv-builder-cli`. + +/// Shader source and entry point that can be used to create shader linkage. +#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Linkage { + pub source_path: std::path::PathBuf, + pub entry_point: String, + pub wgsl_entry_point: String, +} + +impl Linkage { + pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { + Self { + source_path: source_path.as_ref().to_path_buf(), + wgsl_entry_point: entry_point.as_ref().replace("::", ""), + entry_point: entry_point.as_ref().to_string(), + } + } + + pub fn fn_name(&self) -> &str { + self.entry_point.split("::").last().unwrap() + } +} + +/// `spirv-builder-cli` command line interface. +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Args { + /// Path to rustc_codegen_spirv dylib. + pub dylib_path: std::path::PathBuf, + + /// Directory containing the shader crate to compile. + pub shader_crate: std::path::PathBuf, + + /// Shader target. + pub shader_target: String, + + /// Path to target spec file. + pub path_to_target_spec: std::path::PathBuf, + + /// Set cargo default-features. + pub no_default_features: bool, + + /// Set cargo features. + pub features: Vec, + + /// Path to the output directory for the compiled shaders. + pub output_dir: std::path::PathBuf, +} + +/// A built shader entry-point, used in `spirv-builder-cli` to generate +/// a `build-manifest.json` used by `cargo-gpu`. +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct ShaderModule { + pub entry: String, + pub path: std::path::PathBuf, +} + +impl ShaderModule { + pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { + Self { + entry: entry.as_ref().into(), + path: path.as_ref().into(), + } + } +} diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index ab66d1ace0..9c92b0a440 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -1,8 +1,15 @@ //! This program builds rust-gpu shader crates and writes generated spv files //! into the main source repo. + +#[cfg(feature = "spirv-builder-pre-cli")] +use spirv_builder_pre_cli as spirv_builder; + +#[cfg(feature = "spirv-builder-0_10")] +use spirv_builder_0_10 as spirv_builder; + use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; -use spirv_builder_cli::spirv_builder_cli::{Args, ShaderModule}; +use spirv_builder_cli::{Args, ShaderModule}; const RUSTC_NIGHTLY_CHANNEL: &str = "${CHANNEL}"; @@ -14,6 +21,24 @@ fn set_rustup_toolchain() { std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); } +/// Get the OS-dependent ENV variable name for the list of paths pointing to .so/.dll files +const fn dylib_path_envvar() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_FALLBACK_LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + +fn set_codegen_spirv_location(dylib_path: std::path::PathBuf) { + let env_var = dylib_path_envvar(); + let path = dylib_path.parent().unwrap().display().to_string(); + log::debug!("Setting OS-dependent DLL ENV path ({env_var}) to: {path}"); + std::env::set_var(env_var, path); +} + fn main() { env_logger::builder().init(); @@ -41,18 +66,28 @@ fn main() { module, } = { let mut builder = SpirvBuilder::new(shader_crate, &shader_target) - .rustc_codegen_spirv_location(dylib_path) - .target_spec(path_to_target_spec) .print_metadata(MetadataPrintout::None) .multimodule(true); - if no_default_features { - log::info!("setting cargo --no-default-features"); - builder = builder.shader_crate_default_features(false); + #[cfg(feature = "spirv-builder-pre-cli")] + { + set_codegen_spirv_location(dylib_path); } - if !features.is_empty() { - log::info!("setting --features {features:?}"); - builder = builder.shader_crate_features(features); + + #[cfg(feature = "spirv-builder-0_10")] + { + builder = builder + .rustc_codegen_spirv_location(dylib_path) + .target_spec(path_to_target_spec); + + if no_default_features { + log::info!("setting cargo --no-default-features"); + builder = builder.shader_crate_default_features(false); + } + if !features.is_empty() { + log::info!("setting --features {features:?}"); + builder = builder.shader_crate_features(features); + } } builder.build().unwrap() From 8dadc7e7ac70aa6c602a6040618df97a8d6c8692 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Fri, 29 Nov 2024 17:38:41 +0100 Subject: [PATCH 033/162] Hidden command to dump usage for README `cargo gpu dump-usage` I don't think we necessarily should always be copying the full usage into the README, but I think for now it's a quick and easy way to communicate the goals of this project. --- README.md | 132 ++++++++++++++++++++++++++++++++++- crates/cargo-gpu/src/main.rs | 42 +++++++++++ 2 files changed, 173 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c8e3e9bc0..382fdfdc0d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Command line tool for building Rust shaders using rust-gpu. ## Getting Started -### installation +### Installation To install the tool ensure you have `rustup`. Then run: ``` @@ -32,3 +32,133 @@ git clone https://github.com/rust-GPU/shader-crate-template cd shader-crate-template cargo gpu build ``` + +## Usage + +``` +Commands: + install Install rust-gpu compiler artifacts + build Compile a shader crate to SPIR-V + toml Compile a shader crate according to the `cargo gpu build` parameters found in the given toml file + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help + Print help + + -V, --version + Print version + + +* Install + +Install rust-gpu compiler artifacts + +Usage: cargo-gpu install [OPTIONS] + +Options: + --spirv-builder + spirv-builder dependency, written just like in a Cargo.toml file + + [default: "{ git = \"https://github.com/Rust-GPU/rust-gpu.git\" }"] + + --rust-toolchain + Rust toolchain channel to use to build `spirv-builder`. + + This must match the `spirv_builder` argument. + + [default: nightly-2024-04-24] + + --force-spirv-cli-rebuild + Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + + -h, --help + Print help (see a summary with '-h') + + +* Build + +Compile a shader crate to SPIR-V + +Usage: cargo-gpu build [OPTIONS] + +Options: + --spirv-builder + spirv-builder dependency, written just like in a Cargo.toml file + + [default: "{ git = \"https://github.com/Rust-GPU/rust-gpu.git\" }"] + + --rust-toolchain + Rust toolchain channel to use to build `spirv-builder`. + + This must match the `spirv_builder` argument. + + [default: nightly-2024-04-24] + + --force-spirv-cli-rebuild + Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + + --shader-crate + Directory containing the shader crate to compile + + [default: ./] + + --shader-target + Shader target + + [default: spirv-unknown-vulkan1.2] + + --no-default-features + Set cargo default-features + + --features + Set cargo features + + -o, --output-dir + Path to the output directory for the compiled shaders + + [default: ./] + + -h, --help + Print help (see a summary with '-h') + + +* Toml + +Compile a shader crate according to the `cargo gpu build` parameters found in the given toml file + +Usage: cargo-gpu toml [PATH] + +Arguments: + [PATH] + Path to a workspace or package Cargo.toml file. + + Must include a [[workspace | package].metadata.rust-gpu.build] section where + arguments to `cargo gpu build` are listed. + + Path arguments like `output-dir` and `shader-manifest` must be relative to + the location of the Cargo.toml file. + + Example: + + ```toml + [package.metadata.rust-gpu.build.spirv-builder] + git = "https://github.com/Rust-GPU/rust-gpu.git" + rev = "0da80f8" + + [package.metadata.rust-gpu.build] + output-dir = "shaders" + shader-manifest = "shaders/manifest.json" + ``` + + Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that + contains the example above would compile the crate and place the compiled + `.spv` files and manifest in a directory "shaders". + + [default: ./Cargo.toml] + +Options: + -h, --help + Print help (see a summary with '-h') + +``` diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 419b7d4b7e..a4dc283a00 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -641,6 +641,7 @@ impl Toml { log::debug!("build parameters: {parameters:#?}"); if let Cli { command: Command::Build(mut build), + .. } = Cli::parse_from(parameters) { log::debug!("build: {build:?}"); @@ -663,6 +664,12 @@ enum Command { /// Compile a shader crate according to the `cargo gpu build` parameters /// found in the given toml file. Toml(Toml), + + /// A hidden command that can be used to recursively print out all the subcommand help messages: + /// `cargo gpu dump-usage` + /// Useful for updating the README. + #[clap(hide(true))] + DumpUsage, } #[derive(Parser)] @@ -702,6 +709,40 @@ fn main() { } Command::Build(mut build) => build.run(), Command::Toml(toml) => toml.run(), + Command::DumpUsage => dump_full_usage_for_readme(), + } +} + +fn dump_full_usage_for_readme() { + use clap::CommandFactory; + let mut command = Cli::command(); + + let mut buffer: Vec = Default::default(); + command.build(); + + write_help(&mut buffer, &mut command, 0); + let buffer = String::from_utf8(buffer).unwrap(); + println!("{}", buffer); +} + +fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, depth: usize) { + if cmd.get_name() == "help" { + return; + } + + let mut command = cmd.get_name().to_string(); + let _ = writeln!( + buffer, + "\n* {}{}", + command.remove(0).to_uppercase(), + command + ); + let _ = writeln!(buffer); + let _ = cmd.write_long_help(buffer); + + for sub in cmd.get_subcommands_mut() { + let _ = writeln!(buffer); + write_help(buffer, sub, depth + 1); } } @@ -723,6 +764,7 @@ mod test { ]; if let Cli { command: Command::Build(build), + .. } = Cli::parse_from(args) { assert_eq!(shader_crate, build.shader_crate); From f82ac177becf85a9421fd6ad894ee8aee63f50c6 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 08:41:55 +1300 Subject: [PATCH 034/162] initial CI workflow --- .github/workflows/push.yaml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/push.yaml diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml new file mode 100644 index 0000000000..51a023f6ca --- /dev/null +++ b/.github/workflows/push.yaml @@ -0,0 +1,34 @@ +name: push + +on: + push: + branches: + - main + pull_request: + +env: + # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + install-and-build-shaders: + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v2 + - uses: moonrepo/setup-rust@v1 + - run: rustup default stable + - run: rustup update + - run: cargo install --path . cargo-gpu + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: moonrepo/setup-rust@v1 + - run: cargo clippy From 82e10ffae623bd57742062212811f7a088970708 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 08:57:03 +1300 Subject: [PATCH 035/162] correct path --- .github/workflows/push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 51a023f6ca..1c6641920d 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -24,7 +24,7 @@ jobs: - uses: moonrepo/setup-rust@v1 - run: rustup default stable - run: rustup update - - run: cargo install --path . cargo-gpu + - run: cargo install --path crates/cargo-gpu clippy: runs-on: ubuntu-latest From 2afcef9beb01823603c78295cc71168b4bd0f97a Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 09:06:41 +1300 Subject: [PATCH 036/162] install cargo-gpu and compile something --- .github/workflows/push.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 1c6641920d..200d6df741 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -25,6 +25,11 @@ jobs: - run: rustup default stable - run: rustup update - run: cargo install --path crates/cargo-gpu + - run: cargo gpu install + - run: git clone https://github.com/Rust-GPU/shader-crate-template.git + - run: cargo gpu build --shader-crate shader-crate-template --output-dir shaders + - run: ls -lah shaders + - run: cat shaders/manifest.json clippy: runs-on: ubuntu-latest From c5c88d0b211107494bd7cefbece466e31598c2af Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 09:24:05 +1300 Subject: [PATCH 037/162] include shader-crate-template in this repo --- .github/workflows/push.yaml | 7 +- Cargo.lock | 89 ++++++++++++++++- Cargo.toml | 1 + crates/shader-crate-template/.gitignore | 1 + crates/shader-crate-template/Cargo.lock | 123 ++++++++++++++++++++++++ crates/shader-crate-template/Cargo.toml | 21 ++++ crates/shader-crate-template/README.md | 5 + crates/shader-crate-template/src/lib.rs | 42 ++++++++ 8 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 crates/shader-crate-template/.gitignore create mode 100644 crates/shader-crate-template/Cargo.lock create mode 100644 crates/shader-crate-template/Cargo.toml create mode 100644 crates/shader-crate-template/README.md create mode 100644 crates/shader-crate-template/src/lib.rs diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 200d6df741..e3d54b758a 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -26,10 +26,9 @@ jobs: - run: rustup update - run: cargo install --path crates/cargo-gpu - run: cargo gpu install - - run: git clone https://github.com/Rust-GPU/shader-crate-template.git - - run: cargo gpu build --shader-crate shader-crate-template --output-dir shaders - - run: ls -lah shaders - - run: cat shaders/manifest.json + - run: cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders + - run: ls -lah test-shaders + - run: cat test-shaders/manifest.json clippy: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 501e23e429..e27864fb9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -66,6 +66,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.6.0" @@ -134,7 +140,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -206,6 +212,24 @@ dependencies = [ "wasi", ] +[[package]] +name = "glam" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" +dependencies = [ + "libm", +] + +[[package]] +name = "glam" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" +dependencies = [ + "libm", +] + [[package]] name = "hashbrown" version = "0.15.1" @@ -269,13 +293,19 @@ version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.6.0", "libc", ] @@ -298,6 +328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -370,6 +401,14 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "rust-gpu-shader-crate-template" +version = "0.1.0" +dependencies = [ + "glam 0.29.2", + "spirv-std", +] + [[package]] name = "ryu" version = "1.0.18" @@ -393,7 +432,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] @@ -429,12 +468,54 @@ dependencies = [ "toml", ] +[[package]] +name = "spirv-std" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c3c0972a2df79abe2c8af2fe7f7937a9aa558b6a1f78fc5edf93f4d480d757" +dependencies = [ + "bitflags 1.3.2", + "glam 0.24.2", + "num-traits", + "spirv-std-macros", + "spirv-std-types", +] + +[[package]] +name = "spirv-std-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f776bf9f2897ea7acff15d7753711fdf1693592bd7459a01c394262b1df45c" +dependencies = [ + "proc-macro2", + "quote", + "spirv-std-types", + "syn 1.0.109", +] + +[[package]] +name = "spirv-std-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a73417b7d72d95b4995c840dceb4e3b4bcbad4ff7f35df9c1655b6826c18d3a9" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.87" @@ -472,7 +553,7 @@ checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.87", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2c5db4bade..7272a77012 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "crates/cargo-gpu", + "crates/shader-crate-template" ] exclude = [ diff --git a/crates/shader-crate-template/.gitignore b/crates/shader-crate-template/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/crates/shader-crate-template/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock new file mode 100644 index 0000000000..d7a52c4ab6 --- /dev/null +++ b/crates/shader-crate-template/Cargo.lock @@ -0,0 +1,123 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "glam" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" +dependencies = [ + "libm", +] + +[[package]] +name = "glam" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "480c9417a5dc586fc0c0cb67891170e59cc11e9dc79ba1c11ddd2c56ca3f3b90" +dependencies = [ + "libm", +] + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rust-gpu-shader-crate-template" +version = "0.1.0" +dependencies = [ + "glam 0.29.1", + "spirv-std", +] + +[[package]] +name = "spirv-std" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c3c0972a2df79abe2c8af2fe7f7937a9aa558b6a1f78fc5edf93f4d480d757" +dependencies = [ + "bitflags", + "glam 0.24.2", + "num-traits", + "spirv-std-macros", + "spirv-std-types", +] + +[[package]] +name = "spirv-std-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f776bf9f2897ea7acff15d7753711fdf1693592bd7459a01c394262b1df45c" +dependencies = [ + "proc-macro2", + "quote", + "spirv-std-types", + "syn", +] + +[[package]] +name = "spirv-std-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a73417b7d72d95b4995c840dceb4e3b4bcbad4ff7f35df9c1655b6826c18d3a9" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml new file mode 100644 index 0000000000..5d62ebf60b --- /dev/null +++ b/crates/shader-crate-template/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "rust-gpu-shader-crate-template" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["rlib", "cdylib"] + +# Dependencies for CPU and GPU code +[dependencies] +spirv-std = { version = "0.9" } + +# dependencies for GPU code +[target.'cfg(target_arch = "spirv")'.dependencies] +glam = { version = "0.29", default-features = false, features = ["libm"] } + + +# dependencies for CPU code +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +glam = { version = "0.29", features = ["std"] } + diff --git a/crates/shader-crate-template/README.md b/crates/shader-crate-template/README.md new file mode 100644 index 0000000000..847967e484 --- /dev/null +++ b/crates/shader-crate-template/README.md @@ -0,0 +1,5 @@ +# shader-crate + +This is a shader crate that can be compiled to SPIR-V using `rust-gpu`. + +This crate can also be used from CPU Rust code, just like any other crate. diff --git a/crates/shader-crate-template/src/lib.rs b/crates/shader-crate-template/src/lib.rs new file mode 100644 index 0000000000..e98f03de2e --- /dev/null +++ b/crates/shader-crate-template/src/lib.rs @@ -0,0 +1,42 @@ +//! Shader entry points. +//! +//! Contains an example vertex shader, fragment shader and one example compute +//! shader. +#![no_std] +use glam::{Vec2, Vec4}; +use spirv_std::spirv; + +pub const CLIP_SPACE_COORD_QUAD_CCW: [Vec4; 6] = { + let tl = Vec4::new(-1.0, 1.0, 0.5, 1.0); + let tr = Vec4::new(1.0, 1.0, 0.5, 1.0); + let bl = Vec4::new(-1.0, -1.0, 0.5, 1.0); + let br = Vec4::new(1.0, -1.0, 0.5, 1.0); + [bl, br, tr, tr, tl, bl] +}; + +pub const UV_COORD_QUAD_CCW: [Vec2; 6] = { + let tl = Vec2::new(0.0, 0.0); + let tr = Vec2::new(1.0, 0.0); + let bl = Vec2::new(0.0, 1.0); + let br = Vec2::new(1.0, 1.0); + [bl, br, tr, tr, tl, bl] +}; + +/// Vertex shader that renders an implicit quad. +#[spirv(vertex)] +pub fn vertex( + #[spirv(vertex_index)] vertex_id: u32, + out_uv: &mut Vec2, + #[spirv(position)] clip_pos: &mut Vec4, +) { + let index = vertex_id as usize % 6; + *out_uv = UV_COORD_QUAD_CCW[index]; + *clip_pos = CLIP_SPACE_COORD_QUAD_CCW[index]; +} + +/// Fragment shader that uses UV coords passed in from the vertex shader +/// to render a simple gradient. +#[spirv(fragment)] +pub fn fragment(in_uv: Vec2, frag_color: &mut Vec4) { + *frag_color = Vec4::new(in_uv.x, in_uv.y, 0.0, 1.0); +} From 9b950944be95c7e5fa321af73dc87ec910bf2aee Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 10:08:21 +1300 Subject: [PATCH 038/162] sanitise cache checkout dir and sanity test it --- .github/workflows/push.yaml | 1 + crates/cargo-gpu/src/main.rs | 45 +++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index e3d54b758a..11cc56ab1f 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -24,6 +24,7 @@ jobs: - uses: moonrepo/setup-rust@v1 - run: rustup default stable - run: rustup update + - run: cargo test - run: cargo install --path crates/cargo-gpu - run: cargo gpu install - run: cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index aab6d712b2..2d72171348 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -135,6 +135,15 @@ struct Spirv { channel: String, } +impl Default for Spirv { + fn default() -> Self { + Self { + dep: Self::DEFAULT_DEP.into(), + channel: Self::DEFAULT_CHANNEL.into(), + } + } +} + impl core::fmt::Display for Spirv { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { format!("{}+{}", self.dep, self.channel).fmt(f) @@ -142,12 +151,18 @@ impl core::fmt::Display for Spirv { } impl Spirv { + const DEFAULT_DEP: &str = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"#; + const DEFAULT_CHANNEL: &str = "nightly-2024-04-24"; + /// Returns a string suitable to use as a directory. /// /// Created from the spirv-builder source dep and the rustc channel. fn to_dirname(&self) -> String { self.to_string() - .replace([std::path::MAIN_SEPARATOR, '.', ':', '@', '='], "_") + .replace( + [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], + "_", + ) .split(['{', '}', ' ', '\n', '"', '\'']) .collect::>() .concat() @@ -258,16 +273,13 @@ fn target_spec_dir() -> std::path::PathBuf { #[derive(Parser, Debug)] struct Install { /// spirv-builder dependency, written just like in a Cargo.toml file. - #[clap( - long, - default_value = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"# - )] + #[clap(long, default_value = Spirv::DEFAULT_DEP)] spirv_builder: String, /// Rust toolchain channel to use to build `spirv-builder`. /// /// This must match the `spirv_builder` argument. - #[clap(long, default_value = "nightly-2024-04-24")] + #[clap(long, default_value = Spirv::DEFAULT_CHANNEL)] rust_toolchain: String, /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. @@ -312,6 +324,7 @@ impl Install { fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { // Ensure the cache dir exists let cache_dir = cache_dir(); + log::info!("cache directory is '{}'", cache_dir.display()); std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { log::error!( "could not create cache directory '{}': {e}", @@ -757,7 +770,7 @@ fn dump_full_usage_for_readme() { println!("{}", buffer); } -fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, depth: usize) { +fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: usize) { if cmd.get_name() == "help" { return; } @@ -774,7 +787,7 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, depth: for sub in cmd.get_subcommands_mut() { let _ = writeln!(buffer); - write_help(buffer, sub, depth + 1); + write_help(buffer, sub, _depth + 1); } } @@ -782,6 +795,22 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, depth: mod test { use super::*; + #[test] + fn cached_checkout_dir_sanity() { + let spirv = Spirv::default(); + let dir = spirv.cached_checkout_path(); + let name = dir + .file_name() + .unwrap() + .to_str() + .map(|s| s.to_string()) + .unwrap(); + assert_eq!( + "git_https___github_com_Rust-GPU_rust-gpu_git+nightly-2024-04-24", + &name + ); + } + #[test] fn builder_from_params() { let shader_crate = std::path::PathBuf::from("../shader-crate-template"); From 2bc8c8a9806324b57cf129180edc7767009e89a8 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 10:42:42 +1300 Subject: [PATCH 039/162] debug logging --- .github/workflows/push.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 11cc56ab1f..62f638e585 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -19,6 +19,8 @@ jobs: defaults: run: shell: bash + env: + RUST_LOG: debug steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 From 332fcce4cf73661a7211c096f6e6abfc97d2eff9 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 10:56:32 +1300 Subject: [PATCH 040/162] more debugging - print contents of release dir on failure --- crates/cargo-gpu/src/main.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 2d72171348..a4225d94ad 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -400,6 +400,11 @@ impl Install { std::fs::rename(&cli_path, &dest_cli_path).unwrap(); } else { log::error!("could not find {}", cli_path.display()); + log::debug!("contents of '{}':", release.display()); + for entry in std::fs::read_dir(&release).unwrap() { + let entry = entry.unwrap(); + log::debug!("{}", entry.file_name().to_string_lossy()); + } panic!("spirv-builder-cli build failed"); } } @@ -797,6 +802,7 @@ mod test { #[test] fn cached_checkout_dir_sanity() { + // Test that let spirv = Spirv::default(); let dir = spirv.cached_checkout_path(); let name = dir From 5918e696b681470ec5202f56ff17b304ac8a958a Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 11:09:21 +1300 Subject: [PATCH 041/162] permit windows .exe extension when looking for spirv-builder-cli --- crates/cargo-gpu/src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index a4225d94ad..4f0a9adada 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -394,7 +394,11 @@ impl Install { panic!("spirv-builder-cli build failed"); } - let cli_path = release.join("spirv-builder-cli"); + let cli_path = if cfg!(target_os = "windows") { + release.join("spirv-builder-cli").with_extension("exe") + } else { + release.join("spirv-builder-cli") + }; if cli_path.is_file() { log::info!("successfully built {}", cli_path.display()); std::fs::rename(&cli_path, &dest_cli_path).unwrap(); From c358f6b7aa6e33590f8dc85619b82011ebefb501 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 8 Dec 2024 15:28:12 +1300 Subject: [PATCH 042/162] feature: show command --- crates/cargo-gpu/src/main.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 4f0a9adada..e79e83d8a5 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -707,6 +707,22 @@ impl Toml { } } +#[derive(Parser)] +struct Show { + #[clap(long)] + /// Displays the location of the cache directory + cache_directory: bool, +} + +impl Show { + fn run(self) { + if self.cache_directory { + log::info!("cache_directory: "); + println!("{}", cache_dir().display()); + } + } +} + #[derive(Subcommand)] enum Command { /// Install rust-gpu compiler artifacts. @@ -719,6 +735,9 @@ enum Command { /// found in the given toml file. Toml(Toml), + /// Show some useful values. + Show(Show), + /// A hidden command that can be used to recursively print out all the subcommand help messages: /// `cargo gpu dump-usage` /// Useful for updating the README. @@ -763,6 +782,7 @@ fn main() { } Command::Build(mut build) => build.run(), Command::Toml(toml) => toml.run(), + Command::Show(show) => show.run(), Command::DumpUsage => dump_full_usage_for_readme(), } } From e333f9f2fa01771a02582d82b768a52a6d1905f7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 9 Dec 2024 07:34:11 +1300 Subject: [PATCH 043/162] fix: standardize linkage paths with forward slashes --- crates/spirv-builder-cli/src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/spirv-builder-cli/src/lib.rs b/crates/spirv-builder-cli/src/lib.rs index 8f9aea4e21..b26c7b5928 100644 --- a/crates/spirv-builder-cli/src/lib.rs +++ b/crates/spirv-builder-cli/src/lib.rs @@ -3,7 +3,7 @@ /// Shader source and entry point that can be used to create shader linkage. #[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Linkage { - pub source_path: std::path::PathBuf, + pub source_path: String, pub entry_point: String, pub wgsl_entry_point: String, } @@ -11,7 +11,13 @@ pub struct Linkage { impl Linkage { pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { Self { - source_path: source_path.as_ref().to_path_buf(), + // Force a forward slash convention here so it works on all OSs + source_path: source_path + .as_ref() + .components() + .map(|c| c.as_os_str().to_string_lossy()) + .collect::>() + .join("/"), wgsl_entry_point: entry_point.as_ref().replace("::", ""), entry_point: entry_point.as_ref().to_string(), } From 2579b5de5878368875ab5d73802827e37175dbd6 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 14 Dec 2024 23:03:56 +0100 Subject: [PATCH 044/162] Refactor each subcommand to its own file No other changes, just moving code. --- crates/cargo-gpu/src/builder.rs | 137 ++++++ crates/cargo-gpu/src/install.rs | 243 +++++++++++ crates/cargo-gpu/src/main.rs | 719 ++------------------------------ crates/cargo-gpu/src/show.rs | 17 + crates/cargo-gpu/src/spirv.rs | 139 ++++++ crates/cargo-gpu/src/toml.rs | 141 +++++++ 6 files changed, 710 insertions(+), 686 deletions(-) create mode 100644 crates/cargo-gpu/src/builder.rs create mode 100644 crates/cargo-gpu/src/install.rs create mode 100644 crates/cargo-gpu/src/show.rs create mode 100644 crates/cargo-gpu/src/spirv.rs create mode 100644 crates/cargo-gpu/src/toml.rs diff --git a/crates/cargo-gpu/src/builder.rs b/crates/cargo-gpu/src/builder.rs new file mode 100644 index 0000000000..f92965ca38 --- /dev/null +++ b/crates/cargo-gpu/src/builder.rs @@ -0,0 +1,137 @@ +use std::io::Write; + +use clap::Parser; +use spirv_builder_cli::{Linkage, ShaderModule}; + +use crate::{install::Install, target_spec_dir}; + +#[derive(Parser, Debug)] +pub(crate) struct Build { + #[clap(flatten)] + install: Install, + + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, + + /// Shader target. + #[clap(long, default_value = "spirv-unknown-vulkan1.2")] + shader_target: String, + + /// Set cargo default-features. + #[clap(long)] + no_default_features: bool, + + /// Set cargo features. + #[clap(long)] + features: Vec, + + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "./")] + pub output_dir: std::path::PathBuf, +} + +impl Build { + pub fn run(&mut self) { + let (dylib_path, spirv_builder_cli_path) = self.install.run(); + + // Ensure the shader output dir exists + log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); + std::fs::create_dir_all(&self.output_dir).unwrap(); + self.output_dir = self.output_dir.canonicalize().unwrap(); + + // Ensure the shader crate exists + self.shader_crate = self.shader_crate.canonicalize().unwrap(); + assert!( + self.shader_crate.exists(), + "shader crate '{}' does not exist. (Current dir is '{}')", + self.shader_crate.display(), + std::env::current_dir().unwrap().display() + ); + + let spirv_builder_args = spirv_builder_cli::Args { + dylib_path, + shader_crate: self.shader_crate.clone(), + shader_target: self.shader_target.clone(), + path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)), + no_default_features: self.no_default_features, + features: self.features.clone(), + output_dir: self.output_dir.clone(), + }; + + // UNWRAP: safe because we know this always serializes + let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); + log::info!("using spirv-builder-cli arg: {arg}"); + + // Call spirv-builder-cli to compile the shaders. + let output = std::process::Command::new(spirv_builder_cli_path) + .arg(arg) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "build failed"); + + let spirv_manifest = self.output_dir.join("spirv-manifest.json"); + if spirv_manifest.is_file() { + log::debug!( + "successfully built shaders, raw manifest is at '{}'", + spirv_manifest.display() + ); + } else { + log::error!("missing raw manifest '{}'", spirv_manifest.display()); + panic!("missing raw manifest"); + } + + let shaders: Vec = + serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); + + let mut linkage: Vec<_> = shaders + .into_iter() + .map( + |ShaderModule { + entry, + path: filepath, + }| { + use relative_path::PathExt; + let path = self.output_dir.join(filepath.file_name().unwrap()); + std::fs::copy(&filepath, &path).unwrap(); + let path_relative_to_shader_crate = + path.relative_to(&self.shader_crate).unwrap().to_path(""); + Linkage::new(entry, path_relative_to_shader_crate) + }, + ) + .collect(); + + // Write the shader manifest json file + let manifest_path = self.output_dir.join("manifest.json"); + // Sort the contents so the output is deterministic + linkage.sort(); + // UNWRAP: safe because we know this always serializes + let json = serde_json::to_string_pretty(&linkage).unwrap(); + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + log::error!( + "could not create shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + file.write_all(json.as_bytes()).unwrap_or_else(|e| { + log::error!( + "could not write shader manifest file '{}': {e}", + manifest_path.display(), + ); + panic!("{e}") + }); + + log::info!("wrote manifest to '{}'", manifest_path.display()); + + if spirv_manifest.is_file() { + log::debug!( + "removing spirv-manifest.json file '{}'", + spirv_manifest.display() + ); + std::fs::remove_file(spirv_manifest).unwrap(); + } + } +} diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs new file mode 100644 index 0000000000..e884bc5012 --- /dev/null +++ b/crates/cargo-gpu/src/install.rs @@ -0,0 +1,243 @@ +use std::io::Write; + +use crate::{cache_dir, spirv::Spirv, target_spec_dir}; + +const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); +const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); +const SPIRV_BUILDER_CLI_LIB: &str = include_str!("../../spirv-builder-cli/src/lib.rs"); +const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ + ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), + ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), + ("src/lib.rs", SPIRV_BUILDER_CLI_LIB), +]; + +const TARGET_SPECS: &[(&str, &str)] = &[ + ( + "spirv-unknown-opengl4.0.json", + include_str!("../target-specs/spirv-unknown-opengl4.0.json"), + ), + ( + "spirv-unknown-opengl4.1.json", + include_str!("../target-specs/spirv-unknown-opengl4.1.json"), + ), + ( + "spirv-unknown-opengl4.2.json", + include_str!("../target-specs/spirv-unknown-opengl4.2.json"), + ), + ( + "spirv-unknown-opengl4.3.json", + include_str!("../target-specs/spirv-unknown-opengl4.3.json"), + ), + ( + "spirv-unknown-opengl4.5.json", + include_str!("../target-specs/spirv-unknown-opengl4.5.json"), + ), + ( + "spirv-unknown-spv1.0.json", + include_str!("../target-specs/spirv-unknown-spv1.0.json"), + ), + ( + "spirv-unknown-spv1.1.json", + include_str!("../target-specs/spirv-unknown-spv1.1.json"), + ), + ( + "spirv-unknown-spv1.2.json", + include_str!("../target-specs/spirv-unknown-spv1.2.json"), + ), + ( + "spirv-unknown-spv1.3.json", + include_str!("../target-specs/spirv-unknown-spv1.3.json"), + ), + ( + "spirv-unknown-spv1.4.json", + include_str!("../target-specs/spirv-unknown-spv1.4.json"), + ), + ( + "spirv-unknown-spv1.5.json", + include_str!("../target-specs/spirv-unknown-spv1.5.json"), + ), + ( + "spirv-unknown-vulkan1.0.json", + include_str!("../target-specs/spirv-unknown-vulkan1.0.json"), + ), + ( + "spirv-unknown-vulkan1.1.json", + include_str!("../target-specs/spirv-unknown-vulkan1.1.json"), + ), + ( + "spirv-unknown-vulkan1.1spv1.4.json", + include_str!("../target-specs/spirv-unknown-vulkan1.1spv1.4.json"), + ), + ( + "spirv-unknown-vulkan1.2.json", + include_str!("../target-specs/spirv-unknown-vulkan1.2.json"), + ), +]; + +#[derive(clap::Parser, Debug)] +pub(crate) struct Install { + /// spirv-builder dependency, written just like in a Cargo.toml file. + #[clap(long, default_value = Spirv::DEFAULT_DEP)] + spirv_builder: String, + + /// Rust toolchain channel to use to build `spirv-builder`. + /// + /// This must match the `spirv_builder` argument. + #[clap(long, default_value = Spirv::DEFAULT_CHANNEL)] + rust_toolchain: String, + + /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + force_spirv_cli_rebuild: bool, +} + +impl Install { + fn spirv_cli(&self) -> Spirv { + Spirv { + dep: self.spirv_builder.clone(), + channel: self.rust_toolchain.clone(), + } + } + + fn write_source_files(&self) { + let cli = self.spirv_cli(); + let checkout = cli.cached_checkout_path(); + std::fs::create_dir_all(checkout.join("src")).unwrap(); + for (filename, contents) in SPIRV_BUILDER_FILES.iter() { + log::debug!("writing {filename}"); + let path = checkout.join(filename); + let mut file = std::fs::File::create(&path).unwrap(); + let replaced_contents = contents + .replace("${SPIRV_BUILDER_SOURCE}", &cli.dep) + .replace("${CHANNEL}", &cli.channel); + file.write_all(replaced_contents.as_bytes()).unwrap(); + } + } + + fn write_target_spec_files(&self) { + for (filename, contents) in TARGET_SPECS.iter() { + let path = target_spec_dir().join(filename); + if !path.is_file() || self.force_spirv_cli_rebuild { + let mut file = std::fs::File::create(&path).unwrap(); + file.write_all(contents.as_bytes()).unwrap(); + } + } + } + + // Install the binary pair and return the paths, (dylib, cli). + pub fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { + // Ensure the cache dir exists + let cache_dir = cache_dir(); + log::info!("cache directory is '{}'", cache_dir.display()); + std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { + log::error!( + "could not create cache directory '{}': {e}", + cache_dir.display() + ); + panic!("could not create cache dir"); + }); + + let spirv_version = self.spirv_cli(); + spirv_version.ensure_version_channel_compatibility(); + spirv_version.ensure_toolchain_and_components_exist(); + + let checkout = spirv_version.cached_checkout_path(); + let release = checkout.join("target").join("release"); + + let dylib_filename = format!( + "{}rustc_codegen_spirv{}", + std::env::consts::DLL_PREFIX, + std::env::consts::DLL_SUFFIX + ); + let dylib_path = release.join(&dylib_filename); + let dest_dylib_path = checkout.join(&dylib_filename); + let dest_cli_path = checkout.join("spirv-builder-cli"); + if dest_dylib_path.is_file() && dest_cli_path.is_file() { + log::info!( + "cargo-gpu artifacts are already installed in '{}'", + checkout.display() + ); + } + + if dest_dylib_path.is_file() && dest_cli_path.is_file() && !self.force_spirv_cli_rebuild { + log::info!("...and so we are aborting the install step."); + } else { + log::debug!( + "writing spirv-builder-cli source files into '{}'", + checkout.display() + ); + self.write_source_files(); + self.write_target_spec_files(); + + let mut command = std::process::Command::new("cargo"); + command + .current_dir(&checkout) + .arg(format!("+{}", spirv_version.channel)) + .args(["build", "--release"]) + .args(["--no-default-features"]); + + command.args([ + "--features", + &Self::get_required_spirv_builder_version(spirv_version.channel), + ]); + + log::debug!("building artifacts with `{:?}`", command); + + let output = command + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!(output.status.success(), "...build error!"); + + if dylib_path.is_file() { + log::info!("successfully built {}", dylib_path.display()); + std::fs::rename(&dylib_path, &dest_dylib_path).unwrap(); + } else { + log::error!("could not find {}", dylib_path.display()); + panic!("spirv-builder-cli build failed"); + } + + let cli_path = if cfg!(target_os = "windows") { + release.join("spirv-builder-cli").with_extension("exe") + } else { + release.join("spirv-builder-cli") + }; + if cli_path.is_file() { + log::info!("successfully built {}", cli_path.display()); + std::fs::rename(&cli_path, &dest_cli_path).unwrap(); + } else { + log::error!("could not find {}", cli_path.display()); + log::debug!("contents of '{}':", release.display()); + for entry in std::fs::read_dir(&release).unwrap() { + let entry = entry.unwrap(); + log::debug!("{}", entry.file_name().to_string_lossy()); + } + panic!("spirv-builder-cli build failed"); + } + } + (dest_dylib_path, dest_cli_path) + } + + /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to + /// interact with `cargo-gpu`. Older versions don't have the same `SpirvBuilder` interface. So + /// here we choose the right Cargo feature to enable/disable code in `spirv-builder-cli`. + /// + /// TODO: + /// * Download the actual `rust-gpu` repo as pinned in the shader's `Cargo.lock` and get the + /// `spirv-builder` version from there. + /// * Warn the user that certain `cargo-gpu` features aren't available when building with + /// older versions of `spirv-builder`, eg setting the target spec. + fn get_required_spirv_builder_version(toolchain_channel: String) -> String { + let parse_date = chrono::NaiveDate::parse_from_str; + let datetime = parse_date(&toolchain_channel, "nightly-%Y-%m-%d").unwrap(); + let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); + + if datetime < pre_cli_date { + "spirv-builder-pre-cli" + } else { + "spirv-builder-0_10" + } + .into() + } +} diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index e79e83d8a5..575dd4160c 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -49,220 +49,18 @@ //! manifest file can be used by build scripts (`build.rs` files) to generate linkage or //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. -use std::io::Write; -use clap::{Parser, Subcommand}; -use spirv_builder_cli::{Linkage, ShaderModule}; +use builder::Build; +use clap::Parser; +use install::Install; +use show::Show; +use toml::Toml; -const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); -const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); -const SPIRV_BUILDER_CLI_LIB: &str = include_str!("../../spirv-builder-cli/src/lib.rs"); -const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ - ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), - ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), - ("src/lib.rs", SPIRV_BUILDER_CLI_LIB), -]; - -const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; - -const TARGET_SPECS: &[(&str, &str)] = &[ - ( - "spirv-unknown-opengl4.0.json", - include_str!("../target-specs/spirv-unknown-opengl4.0.json"), - ), - ( - "spirv-unknown-opengl4.1.json", - include_str!("../target-specs/spirv-unknown-opengl4.1.json"), - ), - ( - "spirv-unknown-opengl4.2.json", - include_str!("../target-specs/spirv-unknown-opengl4.2.json"), - ), - ( - "spirv-unknown-opengl4.3.json", - include_str!("../target-specs/spirv-unknown-opengl4.3.json"), - ), - ( - "spirv-unknown-opengl4.5.json", - include_str!("../target-specs/spirv-unknown-opengl4.5.json"), - ), - ( - "spirv-unknown-spv1.0.json", - include_str!("../target-specs/spirv-unknown-spv1.0.json"), - ), - ( - "spirv-unknown-spv1.1.json", - include_str!("../target-specs/spirv-unknown-spv1.1.json"), - ), - ( - "spirv-unknown-spv1.2.json", - include_str!("../target-specs/spirv-unknown-spv1.2.json"), - ), - ( - "spirv-unknown-spv1.3.json", - include_str!("../target-specs/spirv-unknown-spv1.3.json"), - ), - ( - "spirv-unknown-spv1.4.json", - include_str!("../target-specs/spirv-unknown-spv1.4.json"), - ), - ( - "spirv-unknown-spv1.5.json", - include_str!("../target-specs/spirv-unknown-spv1.5.json"), - ), - ( - "spirv-unknown-vulkan1.0.json", - include_str!("../target-specs/spirv-unknown-vulkan1.0.json"), - ), - ( - "spirv-unknown-vulkan1.1.json", - include_str!("../target-specs/spirv-unknown-vulkan1.1.json"), - ), - ( - "spirv-unknown-vulkan1.1spv1.4.json", - include_str!("../target-specs/spirv-unknown-vulkan1.1spv1.4.json"), - ), - ( - "spirv-unknown-vulkan1.2.json", - include_str!("../target-specs/spirv-unknown-vulkan1.2.json"), - ), -]; - -/// Cargo dependency for `spirv-builder` and the rust toolchain channel. -#[derive(Debug, Clone)] -struct Spirv { - dep: String, - channel: String, -} - -impl Default for Spirv { - fn default() -> Self { - Self { - dep: Self::DEFAULT_DEP.into(), - channel: Self::DEFAULT_CHANNEL.into(), - } - } -} - -impl core::fmt::Display for Spirv { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - format!("{}+{}", self.dep, self.channel).fmt(f) - } -} - -impl Spirv { - const DEFAULT_DEP: &str = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"#; - const DEFAULT_CHANNEL: &str = "nightly-2024-04-24"; - - /// Returns a string suitable to use as a directory. - /// - /// Created from the spirv-builder source dep and the rustc channel. - fn to_dirname(&self) -> String { - self.to_string() - .replace( - [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], - "_", - ) - .split(['{', '}', ' ', '\n', '"', '\'']) - .collect::>() - .concat() - } - - fn cached_checkout_path(&self) -> std::path::PathBuf { - let checkout_dir = cache_dir().join(self.to_dirname()); - std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { - log::error!( - "could not create checkout dir '{}': {e}", - checkout_dir.display() - ); - panic!("could not create checkout dir"); - }); - - checkout_dir - } - - fn ensure_version_channel_compatibility(&self) { - for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { - if version.starts_with(&self.dep) && channel != &self.channel { - panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); - } - } - } - - /// Use `rustup` to install the toolchain and components, if not already installed. - /// - /// Pretty much runs: - /// - /// * rustup toolchain add nightly-2024-04-24 - /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools - fn ensure_toolchain_and_components_exist(&self) { - // Check for the required toolchain - let output = std::process::Command::new("rustup") - .args(["toolchain", "list"]) - .output() - .unwrap(); - assert!( - output.status.success(), - "could not list installed toolchains" - ); - let stdout = String::from_utf8_lossy(&output.stdout); - if stdout - .split_whitespace() - .any(|toolchain| toolchain.starts_with(&self.channel)) - { - log::debug!("toolchain {} is already installed", self.channel); - } else { - let output = std::process::Command::new("rustup") - .args(["toolchain", "add"]) - .arg(&self.channel) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!( - output.status.success(), - "could not install required toolchain" - ); - } - - // Check for the required components - let output = std::process::Command::new("rustup") - .args(["component", "list", "--toolchain"]) - .arg(&self.channel) - .output() - .unwrap(); - assert!( - output.status.success(), - "could not list installed components" - ); - let stdout = String::from_utf8_lossy(&output.stdout); - let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; - let installed_components = stdout.lines().collect::>(); - let all_components_installed = required_components.iter().all(|component| { - installed_components.iter().any(|installed_component| { - let is_component = installed_component.starts_with(component); - let is_installed = installed_component.ends_with("(installed)"); - is_component && is_installed - }) - }); - if all_components_installed { - log::debug!("all required components are installed"); - } else { - let output = std::process::Command::new("rustup") - .args(["component", "add", "--toolchain"]) - .arg(&self.channel) - .args(["rust-src", "rustc-dev", "llvm-tools"]) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!( - output.status.success(), - "could not install required components" - ); - } - } -} +mod builder; +mod install; +mod show; +mod spirv; +mod toml; fn target_spec_dir() -> std::path::PathBuf { let dir = cache_dir().join("target-specs"); @@ -270,460 +68,31 @@ fn target_spec_dir() -> std::path::PathBuf { dir } -#[derive(Parser, Debug)] -struct Install { - /// spirv-builder dependency, written just like in a Cargo.toml file. - #[clap(long, default_value = Spirv::DEFAULT_DEP)] - spirv_builder: String, - - /// Rust toolchain channel to use to build `spirv-builder`. - /// - /// This must match the `spirv_builder` argument. - #[clap(long, default_value = Spirv::DEFAULT_CHANNEL)] - rust_toolchain: String, - - /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. - #[clap(long)] - force_spirv_cli_rebuild: bool, -} - -impl Install { - fn spirv_cli(&self) -> Spirv { - Spirv { - dep: self.spirv_builder.clone(), - channel: self.rust_toolchain.clone(), - } - } - - fn write_source_files(&self) { - let cli = self.spirv_cli(); - let checkout = cli.cached_checkout_path(); - std::fs::create_dir_all(checkout.join("src")).unwrap(); - for (filename, contents) in SPIRV_BUILDER_FILES.iter() { - log::debug!("writing {filename}"); - let path = checkout.join(filename); - let mut file = std::fs::File::create(&path).unwrap(); - let replaced_contents = contents - .replace("${SPIRV_BUILDER_SOURCE}", &cli.dep) - .replace("${CHANNEL}", &cli.channel); - file.write_all(replaced_contents.as_bytes()).unwrap(); - } - } - - fn write_target_spec_files(&self) { - for (filename, contents) in TARGET_SPECS.iter() { - let path = target_spec_dir().join(filename); - if !path.is_file() || self.force_spirv_cli_rebuild { - let mut file = std::fs::File::create(&path).unwrap(); - file.write_all(contents.as_bytes()).unwrap(); - } - } - } - - // Install the binary pair and return the paths, (dylib, cli). - fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { - // Ensure the cache dir exists - let cache_dir = cache_dir(); - log::info!("cache directory is '{}'", cache_dir.display()); - std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { - log::error!( - "could not create cache directory '{}': {e}", - cache_dir.display() - ); - panic!("could not create cache dir"); - }); - - let spirv_version = self.spirv_cli(); - spirv_version.ensure_version_channel_compatibility(); - spirv_version.ensure_toolchain_and_components_exist(); - - let checkout = spirv_version.cached_checkout_path(); - let release = checkout.join("target").join("release"); - - let dylib_filename = format!( - "{}rustc_codegen_spirv{}", - std::env::consts::DLL_PREFIX, - std::env::consts::DLL_SUFFIX - ); - let dylib_path = release.join(&dylib_filename); - let dest_dylib_path = checkout.join(&dylib_filename); - let dest_cli_path = checkout.join("spirv-builder-cli"); - if dest_dylib_path.is_file() && dest_cli_path.is_file() { - log::info!( - "cargo-gpu artifacts are already installed in '{}'", - checkout.display() - ); - } - - if dest_dylib_path.is_file() && dest_cli_path.is_file() && !self.force_spirv_cli_rebuild { - log::info!("...and so we are aborting the install step."); - } else { - log::debug!( - "writing spirv-builder-cli source files into '{}'", - checkout.display() - ); - self.write_source_files(); - self.write_target_spec_files(); - - let mut command = std::process::Command::new("cargo"); - command - .current_dir(&checkout) - .arg(format!("+{}", spirv_version.channel)) - .args(["build", "--release"]) - .args(["--no-default-features"]); - - command.args([ - "--features", - &Self::get_required_spirv_builder_version(spirv_version.channel), - ]); - - log::debug!("building artifacts with `{:?}`", command); - - let output = command - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "...build error!"); - - if dylib_path.is_file() { - log::info!("successfully built {}", dylib_path.display()); - std::fs::rename(&dylib_path, &dest_dylib_path).unwrap(); - } else { - log::error!("could not find {}", dylib_path.display()); - panic!("spirv-builder-cli build failed"); - } - - let cli_path = if cfg!(target_os = "windows") { - release.join("spirv-builder-cli").with_extension("exe") - } else { - release.join("spirv-builder-cli") - }; - if cli_path.is_file() { - log::info!("successfully built {}", cli_path.display()); - std::fs::rename(&cli_path, &dest_cli_path).unwrap(); - } else { - log::error!("could not find {}", cli_path.display()); - log::debug!("contents of '{}':", release.display()); - for entry in std::fs::read_dir(&release).unwrap() { - let entry = entry.unwrap(); - log::debug!("{}", entry.file_name().to_string_lossy()); - } - panic!("spirv-builder-cli build failed"); - } - } - (dest_dylib_path, dest_cli_path) - } - - /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to - /// interact with `cargo-gpu`. Older versions don't have the same `SpirvBuilder` interface. So - /// here we choose the right Cargo feature to enable/disable code in `spirv-builder-cli`. - /// - /// TODO: - /// * Download the actual `rust-gpu` repo as pinned in the shader's `Cargo.lock` and get the - /// `spirv-builder` version from there. - /// * Warn the user that certain `cargo-gpu` features aren't available when building with - /// older versions of `spirv-builder`, eg setting the target spec. - fn get_required_spirv_builder_version(toolchain_channel: String) -> String { - let parse_date = chrono::NaiveDate::parse_from_str; - let datetime = parse_date(&toolchain_channel, "nightly-%Y-%m-%d").unwrap(); - let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); - - if datetime < pre_cli_date { - "spirv-builder-pre-cli" - } else { - "spirv-builder-0_10" - } - .into() - } -} - -#[derive(Parser, Debug)] -struct Build { - #[clap(flatten)] - install: Install, - - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - shader_crate: std::path::PathBuf, - - /// Shader target. - #[clap(long, default_value = "spirv-unknown-vulkan1.2")] - shader_target: String, - - /// Set cargo default-features. - #[clap(long)] - no_default_features: bool, - - /// Set cargo features. - #[clap(long)] - features: Vec, - - /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "./")] - output_dir: std::path::PathBuf, -} - -impl Build { - fn run(&mut self) { - let (dylib_path, spirv_builder_cli_path) = self.install.run(); - - // Ensure the shader output dir exists - log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); - std::fs::create_dir_all(&self.output_dir).unwrap(); - self.output_dir = self.output_dir.canonicalize().unwrap(); - - // Ensure the shader crate exists - self.shader_crate = self.shader_crate.canonicalize().unwrap(); - assert!( - self.shader_crate.exists(), - "shader crate '{}' does not exist. (Current dir is '{}')", - self.shader_crate.display(), - std::env::current_dir().unwrap().display() - ); - - let spirv_builder_args = spirv_builder_cli::Args { - dylib_path, - shader_crate: self.shader_crate.clone(), - shader_target: self.shader_target.clone(), - path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)), - no_default_features: self.no_default_features, - features: self.features.clone(), - output_dir: self.output_dir.clone(), - }; - - // UNWRAP: safe because we know this always serializes - let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); - log::info!("using spirv-builder-cli arg: {arg}"); - - // Call spirv-builder-cli to compile the shaders. - let output = std::process::Command::new(spirv_builder_cli_path) - .arg(arg) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "build failed"); - - let spirv_manifest = self.output_dir.join("spirv-manifest.json"); - if spirv_manifest.is_file() { - log::debug!( - "successfully built shaders, raw manifest is at '{}'", - spirv_manifest.display() - ); - } else { - log::error!("missing raw manifest '{}'", spirv_manifest.display()); - panic!("missing raw manifest"); - } - - let shaders: Vec = - serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); - - let mut linkage: Vec<_> = shaders - .into_iter() - .map( - |ShaderModule { - entry, - path: filepath, - }| { - use relative_path::PathExt; - let path = self.output_dir.join(filepath.file_name().unwrap()); - std::fs::copy(&filepath, &path).unwrap(); - let path_relative_to_shader_crate = - path.relative_to(&self.shader_crate).unwrap().to_path(""); - Linkage::new(entry, path_relative_to_shader_crate) - }, - ) - .collect(); - - // Write the shader manifest json file - let manifest_path = self.output_dir.join("manifest.json"); - // Sort the contents so the output is deterministic - linkage.sort(); - // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { - log::error!( - "could not create shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { - log::error!( - "could not write shader manifest file '{}': {e}", - manifest_path.display(), - ); - panic!("{e}") - }); - - log::info!("wrote manifest to '{}'", manifest_path.display()); - - if spirv_manifest.is_file() { - log::debug!( - "removing spirv-manifest.json file '{}'", - spirv_manifest.display() - ); - std::fs::remove_file(spirv_manifest).unwrap(); - } - } -} - -#[derive(Parser)] -struct Toml { - /// Path to a workspace or package Cargo.toml file. - /// - /// Must include a [[workspace | package].metadata.rust-gpu.build] section where - /// arguments to `cargo gpu build` are listed. - /// - /// Path arguments like `output-dir` and `shader-manifest` must be relative to - /// the location of the Cargo.toml file. - /// - /// Example: - /// - /// ```toml - /// [package.metadata.rust-gpu.build.spirv-builder] - /// git = "https://github.com/Rust-GPU/rust-gpu.git" - /// rev = "0da80f8" - /// - /// [package.metadata.rust-gpu.build] - /// output-dir = "shaders" - /// shader-manifest = "shaders/manifest.json" - /// ``` - /// - /// Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that - /// contains the example above would compile the crate and place the compiled - /// `.spv` files and manifest in a directory "shaders". - #[clap(default_value = "./Cargo.toml", verbatim_doc_comment)] - path: std::path::PathBuf, -} - -impl Toml { - fn run(&self) { - // Find the path to the toml file to use - let path = if self.path.is_file() && self.path.ends_with(".toml") { - self.path.clone() - } else { - let path = self.path.join("Cargo.toml"); - if path.is_file() { - path - } else { - log::error!("toml file '{}' is not a file", self.path.display()); - panic!("toml file '{}' is not a file", self.path.display()); - } - }; - - log::info!("using toml file '{}'", path.display()); - - // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml - let contents = std::fs::read_to_string(&path).unwrap(); - let toml: toml::Table = toml::from_str(&contents).unwrap(); - - fn get_metadata_rustgpu_table<'a>( - toml: &'a toml::Table, - toml_type: &'static str, - ) -> Option<&'a toml::Table> { - let workspace = toml.get(toml_type)?.as_table()?; - let metadata = workspace.get("metadata")?.as_table()?; - metadata.get("rust-gpu")?.as_table() - } - - let (toml_type, table) = if toml.contains_key("workspace") { - let table = get_metadata_rustgpu_table(&toml, "workspace") - .unwrap_or_else(|| { - panic!( - "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", - path.display() - ); - }) - .clone(); - ("workspace", table) - } else if toml.contains_key("package") { - let mut table = get_metadata_rustgpu_table(&toml, "package") - .unwrap_or_else(|| { - panic!( - "toml file '{}' is missing a [package.metadata.rust-gpu] table", - path.display() - ); - }) - .clone(); - // Ensure the package name is included as the shader-crate parameter - if !table.contains_key("shader-crate") { - table.insert( - "shader-crate".to_string(), - format!("{}", path.parent().unwrap().display()).into(), - ); - } - ("package", table) - } else { - panic!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); - }; - log::info!( - "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", - path.display() - ); - log::debug!("table: {table:#?}"); - - let mut parameters = table - .get("build") - .unwrap_or_else(|| panic!("toml is missing the 'build' table")) - .as_table() - .unwrap_or_else(|| { - panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") - }) - .into_iter() - .flat_map(|(k, v)| match v { - toml::Value::String(s) => [format!("--{k}"), s.clone()], - _ => { - let mut value = String::new(); - let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(v, ser).unwrap(); - [format!("--{k}"), value] - } - }) - .collect::>(); - parameters.insert(0, "cargo-gpu".to_string()); - parameters.insert(1, "build".to_string()); - - let working_directory = path.parent().unwrap(); - log::info!( - "issuing cargo commands from the working directory '{}'", - working_directory.display() - ); - std::env::set_current_dir(working_directory).unwrap(); - - log::debug!("build parameters: {parameters:#?}"); - if let Cli { - command: Command::Build(mut build), - .. - } = Cli::parse_from(parameters) - { - log::debug!("build: {build:?}"); - build.run(); - } else { - log::error!("parameters found in [{toml_type}.metadata.rust-gpu.build] were not parameters to `cargo gpu build`"); - panic!("could not determin build command"); - } - } -} +fn main() { + env_logger::builder().init(); -#[derive(Parser)] -struct Show { - #[clap(long)] - /// Displays the location of the cache directory - cache_directory: bool, -} + let args = std::env::args() + .filter(|p| { + // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" + // as the first parameter, which we want to ignore. + p != "gpu" + }) + .collect::>(); + log::trace!("args: {args:?}"); + let cli = Cli::parse_from(args); -impl Show { - fn run(self) { - if self.cache_directory { - log::info!("cache_directory: "); - println!("{}", cache_dir().display()); + match cli.command { + Command::Install(install) => { + let _ = install.run(); } + Command::Build(mut build) => build.run(), + Command::Toml(toml) => toml.run(), + Command::Show(show) => show.run(), + Command::DumpUsage => dump_full_usage_for_readme(), } } -#[derive(Subcommand)] +#[derive(clap::Subcommand)] enum Command { /// Install rust-gpu compiler artifacts. Install(Install), @@ -745,9 +114,9 @@ enum Command { DumpUsage, } -#[derive(Parser)] +#[derive(clap::Parser)] #[clap(author, version, about, subcommand_required = true)] -struct Cli { +pub(crate) struct Cli { /// The command to run. #[clap(subcommand)] command: Command, @@ -763,30 +132,6 @@ fn cache_dir() -> std::path::PathBuf { .join("rust-gpu") } -fn main() { - env_logger::builder().init(); - - let args = std::env::args() - .filter(|p| { - // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" - // as the first parameter, which we want to ignore. - p != "gpu" - }) - .collect::>(); - log::trace!("args: {args:?}"); - let cli = Cli::parse_from(args); - - match cli.command { - Command::Install(install) => { - let _ = install.run(); - } - Command::Build(mut build) => build.run(), - Command::Toml(toml) => toml.run(), - Command::Show(show) => show.run(), - Command::DumpUsage => dump_full_usage_for_readme(), - } -} - fn dump_full_usage_for_readme() { use clap::CommandFactory; let mut command = Cli::command(); @@ -822,6 +167,8 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: #[cfg(test)] mod test { + use spirv::Spirv; + use super::*; #[test] diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs new file mode 100644 index 0000000000..1dd727e384 --- /dev/null +++ b/crates/cargo-gpu/src/show.rs @@ -0,0 +1,17 @@ +use crate::cache_dir; + +#[derive(clap::Parser)] +pub(crate) struct Show { + #[clap(long)] + /// Displays the location of the cache directory + cache_directory: bool, +} + +impl Show { + pub fn run(self) { + if self.cache_directory { + log::info!("cache_directory: "); + println!("{}", cache_dir().display()); + } + } +} diff --git a/crates/cargo-gpu/src/spirv.rs b/crates/cargo-gpu/src/spirv.rs new file mode 100644 index 0000000000..6ab58da39a --- /dev/null +++ b/crates/cargo-gpu/src/spirv.rs @@ -0,0 +1,139 @@ +use crate::cache_dir; + +const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; + +/// Cargo dependency for `spirv-builder` and the rust toolchain channel. +#[derive(Debug, Clone)] +pub(crate) struct Spirv { + pub dep: String, + pub channel: String, +} + +impl Default for Spirv { + fn default() -> Self { + Self { + dep: Self::DEFAULT_DEP.into(), + channel: Self::DEFAULT_CHANNEL.into(), + } + } +} + +impl core::fmt::Display for Spirv { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + format!("{}+{}", self.dep, self.channel).fmt(f) + } +} + +impl Spirv { + pub const DEFAULT_DEP: &str = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"#; + pub const DEFAULT_CHANNEL: &str = "nightly-2024-04-24"; + + /// Returns a string suitable to use as a directory. + /// + /// Created from the spirv-builder source dep and the rustc channel. + fn to_dirname(&self) -> String { + self.to_string() + .replace( + [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], + "_", + ) + .split(['{', '}', ' ', '\n', '"', '\'']) + .collect::>() + .concat() + } + + pub fn cached_checkout_path(&self) -> std::path::PathBuf { + let checkout_dir = cache_dir().join(self.to_dirname()); + std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { + log::error!( + "could not create checkout dir '{}': {e}", + checkout_dir.display() + ); + panic!("could not create checkout dir"); + }); + + checkout_dir + } + + pub fn ensure_version_channel_compatibility(&self) { + for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { + if version.starts_with(&self.dep) && channel != &self.channel { + panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); + } + } + } + + /// Use `rustup` to install the toolchain and components, if not already installed. + /// + /// Pretty much runs: + /// + /// * rustup toolchain add nightly-2024-04-24 + /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools + pub fn ensure_toolchain_and_components_exist(&self) { + // Check for the required toolchain + let output = std::process::Command::new("rustup") + .args(["toolchain", "list"]) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not list installed toolchains" + ); + let stdout = String::from_utf8_lossy(&output.stdout); + if stdout + .split_whitespace() + .any(|toolchain| toolchain.starts_with(&self.channel)) + { + log::debug!("toolchain {} is already installed", self.channel); + } else { + let output = std::process::Command::new("rustup") + .args(["toolchain", "add"]) + .arg(&self.channel) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not install required toolchain" + ); + } + + // Check for the required components + let output = std::process::Command::new("rustup") + .args(["component", "list", "--toolchain"]) + .arg(&self.channel) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not list installed components" + ); + let stdout = String::from_utf8_lossy(&output.stdout); + let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; + let installed_components = stdout.lines().collect::>(); + let all_components_installed = required_components.iter().all(|component| { + installed_components.iter().any(|installed_component| { + let is_component = installed_component.starts_with(component); + let is_installed = installed_component.ends_with("(installed)"); + is_component && is_installed + }) + }); + if all_components_installed { + log::debug!("all required components are installed"); + } else { + let output = std::process::Command::new("rustup") + .args(["component", "add", "--toolchain"]) + .arg(&self.channel) + .args(["rust-src", "rustc-dev", "llvm-tools"]) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .unwrap(); + assert!( + output.status.success(), + "could not install required components" + ); + } + } +} diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs new file mode 100644 index 0000000000..bf3785f151 --- /dev/null +++ b/crates/cargo-gpu/src/toml.rs @@ -0,0 +1,141 @@ +use clap::Parser; + +use crate::{Cli, Command}; + +#[derive(Parser)] +pub(crate) struct Toml { + /// Path to a workspace or package Cargo.toml file. + /// + /// Must include a [[workspace | package].metadata.rust-gpu.build] section where + /// arguments to `cargo gpu build` are listed. + /// + /// Path arguments like `output-dir` and `shader-manifest` must be relative to + /// the location of the Cargo.toml file. + /// + /// Example: + /// + /// ```toml + /// [package.metadata.rust-gpu.build.spirv-builder] + /// git = "https://github.com/Rust-GPU/rust-gpu.git" + /// rev = "0da80f8" + /// + /// [package.metadata.rust-gpu.build] + /// output-dir = "shaders" + /// shader-manifest = "shaders/manifest.json" + /// ``` + /// + /// Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that + /// contains the example above would compile the crate and place the compiled + /// `.spv` files and manifest in a directory "shaders". + #[clap(default_value = "./Cargo.toml", verbatim_doc_comment)] + path: std::path::PathBuf, +} + +impl Toml { + pub fn run(&self) { + // Find the path to the toml file to use + let path = if self.path.is_file() && self.path.ends_with(".toml") { + self.path.clone() + } else { + let path = self.path.join("Cargo.toml"); + if path.is_file() { + path + } else { + log::error!("toml file '{}' is not a file", self.path.display()); + panic!("toml file '{}' is not a file", self.path.display()); + } + }; + + log::info!("using toml file '{}'", path.display()); + + // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml + let contents = std::fs::read_to_string(&path).unwrap(); + let toml: toml::Table = toml::from_str(&contents).unwrap(); + + fn get_metadata_rustgpu_table<'a>( + toml: &'a toml::Table, + toml_type: &'static str, + ) -> Option<&'a toml::Table> { + let workspace = toml.get(toml_type)?.as_table()?; + let metadata = workspace.get("metadata")?.as_table()?; + metadata.get("rust-gpu")?.as_table() + } + + let (toml_type, table) = if toml.contains_key("workspace") { + let table = get_metadata_rustgpu_table(&toml, "workspace") + .unwrap_or_else(|| { + panic!( + "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", + path.display() + ); + }) + .clone(); + ("workspace", table) + } else if toml.contains_key("package") { + let mut table = get_metadata_rustgpu_table(&toml, "package") + .unwrap_or_else(|| { + panic!( + "toml file '{}' is missing a [package.metadata.rust-gpu] table", + path.display() + ); + }) + .clone(); + // Ensure the package name is included as the shader-crate parameter + if !table.contains_key("shader-crate") { + table.insert( + "shader-crate".to_string(), + format!("{}", path.parent().unwrap().display()).into(), + ); + } + ("package", table) + } else { + panic!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); + }; + log::info!( + "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", + path.display() + ); + log::debug!("table: {table:#?}"); + + let mut parameters = table + .get("build") + .unwrap_or_else(|| panic!("toml is missing the 'build' table")) + .as_table() + .unwrap_or_else(|| { + panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") + }) + .into_iter() + .flat_map(|(k, v)| match v { + toml::Value::String(s) => [format!("--{k}"), s.clone()], + _ => { + let mut value = String::new(); + let ser = toml::ser::ValueSerializer::new(&mut value); + serde::Serialize::serialize(v, ser).unwrap(); + [format!("--{k}"), value] + } + }) + .collect::>(); + parameters.insert(0, "cargo-gpu".to_string()); + parameters.insert(1, "build".to_string()); + + let working_directory = path.parent().unwrap(); + log::info!( + "issuing cargo commands from the working directory '{}'", + working_directory.display() + ); + std::env::set_current_dir(working_directory).unwrap(); + + log::debug!("build parameters: {parameters:#?}"); + if let Cli { + command: Command::Build(mut build), + .. + } = Cli::parse_from(parameters) + { + log::debug!("build: {build:?}"); + build.run(); + } else { + log::error!("parameters found in [{toml_type}.metadata.rust-gpu.build] were not parameters to `cargo gpu build`"); + panic!("could not determin build command"); + } + } +} From 708fefc36e4031f4dc371f9ee000aeaf43af93f6 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 14 Dec 2024 23:56:56 +0100 Subject: [PATCH 045/162] Add stricter lints and make them happy --- .github/workflows/push.yaml | 12 +++---- Cargo.toml | 31 ++++++++++++++++- crates/cargo-gpu/Cargo.toml | 6 +++- crates/cargo-gpu/src/builder.rs | 23 ++++++++----- crates/cargo-gpu/src/install.rs | 51 +++++++++++++++++---------- crates/cargo-gpu/src/main.rs | 49 ++++++++++++++------------ crates/cargo-gpu/src/show.rs | 6 +++- crates/cargo-gpu/src/spirv.rs | 61 ++++++++++++++++++++++----------- crates/cargo-gpu/src/toml.rs | 47 +++++++++++++------------ 9 files changed, 186 insertions(+), 100 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 62f638e585..6d561da560 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -1,8 +1,8 @@ name: push -on: +on: push: - branches: + branches: - main pull_request: @@ -13,18 +13,18 @@ env: jobs: install-and-build-shaders: strategy: - matrix: + matrix: os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} defaults: - run: + run: shell: bash - env: + env: RUST_LOG: debug steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 - - run: rustup default stable + - run: rustup default stable - run: rustup update - run: cargo test - run: cargo install --path crates/cargo-gpu diff --git a/Cargo.toml b/Cargo.toml index 7272a77012..9dd7fcb53e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ - "crates/cargo-gpu", + "crates/cargo-gpu", "crates/shader-crate-template" ] @@ -21,3 +21,32 @@ relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" toml = "0.8.19" + +[workspace.lints.rust] +missing_docs = "warn" + +[workspace.lints.clippy] +all = { level = "warn", priority = 0 } +pedantic = { level = "warn", priority = 0 } +nursery = { level = "warn", priority = 0 } +cargo = { level = "warn", priority = 0 } +restriction = { level = "warn", priority = 0 } +blanket_clippy_restriction_lints = { level = "allow", priority = 1 } + +arithmetic_side_effects = { level = "allow", priority = 1 } +absolute_paths = { level = "allow", priority = 1 } +cargo_common_metadata = { level = "allow", priority = 1 } +implicit_return = { level = "allow", priority = 1 } +single_call_fn = { level = "allow", priority = 1 } +question_mark_used = { level = "allow", priority = 1 } +multiple_crate_versions = { level = "allow", priority = 1 } +pub_with_shorthand = { level = "allow", priority = 1 } +partial_pub_fields = { level = "allow", priority = 1 } +pattern_type_mismatch = { level = "allow", priority = 1 } +print_stdout = { level = "allow", priority = 1 } +std_instead_of_alloc = { level = "allow", priority = 1 } + +# TODO: Try to not depend on these lints +unwrap_used = { level = "allow", priority = 1 } +panic = { level = "allow", priority = 1 } + diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 0bdd10f174..0935ad998f 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -3,8 +3,9 @@ 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" readme = "../../README.md" - +keywords = ["gpu", "compiler"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -33,3 +34,6 @@ codegen-units = 256 opt-level = 3 incremental = true codegen-units = 256 + +[lints] +workspace = true diff --git a/crates/cargo-gpu/src/builder.rs b/crates/cargo-gpu/src/builder.rs index f92965ca38..665dd202b9 100644 --- a/crates/cargo-gpu/src/builder.rs +++ b/crates/cargo-gpu/src/builder.rs @@ -1,12 +1,16 @@ -use std::io::Write; +//! `cargo gpu build`, analogous to `cargo build` + +use std::io::Write as _; use clap::Parser; use spirv_builder_cli::{Linkage, ShaderModule}; use crate::{install::Install, target_spec_dir}; +/// `cargo build` subcommands #[derive(Parser, Debug)] -pub(crate) struct Build { +pub struct Build { + /// Install the `rust-gpu` compiler and components #[clap(flatten)] install: Install, @@ -32,6 +36,7 @@ pub(crate) struct Build { } impl Build { + /// Entrypoint pub fn run(&mut self) { let (dylib_path, spirv_builder_cli_path) = self.install.run(); @@ -93,7 +98,7 @@ impl Build { entry, path: filepath, }| { - use relative_path::PathExt; + use relative_path::PathExt as _; let path = self.output_dir.join(filepath.file_name().unwrap()); std::fs::copy(&filepath, &path).unwrap(); let path_relative_to_shader_crate = @@ -109,19 +114,19 @@ impl Build { linkage.sort(); // UNWRAP: safe because we know this always serializes let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|e| { + let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|error| { log::error!( - "could not create shader manifest file '{}': {e}", + "could not create shader manifest file '{}': {error}", manifest_path.display(), ); - panic!("{e}") + panic!("{error}") }); - file.write_all(json.as_bytes()).unwrap_or_else(|e| { + file.write_all(json.as_bytes()).unwrap_or_else(|error| { log::error!( - "could not write shader manifest file '{}': {e}", + "could not write shader manifest file '{}': {error}", manifest_path.display(), ); - panic!("{e}") + panic!("{error}") }); log::info!("wrote manifest to '{}'", manifest_path.display()); diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index e884bc5012..0e31f2b025 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,16 +1,25 @@ -use std::io::Write; +//! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. +use std::io::Write as _; use crate::{cache_dir, spirv::Spirv, target_spec_dir}; -const SPIRV_BUILDER_CLI_CARGO_TOML: &str = include_str!("../../spirv-builder-cli/Cargo.toml"); -const SPIRV_BUILDER_CLI_MAIN: &str = include_str!("../../spirv-builder-cli/src/main.rs"); -const SPIRV_BUILDER_CLI_LIB: &str = include_str!("../../spirv-builder-cli/src/lib.rs"); +/// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ - ("Cargo.toml", SPIRV_BUILDER_CLI_CARGO_TOML), - ("src/main.rs", SPIRV_BUILDER_CLI_MAIN), - ("src/lib.rs", SPIRV_BUILDER_CLI_LIB), + ( + "Cargo.toml", + include_str!("../../spirv-builder-cli/Cargo.toml"), + ), + ( + "src/main.rs", + include_str!("../../spirv-builder-cli/src/main.rs"), + ), + ( + "src/lib.rs", + include_str!("../../spirv-builder-cli/src/lib.rs"), + ), ]; +/// Metadata for the compile targets supported by `rust-gpu` const TARGET_SPECS: &[(&str, &str)] = &[ ( "spirv-unknown-opengl4.0.json", @@ -74,15 +83,16 @@ const TARGET_SPECS: &[(&str, &str)] = &[ ), ]; +/// `cargo gpu install` #[derive(clap::Parser, Debug)] -pub(crate) struct Install { +pub struct Install { /// spirv-builder dependency, written just like in a Cargo.toml file. #[clap(long, default_value = Spirv::DEFAULT_DEP)] spirv_builder: String, /// Rust toolchain channel to use to build `spirv-builder`. /// - /// This must match the `spirv_builder` argument. + /// This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. #[clap(long, default_value = Spirv::DEFAULT_CHANNEL)] rust_toolchain: String, @@ -92,6 +102,7 @@ pub(crate) struct Install { } impl Install { + /// Returns a [`Spirv`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. fn spirv_cli(&self) -> Spirv { Spirv { dep: self.spirv_builder.clone(), @@ -99,11 +110,12 @@ impl Install { } } + /// Create the `spirv-builder-cli` crate. fn write_source_files(&self) { let cli = self.spirv_cli(); let checkout = cli.cached_checkout_path(); std::fs::create_dir_all(checkout.join("src")).unwrap(); - for (filename, contents) in SPIRV_BUILDER_FILES.iter() { + for (filename, contents) in SPIRV_BUILDER_FILES { log::debug!("writing {filename}"); let path = checkout.join(filename); let mut file = std::fs::File::create(&path).unwrap(); @@ -114,8 +126,9 @@ impl Install { } } + /// Add the target spec files to the crate. fn write_target_spec_files(&self) { - for (filename, contents) in TARGET_SPECS.iter() { + for (filename, contents) in TARGET_SPECS { let path = target_spec_dir().join(filename); if !path.is_file() || self.force_spirv_cli_rebuild { let mut file = std::fs::File::create(&path).unwrap(); @@ -124,14 +137,14 @@ impl Install { } } - // Install the binary pair and return the paths, (dylib, cli). + /// Install the binary pair and return the paths, (dylib, cli). pub fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { // Ensure the cache dir exists let cache_dir = cache_dir(); log::info!("cache directory is '{}'", cache_dir.display()); - std::fs::create_dir_all(&cache_dir).unwrap_or_else(|e| { + std::fs::create_dir_all(&cache_dir).unwrap_or_else(|error| { log::error!( - "could not create cache directory '{}': {e}", + "could not create cache directory '{}': {error}", cache_dir.display() ); panic!("could not create cache dir"); @@ -178,7 +191,7 @@ impl Install { command.args([ "--features", - &Self::get_required_spirv_builder_version(spirv_version.channel), + &Self::get_required_spirv_builder_version(&spirv_version.channel), ]); log::debug!("building artifacts with `{:?}`", command); @@ -209,8 +222,8 @@ impl Install { } else { log::error!("could not find {}", cli_path.display()); log::debug!("contents of '{}':", release.display()); - for entry in std::fs::read_dir(&release).unwrap() { - let entry = entry.unwrap(); + for maybe_entry in std::fs::read_dir(&release).unwrap() { + let entry = maybe_entry.unwrap(); log::debug!("{}", entry.file_name().to_string_lossy()); } panic!("spirv-builder-cli build failed"); @@ -228,9 +241,9 @@ impl Install { /// `spirv-builder` version from there. /// * Warn the user that certain `cargo-gpu` features aren't available when building with /// older versions of `spirv-builder`, eg setting the target spec. - fn get_required_spirv_builder_version(toolchain_channel: String) -> String { + fn get_required_spirv_builder_version(toolchain_channel: &str) -> String { let parse_date = chrono::NaiveDate::parse_from_str; - let datetime = parse_date(&toolchain_channel, "nightly-%Y-%m-%d").unwrap(); + let datetime = parse_date(toolchain_channel, "nightly-%Y-%m-%d").unwrap(); let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); if datetime < pre_cli_date { diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 575dd4160c..3390012d3e 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -51,7 +51,7 @@ //! for example. use builder::Build; -use clap::Parser; +use clap::Parser as _; use install::Install; use show::Show; use toml::Toml; @@ -62,20 +62,14 @@ mod show; mod spirv; mod toml; -fn target_spec_dir() -> std::path::PathBuf { - let dir = cache_dir().join("target-specs"); - std::fs::create_dir_all(&dir).unwrap(); - dir -} - fn main() { env_logger::builder().init(); let args = std::env::args() - .filter(|p| { + .filter(|arg| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" // as the first parameter, which we want to ignore. - p != "gpu" + arg != "gpu" }) .collect::>(); log::trace!("args: {args:?}"); @@ -83,7 +77,7 @@ fn main() { match cli.command { Command::Install(install) => { - let _ = install.run(); + let (_, _) = install.run(); } Command::Build(mut build) => build.run(), Command::Toml(toml) => toml.run(), @@ -92,6 +86,7 @@ fn main() { } } +/// All of the available subcommands for `cargo gpu` #[derive(clap::Subcommand)] enum Command { /// Install rust-gpu compiler artifacts. @@ -132,35 +127,46 @@ fn cache_dir() -> std::path::PathBuf { .join("rust-gpu") } +/// Location of the target spec metadata files +fn target_spec_dir() -> std::path::PathBuf { + let dir = cache_dir().join("target-specs"); + std::fs::create_dir_all(&dir).unwrap(); + dir +} + +/// Convenience function for internal use. Dumps all the CLI usage instructions. Useful for +/// updating the README. fn dump_full_usage_for_readme() { - use clap::CommandFactory; + use clap::CommandFactory as _; let mut command = Cli::command(); - let mut buffer: Vec = Default::default(); + let mut buffer: Vec = Vec::default(); command.build(); write_help(&mut buffer, &mut command, 0); - let buffer = String::from_utf8(buffer).unwrap(); - println!("{}", buffer); + println!("{}", String::from_utf8(buffer).unwrap()); } +/// Recursive function to print the usage instructions for each subcommand. fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: usize) { if cmd.get_name() == "help" { return; } - let mut command = cmd.get_name().to_string(); - let _ = writeln!( + let mut command = cmd.get_name().to_owned(); + writeln!( buffer, "\n* {}{}", command.remove(0).to_uppercase(), command - ); - let _ = writeln!(buffer); - let _ = cmd.write_long_help(buffer); + ) + .unwrap(); + writeln!(buffer).unwrap(); + cmd.write_long_help(buffer).unwrap(); for sub in cmd.get_subcommands_mut() { - let _ = writeln!(buffer); + writeln!(buffer).unwrap(); + #[expect(clippy::used_underscore_binding, reason = "Used in recursion only")] write_help(buffer, sub, _depth + 1); } } @@ -180,7 +186,7 @@ mod test { .file_name() .unwrap() .to_str() - .map(|s| s.to_string()) + .map(std::string::ToString::to_string) .unwrap(); assert_eq!( "git_https___github_com_Rust-GPU_rust-gpu_git+nightly-2024-04-24", @@ -202,7 +208,6 @@ mod test { ]; if let Cli { command: Command::Build(build), - .. } = Cli::parse_from(args) { assert_eq!(shader_crate, build.shader_crate); diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 1dd727e384..24d56320e6 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -1,13 +1,17 @@ +//! Display various information about `cargo gpu`, eg its cache directory. + use crate::cache_dir; +/// `cargo gpu show` #[derive(clap::Parser)] -pub(crate) struct Show { +pub struct Show { #[clap(long)] /// Displays the location of the cache directory cache_directory: bool, } impl Show { + /// Entrypoint pub fn run(self) { if self.cache_directory { log::info!("cache_directory: "); diff --git a/crates/cargo-gpu/src/spirv.rs b/crates/cargo-gpu/src/spirv.rs index 6ab58da39a..4c114b0582 100644 --- a/crates/cargo-gpu/src/spirv.rs +++ b/crates/cargo-gpu/src/spirv.rs @@ -1,11 +1,19 @@ +//! Install the relevant Rust compiler and toolchain components required by the version of +//! `rust-gpu` defined in the shader. use crate::cache_dir; +/// The canonical pairs of `rust-gpu` version to `rust-gpu` Rust toolchain channel. +/// +/// TODO: We may be able to automate this by checking out the locked version of `spirv-std` in the +/// shader's crate. const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; /// Cargo dependency for `spirv-builder` and the rust toolchain channel. #[derive(Debug, Clone)] -pub(crate) struct Spirv { +pub struct Spirv { + /// The version of `rust-gpu`, eg `"0.10"` or `"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }` pub dep: String, + //// The toolchain that `rust-gpu` uses, eg "nightly-2024-04-24" pub channel: String, } @@ -19,13 +27,19 @@ impl Default for Spirv { } impl core::fmt::Display for Spirv { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + #[expect( + clippy::min_ident_chars, + reason = "It's a core library trait implementation" + )] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { format!("{}+{}", self.dep, self.channel).fmt(f) } } impl Spirv { + /// The default `rust-gpu` dependency defintion pub const DEFAULT_DEP: &str = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"#; + /// The default `rust-gpu` toolchain pub const DEFAULT_CHANNEL: &str = "nightly-2024-04-24"; /// Returns a string suitable to use as a directory. @@ -42,11 +56,12 @@ impl Spirv { .concat() } + /// Create and/or return the cache directory pub fn cached_checkout_path(&self) -> std::path::PathBuf { let checkout_dir = cache_dir().join(self.to_dirname()); - std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|e| { + std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|error| { log::error!( - "could not create checkout dir '{}': {e}", + "could not create checkout dir '{}': {error}", checkout_dir.display() ); panic!("could not create checkout dir"); @@ -55,11 +70,17 @@ impl Spirv { checkout_dir } + /// Ensure that the requested `rust-gpu` version/toolchain are known to be canonically + /// compatible. + /// + /// TODO: We may be able to automatically get the pair by downloading the `rust-gpu` repo as defined by the + /// `spriv-std` dependency in the shader. pub fn ensure_version_channel_compatibility(&self) { - for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS.iter() { - if version.starts_with(&self.dep) && channel != &self.channel { - panic!("expected spirv-std version to be matched with rust toolchain channel {channel}"); - } + for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS { + assert!( + !(version.starts_with(&self.dep) && channel != &self.channel), + "expected spirv-std version to be matched with rust toolchain channel {channel}" + ); } } @@ -71,22 +92,22 @@ impl Spirv { /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools pub fn ensure_toolchain_and_components_exist(&self) { // Check for the required toolchain - let output = std::process::Command::new("rustup") + let output_toolchain_list = std::process::Command::new("rustup") .args(["toolchain", "list"]) .output() .unwrap(); assert!( - output.status.success(), + output_toolchain_list.status.success(), "could not list installed toolchains" ); - let stdout = String::from_utf8_lossy(&output.stdout); - if stdout + let string_toolchain_list = String::from_utf8_lossy(&output_toolchain_list.stdout); + if string_toolchain_list .split_whitespace() .any(|toolchain| toolchain.starts_with(&self.channel)) { log::debug!("toolchain {} is already installed", self.channel); } else { - let output = std::process::Command::new("rustup") + let output_toolchain_add = std::process::Command::new("rustup") .args(["toolchain", "add"]) .arg(&self.channel) .stdout(std::process::Stdio::inherit()) @@ -94,24 +115,24 @@ impl Spirv { .output() .unwrap(); assert!( - output.status.success(), + output_toolchain_add.status.success(), "could not install required toolchain" ); } // Check for the required components - let output = std::process::Command::new("rustup") + let output_component_list = std::process::Command::new("rustup") .args(["component", "list", "--toolchain"]) .arg(&self.channel) .output() .unwrap(); assert!( - output.status.success(), + output_component_list.status.success(), "could not list installed components" ); - let stdout = String::from_utf8_lossy(&output.stdout); + let string_component_list = String::from_utf8_lossy(&output_component_list.stdout); let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; - let installed_components = stdout.lines().collect::>(); + let installed_components = string_component_list.lines().collect::>(); let all_components_installed = required_components.iter().all(|component| { installed_components.iter().any(|installed_component| { let is_component = installed_component.starts_with(component); @@ -122,7 +143,7 @@ impl Spirv { if all_components_installed { log::debug!("all required components are installed"); } else { - let output = std::process::Command::new("rustup") + let output_component_add = std::process::Command::new("rustup") .args(["component", "add", "--toolchain"]) .arg(&self.channel) .args(["rust-src", "rustc-dev", "llvm-tools"]) @@ -131,7 +152,7 @@ impl Spirv { .output() .unwrap(); assert!( - output.status.success(), + output_component_add.status.success(), "could not install required components" ); } diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index bf3785f151..ab360ef555 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -1,9 +1,12 @@ +//! Build a shader based on the data in the `[package.metadata.rust-gpu.build.spirv-builder]` section of +//! a shader's `Cargo.toml`. use clap::Parser; use crate::{Cli, Command}; +/// `cargo gpu toml` #[derive(Parser)] -pub(crate) struct Toml { +pub struct Toml { /// Path to a workspace or package Cargo.toml file. /// /// Must include a [[workspace | package].metadata.rust-gpu.build] section where @@ -32,6 +35,7 @@ pub(crate) struct Toml { } impl Toml { + /// Entrypoint pub fn run(&self) { // Find the path to the toml file to use let path = if self.path.is_file() && self.path.ends_with(".toml") { @@ -52,17 +56,8 @@ impl Toml { let contents = std::fs::read_to_string(&path).unwrap(); let toml: toml::Table = toml::from_str(&contents).unwrap(); - fn get_metadata_rustgpu_table<'a>( - toml: &'a toml::Table, - toml_type: &'static str, - ) -> Option<&'a toml::Table> { - let workspace = toml.get(toml_type)?.as_table()?; - let metadata = workspace.get("metadata")?.as_table()?; - metadata.get("rust-gpu")?.as_table() - } - let (toml_type, table) = if toml.contains_key("workspace") { - let table = get_metadata_rustgpu_table(&toml, "workspace") + let table = Self::get_metadata_rustgpu_table(&toml, "workspace") .unwrap_or_else(|| { panic!( "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", @@ -72,7 +67,7 @@ impl Toml { .clone(); ("workspace", table) } else if toml.contains_key("package") { - let mut table = get_metadata_rustgpu_table(&toml, "package") + let mut table = Self::get_metadata_rustgpu_table(&toml, "package") .unwrap_or_else(|| { panic!( "toml file '{}' is missing a [package.metadata.rust-gpu] table", @@ -83,7 +78,7 @@ impl Toml { // Ensure the package name is included as the shader-crate parameter if !table.contains_key("shader-crate") { table.insert( - "shader-crate".to_string(), + "shader-crate".to_owned(), format!("{}", path.parent().unwrap().display()).into(), ); } @@ -105,18 +100,19 @@ impl Toml { panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") }) .into_iter() - .flat_map(|(k, v)| match v { - toml::Value::String(s) => [format!("--{k}"), s.clone()], - _ => { + .flat_map(|(key, val)| { + if let toml::Value::String(string) = val { + [format!("--{key}"), string.clone()] + } else { let mut value = String::new(); let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(v, ser).unwrap(); - [format!("--{k}"), value] + serde::Serialize::serialize(val, ser).unwrap(); + [format!("--{key}"), value] } }) .collect::>(); - parameters.insert(0, "cargo-gpu".to_string()); - parameters.insert(1, "build".to_string()); + parameters.insert(0, "cargo-gpu".to_owned()); + parameters.insert(1, "build".to_owned()); let working_directory = path.parent().unwrap(); log::info!( @@ -128,7 +124,6 @@ impl Toml { log::debug!("build parameters: {parameters:#?}"); if let Cli { command: Command::Build(mut build), - .. } = Cli::parse_from(parameters) { log::debug!("build: {build:?}"); @@ -138,4 +133,14 @@ impl Toml { panic!("could not determin build command"); } } + + /// Parse the `[package.metadata.rust-gpu]` section. + fn get_metadata_rustgpu_table<'toml>( + toml: &'toml toml::Table, + toml_type: &'static str, + ) -> Option<&'toml toml::Table> { + let workspace = toml.get(toml_type)?.as_table()?; + let metadata = workspace.get("metadata")?.as_table()?; + metadata.get("rust-gpu")?.as_table() + } } From 95f248a82c6f1acd17ff57c8ab11699b716a64da Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 15 Dec 2024 13:43:58 +0100 Subject: [PATCH 046/162] Add actual shader compile to smoke tests --- .gitignore | 3 +++ crates/cargo-gpu/src/main.rs | 8 +++++++- crates/shader-crate-template/src/lib.rs | 3 +-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 99d4b406dd..738d6d1fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ test_output cmy_triangle_renderer.svg .aider* flamegraph.svg + +# Compiled shader assets from running tests +crates/shader-crate-template/shaders diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 3390012d3e..a3d9c86403 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -207,11 +207,17 @@ mod test { &format!("{}", output_dir.display()), ]; if let Cli { - command: Command::Build(build), + command: Command::Build(mut build), } = Cli::parse_from(args) { assert_eq!(shader_crate, build.shader_crate); assert_eq!(output_dir, build.output_dir); + + // TODO: + // What's the best way to reset caches for this? For example we could add a + // `--force-spirv-cli-rebuild`, but that would slow down each test. But without + // something like that we might not be getting actual idempotent tests. + build.run(); } else { panic!("was not a build command"); } diff --git a/crates/shader-crate-template/src/lib.rs b/crates/shader-crate-template/src/lib.rs index e98f03de2e..e12c0ff2bb 100644 --- a/crates/shader-crate-template/src/lib.rs +++ b/crates/shader-crate-template/src/lib.rs @@ -1,7 +1,6 @@ //! Shader entry points. //! -//! Contains an example vertex shader, fragment shader and one example compute -//! shader. +//! Contains an example vertex shader, fragment shader. #![no_std] use glam::{Vec2, Vec4}; use spirv_std::spirv; From f0fc1ea6f0fdbdb3d14daaf77aff8e98cb7ea888 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 15 Dec 2024 22:10:59 +0100 Subject: [PATCH 047/162] Rebase into: Refactor each subcommand to its own file --- crates/cargo-gpu/src/{builder.rs => build.rs} | 0 crates/cargo-gpu/src/main.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename crates/cargo-gpu/src/{builder.rs => build.rs} (100%) diff --git a/crates/cargo-gpu/src/builder.rs b/crates/cargo-gpu/src/build.rs similarity index 100% rename from crates/cargo-gpu/src/builder.rs rename to crates/cargo-gpu/src/build.rs diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index a3d9c86403..cb14ee63d8 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -50,13 +50,13 @@ //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. -use builder::Build; +use build::Build; use clap::Parser as _; use install::Install; use show::Show; use toml::Toml; -mod builder; +mod build; mod install; mod show; mod spirv; From 87de5da3c7fe9da3036a094bc08409b553cc66da Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Tue, 17 Dec 2024 13:11:46 +0100 Subject: [PATCH 048/162] Rename Spirv to SpirvCLI --- crates/cargo-gpu/src/install.rs | 2 +- crates/cargo-gpu/src/main.rs | 6 +++--- crates/cargo-gpu/src/{spirv.rs => spirv_cli.rs} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename crates/cargo-gpu/src/{spirv.rs => spirv_cli.rs} (100%) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 0e31f2b025..68d4f4c90d 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,7 +1,7 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. use std::io::Write as _; -use crate::{cache_dir, spirv::Spirv, target_spec_dir}; +use crate::{cache_dir, spirv_cli::Spirv, target_spec_dir}; /// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index cb14ee63d8..542b8475cb 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -59,7 +59,7 @@ use toml::Toml; mod build; mod install; mod show; -mod spirv; +mod spirv_cli; mod toml; fn main() { @@ -173,14 +173,14 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: #[cfg(test)] mod test { - use spirv::Spirv; + use spirv_cli::Spirv as SpirvCLI; use super::*; #[test] fn cached_checkout_dir_sanity() { // Test that - let spirv = Spirv::default(); + let spirv = SpirvCLI::default(); let dir = spirv.cached_checkout_path(); let name = dir .file_name() diff --git a/crates/cargo-gpu/src/spirv.rs b/crates/cargo-gpu/src/spirv_cli.rs similarity index 100% rename from crates/cargo-gpu/src/spirv.rs rename to crates/cargo-gpu/src/spirv_cli.rs From 79cb0def6f244fd2912b7041d44a54c0323419ae Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Tue, 17 Dec 2024 21:17:28 +0100 Subject: [PATCH 049/162] Use shader's Cargo.toml for rust-gpu version/toolchain We can still override the version and toolchain with CLI args. This commit just changes the defaults. I feel like there could be a lot of edge cases for this implementation. So I consider it more of a first draft. Notable changes: * `Spirv` renamed to `SpirvCli`. * New `impl SpirvSource` that does all the shader crate querying. * CLI args change: `--spirv-builder` is now split into `--spirv-builder-source` and `--spirv-builder-version`. * `--shader-crate` now lives on the `install` subcommand, which because it is inherited by `build` (where it was originally), means it doesn't make much of a difference. * The full build test now has a teardown function making it idempotent. * Cache folder structure now has sub folders for `spirv-builder-cli`'s and `rust-gpu` repos. * `spirv-crate-template` is updated to Git with revision `82a0f69` because "0.9" doesn't seem to compile on Windows. Things to consider: * Can we remove `TARGET_SPECS` now, because we have a copy of the `rust-gpu` repo, we can get them from there instead? * What's the UX expectations for changing `spirv-std` versions or overriding `rust-gpu` versions and toolchain? I think in most cases `spirv-builder-cli` rebuilds should occur because the changes will cause cache directory changes. But I think it'd be good to at least manually test this. * Should the main build test be moved out into an integrations tests folder? * I'd still like to test each `spirv-builder-cli` feature, ie: `spirv-builder-pre-cli` and `spirv-builder-0_10`. We're currently only testing `spirv-builder-pre-cli`. --- .github/workflows/push.yaml | 19 +- Cargo.lock | 320 +++++++++++++++++------- Cargo.toml | 13 +- README.md | 89 +++++-- crates/cargo-gpu/Cargo.toml | 4 + crates/cargo-gpu/src/build.rs | 55 +++- crates/cargo-gpu/src/install.rs | 94 +++++-- crates/cargo-gpu/src/main.rs | 81 +++--- crates/cargo-gpu/src/spirv_cli.rs | 124 +++++---- crates/cargo-gpu/src/spirv_source.rs | 304 ++++++++++++++++++++++ crates/cargo-gpu/src/toml.rs | 41 +-- crates/shader-crate-template/Cargo.lock | 40 ++- crates/shader-crate-template/Cargo.toml | 7 +- crates/spirv-builder-cli/Cargo.toml | 33 ++- crates/spirv-builder-cli/src/main.rs | 1 + 15 files changed, 905 insertions(+), 320 deletions(-) create mode 100644 crates/cargo-gpu/src/spirv_source.rs diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 6d561da560..4eb468e37b 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -13,8 +13,12 @@ env: jobs: install-and-build-shaders: strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: + - ubuntu-latest + - macos-latest + - windows-latest runs-on: ${{ matrix.os }} defaults: run: @@ -24,18 +28,15 @@ jobs: steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 - - run: rustup default stable - - run: rustup update + - name: Install Rust toolchain + run: | + rustup default stable + rustup update - run: cargo test - - run: cargo install --path crates/cargo-gpu - - run: cargo gpu install - - run: cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders - - run: ls -lah test-shaders - - run: cat test-shaders/manifest.json clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 - - run: cargo clippy + - run: cargo clippy -- --deny warnings diff --git a/Cargo.lock b/Cargo.lock index e27864fb9e..88ba813167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -68,15 +68,15 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] -name = "bitflags" -version = "2.6.0" +name = "bytes" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cargo-gpu" @@ -85,12 +85,14 @@ dependencies = [ "chrono", "clap", "directories", - "env_logger", + "env_logger 0.10.2", + "http", "log", "relative-path", "serde", "serde_json", "spirv-builder-cli", + "test-log", "toml", ] @@ -140,7 +142,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn", ] [[package]] @@ -176,6 +178,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", +] + [[package]] name = "env_home" version = "0.1.0" @@ -195,12 +206,30 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "getrandom" version = "0.2.15" @@ -212,24 +241,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "glam" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" -dependencies = [ - "libm", -] - -[[package]] -name = "glam" -version = "0.29.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" -dependencies = [ - "libm", -] - [[package]] name = "hashbrown" version = "0.15.1" @@ -248,6 +259,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "humantime" version = "2.1.0" @@ -288,16 +310,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "libc" -version = "0.2.161" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "libm" -version = "0.2.11" +name = "libc" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libredox" @@ -305,7 +327,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags", "libc", ] @@ -315,12 +337,31 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -328,15 +369,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + [[package]] name = "proc-macro2" version = "1.0.89" @@ -374,8 +432,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -386,9 +453,15 @@ checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.5", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.5" @@ -401,14 +474,6 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" -[[package]] -name = "rust-gpu-shader-crate-template" -version = "0.1.0" -dependencies = [ - "glam 0.29.2", - "spirv-std", -] - [[package]] name = "ryu" version = "1.0.18" @@ -432,7 +497,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn", ] [[package]] @@ -456,66 +521,33 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "spirv-builder-cli" version = "0.1.0" dependencies = [ "env_home", - "env_logger", + "env_logger 0.10.2", "log", "serde", "serde_json", "toml", ] -[[package]] -name = "spirv-std" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c3c0972a2df79abe2c8af2fe7f7937a9aa558b6a1f78fc5edf93f4d480d757" -dependencies = [ - "bitflags 1.3.2", - "glam 0.24.2", - "num-traits", - "spirv-std-macros", - "spirv-std-types", -] - -[[package]] -name = "spirv-std-macros" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f776bf9f2897ea7acff15d7753711fdf1693592bd7459a01c394262b1df45c" -dependencies = [ - "proc-macro2", - "quote", - "spirv-std-types", - "syn 1.0.109", -] - -[[package]] -name = "spirv-std-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a73417b7d72d95b4995c840dceb4e3b4bcbad4ff7f35df9c1655b6826c18d3a9" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.87" @@ -536,6 +568,28 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-log" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +dependencies = [ + "env_logger 0.11.5", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "1.0.68" @@ -553,7 +607,17 @@ checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] @@ -590,6 +654,54 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicode-ident" version = "1.0.13" @@ -602,12 +714,34 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -617,6 +751,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 9dd7fcb53e..f8122deef9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,14 @@ [workspace] members = [ "crates/cargo-gpu", - "crates/shader-crate-template" ] exclude = [ - "crates/spirv-builder-cli" + "crates/spirv-builder-cli", + + # 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" ] resolver = "2" @@ -16,11 +19,13 @@ chrono = { version = "0.4.38", default-features = false } directories = "5.0.1" env_home = "0.1.0" env_logger = "0.10" +http = "1.2.0" log = "0.4" relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" toml = "0.8.19" +test-log = "0.2.16" [workspace.lints.rust] missing_docs = "warn" @@ -46,7 +51,9 @@ pattern_type_mismatch = { level = "allow", priority = 1 } print_stdout = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } -# TODO: Try to not depend on these lints +# TODO: Try to not depend on allowing these lints unwrap_used = { level = "allow", priority = 1 } +get_unwrap = { level = "allow", priority = 1 } +expect_used = { level = "allow", priority = 1 } panic = { level = "allow", priority = 1 } diff --git a/README.md b/README.md index 382fdfdc0d..e0a2b1fe87 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ # cargo-gpu + Command line tool for building Rust shaders using rust-gpu. ## Getting Started ### Installation -To install the tool ensure you have `rustup`. Then run: + +To install the tool ensure you have `rustup`. Then run: ``` cargo install --git https://github.com/rust-gpu/cargo-gpu ``` -After that you can use `cargo gpu` to compile your shader crates with: +After that you can use `cargo gpu` to compile your shader crates with: ``` cargo gpu build ``` -This plain invocation will compile the crate in the current directory and +This plain invocation will compile the crate in the current directory and place the compiled shaders in the current directory. Use `cargo gpu help` to see other options :) @@ -33,13 +35,31 @@ cd shader-crate-template cargo gpu build ``` +## How it works + +Behind the scenes `cargo gpu` compiles a custom [codegen backend](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/codegen-backend.html) +for `rustc` that allows emitting [SPIR-V](https://www.khronos.org/spir/) assembly, instead of the conventional LLVM assembly. SPIR-V is a dedicated +graphics language that is aimed to be open and portable so that it works with as many drivers and devices as possible. + +With the custom codegen backend (`rustc_codegen_spirv`) `cargo gpu` then compiles the shader it is pointed to. However, because custom codegen backends +are currently [an unstable feature](https://github.com/rust-lang/rust/issues/77933), `cargo gpu` also needs to install a "nightly" version of Rust. In +the usage instructions the backend and nightly Rust version are referred to as "artefacts" and can be explicitly managed with the arguments to the +`install` subcommand. + +> [!TIP] +> Whilst `cargo gpu` attempts to isolate shader compilation as much possible, if the shader crate is contained in a workspace then it's possible that +> the nightly version required by the shader is, ironically, older than the Rust/Cargo versions required by the workspace. Say for instance the +> workspace might use a newer `Cargo.lock` layout not supported by the pinned version of the shader crate's custom codegen backend. The solution to +> this is to either exclude the shader from the workspace, or upgrade the shader's `spirv-std` dependency to the latest. + ## Usage -``` +```` Commands: install Install rust-gpu compiler artifacts build Compile a shader crate to SPIR-V toml Compile a shader crate according to the `cargo gpu build` parameters found in the given toml file + show Show some useful values help Print this message or the help of the given subcommand(s) Options: @@ -57,17 +77,25 @@ Install rust-gpu compiler artifacts Usage: cargo-gpu install [OPTIONS] Options: - --spirv-builder - spirv-builder dependency, written just like in a Cargo.toml file + --shader-crate + Directory containing the shader crate to compile - [default: "{ git = \"https://github.com/Rust-GPU/rust-gpu.git\" }"] + [default: ./] + + --spirv-builder-source + Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" + + --spirv-builder-version + 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. --rust-toolchain Rust toolchain channel to use to build `spirv-builder`. - This must match the `spirv_builder` argument. - - [default: nightly-2024-04-24] + This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. --force-spirv-cli-rebuild Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt @@ -83,26 +111,29 @@ Compile a shader crate to SPIR-V Usage: cargo-gpu build [OPTIONS] Options: - --spirv-builder - spirv-builder dependency, written just like in a Cargo.toml file + --shader-crate + Directory containing the shader crate to compile + + [default: ./] - [default: "{ git = \"https://github.com/Rust-GPU/rust-gpu.git\" }"] + --spirv-builder-source + Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" + + --spirv-builder-version + 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. --rust-toolchain Rust toolchain channel to use to build `spirv-builder`. - This must match the `spirv_builder` argument. - - [default: nightly-2024-04-24] + This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. --force-spirv-cli-rebuild Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt - --shader-crate - Directory containing the shader crate to compile - - [default: ./] - --shader-target Shader target @@ -161,4 +192,18 @@ Options: -h, --help Print help (see a summary with '-h') -``` + +* Show + +Show some useful values + +Usage: cargo-gpu show [OPTIONS] + +Options: + --cache-directory + Displays the location of the cache directory + + -h, --help + Print help + +```` diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 0935ad998f..e6043d1bcc 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -19,6 +19,10 @@ serde.workspace = true serde_json.workspace = true toml.workspace = true chrono.workspace = true +http.workspace = true + +[dev-dependencies] +test-log.workspace = true # Enable incremental by default in release mode. [profile.release] diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 665dd202b9..d6c90168f2 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -12,11 +12,7 @@ use crate::{install::Install, target_spec_dir}; pub struct Build { /// Install the `rust-gpu` compiler and components #[clap(flatten)] - install: Install, - - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - pub shader_crate: std::path::PathBuf, + pub install: Install, /// Shader target. #[clap(long, default_value = "spirv-unknown-vulkan1.2")] @@ -46,17 +42,17 @@ impl Build { self.output_dir = self.output_dir.canonicalize().unwrap(); // Ensure the shader crate exists - self.shader_crate = self.shader_crate.canonicalize().unwrap(); + self.install.shader_crate = self.install.shader_crate.canonicalize().unwrap(); assert!( - self.shader_crate.exists(), + self.install.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", - self.shader_crate.display(), + self.install.shader_crate.display(), std::env::current_dir().unwrap().display() ); let spirv_builder_args = spirv_builder_cli::Args { dylib_path, - shader_crate: self.shader_crate.clone(), + shader_crate: self.install.shader_crate.clone(), shader_target: self.shader_target.clone(), path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)), no_default_features: self.no_default_features, @@ -101,8 +97,10 @@ impl Build { use relative_path::PathExt as _; let path = self.output_dir.join(filepath.file_name().unwrap()); std::fs::copy(&filepath, &path).unwrap(); - let path_relative_to_shader_crate = - path.relative_to(&self.shader_crate).unwrap().to_path(""); + let path_relative_to_shader_crate = path + .relative_to(&self.install.shader_crate) + .unwrap() + .to_path(""); Linkage::new(entry, path_relative_to_shader_crate) }, ) @@ -140,3 +138,38 @@ impl Build { } } } + +#[cfg(test)] +mod test { + use crate::{Cli, Command}; + + use super::*; + + #[test_log::test] + fn builder_from_params() { + crate::test::tests_teardown(); + + let shader_crate_path = crate::test::shader_crate_template_path(); + let output_dir = shader_crate_path.join("shaders"); + + let args = [ + "target/debug/cargo-gpu", + "build", + "--shader-crate", + &format!("{}", shader_crate_path.display()), + "--output-dir", + &format!("{}", output_dir.display()), + ]; + if let Cli { + command: Command::Build(mut build), + } = Cli::parse_from(args) + { + assert_eq!(shader_crate_path, build.install.shader_crate); + assert_eq!(output_dir, build.output_dir); + + build.run(); + } else { + panic!("was not a build command"); + } + } +} diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 68d4f4c90d..e3d7c0b80f 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,7 +1,7 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. use std::io::Write as _; -use crate::{cache_dir, spirv_cli::Spirv, target_spec_dir}; +use crate::{cache_dir, spirv_cli::SpirvCli, spirv_source::SpirvSource, target_spec_dir}; /// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ @@ -86,15 +86,32 @@ const TARGET_SPECS: &[(&str, &str)] = &[ /// `cargo gpu install` #[derive(clap::Parser, Debug)] pub struct Install { - /// spirv-builder dependency, written just like in a Cargo.toml file. - #[clap(long, default_value = Spirv::DEFAULT_DEP)] - spirv_builder: String, + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, + + #[expect( + clippy::doc_markdown, + reason = "The URL should appear literally like this. But Clippy wants it to be a in markdown clickable link" + )] + /// Source of `spirv-builder` dependency + /// Eg: "https://github.com/Rust-GPU/rust-gpu" + #[clap(long)] + spirv_builder_source: Option, + + /// 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)] + spirv_builder_version: Option, /// Rust toolchain channel to use to build `spirv-builder`. /// /// This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - #[clap(long, default_value = Spirv::DEFAULT_CHANNEL)] - rust_toolchain: String, + #[clap(long)] + rust_toolchain: Option, /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. #[clap(long)] @@ -102,30 +119,61 @@ pub struct Install { } impl Install { - /// Returns a [`Spirv`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. - fn spirv_cli(&self) -> Spirv { - Spirv { - dep: self.spirv_builder.clone(), - channel: self.rust_toolchain.clone(), - } + /// Returns a [`SpirvCLI`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. + fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> SpirvCli { + SpirvCli::new( + shader_crate_path, + self.spirv_builder_source.clone(), + self.spirv_builder_version.clone(), + self.rust_toolchain.clone(), + ) } /// Create the `spirv-builder-cli` crate. fn write_source_files(&self) { - let cli = self.spirv_cli(); - let checkout = cli.cached_checkout_path(); + let spirv_cli = self.spirv_cli(&self.shader_crate); + let checkout = spirv_cli.cached_checkout_path(); std::fs::create_dir_all(checkout.join("src")).unwrap(); for (filename, contents) in SPIRV_BUILDER_FILES { log::debug!("writing {filename}"); let path = checkout.join(filename); let mut file = std::fs::File::create(&path).unwrap(); - let replaced_contents = contents - .replace("${SPIRV_BUILDER_SOURCE}", &cli.dep) - .replace("${CHANNEL}", &cli.channel); + let mut replaced_contents = contents.replace("${CHANNEL}", &spirv_cli.channel); + if filename == &"Cargo.toml" { + replaced_contents = Self::update_cargo_toml(&replaced_contents, &spirv_cli.source); + } file.write_all(replaced_contents.as_bytes()).unwrap(); } } + /// Create the `spirv-builder-cli` crate. + fn update_cargo_toml(contents: &str, spirv_source: &SpirvSource) -> String { + let updated = contents.lines().map(|line| { + if line.contains("${AUTO-REPLACE-SOURCE}") { + let replaced_line = match spirv_source { + SpirvSource::CratesIO(_) => String::new(), + SpirvSource::Git((repo, _)) => format!("git = \"{repo}\""), + SpirvSource::Path((path, _)) => format!("path = \"{path}\""), + }; + return format!("{replaced_line}\n"); + } + + if line.contains("${AUTO-REPLACE-VERSION}") { + let replaced_line = match spirv_source { + SpirvSource::CratesIO(version) | SpirvSource::Path((_, version)) => { + format!("version = \"{}\"", version.replace('v', "")) + } + SpirvSource::Git((_, revision)) => format!("rev = \"{revision}\""), + }; + return format!("{replaced_line}\n"); + } + + format!("{line}\n") + }); + + updated.collect() + } + /// Add the target spec files to the crate. fn write_target_spec_files(&self) { for (filename, contents) in TARGET_SPECS { @@ -150,8 +198,7 @@ impl Install { panic!("could not create cache dir"); }); - let spirv_version = self.spirv_cli(); - spirv_version.ensure_version_channel_compatibility(); + let spirv_version = self.spirv_cli(&self.shader_crate); spirv_version.ensure_toolchain_and_components_exist(); let checkout = spirv_version.cached_checkout_path(); @@ -191,7 +238,7 @@ impl Install { command.args([ "--features", - &Self::get_required_spirv_builder_version(&spirv_version.channel), + &Self::get_required_spirv_builder_version(spirv_version.date), ]); log::debug!("building artifacts with `{:?}`", command); @@ -237,16 +284,13 @@ impl Install { /// here we choose the right Cargo feature to enable/disable code in `spirv-builder-cli`. /// /// TODO: - /// * Download the actual `rust-gpu` repo as pinned in the shader's `Cargo.lock` and get the - /// `spirv-builder` version from there. /// * Warn the user that certain `cargo-gpu` features aren't available when building with /// older versions of `spirv-builder`, eg setting the target spec. - fn get_required_spirv_builder_version(toolchain_channel: &str) -> String { + fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> String { let parse_date = chrono::NaiveDate::parse_from_str; - let datetime = parse_date(toolchain_channel, "nightly-%Y-%m-%d").unwrap(); let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); - if datetime < pre_cli_date { + if date < pre_cli_date { "spirv-builder-pre-cli" } else { "spirv-builder-0_10" diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 542b8475cb..267fd1432a 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -60,6 +60,7 @@ mod build; mod install; mod show; mod spirv_cli; +mod spirv_source; mod toml; fn main() { @@ -118,13 +119,21 @@ pub(crate) struct Cli { } fn cache_dir() -> std::path::PathBuf { - directories::BaseDirs::new() + let dir = directories::BaseDirs::new() .unwrap_or_else(|| { log::error!("could not find the user home directory"); panic!("cache_dir failed"); }) .cache_dir() - .join("rust-gpu") + .join("rust-gpu"); + + if cfg!(test) { + let thread_id = std::thread::current().id(); + let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); + dir.join("tests").join(id) + } else { + dir + } } /// Location of the target spec metadata files @@ -171,55 +180,33 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: } } +/// Returns a string suitable to use as a directory. +/// +/// Created from the spirv-builder source dep and the rustc channel. +fn to_dirname(text: &str) -> String { + text.replace( + [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], + "_", + ) + .split(['{', '}', ' ', '\n', '"', '\'']) + .collect::>() + .concat() +} + #[cfg(test)] mod test { - use spirv_cli::Spirv as SpirvCLI; - - use super::*; - - #[test] - fn cached_checkout_dir_sanity() { - // Test that - let spirv = SpirvCLI::default(); - let dir = spirv.cached_checkout_path(); - let name = dir - .file_name() - .unwrap() - .to_str() - .map(std::string::ToString::to_string) - .unwrap(); - assert_eq!( - "git_https___github_com_Rust-GPU_rust-gpu_git+nightly-2024-04-24", - &name - ); + use crate::cache_dir; + + pub fn shader_crate_template_path() -> std::path::PathBuf { + let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + project_base.join("../shader-crate-template") } - #[test] - fn builder_from_params() { - let shader_crate = std::path::PathBuf::from("../shader-crate-template"); - let output_dir = std::path::PathBuf::from("../shader-crate-template/shaders"); - let args = [ - "target/debug/cargo-gpu", - "build", - "--shader-crate", - &format!("{}", shader_crate.display()), - "--output-dir", - &format!("{}", output_dir.display()), - ]; - if let Cli { - command: Command::Build(mut build), - } = Cli::parse_from(args) - { - assert_eq!(shader_crate, build.shader_crate); - assert_eq!(output_dir, build.output_dir); - - // TODO: - // What's the best way to reset caches for this? For example we could add a - // `--force-spirv-cli-rebuild`, but that would slow down each test. But without - // something like that we might not be getting actual idempotent tests. - build.run(); - } else { - panic!("was not a build command"); + pub fn tests_teardown() { + let cache_dir = cache_dir(); + if !cache_dir.exists() { + return; } + std::fs::remove_dir_all(cache_dir).unwrap(); } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 4c114b0582..2355530e73 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -1,64 +1,70 @@ -//! Install the relevant Rust compiler and toolchain components required by the version of -//! `rust-gpu` defined in the shader. -use crate::cache_dir; +//! Query the shader crate to find what version of `rust-gpu` it depends on. +//! Then ensure that the relevant Rust toolchain and components are installed. -/// The canonical pairs of `rust-gpu` version to `rust-gpu` Rust toolchain channel. -/// -/// TODO: We may be able to automate this by checking out the locked version of `spirv-std` in the -/// shader's crate. -const SPIRV_STD_TOOLCHAIN_PAIRS: &[(&str, &str)] = &[("0.10", "nightly-2024-04-24")]; +use crate::spirv_source::SpirvSource; /// Cargo dependency for `spirv-builder` and the rust toolchain channel. #[derive(Debug, Clone)] -pub struct Spirv { - /// The version of `rust-gpu`, eg `"0.10"` or `"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }` - pub dep: String, - //// The toolchain that `rust-gpu` uses, eg "nightly-2024-04-24" +pub struct SpirvCli { + #[expect( + clippy::doc_markdown, + reason = "The URL should appear literally like this. But Clippy wants it to be a in markdown clickable link" + )] + /// The source and version of `rust-gpu`. + /// Eg: + /// * From crates.io with version "0.10.0" + /// * From Git with: + /// - a repo of "https://github.com/Rust-GPU/rust-gpu.git" + /// - a revision of "abc213" + pub source: SpirvSource, + /// The toolchain channel that `rust-gpu` uses, eg "nightly-2024-04-24" pub channel: String, + /// The date of the pinned version of `rust-gpu` + pub date: chrono::NaiveDate, } -impl Default for Spirv { - fn default() -> Self { - Self { - dep: Self::DEFAULT_DEP.into(), - channel: Self::DEFAULT_CHANNEL.into(), - } - } -} - -impl core::fmt::Display for Spirv { +impl core::fmt::Display for SpirvCli { #[expect( clippy::min_ident_chars, reason = "It's a core library trait implementation" )] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - format!("{}+{}", self.dep, self.channel).fmt(f) + format!("{}+{}", self.source, self.channel).fmt(f) } } -impl Spirv { - /// The default `rust-gpu` dependency defintion - pub const DEFAULT_DEP: &str = r#"{ git = "https://github.com/Rust-GPU/rust-gpu.git" }"#; - /// The default `rust-gpu` toolchain - pub const DEFAULT_CHANNEL: &str = "nightly-2024-04-24"; +impl SpirvCli { + /// Create instance + pub fn new( + shader_crate_path: &std::path::PathBuf, + maybe_rust_gpu_source: Option, + maybe_rust_gpu_version: Option, + maybe_rust_gpu_channel: Option, + ) -> Self { + let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = + SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path); - /// Returns a string suitable to use as a directory. - /// - /// Created from the spirv-builder source dep and the rustc channel. - fn to_dirname(&self) -> String { - self.to_string() - .replace( - [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], - "_", - ) - .split(['{', '}', ' ', '\n', '"', '\'']) - .collect::>() - .concat() + let mut maybe_spirv_source: Option = None; + if let Some(rust_gpu_version) = maybe_rust_gpu_version { + let mut source = SpirvSource::CratesIO(rust_gpu_version.clone()); + if let Some(rust_gpu_source) = maybe_rust_gpu_source { + source = SpirvSource::Git((rust_gpu_source, rust_gpu_version)); + } + maybe_spirv_source = Some(source); + } + + Self { + source: maybe_spirv_source.unwrap_or(default_rust_gpu_source), + channel: maybe_rust_gpu_channel.unwrap_or(default_rust_gpu_channel), + date: rust_gpu_date, + } } /// Create and/or return the cache directory pub fn cached_checkout_path(&self) -> std::path::PathBuf { - let checkout_dir = cache_dir().join(self.to_dirname()); + let checkout_dir = crate::cache_dir() + .join("spirv-builder-cli") + .join(crate::to_dirname(self.to_string().as_ref())); std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|error| { log::error!( "could not create checkout dir '{}': {error}", @@ -70,20 +76,6 @@ impl Spirv { checkout_dir } - /// Ensure that the requested `rust-gpu` version/toolchain are known to be canonically - /// compatible. - /// - /// TODO: We may be able to automatically get the pair by downloading the `rust-gpu` repo as defined by the - /// `spriv-std` dependency in the shader. - pub fn ensure_version_channel_compatibility(&self) { - for (version, channel) in SPIRV_STD_TOOLCHAIN_PAIRS { - assert!( - !(version.starts_with(&self.dep) && channel != &self.channel), - "expected spirv-std version to be matched with rust toolchain channel {channel}" - ); - } - } - /// Use `rustup` to install the toolchain and components, if not already installed. /// /// Pretty much runs: @@ -158,3 +150,25 @@ impl Spirv { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test_log::test] + fn cached_checkout_dir_sanity() { + let shader_template_path = crate::test::shader_crate_template_path(); + let spirv = SpirvCli::new(&shader_template_path, None, None, None); + let dir = spirv.cached_checkout_path(); + let name = dir + .file_name() + .unwrap() + .to_str() + .map(std::string::ToString::to_string) + .unwrap(); + assert_eq!( + "https___github_com_Rust-GPU_rust-gpu+82a0f69+nightly-2024-04-24", + &name + ); + } +} diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs new file mode 100644 index 0000000000..6e8ab81e21 --- /dev/null +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -0,0 +1,304 @@ +//! Use the shader that we're compiling as the default source for which version of `rust-gpu` to use. +//! +//! We do this by calling `cargo tree` inside the shader's crate to get the defined `spirv-std` +//! version. Then with that we `git checkout` the `rust-gpu` repo that corresponds to that version. +//! From there we can look at the source code to get the required Rust toolchain. + +/// The canonical `rust-gpu` URI +const RUST_GPU_REPO: &str = "https://github.com/Rust-GPU/rust-gpu"; + +/// The various sources that the `rust-gpu` repo can have. +/// Most commonly it will simply be the canonical version on crates.io. But it could also be the +/// Git version, or a fork. +#[derive(Eq, PartialEq, Clone, Debug)] +pub enum SpirvSource { + /// If the shader specifies a simple version like `spirv-std = "0.9.0"` then the source of + /// `rust-gpu` is the conventional crates.io version. + /// + /// `String` is the simple version like, "0.9.0" + CratesIO(String), + /// If the shader specifies a version like: + /// `spirv-std = { git = "https://github.com..." ... }` + /// then the source of `rust-gpu` is `Git`. + /// + /// `(String, String)` is the repo source and revision hash or tag. + Git((String, String)), + /// If the shader specifies a version like: + /// `spirv-std = { path = "/path/to/rust-gpu" ... }` + /// then the source of `rust-gpu` is `Path`. + /// + /// `(String, String)` is the repo path and the version. + Path((String, String)), +} + +impl core::fmt::Display for SpirvSource { + #[expect( + clippy::min_ident_chars, + reason = "It's a core library trait implementation" + )] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + format!("{}+{}", self.to_repo(), self.to_version()).fmt(f) + } +} + +impl SpirvSource { + /// Look into the shader crate to get the version of `rust-gpu` it's using. + pub fn get_rust_gpu_deps_from_shader( + shader_crate_path: &std::path::PathBuf, + ) -> (Self, chrono::NaiveDate, String) { + let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path); + + rust_gpu_source.ensure_repo_is_installed(); + rust_gpu_source.checkout(); + + let date = rust_gpu_source.get_version_date(); + let channel = Self::get_channel_from_toolchain_toml(&rust_gpu_source.to_dirname()); + + log::debug!("Parsed version, date and toolchain channel from shader-defined `rust-gpu`: {rust_gpu_source:?}, {date}, {channel}"); + + (rust_gpu_source, date, channel) + } + + /// Convert the source to just its version. + pub fn to_version(&self) -> String { + match self { + Self::CratesIO(version) | Self::Path((_, version)) => version.to_string(), + Self::Git((_, revision)) => revision.to_string(), + } + } + + /// Convert the source to just its repo or path. + fn to_repo(&self) -> String { + match self { + Self::CratesIO(_) => RUST_GPU_REPO.to_owned(), + Self::Git((repo, _)) => repo.to_owned(), + Self::Path((path, _)) => path.to_owned(), + } + } + + /// Convert the `rust-gpu` source into a string that can be used as a directory. + /// It needs to be dynamically created because an end-user might want to swap out the source, + /// maybe using their own fork for example. + fn to_dirname(&self) -> std::path::PathBuf { + let dir = crate::to_dirname(self.to_string().as_ref()); + crate::cache_dir().join("rust-gpu-repo").join(dir) + } + + /// Checkout the `rust-gpu` to the requested version. + fn checkout(&self) { + log::debug!( + "Checking out `rust-gpu` repo at {} to {}", + self.to_dirname().display(), + self.to_version() + ); + let output_checkout = std::process::Command::new("git") + .current_dir(self.to_dirname()) + .args(["checkout", self.to_version().as_ref()]) + .output() + .unwrap(); + assert!( + output_checkout.status.success(), + "couldn't checkout revision '{}' of `rust-gpu` at {}", + self.to_version(), + self.to_dirname().to_string_lossy() + ); + } + + /// Get the date of the version of `rust-gpu` used by the shader. This allows us to know what + /// features we can use in the `spirv-builder` crate. + fn get_version_date(&self) -> chrono::NaiveDate { + let date_format = "%Y-%m-%d"; + + log::debug!( + "Getting `rust-gpu` version date from {}", + self.to_dirname().display(), + ); + let output_date = std::process::Command::new("git") + .current_dir(self.to_dirname()) + .args([ + "show", + "--no-patch", + "--format=%cd", + format!("--date=format:'{date_format}'").as_ref(), + self.to_version().as_ref(), + ]) + .output() + .unwrap(); + assert!( + output_date.status.success(), + "couldn't get `rust-gpu` version date at for {} at {}", + self.to_version(), + self.to_dirname().to_string_lossy() + ); + let date_string = String::from_utf8_lossy(&output_date.stdout) + .to_string() + .trim() + .replace('\'', ""); + + log::debug!( + "Parsed date for version {}: {date_string}", + self.to_version() + ); + + chrono::NaiveDate::parse_from_str(&date_string, date_format).unwrap() + } + + /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. + fn get_channel_from_toolchain_toml(path: &std::path::PathBuf) -> String { + log::debug!("Parsing `rust-toolchain.toml` at {path:?} for the used toolchain"); + + let contents = std::fs::read_to_string(path.join("rust-toolchain.toml")).unwrap(); + let toml: toml::Table = toml::from_str(&contents).unwrap(); + let Some(toolchain) = toml.get("toolchain") else { + panic!("Couldn't find `[toolchain]` section in `rust-toolchain.toml` at {path:?}"); + }; + let Some(channel) = toolchain.get("channel") else { + panic!("Couldn't find `channel` field in `rust-toolchain.toml` at {path:?}"); + }; + + channel.to_string().replace('"', "") + } + + /// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml` + fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self { + log::debug!("Running `cargo tree` on {}", shader_crate_path.display()); + let output_cargo_tree = std::process::Command::new("cargo") + .current_dir(shader_crate_path) + .args(["tree", "--workspace", "--depth", "1", "--prefix", "none"]) + .output() + .unwrap(); + assert!( + output_cargo_tree.status.success(), + "could not query shader's `Cargo.toml` for `spirv-std` dependency" + ); + let cargo_tree_string = String::from_utf8_lossy(&output_cargo_tree.stdout); + + let maybe_spirv_std_def = cargo_tree_string + .lines() + .find(|line| line.contains("spirv-std")); + + let Some(spirv_std_def) = maybe_spirv_std_def else { + panic!("`spirv-std` not found in shader's `Cargo.toml` at {shader_crate_path:?}:\n{cargo_tree_string}"); + }; + + Self::parse_spirv_std_source_and_version(spirv_std_def) + } + + /// Parse a string like: + /// `spirv-std v0.9.0 (https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c) (*)` + /// Which would return: + /// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")` + fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> Self { + let parts: Vec = spirv_std_def.split_whitespace().map(String::from).collect(); + let version = parts + .get(1) + .expect("Couldn't find `spirv_std` version in shader crate") + .to_owned(); + let mut source = Self::CratesIO(version.clone()); + + if parts.len() > 2 { + let mut source_string = parts.get(2).unwrap().to_owned(); + source_string = source_string.replace(['(', ')'], ""); + + let uri = source_string.parse::().unwrap(); + if uri.scheme().is_some() { + source = Self::parse_git_source(version, &uri); + } else { + source = Self::Path((source_string, version)); + } + } + + log::debug!("Parsed `rust-gpu` source and version: {source:?}"); + + source + } + + /// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c` + fn parse_git_source(version: String, uri: &http::Uri) -> Self { + let mut revision = version; + + let repo = format!( + "{}://{}{}", + uri.scheme().unwrap(), + uri.host().unwrap(), + uri.path() + ); + + if let Some(query) = uri.query() { + let marker = "rev="; + let sanity_check = query.contains(marker) && query.split('=').count() == 2; + assert!(sanity_check, "revision not found in Git URI: {query}"); + revision = query.replace(marker, ""); + } + + Self::Git((repo, revision)) + } + + /// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile + /// the shader. + fn ensure_repo_is_installed(&self) { + if self.to_dirname().exists() { + log::debug!( + "Not cloning `rust-gpu` repo ({}) as it already exists at {}", + self.to_repo(), + self.to_dirname().to_string_lossy().as_ref(), + ); + return; + } + + log::debug!( + "Cloning `rust-gpu` repo {} to {}", + self.to_repo(), + self.to_dirname().to_string_lossy().as_ref(), + ); + + let output_clone = std::process::Command::new("git") + .args([ + "clone", + self.to_repo().as_ref(), + self.to_dirname().to_string_lossy().as_ref(), + ]) + .output() + .unwrap(); + + assert!( + output_clone.status.success(), + "couldn't clone `rust-gpu` {} to {}\n{}", + self.to_repo(), + self.to_dirname().to_string_lossy(), + String::from_utf8_lossy(&output_clone.stderr) + ); + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test_log::test] + fn parsing_spirv_std_dep_for_shader_template() { + let shader_template_path = crate::test::shader_crate_template_path(); + let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path); + assert_eq!( + source, + SpirvSource::Git(( + "https://github.com/Rust-GPU/rust-gpu".to_owned(), + "82a0f69".to_owned() + )) + ); + } + + #[test_log::test] + fn parsing_spirv_std_dep_for_git_source() { + let definition = + "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69) (*)"; + let source = SpirvSource::parse_spirv_std_source_and_version(definition); + assert_eq!( + source, + SpirvSource::Git(( + "https://github.com/Rust-GPU/rust-gpu".to_owned(), + "82a0f69".to_owned() + )) + ); + } +} diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index ab360ef555..cf76f7d855 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -37,25 +37,9 @@ pub struct Toml { impl Toml { /// Entrypoint pub fn run(&self) { - // Find the path to the toml file to use - let path = if self.path.is_file() && self.path.ends_with(".toml") { - self.path.clone() - } else { - let path = self.path.join("Cargo.toml"); - if path.is_file() { - path - } else { - log::error!("toml file '{}' is not a file", self.path.display()); - panic!("toml file '{}' is not a file", self.path.display()); - } - }; - - log::info!("using toml file '{}'", path.display()); + let (path, toml) = Self::parse_cargo_toml(self.path.clone()); // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml - let contents = std::fs::read_to_string(&path).unwrap(); - let toml: toml::Table = toml::from_str(&contents).unwrap(); - let (toml_type, table) = if toml.contains_key("workspace") { let table = Self::get_metadata_rustgpu_table(&toml, "workspace") .unwrap_or_else(|| { @@ -134,6 +118,29 @@ impl Toml { } } + /// Parse the contents of the shader's `Cargo.toml` + pub fn parse_cargo_toml(mut path: std::path::PathBuf) -> (std::path::PathBuf, toml::Table) { + // Find the path to the toml file to use + let parsed_path = if path.is_file() && path.ends_with(".toml") { + path + } else { + path = path.join("Cargo.toml"); + if path.is_file() { + path + } else { + log::error!("toml file '{}' is not a file", path.display()); + panic!("toml file '{}' is not a file", path.display()); + } + }; + + log::info!("using toml file '{}'", parsed_path.display()); + + let contents = std::fs::read_to_string(&parsed_path).unwrap(); + let toml: toml::Table = toml::from_str(&contents).unwrap(); + + (parsed_path, toml) + } + /// Parse the `[package.metadata.rust-gpu]` section. fn get_metadata_rustgpu_table<'toml>( toml: &'toml toml::Table, diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index d7a52c4ab6..8a30859684 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" @@ -16,18 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "glam" -version = "0.24.2" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" -dependencies = [ - "libm", -] - -[[package]] -name = "glam" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "480c9417a5dc586fc0c0cb67891170e59cc11e9dc79ba1c11ddd2c56ca3f3b90" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" dependencies = [ "libm", ] @@ -50,9 +41,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -70,18 +61,17 @@ dependencies = [ name = "rust-gpu-shader-crate-template" version = "0.1.0" dependencies = [ - "glam 0.29.1", + "glam", "spirv-std", ] [[package]] name = "spirv-std" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c3c0972a2df79abe2c8af2fe7f7937a9aa558b6a1f78fc5edf93f4d480d757" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" dependencies = [ "bitflags", - "glam 0.24.2", + "glam", "num-traits", "spirv-std-macros", "spirv-std-types", @@ -90,8 +80,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f776bf9f2897ea7acff15d7753711fdf1693592bd7459a01c394262b1df45c" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" dependencies = [ "proc-macro2", "quote", @@ -102,14 +91,13 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a73417b7d72d95b4995c840dceb4e3b4bcbad4ff7f35df9c1655b6826c18d3a9" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -118,6 +106,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 5d62ebf60b..3ec4841063 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -8,14 +8,15 @@ crate-type = ["rlib", "cdylib"] # Dependencies for CPU and GPU code [dependencies] -spirv-std = { version = "0.9" } +# "v0.9" doesn't seem to compile on windows? +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "82a0f69" } -# dependencies for GPU code +# Dependencies for GPU code [target.'cfg(target_arch = "spirv")'.dependencies] glam = { version = "0.29", default-features = false, features = ["libm"] } -# dependencies for CPU code +# Dependencies for CPU code [target.'cfg(not(target_arch = "spirv"))'.dependencies] glam = { version = "0.29", features = ["std"] } diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 67f9ee82ca..c89b824612 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -4,6 +4,11 @@ version = "0.1.0" edition = "2021" [lib] +path = "src/lib.rs" + +[[bin]] +name = "spirv-builder-cli" +path = "src/main.rs" [dependencies] env_home = "0.1.0" @@ -13,18 +18,6 @@ serde = "1.0.214" serde_json = "1.0.132" toml = "0.8.19" -[dependencies.spirv-builder-pre-cli] -package = "spirv-builder" -optional = true -git = "https://github.com/Rust-GPU/rust-gpu" -rev = "4c633aec" - -[dependencies.spirv-builder-0_10] -package = "spirv-builder" -optional = true -git = "https://github.com/Rust-GPU/rust-gpu" -rev = "60dcb82" - [features] default = ["spirv-builder-0_10"] # The `spirv-builder` before `cargo gpu` existed. It has an incompatible `SpirvBuilder` interface. @@ -32,3 +25,19 @@ spirv-builder-pre-cli = ["dep:spirv-builder-pre-cli"] # The first version that introduced `cargo gpu`. It has some extra `.builder()` args that make # dynamically changing build dependencies easier. spirv-builder-0_10 = ["dep:spirv-builder-0_10"] + +# NB: All the `${AUTO-REPLACE*}` tokens in each feature get replaced with the same values. +# This is because only one feature can ever be used at once and it makes it easier to just +# replace each token rather than figure out to what feature each token belongs. + +[dependencies.spirv-builder-pre-cli] +package = "spirv-builder" +optional = true +git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} +rev = "4c633aec" # ${AUTO-REPLACE-VERSION} + +[dependencies.spirv-builder-0_10] +package = "spirv-builder" +optional = true +git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} +rev = "60dcb82" # ${AUTO-REPLACE-VERSION} diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 9c92b0a440..a18a339b6a 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -90,6 +90,7 @@ fn main() { } } + log::debug!("Calling `rust-gpu`'s `spirv-builder` library"); builder.build().unwrap() }; From e1b9e8c6cb1c6cd4e51ddb71716bf5d2820108d8 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 20 Dec 2024 11:00:18 +1300 Subject: [PATCH 050/162] Add test comment in spirv_source.rs --- crates/cargo-gpu/src/spirv_source.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 6e8ab81e21..24790cc1ab 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -3,6 +3,8 @@ //! We do this by calling `cargo tree` inside the shader's crate to get the defined `spirv-std` //! version. Then with that we `git checkout` the `rust-gpu` repo that corresponds to that version. //! From there we can look at the source code to get the required Rust toolchain. +//! +//! This is just a test. /// The canonical `rust-gpu` URI const RUST_GPU_REPO: &str = "https://github.com/Rust-GPU/rust-gpu"; From 3f1ab564a2e136c6d2d20808bc7bee1ceec0b560 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 20 Dec 2024 10:18:09 +1300 Subject: [PATCH 051/162] make Git source respect revision, show source command --- Cargo.lock | 22 ++++++++ Cargo.toml | 1 + crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/install.rs | 4 +- crates/cargo-gpu/src/show.rs | 35 ++++++++++-- crates/cargo-gpu/src/spirv_cli.rs | 5 +- crates/cargo-gpu/src/spirv_source.rs | 84 ++++++++++++++++++++-------- 7 files changed, 119 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88ba813167..d11c416333 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,6 +91,7 @@ dependencies = [ "relative-path", "serde", "serde_json", + "snafu", "spirv-builder-cli", "test-log", "toml", @@ -530,6 +531,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "snafu" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" +dependencies = [ + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "spirv-builder-cli" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index f8122deef9..283e9ef106 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ log = "0.4" relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" +snafu = "0.8.5" toml = "0.8.19" test-log = "0.2.16" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index e6043d1bcc..67df7993c5 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -17,6 +17,7 @@ log.workspace = true relative-path.workspace = true serde.workspace = true serde_json.workspace = true +snafu.workspace = true toml.workspace = true chrono.workspace = true http.workspace = true diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index e3d7c0b80f..7e7953350b 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -152,7 +152,7 @@ impl Install { if line.contains("${AUTO-REPLACE-SOURCE}") { let replaced_line = match spirv_source { SpirvSource::CratesIO(_) => String::new(), - SpirvSource::Git((repo, _)) => format!("git = \"{repo}\""), + SpirvSource::Git { url, .. } => format!("git = \"{url}\""), SpirvSource::Path((path, _)) => format!("path = \"{path}\""), }; return format!("{replaced_line}\n"); @@ -163,7 +163,7 @@ impl Install { SpirvSource::CratesIO(version) | SpirvSource::Path((_, version)) => { format!("version = \"{}\"", version.replace('v', "")) } - SpirvSource::Git((_, revision)) => format!("rev = \"{revision}\""), + SpirvSource::Git { rev, .. } => format!("rev = \"{rev}\""), }; return format!("{replaced_line}\n"); } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 24d56320e6..56f8c3b190 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -2,20 +2,43 @@ use crate::cache_dir; +#[derive(Clone, Debug, clap::Parser)] +pub struct ShowSpirvSource { + /// The location of the shader-crate to inspect to determine its spirv-std dependency. + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, +} + +/// Different tidbits of information that can be queried at the command line. +#[derive(Clone, Debug, clap::Subcommand)] +pub enum Info { + /// Displays the location of the cache directory + CacheDirectory, + /// The source location of spirv-std + SpirvSource(ShowSpirvSource), +} + /// `cargo gpu show` #[derive(clap::Parser)] pub struct Show { - #[clap(long)] - /// Displays the location of the cache directory - cache_directory: bool, + /// Display information about rust-gpu + #[clap(subcommand)] + command: Info, } impl Show { /// Entrypoint pub fn run(self) { - if self.cache_directory { - log::info!("cache_directory: "); - println!("{}", cache_dir().display()); + log::info!("{:?}: ", self.command); + match self.command { + Info::CacheDirectory => { + println!("{}", cache_dir().display()); + } + Info::SpirvSource(ShowSpirvSource { shader_crate }) => { + let rust_gpu_source = + crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate); + println!("{rust_gpu_source}"); + } } } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 2355530e73..52c4c0e242 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -48,7 +48,10 @@ impl SpirvCli { if let Some(rust_gpu_version) = maybe_rust_gpu_version { let mut source = SpirvSource::CratesIO(rust_gpu_version.clone()); if let Some(rust_gpu_source) = maybe_rust_gpu_source { - source = SpirvSource::Git((rust_gpu_source, rust_gpu_version)); + source = SpirvSource::Git { + url: rust_gpu_source, + rev: rust_gpu_version, + }; } maybe_spirv_source = Some(source); } diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 24790cc1ab..c12d39ef15 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -24,7 +24,7 @@ pub enum SpirvSource { /// then the source of `rust-gpu` is `Git`. /// /// `(String, String)` is the repo source and revision hash or tag. - Git((String, String)), + Git { url: String, rev: String }, /// If the shader specifies a version like: /// `spirv-std = { path = "/path/to/rust-gpu" ... }` /// then the source of `rust-gpu` is `Path`. @@ -39,7 +39,11 @@ impl core::fmt::Display for SpirvSource { reason = "It's a core library trait implementation" )] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - format!("{}+{}", self.to_repo(), self.to_version()).fmt(f) + match self { + SpirvSource::CratesIO(version) => f.write_str(version), + SpirvSource::Git { url, rev } => f.write_str(&format!("{url}+{rev}")), + SpirvSource::Path((a, b)) => f.write_str(&format!("{a}+{b}")), + } } } @@ -65,7 +69,7 @@ impl SpirvSource { pub fn to_version(&self) -> String { match self { Self::CratesIO(version) | Self::Path((_, version)) => version.to_string(), - Self::Git((_, revision)) => revision.to_string(), + Self::Git { rev, .. } => rev.to_string(), } } @@ -73,7 +77,7 @@ impl SpirvSource { fn to_repo(&self) -> String { match self { Self::CratesIO(_) => RUST_GPU_REPO.to_owned(), - Self::Git((repo, _)) => repo.to_owned(), + Self::Git { url, .. } => url.to_owned(), Self::Path((path, _)) => path.to_owned(), } } @@ -162,7 +166,7 @@ impl SpirvSource { } /// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml` - fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self { + pub fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self { log::debug!("Running `cargo tree` on {}", shader_crate_path.display()); let output_cargo_tree = std::process::Command::new("cargo") .current_dir(shader_crate_path) @@ -178,6 +182,7 @@ impl SpirvSource { let maybe_spirv_std_def = cargo_tree_string .lines() .find(|line| line.contains("spirv-std")); + log::trace!(" found {maybe_spirv_std_def:?}"); let Some(spirv_std_def) = maybe_spirv_std_def else { panic!("`spirv-std` not found in shader's `Cargo.toml` at {shader_crate_path:?}:\n{cargo_tree_string}"); @@ -191,6 +196,7 @@ impl SpirvSource { /// Which would return: /// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")` fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> Self { + log::trace!("parsing spirv-std source and version from def: '{spirv_std_def}'"); let parts: Vec = spirv_std_def.split_whitespace().map(String::from).collect(); let version = parts .get(1) @@ -202,9 +208,21 @@ impl SpirvSource { let mut source_string = parts.get(2).unwrap().to_owned(); source_string = source_string.replace(['(', ')'], ""); + // Unfortunately Uri ignores the fragment/hash portion of the Uri. + // + // There's been a ticket open for years: + // + // + // So here we'll parse the fragment out of the source string by hand let uri = source_string.parse::().unwrap(); + let maybe_hash = if source_string.contains('#') { + let splits = source_string.split('#'); + splits.last().map(std::borrow::ToOwned::to_owned) + } else { + None + }; if uri.scheme().is_some() { - source = Self::parse_git_source(version, &uri); + source = Self::parse_git_source(version, &uri, maybe_hash); } else { source = Self::Path((source_string, version)); } @@ -216,9 +234,11 @@ impl SpirvSource { } /// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c` - fn parse_git_source(version: String, uri: &http::Uri) -> Self { - let mut revision = version; - + fn parse_git_source(version: String, uri: &http::Uri, fragment: Option) -> Self { + log::trace!( + "parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}", + fragment.as_deref().unwrap_or("?") + ); let repo = format!( "{}://{}{}", uri.scheme().unwrap(), @@ -226,14 +246,17 @@ impl SpirvSource { uri.path() ); - if let Some(query) = uri.query() { - let marker = "rev="; - let sanity_check = query.contains(marker) && query.split('=').count() == 2; - assert!(sanity_check, "revision not found in Git URI: {query}"); - revision = query.replace(marker, ""); - } + let rev = uri.query().map_or_else( + || fragment.unwrap_or(version), + |query| { + let marker = "rev="; + let sanity_check = query.contains(marker) && query.split('=').count() == 2; + assert!(sanity_check, "revision not found in Git URI: {query}"); + query.replace(marker, "") + }, + ); - Self::Git((repo, revision)) + Self::Git { url: repo, rev } } /// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile @@ -283,10 +306,10 @@ mod test { let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path); assert_eq!( source, - SpirvSource::Git(( - "https://github.com/Rust-GPU/rust-gpu".to_owned(), - "82a0f69".to_owned() - )) + SpirvSource::Git { + url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), + rev: "82a0f69".to_owned() + } ); } @@ -297,10 +320,23 @@ mod test { let source = SpirvSource::parse_spirv_std_source_and_version(definition); assert_eq!( source, - SpirvSource::Git(( - "https://github.com/Rust-GPU/rust-gpu".to_owned(), - "82a0f69".to_owned() - )) + SpirvSource::Git { + url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), + rev: "82a0f69".to_owned() + } + ); + } + + #[test_log::test] + fn parsing_spirv_std_dep_for_git_source_hash() { + let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)"; + let source = SpirvSource::parse_spirv_std_source_and_version(definition); + assert_eq!( + source, + SpirvSource::Git { + url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), + rev: "82a0f69".to_owned() + } ); } } From 2ec65249a9152f22f8468fa59b2af9438ba578ac Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Dec 2024 10:10:16 +1300 Subject: [PATCH 052/162] add extra debugging --- crates/spirv-builder-cli/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index a18a339b6a..496c2cc66a 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -93,6 +93,7 @@ fn main() { log::debug!("Calling `rust-gpu`'s `spirv-builder` library"); builder.build().unwrap() }; + log::debug!("found entry points: {entry_points:#?}"); let dir = output_dir; let mut shaders = vec![]; @@ -100,6 +101,7 @@ fn main() { ModuleResult::MultiModule(modules) => { assert!(!modules.is_empty(), "No shader modules to compile"); for (entry, filepath) in modules.into_iter() { + log::debug!("compiled {entry} {}", filepath.display()); shaders.push(ShaderModule::new(entry, filepath)); } } From 1bb88f9f2ba554413c4387099397d2864c87a24a Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Dec 2024 10:23:54 +1300 Subject: [PATCH 053/162] appease clippy --- crates/cargo-gpu/src/show.rs | 7 ++++--- crates/cargo-gpu/src/spirv_source.rs | 13 +++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 56f8c3b190..cc1e9d8fc4 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -2,8 +2,9 @@ use crate::cache_dir; +/// Show the computed source of the spirv-std dependency. #[derive(Clone, Debug, clap::Parser)] -pub struct ShowSpirvSource { +pub struct SpirvSourceDep { /// The location of the shader-crate to inspect to determine its spirv-std dependency. #[clap(long, default_value = "./")] pub shader_crate: std::path::PathBuf, @@ -15,7 +16,7 @@ pub enum Info { /// Displays the location of the cache directory CacheDirectory, /// The source location of spirv-std - SpirvSource(ShowSpirvSource), + SpirvSource(SpirvSourceDep), } /// `cargo gpu show` @@ -34,7 +35,7 @@ impl Show { Info::CacheDirectory => { println!("{}", cache_dir().display()); } - Info::SpirvSource(ShowSpirvSource { shader_crate }) => { + Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate); println!("{rust_gpu_source}"); diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index c12d39ef15..233b7991c4 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -24,7 +24,12 @@ pub enum SpirvSource { /// then the source of `rust-gpu` is `Git`. /// /// `(String, String)` is the repo source and revision hash or tag. - Git { url: String, rev: String }, + Git { + /// URL of the repository + url: String, + /// Revision or "commitsh" + rev: String, + }, /// If the shader specifies a version like: /// `spirv-std = { path = "/path/to/rust-gpu" ... }` /// then the source of `rust-gpu` is `Path`. @@ -40,9 +45,9 @@ impl core::fmt::Display for SpirvSource { )] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - SpirvSource::CratesIO(version) => f.write_str(version), - SpirvSource::Git { url, rev } => f.write_str(&format!("{url}+{rev}")), - SpirvSource::Path((a, b)) => f.write_str(&format!("{a}+{b}")), + Self::CratesIO(version) => f.write_str(version), + Self::Git { url, rev } => f.write_str(&format!("{url}+{rev}")), + Self::Path((a, b)) => f.write_str(&format!("{a}+{b}")), } } } From feedfe1c501bb861c37146484dbf9dcb6106afa2 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Dec 2024 10:50:14 +1300 Subject: [PATCH 054/162] sanitise the path for cargo tree invocation --- crates/cargo-gpu/src/main.rs | 11 +++++++++-- crates/cargo-gpu/src/spirv_source.rs | 25 ++++++++++++++++++++++--- crates/cargo-gpu/src/toml.rs | 2 +- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 267fd1432a..1c80d66c6f 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -78,10 +78,17 @@ fn main() { match cli.command { Command::Install(install) => { + log::debug!("installing with arguments: {install:#?}"); let (_, _) = install.run(); } - Command::Build(mut build) => build.run(), - Command::Toml(toml) => toml.run(), + Command::Build(mut build) => { + log::debug!("building with arguments: {build:#?}"); + build.run() + } + Command::Toml(toml) => { + log::debug!("building by toml file with arguments: {toml:#?}"); + toml.run() + } Command::Show(show) => show.run(), Command::DumpUsage => dump_full_usage_for_readme(), } diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 233b7991c4..c16cdf200b 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -172,9 +172,22 @@ impl SpirvSource { /// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml` pub fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self { - log::debug!("Running `cargo tree` on {}", shader_crate_path.display()); + let cwd = std::env::current_dir().expect("no cwd"); + let exec_path = if shader_crate_path.is_absolute() { + shader_crate_path.clone() + } else { + cwd.join(shader_crate_path) + } + .canonicalize() + .expect("could not get absolute path to shader crate"); + if !exec_path.is_dir() { + log::error!("{exec_path:?} is not a directory, aborting"); + panic!("{exec_path:?} is not a directory"); + } + + log::debug!("Running `cargo tree` on {}", exec_path.display()); let output_cargo_tree = std::process::Command::new("cargo") - .current_dir(shader_crate_path) + .current_dir(&exec_path) .args(["tree", "--workspace", "--depth", "1", "--prefix", "none"]) .output() .unwrap(); @@ -190,7 +203,7 @@ impl SpirvSource { log::trace!(" found {maybe_spirv_std_def:?}"); let Some(spirv_std_def) = maybe_spirv_std_def else { - panic!("`spirv-std` not found in shader's `Cargo.toml` at {shader_crate_path:?}:\n{cargo_tree_string}"); + panic!("`spirv-std` not found in shader's `Cargo.toml` at {exec_path:?}:\n{cargo_tree_string}"); }; Self::parse_spirv_std_source_and_version(spirv_std_def) @@ -344,4 +357,10 @@ mod test { } ); } + + #[test_log::test] + fn path_sanity() { + let path = std::path::PathBuf::from("./"); + assert!(path.is_relative()); + } } diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index cf76f7d855..8d82cde2d4 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -5,7 +5,7 @@ use clap::Parser; use crate::{Cli, Command}; /// `cargo gpu toml` -#[derive(Parser)] +#[derive(Debug, Parser)] pub struct Toml { /// Path to a workspace or package Cargo.toml file. /// From f1a947b38467f29cf97265f1cf30a7cd4851d4e2 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Dec 2024 11:19:10 +1300 Subject: [PATCH 055/162] don't use depth=1 for cargo tree as it misses spirv-std sometimes --- crates/cargo-gpu/src/spirv_source.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index c16cdf200b..95fcb93d50 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -188,7 +188,7 @@ impl SpirvSource { log::debug!("Running `cargo tree` on {}", exec_path.display()); let output_cargo_tree = std::process::Command::new("cargo") .current_dir(&exec_path) - .args(["tree", "--workspace", "--depth", "1", "--prefix", "none"]) + .args(["tree", "--workspace", "--prefix", "none"]) .output() .unwrap(); assert!( From fc8ecfc71cd6504b67794149cd26391514af4afb Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 21 Dec 2024 11:19:42 +1300 Subject: [PATCH 056/162] ensure output-dir is relative to toml when building with `toml` --- crates/cargo-gpu/src/toml.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index 8d82cde2d4..f067f5a038 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -110,6 +110,12 @@ impl Toml { command: Command::Build(mut build), } = Cli::parse_from(parameters) { + // Ensure that the output directory is relative to the toml file + if build.output_dir.is_relative() { + let dir = path.parent().expect("no path parent"); + build.output_dir = dir.join(build.output_dir); + } + log::debug!("build: {build:?}"); build.run(); } else { From 2395dd76d0e6fb9e628c55a936e313bc9b69a469 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 21 Dec 2024 08:37:21 +0100 Subject: [PATCH 057/162] Fix for failing Windows build For some reason `spirv-tools-sys` only fails to build on windows when run from inside `cargo test`. Maybe it's something to do with what gets set in ENV? Also added `just` so that we have a canonical way of running CI-related tasks. --- .github/workflows/push.yaml | 11 +++++++++-- Cargo.lock | 22 ---------------------- Cargo.toml | 1 - crates/cargo-gpu/Cargo.toml | 1 - crates/cargo-gpu/src/build.rs | 8 ++++++-- crates/cargo-gpu/src/install.rs | 3 ++- crates/cargo-gpu/src/main.rs | 4 ++-- crates/cargo-gpu/src/spirv_source.rs | 8 +------- justfile | 19 +++++++++++++++++++ 9 files changed, 39 insertions(+), 38 deletions(-) create mode 100644 justfile diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 4eb468e37b..26dca5b258 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -28,15 +28,22 @@ jobs: steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 + - uses: extractions/setup-just@v2 - name: Install Rust toolchain run: | rustup default stable rustup update - run: cargo test + - name: Run a full build + run: just build-shader-template + - clippy: + lints: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: moonrepo/setup-rust@v1 - - run: cargo clippy -- --deny warnings + - uses: extractions/setup-just@v2 + - uses: cargo-bins/cargo-binstall@main + - run: just setup-lints + - run: just lints diff --git a/Cargo.lock b/Cargo.lock index d11c416333..88ba813167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,6 @@ dependencies = [ "relative-path", "serde", "serde_json", - "snafu", "spirv-builder-cli", "test-log", "toml", @@ -531,27 +530,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "snafu" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" -dependencies = [ - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "spirv-builder-cli" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 283e9ef106..f8122deef9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ log = "0.4" relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" -snafu = "0.8.5" toml = "0.8.19" test-log = "0.2.16" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 67df7993c5..e6043d1bcc 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -17,7 +17,6 @@ log.workspace = true relative-path.workspace = true serde.workspace = true serde_json.workspace = true -snafu.workspace = true toml.workspace = true chrono.workspace = true http.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index d6c90168f2..d26718a63b 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -161,13 +161,17 @@ mod test { &format!("{}", output_dir.display()), ]; if let Cli { - command: Command::Build(mut build), + command: Command::Build(build), } = Cli::parse_from(args) { assert_eq!(shader_crate_path, build.install.shader_crate); assert_eq!(output_dir, build.output_dir); - build.run(); + // TODO: + // For some reason running a full build (`build.run()`) inside tests fails on Windows. + // The error is in the `build.rs` step of compiling `spirv-tools-sys`. It is not clear + // from the logged error what the problem is. For now we'll just run a full build + // outside the tests environment, see `justfile`'s `build-shader-template`. } else { panic!("was not a build command"); } diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 7e7953350b..ca73728667 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -146,7 +146,8 @@ impl Install { } } - /// Create the `spirv-builder-cli` crate. + /// Update the `Cargo.toml` file in the `spirv-builder-cli` crate so that it contains + /// the correct version of `spirv-builder-cli`. fn update_cargo_toml(contents: &str, spirv_source: &SpirvSource) -> String { let updated = contents.lines().map(|line| { if line.contains("${AUTO-REPLACE-SOURCE}") { diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 1c80d66c6f..364b3e14e7 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -83,11 +83,11 @@ fn main() { } Command::Build(mut build) => { log::debug!("building with arguments: {build:#?}"); - build.run() + build.run(); } Command::Toml(toml) => { log::debug!("building by toml file with arguments: {toml:#?}"); - toml.run() + toml.run(); } Command::Show(show) => show.run(), Command::DumpUsage => dump_full_usage_for_readme(), diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 95fcb93d50..bd2f20009d 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -3,8 +3,6 @@ //! We do this by calling `cargo tree` inside the shader's crate to get the defined `spirv-std` //! version. Then with that we `git checkout` the `rust-gpu` repo that corresponds to that version. //! From there we can look at the source code to get the required Rust toolchain. -//! -//! This is just a test. /// The canonical `rust-gpu` URI const RUST_GPU_REPO: &str = "https://github.com/Rust-GPU/rust-gpu"; @@ -22,8 +20,6 @@ pub enum SpirvSource { /// If the shader specifies a version like: /// `spirv-std = { git = "https://github.com..." ... }` /// then the source of `rust-gpu` is `Git`. - /// - /// `(String, String)` is the repo source and revision hash or tag. Git { /// URL of the repository url: String, @@ -33,8 +29,6 @@ pub enum SpirvSource { /// If the shader specifies a version like: /// `spirv-std = { path = "/path/to/rust-gpu" ... }` /// then the source of `rust-gpu` is `Path`. - /// - /// `(String, String)` is the repo path and the version. Path((String, String)), } @@ -95,7 +89,7 @@ impl SpirvSource { crate::cache_dir().join("rust-gpu-repo").join(dir) } - /// Checkout the `rust-gpu` to the requested version. + /// Checkout the `rust-gpu` repo to the requested version. fn checkout(&self) { log::debug!( "Checking out `rust-gpu` repo at {} to {}", diff --git a/justfile b/justfile new file mode 100644 index 0000000000..1f53c294bb --- /dev/null +++ b/justfile @@ -0,0 +1,19 @@ +[group: 'ci'] +build-shader-template: + cargo install --path crates/cargo-gpu + cargo gpu install --shader-crate crates/shader-crate-template + cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders + ls -lah test-shaders + cat test-shaders/manifest.json + +[group: 'ci'] +setup-lints: + cargo binstall cargo-shear + +[group: 'ci'] +lints: + cargo clippy -- --deny warnings + cargo fmt --check + # Look for unused crates + cargo shear + From 5c544f87bccb850211f01c5f410d85fac9a9ad77 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 21 Dec 2024 17:09:22 +0100 Subject: [PATCH 058/162] Refactor out all panics. Use `anyhow` instead. --- Cargo.lock | 7 ++ Cargo.toml | 8 +- clippy.toml | 2 + crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 80 +++++++------ crates/cargo-gpu/src/install.rs | 79 ++++++------ crates/cargo-gpu/src/main.rs | 68 ++++++----- crates/cargo-gpu/src/show.rs | 8 +- crates/cargo-gpu/src/spirv_cli.rs | 54 ++++----- crates/cargo-gpu/src/spirv_source.rs | 172 ++++++++++++++++----------- crates/cargo-gpu/src/toml.rs | 79 ++++++------ crates/spirv-builder-cli/src/main.rs | 2 +- 12 files changed, 308 insertions(+), 252 deletions(-) create mode 100644 clippy.toml diff --git a/Cargo.lock b/Cargo.lock index 88ba813167..ec3345bc7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "anyhow" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" + [[package]] name = "autocfg" version = "1.4.0" @@ -82,6 +88,7 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" name = "cargo-gpu" version = "0.1.0" dependencies = [ + "anyhow", "chrono", "clap", "directories", diff --git a/Cargo.toml b/Cargo.toml index f8122deef9..a97e989027 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,9 @@ exclude = [ resolver = "2" [workspace.dependencies] +anyhow = "1.0.94" clap = { version = "4.4.8", features = ["derive"] } -chrono = { version = "0.4.38", default-features = false } +chrono = { version = "0.4.38", default-features = false, features = ["std"] } directories = "5.0.1" env_home = "0.1.0" env_logger = "0.10" @@ -51,9 +52,4 @@ pattern_type_mismatch = { level = "allow", priority = 1 } print_stdout = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } -# TODO: Try to not depend on allowing these lints -unwrap_used = { level = "allow", priority = 1 } -get_unwrap = { level = "allow", priority = 1 } -expect_used = { level = "allow", priority = 1 } -panic = { level = "allow", priority = 1 } diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000..f69b4a67f9 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,2 @@ +allow-unwrap-in-tests = true +allow-panic-in-tests = true diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index e6043d1bcc..e7ad33ce83 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -9,6 +9,7 @@ keywords = ["gpu", "compiler"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow.workspace = true spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false } clap.workspace = true directories.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index d26718a63b..b6f958a4d8 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -2,6 +2,7 @@ use std::io::Write as _; +use anyhow::Context as _; use clap::Parser; use spirv_builder_cli::{Linkage, ShaderModule}; @@ -33,35 +34,34 @@ pub struct Build { impl Build { /// Entrypoint - pub fn run(&mut self) { - let (dylib_path, spirv_builder_cli_path) = self.install.run(); + pub fn run(&mut self) -> anyhow::Result<()> { + let (dylib_path, spirv_builder_cli_path) = self.install.run()?; // Ensure the shader output dir exists log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); - std::fs::create_dir_all(&self.output_dir).unwrap(); - self.output_dir = self.output_dir.canonicalize().unwrap(); + std::fs::create_dir_all(&self.output_dir)?; + self.output_dir = self.output_dir.canonicalize()?; // Ensure the shader crate exists - self.install.shader_crate = self.install.shader_crate.canonicalize().unwrap(); - assert!( + self.install.shader_crate = self.install.shader_crate.canonicalize()?; + anyhow::ensure!( self.install.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", self.install.shader_crate.display(), - std::env::current_dir().unwrap().display() + std::env::current_dir()?.display() ); let spirv_builder_args = spirv_builder_cli::Args { dylib_path, shader_crate: self.install.shader_crate.clone(), shader_target: self.shader_target.clone(), - path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)), + path_to_target_spec: target_spec_dir()?.join(format!("{}.json", self.shader_target)), no_default_features: self.no_default_features, features: self.features.clone(), output_dir: self.output_dir.clone(), }; - // UNWRAP: safe because we know this always serializes - let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap(); + let arg = serde_json::to_string_pretty(&spirv_builder_args)?; log::info!("using spirv-builder-cli arg: {arg}"); // Call spirv-builder-cli to compile the shaders. @@ -69,9 +69,8 @@ impl Build { .arg(arg) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "build failed"); + .output()?; + anyhow::ensure!(output.status.success(), "build failed"); let spirv_manifest = self.output_dir.join("spirv-manifest.json"); if spirv_manifest.is_file() { @@ -81,51 +80,52 @@ impl Build { ); } else { log::error!("missing raw manifest '{}'", spirv_manifest.display()); - panic!("missing raw manifest"); + anyhow::bail!("missing raw manifest"); } let shaders: Vec = - serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap(); + serde_json::from_reader(std::fs::File::open(&spirv_manifest)?)?; - let mut linkage: Vec<_> = shaders + let mut linkage: Vec = shaders .into_iter() .map( |ShaderModule { entry, path: filepath, - }| { + }| + -> anyhow::Result { use relative_path::PathExt as _; - let path = self.output_dir.join(filepath.file_name().unwrap()); - std::fs::copy(&filepath, &path).unwrap(); - let path_relative_to_shader_crate = path - .relative_to(&self.install.shader_crate) - .unwrap() - .to_path(""); - Linkage::new(entry, path_relative_to_shader_crate) + let path = self.output_dir.join( + filepath + .file_name() + .context("Couldn't parse file name from shader module path")?, + ); + std::fs::copy(&filepath, &path)?; + let path_relative_to_shader_crate = + path.relative_to(&self.install.shader_crate)?.to_path(""); + Ok(Linkage::new(entry, path_relative_to_shader_crate)) }, ) - .collect(); + .collect::>>()?; // Write the shader manifest json file let manifest_path = self.output_dir.join("manifest.json"); // Sort the contents so the output is deterministic linkage.sort(); // UNWRAP: safe because we know this always serializes - let json = serde_json::to_string_pretty(&linkage).unwrap(); - let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|error| { - log::error!( - "could not create shader manifest file '{}': {error}", + let json = serde_json::to_string_pretty(&linkage)?; + let mut file = std::fs::File::create(&manifest_path).with_context(|| { + format!( + "could not create shader manifest file '{}'", manifest_path.display(), - ); - panic!("{error}") - }); - file.write_all(json.as_bytes()).unwrap_or_else(|error| { - log::error!( - "could not write shader manifest file '{}': {error}", + ) + })?; + file.write_all(json.as_bytes()).with_context(|| { + format!( + "could not write shader manifest file '{}'", manifest_path.display(), - ); - panic!("{error}") - }); + ) + })?; log::info!("wrote manifest to '{}'", manifest_path.display()); @@ -134,8 +134,10 @@ impl Build { "removing spirv-manifest.json file '{}'", spirv_manifest.display() ); - std::fs::remove_file(spirv_manifest).unwrap(); + std::fs::remove_file(spirv_manifest)?; } + + Ok(()) } } diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index ca73728667..ce02d737c0 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,6 +1,8 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. use std::io::Write as _; +use anyhow::Context as _; + use crate::{cache_dir, spirv_cli::SpirvCli, spirv_source::SpirvSource, target_spec_dir}; /// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. @@ -120,7 +122,7 @@ pub struct Install { impl Install { /// Returns a [`SpirvCLI`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. - fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> SpirvCli { + fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> anyhow::Result { SpirvCli::new( shader_crate_path, self.spirv_builder_source.clone(), @@ -130,20 +132,21 @@ impl Install { } /// Create the `spirv-builder-cli` crate. - fn write_source_files(&self) { - let spirv_cli = self.spirv_cli(&self.shader_crate); - let checkout = spirv_cli.cached_checkout_path(); - std::fs::create_dir_all(checkout.join("src")).unwrap(); + fn write_source_files(&self) -> anyhow::Result<()> { + let spirv_cli = self.spirv_cli(&self.shader_crate)?; + let checkout = spirv_cli.cached_checkout_path()?; + std::fs::create_dir_all(checkout.join("src"))?; for (filename, contents) in SPIRV_BUILDER_FILES { log::debug!("writing {filename}"); let path = checkout.join(filename); - let mut file = std::fs::File::create(&path).unwrap(); + let mut file = std::fs::File::create(&path)?; let mut replaced_contents = contents.replace("${CHANNEL}", &spirv_cli.channel); if filename == &"Cargo.toml" { replaced_contents = Self::update_cargo_toml(&replaced_contents, &spirv_cli.source); } - file.write_all(replaced_contents.as_bytes()).unwrap(); + file.write_all(replaced_contents.as_bytes())?; } + Ok(()) } /// Update the `Cargo.toml` file in the `spirv-builder-cli` crate so that it contains @@ -176,33 +179,30 @@ impl Install { } /// Add the target spec files to the crate. - fn write_target_spec_files(&self) { + fn write_target_spec_files(&self) -> anyhow::Result<()> { for (filename, contents) in TARGET_SPECS { - let path = target_spec_dir().join(filename); + let path = target_spec_dir()?.join(filename); if !path.is_file() || self.force_spirv_cli_rebuild { - let mut file = std::fs::File::create(&path).unwrap(); - file.write_all(contents.as_bytes()).unwrap(); + let mut file = std::fs::File::create(&path)?; + file.write_all(contents.as_bytes())?; } } + Ok(()) } /// Install the binary pair and return the paths, (dylib, cli). - pub fn run(&self) -> (std::path::PathBuf, std::path::PathBuf) { + pub fn run(&self) -> anyhow::Result<(std::path::PathBuf, std::path::PathBuf)> { // Ensure the cache dir exists - let cache_dir = cache_dir(); + let cache_dir = cache_dir()?; log::info!("cache directory is '{}'", cache_dir.display()); - std::fs::create_dir_all(&cache_dir).unwrap_or_else(|error| { - log::error!( - "could not create cache directory '{}': {error}", - cache_dir.display() - ); - panic!("could not create cache dir"); - }); + std::fs::create_dir_all(&cache_dir).with_context(|| { + format!("could not create cache directory '{}'", cache_dir.display()) + })?; - let spirv_version = self.spirv_cli(&self.shader_crate); - spirv_version.ensure_toolchain_and_components_exist(); + let spirv_version = self.spirv_cli(&self.shader_crate)?; + spirv_version.ensure_toolchain_and_components_exist()?; - let checkout = spirv_version.cached_checkout_path(); + let checkout = spirv_version.cached_checkout_path()?; let release = checkout.join("target").join("release"); let dylib_filename = format!( @@ -227,8 +227,8 @@ impl Install { "writing spirv-builder-cli source files into '{}'", checkout.display() ); - self.write_source_files(); - self.write_target_spec_files(); + self.write_source_files()?; + self.write_target_spec_files()?; let mut command = std::process::Command::new("cargo"); command @@ -239,7 +239,7 @@ impl Install { command.args([ "--features", - &Self::get_required_spirv_builder_version(spirv_version.date), + &Self::get_required_spirv_builder_version(spirv_version.date)?, ]); log::debug!("building artifacts with `{:?}`", command); @@ -247,16 +247,15 @@ impl Install { let output = command .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!(output.status.success(), "...build error!"); + .output()?; + anyhow::ensure!(output.status.success(), "...build error!"); if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); - std::fs::rename(&dylib_path, &dest_dylib_path).unwrap(); + std::fs::rename(&dylib_path, &dest_dylib_path)?; } else { log::error!("could not find {}", dylib_path.display()); - panic!("spirv-builder-cli build failed"); + anyhow::bail!("spirv-builder-cli build failed"); } let cli_path = if cfg!(target_os = "windows") { @@ -266,18 +265,18 @@ impl Install { }; if cli_path.is_file() { log::info!("successfully built {}", cli_path.display()); - std::fs::rename(&cli_path, &dest_cli_path).unwrap(); + std::fs::rename(&cli_path, &dest_cli_path)?; } else { log::error!("could not find {}", cli_path.display()); log::debug!("contents of '{}':", release.display()); - for maybe_entry in std::fs::read_dir(&release).unwrap() { - let entry = maybe_entry.unwrap(); + for maybe_entry in std::fs::read_dir(&release)? { + let entry = maybe_entry?; log::debug!("{}", entry.file_name().to_string_lossy()); } - panic!("spirv-builder-cli build failed"); + anyhow::bail!("spirv-builder-cli build failed"); } } - (dest_dylib_path, dest_cli_path) + Ok((dest_dylib_path, dest_cli_path)) } /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to @@ -287,15 +286,15 @@ impl Install { /// TODO: /// * Warn the user that certain `cargo-gpu` features aren't available when building with /// older versions of `spirv-builder`, eg setting the target spec. - fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> String { + fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> anyhow::Result { let parse_date = chrono::NaiveDate::parse_from_str; - let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d").unwrap(); + let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d")?; - if date < pre_cli_date { + Ok(if date < pre_cli_date { "spirv-builder-pre-cli" } else { "spirv-builder-0_10" } - .into() + .into()) } } diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 364b3e14e7..86167c01a9 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -50,6 +50,8 @@ //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. +use anyhow::Context as _; + use build::Build; use clap::Parser as _; use install::Install; @@ -63,7 +65,7 @@ mod spirv_cli; mod spirv_source; mod toml; -fn main() { +fn main() -> anyhow::Result<()> { env_logger::builder().init(); let args = std::env::args() @@ -79,19 +81,21 @@ fn main() { match cli.command { Command::Install(install) => { log::debug!("installing with arguments: {install:#?}"); - let (_, _) = install.run(); + let (_, _) = install.run()?; } Command::Build(mut build) => { log::debug!("building with arguments: {build:#?}"); - build.run(); + build.run()?; } Command::Toml(toml) => { log::debug!("building by toml file with arguments: {toml:#?}"); - toml.run(); + toml.run()?; } - Command::Show(show) => show.run(), - Command::DumpUsage => dump_full_usage_for_readme(), - } + Command::Show(show) => show.run()?, + Command::DumpUsage => dump_full_usage_for_readme()?, + }; + + Ok(()) } /// All of the available subcommands for `cargo gpu` @@ -125,48 +129,51 @@ pub(crate) struct Cli { command: Command, } -fn cache_dir() -> std::path::PathBuf { +fn cache_dir() -> anyhow::Result { let dir = directories::BaseDirs::new() - .unwrap_or_else(|| { - log::error!("could not find the user home directory"); - panic!("cache_dir failed"); - }) + .with_context(|| "could not find the user home directory")? .cache_dir() .join("rust-gpu"); - if cfg!(test) { + Ok(if cfg!(test) { let thread_id = std::thread::current().id(); let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); dir.join("tests").join(id) } else { dir - } + }) } /// Location of the target spec metadata files -fn target_spec_dir() -> std::path::PathBuf { - let dir = cache_dir().join("target-specs"); - std::fs::create_dir_all(&dir).unwrap(); - dir +fn target_spec_dir() -> anyhow::Result { + let dir = cache_dir()?.join("target-specs"); + std::fs::create_dir_all(&dir)?; + Ok(dir) } /// Convenience function for internal use. Dumps all the CLI usage instructions. Useful for /// updating the README. -fn dump_full_usage_for_readme() { +fn dump_full_usage_for_readme() -> anyhow::Result<()> { use clap::CommandFactory as _; let mut command = Cli::command(); let mut buffer: Vec = Vec::default(); command.build(); - write_help(&mut buffer, &mut command, 0); - println!("{}", String::from_utf8(buffer).unwrap()); + write_help(&mut buffer, &mut command, 0)?; + println!("{}", String::from_utf8(buffer)?); + + Ok(()) } /// Recursive function to print the usage instructions for each subcommand. -fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: usize) { +fn write_help( + buffer: &mut impl std::io::Write, + cmd: &mut clap::Command, + _depth: usize, +) -> anyhow::Result<()> { if cmd.get_name() == "help" { - return; + return Ok(()); } let mut command = cmd.get_name().to_owned(); @@ -175,16 +182,17 @@ fn write_help(buffer: &mut impl std::io::Write, cmd: &mut clap::Command, _depth: "\n* {}{}", command.remove(0).to_uppercase(), command - ) - .unwrap(); - writeln!(buffer).unwrap(); - cmd.write_long_help(buffer).unwrap(); + )?; + writeln!(buffer)?; + cmd.write_long_help(buffer)?; for sub in cmd.get_subcommands_mut() { - writeln!(buffer).unwrap(); + writeln!(buffer)?; #[expect(clippy::used_underscore_binding, reason = "Used in recursion only")] - write_help(buffer, sub, _depth + 1); + write_help(buffer, sub, _depth + 1)?; } + + Ok(()) } /// Returns a string suitable to use as a directory. @@ -210,7 +218,7 @@ mod test { } pub fn tests_teardown() { - let cache_dir = cache_dir(); + let cache_dir = cache_dir().unwrap(); if !cache_dir.exists() { return; } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index cc1e9d8fc4..c1668e228d 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -29,17 +29,19 @@ pub struct Show { impl Show { /// Entrypoint - pub fn run(self) { + pub fn run(self) -> anyhow::Result<()> { log::info!("{:?}: ", self.command); match self.command { Info::CacheDirectory => { - println!("{}", cache_dir().display()); + println!("{}", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = - crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate); + crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate)?; println!("{rust_gpu_source}"); } } + + Ok(()) } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 52c4c0e242..bc26ed946d 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -1,6 +1,8 @@ //! Query the shader crate to find what version of `rust-gpu` it depends on. //! Then ensure that the relevant Rust toolchain and components are installed. +use anyhow::Context as _; + use crate::spirv_source::SpirvSource; /// Cargo dependency for `spirv-builder` and the rust toolchain channel. @@ -40,9 +42,9 @@ impl SpirvCli { maybe_rust_gpu_source: Option, maybe_rust_gpu_version: Option, maybe_rust_gpu_channel: Option, - ) -> Self { + ) -> anyhow::Result { let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = - SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path); + SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path)?; let mut maybe_spirv_source: Option = None; if let Some(rust_gpu_version) = maybe_rust_gpu_version { @@ -56,27 +58,23 @@ impl SpirvCli { maybe_spirv_source = Some(source); } - Self { + Ok(Self { source: maybe_spirv_source.unwrap_or(default_rust_gpu_source), channel: maybe_rust_gpu_channel.unwrap_or(default_rust_gpu_channel), date: rust_gpu_date, - } + }) } /// Create and/or return the cache directory - pub fn cached_checkout_path(&self) -> std::path::PathBuf { - let checkout_dir = crate::cache_dir() + pub fn cached_checkout_path(&self) -> anyhow::Result { + let checkout_dir = crate::cache_dir()? .join("spirv-builder-cli") .join(crate::to_dirname(self.to_string().as_ref())); - std::fs::create_dir_all(&checkout_dir).unwrap_or_else(|error| { - log::error!( - "could not create checkout dir '{}': {error}", - checkout_dir.display() - ); - panic!("could not create checkout dir"); - }); + std::fs::create_dir_all(&checkout_dir).with_context(|| { + format!("could not create checkout dir '{}'", checkout_dir.display()) + })?; - checkout_dir + Ok(checkout_dir) } /// Use `rustup` to install the toolchain and components, if not already installed. @@ -85,13 +83,12 @@ impl SpirvCli { /// /// * rustup toolchain add nightly-2024-04-24 /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools - pub fn ensure_toolchain_and_components_exist(&self) { + pub fn ensure_toolchain_and_components_exist(&self) -> anyhow::Result<()> { // Check for the required toolchain let output_toolchain_list = std::process::Command::new("rustup") .args(["toolchain", "list"]) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_toolchain_list.status.success(), "could not list installed toolchains" ); @@ -107,9 +104,8 @@ impl SpirvCli { .arg(&self.channel) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_toolchain_add.status.success(), "could not install required toolchain" ); @@ -119,9 +115,8 @@ impl SpirvCli { let output_component_list = std::process::Command::new("rustup") .args(["component", "list", "--toolchain"]) .arg(&self.channel) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_component_list.status.success(), "could not list installed components" ); @@ -144,13 +139,14 @@ impl SpirvCli { .args(["rust-src", "rustc-dev", "llvm-tools"]) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_component_add.status.success(), "could not install required components" ); } + + Ok(()) } } @@ -161,8 +157,8 @@ mod test { #[test_log::test] fn cached_checkout_dir_sanity() { let shader_template_path = crate::test::shader_crate_template_path(); - let spirv = SpirvCli::new(&shader_template_path, None, None, None); - let dir = spirv.cached_checkout_path(); + let spirv = SpirvCli::new(&shader_template_path, None, None, None).unwrap(); + let dir = spirv.cached_checkout_path().unwrap(); let name = dir .file_name() .unwrap() diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index bd2f20009d..f6e0ac3e27 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -4,6 +4,8 @@ //! version. Then with that we `git checkout` the `rust-gpu` repo that corresponds to that version. //! From there we can look at the source code to get the required Rust toolchain. +use anyhow::Context as _; + /// The canonical `rust-gpu` URI const RUST_GPU_REPO: &str = "https://github.com/Rust-GPU/rust-gpu"; @@ -50,18 +52,18 @@ impl SpirvSource { /// Look into the shader crate to get the version of `rust-gpu` it's using. pub fn get_rust_gpu_deps_from_shader( shader_crate_path: &std::path::PathBuf, - ) -> (Self, chrono::NaiveDate, String) { - let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path); + ) -> anyhow::Result<(Self, chrono::NaiveDate, String)> { + let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path)?; - rust_gpu_source.ensure_repo_is_installed(); - rust_gpu_source.checkout(); + rust_gpu_source.ensure_repo_is_installed()?; + rust_gpu_source.checkout()?; - let date = rust_gpu_source.get_version_date(); - let channel = Self::get_channel_from_toolchain_toml(&rust_gpu_source.to_dirname()); + let date = rust_gpu_source.get_version_date()?; + let channel = Self::get_channel_from_toolchain_toml(&rust_gpu_source.to_dirname()?)?; log::debug!("Parsed version, date and toolchain channel from shader-defined `rust-gpu`: {rust_gpu_source:?}, {date}, {channel}"); - (rust_gpu_source, date, channel) + Ok((rust_gpu_source, date, channel)) } /// Convert the source to just its version. @@ -84,42 +86,43 @@ impl SpirvSource { /// Convert the `rust-gpu` source into a string that can be used as a directory. /// It needs to be dynamically created because an end-user might want to swap out the source, /// maybe using their own fork for example. - fn to_dirname(&self) -> std::path::PathBuf { + fn to_dirname(&self) -> anyhow::Result { let dir = crate::to_dirname(self.to_string().as_ref()); - crate::cache_dir().join("rust-gpu-repo").join(dir) + Ok(crate::cache_dir()?.join("rust-gpu-repo").join(dir)) } /// Checkout the `rust-gpu` repo to the requested version. - fn checkout(&self) { + fn checkout(&self) -> anyhow::Result<()> { log::debug!( "Checking out `rust-gpu` repo at {} to {}", - self.to_dirname().display(), + self.to_dirname()?.display(), self.to_version() ); let output_checkout = std::process::Command::new("git") - .current_dir(self.to_dirname()) + .current_dir(self.to_dirname()?) .args(["checkout", self.to_version().as_ref()]) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_checkout.status.success(), "couldn't checkout revision '{}' of `rust-gpu` at {}", self.to_version(), - self.to_dirname().to_string_lossy() + self.to_dirname()?.to_string_lossy() ); + + Ok(()) } /// Get the date of the version of `rust-gpu` used by the shader. This allows us to know what /// features we can use in the `spirv-builder` crate. - fn get_version_date(&self) -> chrono::NaiveDate { + fn get_version_date(&self) -> anyhow::Result { let date_format = "%Y-%m-%d"; log::debug!( "Getting `rust-gpu` version date from {}", - self.to_dirname().display(), + self.to_dirname()?.display(), ); let output_date = std::process::Command::new("git") - .current_dir(self.to_dirname()) + .current_dir(self.to_dirname()?) .args([ "show", "--no-patch", @@ -127,13 +130,12 @@ impl SpirvSource { format!("--date=format:'{date_format}'").as_ref(), self.to_version().as_ref(), ]) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_date.status.success(), "couldn't get `rust-gpu` version date at for {} at {}", self.to_version(), - self.to_dirname().to_string_lossy() + self.to_dirname()?.to_string_lossy() ); let date_string = String::from_utf8_lossy(&output_date.stdout) .to_string() @@ -145,47 +147,53 @@ impl SpirvSource { self.to_version() ); - chrono::NaiveDate::parse_from_str(&date_string, date_format).unwrap() + Ok(chrono::NaiveDate::parse_from_str( + &date_string, + date_format, + )?) } /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. - fn get_channel_from_toolchain_toml(path: &std::path::PathBuf) -> String { + fn get_channel_from_toolchain_toml(path: &std::path::PathBuf) -> anyhow::Result { log::debug!("Parsing `rust-toolchain.toml` at {path:?} for the used toolchain"); - let contents = std::fs::read_to_string(path.join("rust-toolchain.toml")).unwrap(); - let toml: toml::Table = toml::from_str(&contents).unwrap(); + let contents = std::fs::read_to_string(path.join("rust-toolchain.toml"))?; + let toml: toml::Table = toml::from_str(&contents)?; let Some(toolchain) = toml.get("toolchain") else { - panic!("Couldn't find `[toolchain]` section in `rust-toolchain.toml` at {path:?}"); + anyhow::bail!( + "Couldn't find `[toolchain]` section in `rust-toolchain.toml` at {path:?}" + ); }; let Some(channel) = toolchain.get("channel") else { - panic!("Couldn't find `channel` field in `rust-toolchain.toml` at {path:?}"); + anyhow::bail!("Couldn't find `channel` field in `rust-toolchain.toml` at {path:?}"); }; - channel.to_string().replace('"', "") + Ok(channel.to_string().replace('"', "")) } /// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml` - pub fn get_spirv_std_dep_definition(shader_crate_path: &std::path::PathBuf) -> Self { - let cwd = std::env::current_dir().expect("no cwd"); + pub fn get_spirv_std_dep_definition( + shader_crate_path: &std::path::PathBuf, + ) -> anyhow::Result { + let cwd = std::env::current_dir().context("no cwd")?; let exec_path = if shader_crate_path.is_absolute() { shader_crate_path.clone() } else { cwd.join(shader_crate_path) } .canonicalize() - .expect("could not get absolute path to shader crate"); + .context("could not get absolute path to shader crate")?; if !exec_path.is_dir() { log::error!("{exec_path:?} is not a directory, aborting"); - panic!("{exec_path:?} is not a directory"); + anyhow::bail!("{exec_path:?} is not a directory"); } log::debug!("Running `cargo tree` on {}", exec_path.display()); let output_cargo_tree = std::process::Command::new("cargo") .current_dir(&exec_path) .args(["tree", "--workspace", "--prefix", "none"]) - .output() - .unwrap(); - assert!( + .output()?; + anyhow::ensure!( output_cargo_tree.status.success(), "could not query shader's `Cargo.toml` for `spirv-std` dependency" ); @@ -197,7 +205,7 @@ impl SpirvSource { log::trace!(" found {maybe_spirv_std_def:?}"); let Some(spirv_std_def) = maybe_spirv_std_def else { - panic!("`spirv-std` not found in shader's `Cargo.toml` at {exec_path:?}:\n{cargo_tree_string}"); + anyhow::bail!("`spirv-std` not found in shader's `Cargo.toml` at {exec_path:?}:\n{cargo_tree_string}"); }; Self::parse_spirv_std_source_and_version(spirv_std_def) @@ -207,17 +215,20 @@ impl SpirvSource { /// `spirv-std v0.9.0 (https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c) (*)` /// Which would return: /// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")` - fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> Self { + fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> anyhow::Result { log::trace!("parsing spirv-std source and version from def: '{spirv_std_def}'"); let parts: Vec = spirv_std_def.split_whitespace().map(String::from).collect(); let version = parts .get(1) - .expect("Couldn't find `spirv_std` version in shader crate") + .context("Couldn't find `spirv_std` version in shader crate")? .to_owned(); let mut source = Self::CratesIO(version.clone()); if parts.len() > 2 { - let mut source_string = parts.get(2).unwrap().to_owned(); + let mut source_string = parts + .get(2) + .context("Couldn't get Uri from dependency string")? + .to_owned(); source_string = source_string.replace(['(', ')'], ""); // Unfortunately Uri ignores the fragment/hash portion of the Uri. @@ -226,7 +237,7 @@ impl SpirvSource { // // // So here we'll parse the fragment out of the source string by hand - let uri = source_string.parse::().unwrap(); + let uri = source_string.parse::()?; let maybe_hash = if source_string.contains('#') { let splits = source_string.split('#'); splits.last().map(std::borrow::ToOwned::to_owned) @@ -234,7 +245,7 @@ impl SpirvSource { None }; if uri.scheme().is_some() { - source = Self::parse_git_source(version, &uri, maybe_hash); + source = Self::parse_git_source(version, &uri, maybe_hash)?; } else { source = Self::Path((source_string, version)); } @@ -242,69 +253,90 @@ impl SpirvSource { log::debug!("Parsed `rust-gpu` source and version: {source:?}"); - source + Ok(source) } /// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c` - fn parse_git_source(version: String, uri: &http::Uri, fragment: Option) -> Self { + fn parse_git_source( + version: String, + uri: &http::Uri, + fragment: Option, + ) -> anyhow::Result { log::trace!( "parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}", fragment.as_deref().unwrap_or("?") ); let repo = format!( "{}://{}{}", - uri.scheme().unwrap(), - uri.host().unwrap(), + uri.scheme().context("Couldn't parse scheme from Uri")?, + uri.host().context("Couldn't parse host from Uri")?, uri.path() ); - let rev = uri.query().map_or_else( - || fragment.unwrap_or(version), - |query| { - let marker = "rev="; - let sanity_check = query.contains(marker) && query.split('=').count() == 2; - assert!(sanity_check, "revision not found in Git URI: {query}"); - query.replace(marker, "") - }, - ); + let rev = Self::parse_git_revision(uri.query(), fragment, version); + + Ok(Self::Git { url: repo, rev }) + } + + /// Decide the Git revision to use. + fn parse_git_revision( + maybe_query: Option<&str>, + maybe_fragment: Option, + version: String, + ) -> String { + let marker = "rev="; + let maybe_sane_query = maybe_query.and_then(|query| { + // TODO: This might seem a little crude, but it saves adding a whole query parsing dependency. + let sanity_check = query.contains(marker) && query.split('=').count() == 2; + sanity_check.then_some(query) + }); + + if let Some(query) = maybe_sane_query { + return query.replace(marker, ""); + } - Self::Git { url: repo, rev } + if let Some(fragment) = maybe_fragment { + return fragment; + } + + version } /// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile /// the shader. - fn ensure_repo_is_installed(&self) { - if self.to_dirname().exists() { + fn ensure_repo_is_installed(&self) -> anyhow::Result<()> { + if self.to_dirname()?.exists() { log::debug!( "Not cloning `rust-gpu` repo ({}) as it already exists at {}", self.to_repo(), - self.to_dirname().to_string_lossy().as_ref(), + self.to_dirname()?.to_string_lossy().as_ref(), ); - return; + return Ok(()); } log::debug!( "Cloning `rust-gpu` repo {} to {}", self.to_repo(), - self.to_dirname().to_string_lossy().as_ref(), + self.to_dirname()?.to_string_lossy().as_ref(), ); let output_clone = std::process::Command::new("git") .args([ "clone", self.to_repo().as_ref(), - self.to_dirname().to_string_lossy().as_ref(), + self.to_dirname()?.to_string_lossy().as_ref(), ]) - .output() - .unwrap(); + .output()?; - assert!( + anyhow::ensure!( output_clone.status.success(), "couldn't clone `rust-gpu` {} to {}\n{}", self.to_repo(), - self.to_dirname().to_string_lossy(), + self.to_dirname()?.to_string_lossy(), String::from_utf8_lossy(&output_clone.stderr) ); + + Ok(()) } } @@ -315,7 +347,7 @@ mod test { #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { let shader_template_path = crate::test::shader_crate_template_path(); - let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path); + let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path).unwrap(); assert_eq!( source, SpirvSource::Git { @@ -329,7 +361,7 @@ mod test { fn parsing_spirv_std_dep_for_git_source() { let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69) (*)"; - let source = SpirvSource::parse_spirv_std_source_and_version(definition); + let source = SpirvSource::parse_spirv_std_source_and_version(definition).unwrap(); assert_eq!( source, SpirvSource::Git { @@ -342,7 +374,7 @@ mod test { #[test_log::test] fn parsing_spirv_std_dep_for_git_source_hash() { let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)"; - let source = SpirvSource::parse_spirv_std_source_and_version(definition); + let source = SpirvSource::parse_spirv_std_source_and_version(definition).unwrap(); assert_eq!( source, SpirvSource::Git { diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index f067f5a038..69a5f53b1f 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -1,5 +1,7 @@ //! Build a shader based on the data in the `[package.metadata.rust-gpu.build.spirv-builder]` section of //! a shader's `Cargo.toml`. + +use anyhow::Context as _; use clap::Parser; use crate::{Cli, Command}; @@ -36,39 +38,42 @@ pub struct Toml { impl Toml { /// Entrypoint - pub fn run(&self) { - let (path, toml) = Self::parse_cargo_toml(self.path.clone()); + pub fn run(&self) -> anyhow::Result<()> { + let (path, toml) = Self::parse_cargo_toml(self.path.clone())?; + let working_directory = path + .parent() + .context("Couldn't find parent for shader's `Cargo.toml`")?; // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml let (toml_type, table) = if toml.contains_key("workspace") { let table = Self::get_metadata_rustgpu_table(&toml, "workspace") - .unwrap_or_else(|| { - panic!( + .with_context(|| { + format!( "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", path.display() - ); - }) + ) + })? .clone(); ("workspace", table) } else if toml.contains_key("package") { let mut table = Self::get_metadata_rustgpu_table(&toml, "package") - .unwrap_or_else(|| { - panic!( + .with_context(|| { + format!( "toml file '{}' is missing a [package.metadata.rust-gpu] table", path.display() - ); - }) + ) + })? .clone(); // Ensure the package name is included as the shader-crate parameter if !table.contains_key("shader-crate") { table.insert( "shader-crate".to_owned(), - format!("{}", path.parent().unwrap().display()).into(), + format!("{}", working_directory.display()).into(), ); } ("package", table) } else { - panic!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); + anyhow::bail!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); }; log::info!( "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", @@ -76,34 +81,36 @@ impl Toml { ); log::debug!("table: {table:#?}"); - let mut parameters = table + let mut parameters: Vec = table .get("build") - .unwrap_or_else(|| panic!("toml is missing the 'build' table")) + .with_context(|| "toml is missing the 'build' table")? .as_table() - .unwrap_or_else(|| { - panic!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") - }) + .with_context(|| { + format!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") + })? .into_iter() - .flat_map(|(key, val)| { - if let toml::Value::String(string) = val { - [format!("--{key}"), string.clone()] + .map(|(key, val)| -> anyhow::Result> { + Ok(if let toml::Value::String(string) = val { + [format!("--{key}"), string.clone()].into() } else { let mut value = String::new(); let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(val, ser).unwrap(); - [format!("--{key}"), value] - } + serde::Serialize::serialize(val, ser)?; + [format!("--{key}"), value].into() + }) }) - .collect::>(); + .collect::>>>()? + .into_iter() + .flatten() + .collect(); parameters.insert(0, "cargo-gpu".to_owned()); parameters.insert(1, "build".to_owned()); - let working_directory = path.parent().unwrap(); log::info!( "issuing cargo commands from the working directory '{}'", working_directory.display() ); - std::env::set_current_dir(working_directory).unwrap(); + std::env::set_current_dir(working_directory)?; log::debug!("build parameters: {parameters:#?}"); if let Cli { @@ -112,20 +119,24 @@ impl Toml { { // Ensure that the output directory is relative to the toml file if build.output_dir.is_relative() { - let dir = path.parent().expect("no path parent"); + let dir = path.parent().context("no path parent")?; build.output_dir = dir.join(build.output_dir); } log::debug!("build: {build:?}"); - build.run(); + build.run()?; } else { log::error!("parameters found in [{toml_type}.metadata.rust-gpu.build] were not parameters to `cargo gpu build`"); - panic!("could not determin build command"); + anyhow::bail!("could not determin build command"); } + + Ok(()) } /// Parse the contents of the shader's `Cargo.toml` - pub fn parse_cargo_toml(mut path: std::path::PathBuf) -> (std::path::PathBuf, toml::Table) { + pub fn parse_cargo_toml( + mut path: std::path::PathBuf, + ) -> anyhow::Result<(std::path::PathBuf, toml::Table)> { // Find the path to the toml file to use let parsed_path = if path.is_file() && path.ends_with(".toml") { path @@ -135,16 +146,16 @@ impl Toml { path } else { log::error!("toml file '{}' is not a file", path.display()); - panic!("toml file '{}' is not a file", path.display()); + anyhow::bail!("toml file '{}' is not a file", path.display()); } }; log::info!("using toml file '{}'", parsed_path.display()); - let contents = std::fs::read_to_string(&parsed_path).unwrap(); - let toml: toml::Table = toml::from_str(&contents).unwrap(); + let contents = std::fs::read_to_string(&parsed_path)?; + let toml: toml::Table = toml::from_str(&contents)?; - (parsed_path, toml) + Ok((parsed_path, toml)) } /// Parse the `[package.metadata.rust-gpu]` section. diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 496c2cc66a..09b2780869 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -99,7 +99,7 @@ fn main() { let mut shaders = vec![]; match module { ModuleResult::MultiModule(modules) => { - assert!(!modules.is_empty(), "No shader modules to compile"); + anyhow::ensure!(!modules.is_empty(), "No shader modules to compile"); for (entry, filepath) in modules.into_iter() { log::debug!("compiled {entry} {}", filepath.display()); shaders.push(ShaderModule::new(entry, filepath)); From 9dc0c0337d4bbc6c786f83587abac482332537f1 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 21 Dec 2024 20:49:02 +0100 Subject: [PATCH 059/162] Ask user if they want to install new toolchains Also add some user output for the major steps of installing toolchains, compiling `spirv-builder-cli` and compiling the actual shader. Surprisingly there's no way in the standard library to get a single keypress from the user! There's ways to get a line, therefore a keypress then a newline, but that's not so conventional for responding to a "y/n" prompt. Fixes #14 --- Cargo.lock | 151 +++++++++++++++++++++++++++ Cargo.toml | 2 +- README.md | 45 +++++++- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 8 +- crates/cargo-gpu/src/install.rs | 10 ++ crates/cargo-gpu/src/main.rs | 46 +++++++- crates/cargo-gpu/src/show.rs | 4 +- crates/cargo-gpu/src/spirv_cli.rs | 37 ++++++- crates/cargo-gpu/src/spirv_source.rs | 2 + crates/spirv-builder-cli/Cargo.toml | 5 + crates/spirv-builder-cli/src/main.rs | 2 +- justfile | 2 +- 13 files changed, 300 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ec3345bc7a..607acfe309 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,6 +91,7 @@ dependencies = [ "anyhow", "chrono", "clap", + "crossterm", "directories", "env_logger 0.10.2", "http", @@ -164,6 +165,31 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags", + "crossterm_winapi", + "mio", + "parking_lot", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "directories" version = "5.0.1" @@ -231,6 +257,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -338,6 +374,22 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.22" @@ -359,6 +411,18 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -396,6 +460,29 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "pin-project-lite" version = "0.2.15" @@ -420,6 +507,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.4.6" @@ -481,12 +577,31 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "rustix" +version = "0.38.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.214" @@ -537,6 +652,42 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "spirv-builder-cli" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a97e989027..a23359ed75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ resolver = "2" anyhow = "1.0.94" clap = { version = "4.4.8", features = ["derive"] } chrono = { version = "0.4.38", default-features = false, features = ["std"] } +crossterm = "0.28.1" directories = "5.0.1" env_home = "0.1.0" env_logger = "0.10" @@ -49,7 +50,6 @@ multiple_crate_versions = { level = "allow", priority = 1 } pub_with_shorthand = { level = "allow", priority = 1 } partial_pub_fields = { level = "allow", priority = 1 } pattern_type_mismatch = { level = "allow", priority = 1 } -print_stdout = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } diff --git a/README.md b/README.md index e0a2b1fe87..ace69f4bd6 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,9 @@ Options: --force-spirv-cli-rebuild Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + --auto-install-rust-toolchain + Assume "yes" to "Install Rust toolchain: [y/n]" prompt + -h, --help Print help (see a summary with '-h') @@ -134,6 +137,9 @@ Options: --force-spirv-cli-rebuild Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + --auto-install-rust-toolchain + Assume "yes" to "Install Rust toolchain: [y/n]" prompt + --shader-target Shader target @@ -197,13 +203,44 @@ Options: Show some useful values -Usage: cargo-gpu show [OPTIONS] +Usage: cargo-gpu show -Options: - --cache-directory - Displays the location of the cache directory +Commands: + cache-directory Displays the location of the cache directory + spirv-source The source location of spirv-std + help Print this message or the help of the given subcommand(s) +Options: -h, --help Print help + + * Cache-directory + + Displays the location of the cache directory + + Usage: cargo-gpu show cache-directory + + Options: + -h, --help + Print help + + + * Spirv-source + + The source location of spirv-std + + Usage: cargo-gpu show spirv-source [OPTIONS] + + Options: + --shader-crate + The location of the shader-crate to inspect to determine its spirv-std dependency + + [default: ./] + + -h, --help + Print help + + + ```` diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index e7ad33ce83..b05cd68304 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -21,6 +21,7 @@ serde_json.workspace = true toml.workspace = true chrono.workspace = true http.workspace = true +crossterm.workspace = true [dev-dependencies] test-log.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index b6f958a4d8..0f7bf6870d 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -1,7 +1,5 @@ //! `cargo gpu build`, analogous to `cargo build` -use std::io::Write as _; - use anyhow::Context as _; use clap::Parser; use spirv_builder_cli::{Linkage, ShaderModule}; @@ -64,6 +62,11 @@ impl Build { let arg = serde_json::to_string_pretty(&spirv_builder_args)?; log::info!("using spirv-builder-cli arg: {arg}"); + crate::user_output!( + "Running `spirv-builder-cli` to compile shader at {}...\n", + self.install.shader_crate.display() + ); + // Call spirv-builder-cli to compile the shaders. let output = std::process::Command::new(spirv_builder_cli_path) .arg(arg) @@ -112,7 +115,6 @@ impl Build { let manifest_path = self.output_dir.join("manifest.json"); // Sort the contents so the output is deterministic linkage.sort(); - // UNWRAP: safe because we know this always serializes let json = serde_json::to_string_pretty(&linkage)?; let mut file = std::fs::File::create(&manifest_path).with_context(|| { format!( diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index ce02d737c0..c6e3eefea3 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -118,6 +118,10 @@ pub struct Install { /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. #[clap(long)] force_spirv_cli_rebuild: bool, + + /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. + #[clap(long, action)] + auto_install_rust_toolchain: bool, } impl Install { @@ -128,6 +132,7 @@ impl Install { self.spirv_builder_source.clone(), self.spirv_builder_version.clone(), self.rust_toolchain.clone(), + self.auto_install_rust_toolchain, ) } @@ -230,6 +235,11 @@ impl Install { self.write_source_files()?; self.write_target_spec_files()?; + crate::user_output!( + "Compiling shader-specific `spirv-builder-cli` for {}\n", + self.shader_crate.display() + ); + let mut command = std::process::Command::new("cargo"); command .current_dir(&checkout) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 86167c01a9..1c11f4f93e 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -65,9 +65,51 @@ mod spirv_cli; mod spirv_source; mod toml; -fn main() -> anyhow::Result<()> { +/// Central function to write to the user. +#[macro_export] +macro_rules! user_output { + ($($args: tt)*) => { + #[allow( + clippy::allow_attributes, + clippy::useless_attribute, + unused_imports, + reason = "`std::io::Write` is only sometimes called??" + )] + use std::io::Write as _; + + #[expect( + clippy::non_ascii_literal, + reason = "CRAB GOOD. CRAB IMPORTANT." + )] + { + print!("🦀 "); + } + print!($($args)*); + std::io::stdout().flush().unwrap(); + } +} + +fn main() { + #[cfg(debug_assertions)] + std::env::set_var("RUST_BACKTRACE", "1"); + env_logger::builder().init(); + if let Err(error) = run() { + log::error!("{error:?}"); + + #[expect( + clippy::print_stderr, + reason = "Our central place for outputting error messages" + )] + { + eprintln!("Error: {error}"); + } + }; +} + +/// Wrappable "main" to catch errors. +fn run() -> anyhow::Result<()> { let args = std::env::args() .filter(|arg| { // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" @@ -161,7 +203,7 @@ fn dump_full_usage_for_readme() -> anyhow::Result<()> { command.build(); write_help(&mut buffer, &mut command, 0)?; - println!("{}", String::from_utf8(buffer)?); + user_output!("{}", String::from_utf8(buffer)?); Ok(()) } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index c1668e228d..cc9c6230a0 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -33,12 +33,12 @@ impl Show { log::info!("{:?}: ", self.command); match self.command { Info::CacheDirectory => { - println!("{}", cache_dir()?.display()); + crate::user_output!("{}\n", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate)?; - println!("{rust_gpu_source}"); + crate::user_output!("{rust_gpu_source}\n"); } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index bc26ed946d..13813f9bc4 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -23,6 +23,8 @@ pub struct SpirvCli { pub channel: String, /// The date of the pinned version of `rust-gpu` pub date: chrono::NaiveDate, + /// Has the user overridden the toolchain consent prompt + is_toolchain_install_consent: bool, } impl core::fmt::Display for SpirvCli { @@ -42,6 +44,7 @@ impl SpirvCli { maybe_rust_gpu_source: Option, maybe_rust_gpu_version: Option, maybe_rust_gpu_channel: Option, + is_toolchain_install_consent: bool, ) -> anyhow::Result { let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path)?; @@ -62,6 +65,7 @@ impl SpirvCli { source: maybe_spirv_source.unwrap_or(default_rust_gpu_source), channel: maybe_rust_gpu_channel.unwrap_or(default_rust_gpu_channel), date: rust_gpu_date, + is_toolchain_install_consent, }) } @@ -99,6 +103,10 @@ impl SpirvCli { { log::debug!("toolchain {} is already installed", self.channel); } else { + self.get_consent_for_toolchain_install( + format!("Install Rust {} with `rustup`", self.channel).as_ref(), + )?; + let output_toolchain_add = std::process::Command::new("rustup") .args(["toolchain", "add"]) .arg(&self.channel) @@ -133,6 +141,10 @@ impl SpirvCli { if all_components_installed { log::debug!("all required components are installed"); } else { + self.get_consent_for_toolchain_install( + "Install toolchain components (rust-src, rustc-dev, llvm-tools) with `rustup`", + )?; + let output_component_add = std::process::Command::new("rustup") .args(["component", "add", "--toolchain"]) .arg(&self.channel) @@ -148,6 +160,29 @@ impl SpirvCli { Ok(()) } + + /// Prompt user if they want to install a new Rust toolchain. + fn get_consent_for_toolchain_install(&self, prompt: &str) -> anyhow::Result<()> { + if self.is_toolchain_install_consent { + return Ok(()); + } + crossterm::terminal::enable_raw_mode()?; + crate::user_output!("{prompt} [y/n]: "); + let input = crossterm::event::read()?; + crossterm::terminal::disable_raw_mode()?; + crate::user_output!("{:?}\n", input); + + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { + code: crossterm::event::KeyCode::Char('y'), + .. + }) = input + { + Ok(()) + } else { + crate::user_output!("Exiting...\n"); + std::process::exit(0); + } + } } #[cfg(test)] @@ -157,7 +192,7 @@ mod test { #[test_log::test] fn cached_checkout_dir_sanity() { let shader_template_path = crate::test::shader_crate_template_path(); - let spirv = SpirvCli::new(&shader_template_path, None, None, None).unwrap(); + let spirv = SpirvCli::new(&shader_template_path, None, None, None, true).unwrap(); let dir = spirv.cached_checkout_path().unwrap(); let name = dir .file_name() diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index f6e0ac3e27..d98fde9df7 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -320,6 +320,8 @@ impl SpirvSource { self.to_dirname()?.to_string_lossy().as_ref(), ); + crate::user_output!("Cloning `rust-gpu` repo..."); + let output_clone = std::process::Command::new("git") .args([ "clone", diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index c89b824612..6723c5b8a1 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -41,3 +41,8 @@ package = "spirv-builder" optional = true git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} rev = "60dcb82" # ${AUTO-REPLACE-VERSION} + +[lints.rust] +# This crate is most often run by end users compiling their shaders so it's not so relevant +# for them to see warnings. +warnings = "allow" diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 09b2780869..496c2cc66a 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -99,7 +99,7 @@ fn main() { let mut shaders = vec![]; match module { ModuleResult::MultiModule(modules) => { - anyhow::ensure!(!modules.is_empty(), "No shader modules to compile"); + assert!(!modules.is_empty(), "No shader modules to compile"); for (entry, filepath) in modules.into_iter() { log::debug!("compiled {entry} {}", filepath.display()); shaders.push(ShaderModule::new(entry, filepath)); diff --git a/justfile b/justfile index 1f53c294bb..ff42105c05 100644 --- a/justfile +++ b/justfile @@ -1,7 +1,7 @@ [group: 'ci'] build-shader-template: cargo install --path crates/cargo-gpu - cargo gpu install --shader-crate crates/shader-crate-template + cargo gpu install --shader-crate crates/shader-crate-template --auto-install-rust-toolchain cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders ls -lah test-shaders cat test-shaders/manifest.json From 40d1380a6bd58fa885dcd105262eaf879d1b39f7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 28 Dec 2024 09:18:18 +1300 Subject: [PATCH 060/162] don't mess with the output_dir parameter in the toml file --- crates/cargo-gpu/src/build.rs | 4 +++- crates/cargo-gpu/src/toml.rs | 6 ------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 0f7bf6870d..fce6e363ef 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -38,7 +38,9 @@ impl Build { // Ensure the shader output dir exists log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); std::fs::create_dir_all(&self.output_dir)?; - self.output_dir = self.output_dir.canonicalize()?; + let canonicalized = self.output_dir.canonicalize()?; + log::debug!("canonicalized output dir: {canonicalized:?}"); + self.output_dir = canonicalized; // Ensure the shader crate exists self.install.shader_crate = self.install.shader_crate.canonicalize()?; diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index 69a5f53b1f..8010afb8bf 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -117,12 +117,6 @@ impl Toml { command: Command::Build(mut build), } = Cli::parse_from(parameters) { - // Ensure that the output directory is relative to the toml file - if build.output_dir.is_relative() { - let dir = path.parent().context("no path parent")?; - build.output_dir = dir.join(build.output_dir); - } - log::debug!("build: {build:?}"); build.run()?; } else { From dbf193e5f5ef14acbc1a1bd24d92e275c89a9556 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 28 Dec 2024 11:30:42 +1300 Subject: [PATCH 061/162] don't prefix crabs on `cargo gpu show` output --- crates/cargo-gpu/src/show.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index cc9c6230a0..814c057a5a 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -31,14 +31,22 @@ impl Show { /// Entrypoint pub fn run(self) -> anyhow::Result<()> { log::info!("{:?}: ", self.command); + + #[expect( + clippy::print_stdout, + reason = "The output of this command could potentially be used in a script, \ + so we _don't_ want to use `crate::user_output`, as that prefixes a crab." + )] match self.command { Info::CacheDirectory => { - crate::user_output!("{}\n", cache_dir()?.display()); + println!("{}\n", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate)?; - crate::user_output!("{rust_gpu_source}\n"); + { + println!("{rust_gpu_source}\n"); + } } } From d63eb21733ecaefc3e2f22525e635edadd4b5e55 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 30 Dec 2024 07:41:30 +1300 Subject: [PATCH 062/162] feature: treat boolean values in toml files as flags --- crates/cargo-gpu/src/spirv_cli.rs | 1 + crates/cargo-gpu/src/toml.rs | 84 ++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 13813f9bc4..d2cf649c67 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -166,6 +166,7 @@ impl SpirvCli { if self.is_toolchain_install_consent { return Ok(()); } + log::debug!("asking for consent to install the required toolchain"); crossterm::terminal::enable_raw_mode()?; crate::user_output!("{prompt} [y/n]: "); let input = crossterm::event::read()?; diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index 8010afb8bf..b54c26765a 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -75,43 +75,20 @@ impl Toml { } else { anyhow::bail!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); }; + log::info!( "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", path.display() ); log::debug!("table: {table:#?}"); - let mut parameters: Vec = table - .get("build") - .with_context(|| "toml is missing the 'build' table")? - .as_table() - .with_context(|| { - format!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") - })? - .into_iter() - .map(|(key, val)| -> anyhow::Result> { - Ok(if let toml::Value::String(string) = val { - [format!("--{key}"), string.clone()].into() - } else { - let mut value = String::new(); - let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(val, ser)?; - [format!("--{key}"), value].into() - }) - }) - .collect::>>>()? - .into_iter() - .flatten() - .collect(); - parameters.insert(0, "cargo-gpu".to_owned()); - parameters.insert(1, "build".to_owned()); - log::info!( "issuing cargo commands from the working directory '{}'", working_directory.display() ); std::env::set_current_dir(working_directory)?; + let parameters = construct_build_parameters_from_toml_table(toml_type, table)?; log::debug!("build parameters: {parameters:#?}"); if let Cli { command: Command::Build(mut build), @@ -162,3 +139,60 @@ impl Toml { metadata.get("rust-gpu")?.as_table() } } + +/// Construct the cli parameters to run a `cargo gpu build` command from a TOML table. +fn construct_build_parameters_from_toml_table( + toml_type: &str, + mut table: toml::map::Map, +) -> Result, anyhow::Error> { + let build_table = table + .get_mut("build") + .with_context(|| "toml is missing the 'build' table")? + .as_table_mut() + .with_context(|| { + format!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") + })?; + let auto_install_rust_toolchain = if build_table.contains_key("auto_install_rust_toolchain") { + build_table + .remove("auto_install_rust_toolchain") + .context("unreachable")? + .as_bool() + .context("auto_install_rust_toolchain must be bool")? + } else { + false + }; + let mut parameters: Vec = build_table + .into_iter() + .map(|(key, val)| -> anyhow::Result> { + Ok(match val { + toml::Value::String(string) => vec![format!("--{key}"), string.clone()], + toml::Value::Boolean(truthy) => { + if *truthy { + vec![format!("--{key}")] + } else { + vec![] + } + } + toml::Value::Integer(_) + | toml::Value::Float(_) + | toml::Value::Datetime(_) + | toml::Value::Array(_) + | toml::Value::Table(_) => { + let mut value = String::new(); + let ser = toml::ser::ValueSerializer::new(&mut value); + serde::Serialize::serialize(val, ser)?; + vec![format!("--{key}"), value] + } + }) + }) + .collect::>>>()? + .into_iter() + .flatten() + .collect(); + parameters.insert(0, "cargo-gpu".to_owned()); + parameters.insert(1, "build".to_owned()); + if auto_install_rust_toolchain { + parameters.push("--auto_install_rust_toolchain".to_owned()); + } + Ok(parameters) +} From baeaa636697dda633f03aeff37796435c0b79bb5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 30 Dec 2024 09:55:43 +1300 Subject: [PATCH 063/162] don't need to handle any flags explicitly --- crates/cargo-gpu/src/toml.rs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs index b54c26765a..c43146776c 100644 --- a/crates/cargo-gpu/src/toml.rs +++ b/crates/cargo-gpu/src/toml.rs @@ -88,7 +88,7 @@ impl Toml { ); std::env::set_current_dir(working_directory)?; - let parameters = construct_build_parameters_from_toml_table(toml_type, table)?; + let parameters = construct_build_parameters_from_toml_table(toml_type, &table)?; log::debug!("build parameters: {parameters:#?}"); if let Cli { command: Command::Build(mut build), @@ -143,24 +143,15 @@ impl Toml { /// Construct the cli parameters to run a `cargo gpu build` command from a TOML table. fn construct_build_parameters_from_toml_table( toml_type: &str, - mut table: toml::map::Map, + table: &toml::map::Map, ) -> Result, anyhow::Error> { let build_table = table - .get_mut("build") + .get("build") .with_context(|| "toml is missing the 'build' table")? - .as_table_mut() + .as_table() .with_context(|| { format!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") })?; - let auto_install_rust_toolchain = if build_table.contains_key("auto_install_rust_toolchain") { - build_table - .remove("auto_install_rust_toolchain") - .context("unreachable")? - .as_bool() - .context("auto_install_rust_toolchain must be bool")? - } else { - false - }; let mut parameters: Vec = build_table .into_iter() .map(|(key, val)| -> anyhow::Result> { @@ -191,8 +182,5 @@ fn construct_build_parameters_from_toml_table( .collect(); parameters.insert(0, "cargo-gpu".to_owned()); parameters.insert(1, "build".to_owned()); - if auto_install_rust_toolchain { - parameters.push("--auto_install_rust_toolchain".to_owned()); - } Ok(parameters) } From c95dcc7f3d7cb7eeaf611d16c05470fbf050809b Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 8 Jan 2025 17:05:53 +1300 Subject: [PATCH 064/162] show git commit revision command --- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/build.rs | 12 ++++++++++++ crates/cargo-gpu/src/show.rs | 5 +++++ 3 files changed, 18 insertions(+) create mode 100644 crates/cargo-gpu/build.rs diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index b05cd68304..60007154ab 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -6,6 +6,7 @@ description = "Generates shader .spv files from rust-gpu shader crates" repository = "https://github.com/Rust-GPU/cargo-gpu" readme = "../../README.md" keywords = ["gpu", "compiler"] +build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/cargo-gpu/build.rs b/crates/cargo-gpu/build.rs new file mode 100644 index 0000000000..31a33575ce --- /dev/null +++ b/crates/cargo-gpu/build.rs @@ -0,0 +1,12 @@ +//! cargo-gpu build script. + +fn main() { + let git_hash = std::process::Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .map_or_else( + |_| "unknown".to_owned(), + |output| String::from_utf8(output.stdout).unwrap_or_else(|_| "unknown".to_owned()), + ); + println!("cargo:rustc-env=GIT_HASH={git_hash}"); +} diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 814c057a5a..3fb8c721e7 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -17,6 +17,8 @@ pub enum Info { CacheDirectory, /// The source location of spirv-std SpirvSource(SpirvSourceDep), + /// The git commitsh of this cli tool. + Commitsh, } /// `cargo gpu show` @@ -48,6 +50,9 @@ impl Show { println!("{rust_gpu_source}\n"); } } + Info::Commitsh => { + println!("{}", std::env!("GIT_HASH")); + } } Ok(()) From 92cd18a232a0e951c853d3c6621d896f9b298be0 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 22 Dec 2024 12:02:52 +0100 Subject: [PATCH 065/162] Exit with error code 1 on error --- crates/cargo-gpu/src/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 1c11f4f93e..c180973393 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -104,7 +104,12 @@ fn main() { )] { eprintln!("Error: {error}"); - } + + // `clippy::exit` seems to be a false positive in `main()`. + // See: https://github.com/rust-lang/rust-clippy/issues/13518 + #[expect(clippy::restriction, reason = "Our central place for safely exiting")] + std::process::exit(1); + }; }; } From 70224f6447b64007ff4d09ea8a20a329c9c7c1ca Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 22 Dec 2024 12:06:36 +0100 Subject: [PATCH 066/162] Output "installing..." message after consent prompt This is particularly useful when `--auto-install-rust-toolchain` is used as the consent prompt isn't show and no indication at all of what's happening was given. --- crates/cargo-gpu/src/spirv_cli.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index d2cf649c67..4e07a735fe 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -103,9 +103,9 @@ impl SpirvCli { { log::debug!("toolchain {} is already installed", self.channel); } else { - self.get_consent_for_toolchain_install( - format!("Install Rust {} with `rustup`", self.channel).as_ref(), - )?; + let message = format!("Rust {} with `rustup`", self.channel); + self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; + crate::user_output!("Installing {message}"); let output_toolchain_add = std::process::Command::new("rustup") .args(["toolchain", "add"]) @@ -141,9 +141,9 @@ impl SpirvCli { if all_components_installed { log::debug!("all required components are installed"); } else { - self.get_consent_for_toolchain_install( - "Install toolchain components (rust-src, rustc-dev, llvm-tools) with `rustup`", - )?; + let message = "toolchain components (rust-src, rustc-dev, llvm-tools) with `rustup`"; + self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; + crate::user_output!("Installing {message}"); let output_component_add = std::process::Command::new("rustup") .args(["component", "add", "--toolchain"]) From 95efce2da340fac2b5935494524020a60fe35e05 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 5 Jan 2025 19:37:28 -0300 Subject: [PATCH 067/162] Support for setting config in shader's `Cargo.toml` Values are set in the TOML section: `[package.metadata.rust-gpu.*]`. So now the priority, from least to most, is: * Workspace metadata * Shader crate's metadata * CLI args Fixes #15 Notable changes: * All `clap` args for the `build` and `install` subcommands are now defined in the `spirv-builder-cli` crate. This makes passing all the config between `cargo gpu` and `spirv-builder-cli` trivial as `serde` now does all the heavy lifting of creating and reading the JSON arguments. * There is no longer a `toml` subcommand. The shader crate's `Cargo.toml`s are always read and their configs used as the base for CLI args to override. --- Cargo.lock | 15 ++ Cargo.toml | 6 +- README.md | 248 ++++++++++++------------ crates/cargo-gpu/Cargo.toml | 2 +- crates/cargo-gpu/src/build.rs | 87 ++++----- crates/cargo-gpu/src/config.rs | 236 ++++++++++++++++++++++ crates/cargo-gpu/src/install.rs | 72 +++---- crates/cargo-gpu/src/main.rs | 93 ++++++--- crates/cargo-gpu/src/metadata.rs | 197 +++++++++++++++++++ crates/cargo-gpu/src/spirv_cli.rs | 6 +- crates/cargo-gpu/src/spirv_source.rs | 2 +- crates/cargo-gpu/src/toml.rs | 186 ------------------ crates/shader-crate-template/Cargo.toml | 73 ++++++- crates/spirv-builder-cli/Cargo.lock | 125 ++++++++++++ crates/spirv-builder-cli/Cargo.toml | 11 +- crates/spirv-builder-cli/src/args.rs | 165 ++++++++++++++++ crates/spirv-builder-cli/src/lib.rs | 29 +-- crates/spirv-builder-cli/src/main.rs | 72 ++++--- justfile | 6 +- scripts/build_shader_template.sh | 21 ++ 20 files changed, 1149 insertions(+), 503 deletions(-) create mode 100644 crates/cargo-gpu/src/config.rs create mode 100644 crates/cargo-gpu/src/metadata.rs delete mode 100644 crates/cargo-gpu/src/toml.rs create mode 100644 crates/spirv-builder-cli/src/args.rs create mode 100755 scripts/build_shader_template.sh diff --git a/Cargo.lock b/Cargo.lock index 607acfe309..64cedc6452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "bytes" @@ -688,15 +691,27 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags", + "serde", +] + [[package]] name = "spirv-builder-cli" version = "0.1.0" dependencies = [ + "clap", "env_home", "env_logger 0.10.2", "log", "serde", "serde_json", + "spirv", "toml", ] diff --git a/Cargo.toml b/Cargo.toml index a23359ed75..5a605381a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,9 @@ members = [ ] exclude = [ + # Can't be included because it depends on a specific Rust toolchain and considering that + # the reason it exists is to prevent Rust toolchain requirements from polluting workspaces + # then let's just not try to workaround it. "crates/spirv-builder-cli", # This currently needs to be excluded because it depends on a version of `rust-gpu` that @@ -51,5 +54,4 @@ pub_with_shorthand = { level = "allow", priority = 1 } partial_pub_fields = { level = "allow", priority = 1 } pattern_type_mismatch = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } - - +arbitrary_source_item_ordering = { level = "allow", priority = 1 } diff --git a/README.md b/README.md index ace69f4bd6..992156a92b 100644 --- a/README.md +++ b/README.md @@ -54,193 +54,195 @@ the usage instructions the backend and nightly Rust version are referred to as " ## Usage +All the following arguments for the `build` and `install` commands can also be set in the shader crate's `Cargo.toml` +file. In general usage that would be the recommended way to set config. See `crates/shader-crate-template/Cargo.toml` +for an example. + ```` -Commands: - install Install rust-gpu compiler artifacts - build Compile a shader crate to SPIR-V - toml Compile a shader crate according to the `cargo gpu build` parameters found in the given toml file - show Show some useful values - help Print this message or the help of the given subcommand(s) + Commands: + install Install rust-gpu compiler artifacts + build Compile a shader crate to SPIR-V + show Show some useful values + help Print this message or the help of the given subcommand(s) -Options: - -h, --help - Print help + Options: + -h, --help + Print help - -V, --version - Print version + -V, --version + Print version * Install + Install rust-gpu compiler artifacts -Install rust-gpu compiler artifacts - -Usage: cargo-gpu install [OPTIONS] + Usage: cargo-gpu install [OPTIONS] -Options: - --shader-crate - Directory containing the shader crate to compile + Options: + --shader-crate + Directory containing the shader crate to compile - [default: ./] + [default: ./] - --spirv-builder-source - Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" + --spirv-builder-source + Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" - --spirv-builder-version - 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. + --spirv-builder-version + 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. - --rust-toolchain - Rust toolchain channel to use to build `spirv-builder`. + --rust-toolchain + Rust toolchain channel to use to build `spirv-builder`. - This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. + This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - --force-spirv-cli-rebuild - Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + --force-spirv-cli-rebuild + Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt - --auto-install-rust-toolchain - Assume "yes" to "Install Rust toolchain: [y/n]" prompt + --auto-install-rust-toolchain + Assume "yes" to "Install Rust toolchain: [y/n]" prompt - -h, --help - Print help (see a summary with '-h') + -h, --help + Print help (see a summary with '-h') * Build + Compile a shader crate to SPIR-V -Compile a shader crate to SPIR-V - -Usage: cargo-gpu build [OPTIONS] - -Options: - --shader-crate - Directory containing the shader crate to compile + Usage: cargo-gpu build [OPTIONS] - [default: ./] + Options: + --shader-crate + Directory containing the shader crate to compile - --spirv-builder-source - Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" + [default: ./] - --spirv-builder-version - 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. + --spirv-builder-source + Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" - --rust-toolchain - Rust toolchain channel to use to build `spirv-builder`. + --spirv-builder-version + 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. - This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. + --rust-toolchain + Rust toolchain channel to use to build `spirv-builder`. - --force-spirv-cli-rebuild - Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt + This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - --auto-install-rust-toolchain - Assume "yes" to "Install Rust toolchain: [y/n]" prompt + --force-spirv-cli-rebuild + Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt - --shader-target - Shader target + --auto-install-rust-toolchain + Assume "yes" to "Install Rust toolchain: [y/n]" prompt - [default: spirv-unknown-vulkan1.2] + -o, --output-dir + Path to the output directory for the compiled shaders - --no-default-features - Set cargo default-features + [default: ./] - --features - Set cargo features + --no-default-features + Set cargo default-features - -o, --output-dir - Path to the output directory for the compiled shaders + --features + Set cargo features - [default: ./] + --target + `rust-gpu` compile target - -h, --help - Print help (see a summary with '-h') + [default: spirv-unknown-vulkan1.2] + --shader-target + Shader target -* Toml + [default: spirv-unknown-vulkan1.2] -Compile a shader crate according to the `cargo gpu build` parameters found in the given toml file + --deny-warnings + Treat warnings as errors during compilation -Usage: cargo-gpu toml [PATH] + --debug + Compile shaders in debug mode -Arguments: - [PATH] - Path to a workspace or package Cargo.toml file. + --capability + Enables the provided SPIR-V capabilities. See: `impl core::str::FromStr for spirv_builder::Capability` - Must include a [[workspace | package].metadata.rust-gpu.build] section where - arguments to `cargo gpu build` are listed. + --extension + Enables the provided SPIR-V extensions. See for all extensions - Path arguments like `output-dir` and `shader-manifest` must be relative to - the location of the Cargo.toml file. + --multimodule + Compile one .spv file per entry point - Example: + --spirv-metadata + Set the level of metadata included in the SPIR-V binary - ```toml - [package.metadata.rust-gpu.build.spirv-builder] - git = "https://github.com/Rust-GPU/rust-gpu.git" - rev = "0da80f8" + [default: none] - [package.metadata.rust-gpu.build] - output-dir = "shaders" - shader-manifest = "shaders/manifest.json" - ``` + --relax-struct-store + Allow store from one struct type to a different type with compatible layout and members - Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that - contains the example above would compile the crate and place the compiled - `.spv` files and manifest in a directory "shaders". + --relax-logical-pointer + Allow allocating an object of a pointer type and returning a pointer value from a function in logical addressing mode - [default: ./Cargo.toml] + --relax-block-layout + Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, storage buffer, and push constant layouts. This is the default when targeting Vulkan 1.1 or later -Options: - -h, --help - Print help (see a summary with '-h') + --uniform-buffer-standard-layout + Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer layouts + --scalar-block-layout + Enable `VK_EXT_scalar_block_layout` when checking standard uniform, storage buffer, and push constant layouts. Scalar layout rules are more permissive than relaxed block layout so in effect this will override the --relax-block-layout option -* Show - -Show some useful values + --skip-block-layout + Skip checking standard uniform / storage buffer layout. Overrides any --relax-block-layout or --scalar-block-layout option -Usage: cargo-gpu show + --preserve-bindings + Preserve unused descriptor bindings. Useful for reflection -Commands: - cache-directory Displays the location of the cache directory - spirv-source The source location of spirv-std - help Print this message or the help of the given subcommand(s) + -h, --help + Print help (see a summary with '-h') -Options: - -h, --help - Print help +* Show + Show some useful values - * Cache-directory - - Displays the location of the cache directory + Usage: cargo-gpu show - Usage: cargo-gpu show cache-directory + Commands: + cache-directory Displays the location of the cache directory + spirv-source The source location of spirv-std + help Print this message or the help of the given subcommand(s) - Options: - -h, --help - Print help + Options: + -h, --help + Print help - * Spirv-source + * Cache-directory + Displays the location of the cache directory - The source location of spirv-std + Usage: cargo-gpu show cache-directory - Usage: cargo-gpu show spirv-source [OPTIONS] + Options: + -h, --help + Print help - Options: - --shader-crate - The location of the shader-crate to inspect to determine its spirv-std dependency - [default: ./] + * Spirv-source + The source location of spirv-std - -h, --help - Print help + Usage: cargo-gpu show spirv-source [OPTIONS] + Options: + --shader-crate + The location of the shader-crate to inspect to determine its spirv-std dependency + [default: ./] + -h, --help + Print help ```` diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 60007154ab..e19a08448b 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -41,6 +41,6 @@ codegen-units = 256 opt-level = 3 incremental = true codegen-units = 256 - + [lints] workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index fce6e363ef..41b3c19864 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -1,72 +1,62 @@ //! `cargo gpu build`, analogous to `cargo build` use anyhow::Context as _; -use clap::Parser; -use spirv_builder_cli::{Linkage, ShaderModule}; use crate::{install::Install, target_spec_dir}; +use spirv_builder_cli::{args::BuildArgs, Linkage, ShaderModule}; /// `cargo build` subcommands -#[derive(Parser, Debug)] +#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] pub struct Build { - /// Install the `rust-gpu` compiler and components + /// CLI args for install the `rust-gpu` compiler and components #[clap(flatten)] pub install: Install, - /// Shader target. - #[clap(long, default_value = "spirv-unknown-vulkan1.2")] - shader_target: String, - - /// Set cargo default-features. - #[clap(long)] - no_default_features: bool, - - /// Set cargo features. - #[clap(long)] - features: Vec, - - /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "./")] - pub output_dir: std::path::PathBuf, + /// CLI args for configuring the build of the shader + #[clap(flatten)] + pub build_args: BuildArgs, } impl Build { /// Entrypoint pub fn run(&mut self) -> anyhow::Result<()> { - let (dylib_path, spirv_builder_cli_path) = self.install.run()?; + let spirv_builder_cli_path = self.install.run()?; // Ensure the shader output dir exists - log::debug!("ensuring output-dir '{}' exists", self.output_dir.display()); - std::fs::create_dir_all(&self.output_dir)?; - let canonicalized = self.output_dir.canonicalize()?; + log::debug!( + "ensuring output-dir '{}' exists", + self.build_args.output_dir.display() + ); + std::fs::create_dir_all(&self.build_args.output_dir)?; + let canonicalized = self.build_args.output_dir.canonicalize()?; log::debug!("canonicalized output dir: {canonicalized:?}"); - self.output_dir = canonicalized; + self.build_args.output_dir = canonicalized; // Ensure the shader crate exists - self.install.shader_crate = self.install.shader_crate.canonicalize()?; + self.install.spirv_install.shader_crate = + self.install.spirv_install.shader_crate.canonicalize()?; anyhow::ensure!( - self.install.shader_crate.exists(), + self.install.spirv_install.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", - self.install.shader_crate.display(), + self.install.spirv_install.shader_crate.display(), std::env::current_dir()?.display() ); - let spirv_builder_args = spirv_builder_cli::Args { - dylib_path, - shader_crate: self.install.shader_crate.clone(), - shader_target: self.shader_target.clone(), - path_to_target_spec: target_spec_dir()?.join(format!("{}.json", self.shader_target)), - no_default_features: self.no_default_features, - features: self.features.clone(), - output_dir: self.output_dir.clone(), - }; - - let arg = serde_json::to_string_pretty(&spirv_builder_args)?; + self.build_args.shader_target = target_spec_dir()? + .join(format!("{}.json", self.build_args.shader_target)) + .display() + .to_string(); + + let args_as_json = serde_json::json!({ + "install": self.install.spirv_install, + "build": self.build_args + }); + let arg = serde_json::to_string_pretty(&args_as_json)?; log::info!("using spirv-builder-cli arg: {arg}"); crate::user_output!( "Running `spirv-builder-cli` to compile shader at {}...\n", - self.install.shader_crate.display() + self.install.spirv_install.shader_crate.display() ); // Call spirv-builder-cli to compile the shaders. @@ -77,7 +67,7 @@ impl Build { .output()?; anyhow::ensure!(output.status.success(), "build failed"); - let spirv_manifest = self.output_dir.join("spirv-manifest.json"); + let spirv_manifest = self.build_args.output_dir.join("spirv-manifest.json"); if spirv_manifest.is_file() { log::debug!( "successfully built shaders, raw manifest is at '{}'", @@ -100,21 +90,22 @@ impl Build { }| -> anyhow::Result { use relative_path::PathExt as _; - let path = self.output_dir.join( + let path = self.build_args.output_dir.join( filepath .file_name() .context("Couldn't parse file name from shader module path")?, ); std::fs::copy(&filepath, &path)?; - let path_relative_to_shader_crate = - path.relative_to(&self.install.shader_crate)?.to_path(""); + let path_relative_to_shader_crate = path + .relative_to(&self.install.spirv_install.shader_crate)? + .to_path(""); Ok(Linkage::new(entry, path_relative_to_shader_crate)) }, ) .collect::>>()?; // Write the shader manifest json file - let manifest_path = self.output_dir.join("manifest.json"); + let manifest_path = self.build_args.output_dir.join("manifest.json"); // Sort the contents so the output is deterministic linkage.sort(); let json = serde_json::to_string_pretty(&linkage)?; @@ -147,9 +138,9 @@ impl Build { #[cfg(test)] mod test { - use crate::{Cli, Command}; + use clap::Parser as _; - use super::*; + use crate::{Cli, Command}; #[test_log::test] fn builder_from_params() { @@ -170,8 +161,8 @@ mod test { command: Command::Build(build), } = Cli::parse_from(args) { - assert_eq!(shader_crate_path, build.install.shader_crate); - assert_eq!(output_dir, build.output_dir); + assert_eq!(shader_crate_path, build.install.spirv_install.shader_crate); + assert_eq!(output_dir, build.build_args.output_dir); // TODO: // For some reason running a full build (`build.run()`) inside tests fails on Windows. diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs new file mode 100644 index 0000000000..f00ea0b3ea --- /dev/null +++ b/crates/cargo-gpu/src/config.rs @@ -0,0 +1,236 @@ +//! Manage and merge the various sources of config: shader crate's `Cargo.toml`(s) and CLI args. +use anyhow::Context as _; +use clap::Parser as _; + +/// Config +pub struct Config; + +impl Config { + /// Get all the config defaults as JSON. + pub fn defaults_as_json() -> anyhow::Result { + let defaults_json = Self::cli_args_to_json(vec![String::new()])?; + Ok(defaults_json) + } + + /// Convert CLI args to their serde JSON representation. + fn cli_args_to_json(env_args: Vec) -> anyhow::Result { + let mut cli_args_json = serde_json::to_value(crate::build::Build::parse_from(env_args))?; + + // Move `/install/spirv_install` to `/install` + let spirv_install = cli_args_json + .pointer("/install/spirv_install") + .context("`/install/spirv_install` not found in config")? + .clone(); + *cli_args_json + .get_mut("install") + .context("`/install` not found in config")? = spirv_install; + + let build = cli_args_json + .pointer("/build_args") + .context("`/build_args` not found in config")? + .clone(); + + // Move `/build_args` to `/build` + let object = cli_args_json.as_object_mut().context("!")?; + object.remove("build_args"); + object.insert("build".to_owned(), build); + + Ok(cli_args_json) + } + + /// Config for the `cargo gpu build` and `cargo gpu install` can be set in the shader crate's + /// `Cargo.toml`, so here we load that config first as the base config, and the CLI arguments can + /// then later override it. + pub fn clap_command_with_cargo_config( + shader_crate_path: &std::path::PathBuf, + mut env_args: Vec, + ) -> anyhow::Result { + let mut config = crate::metadata::Metadata::as_json(shader_crate_path)?; + + env_args = env_args + .into_iter() + .filter(|arg| !(arg == "build" || arg == "install")) + .collect::>(); + let cli_args_json = Self::cli_args_to_json(env_args)?; + + Self::json_merge(&mut config, cli_args_json, None)?; + + let build = config + .get("build") + .context("`build` not found in merged configs")? + .clone(); + + let install = config + .get("install") + .context("`install` not found in merged configs")? + .clone(); + + let args = serde_json::from_value::(serde_json::json!({ + "build_args": build, + "install": { + "spirv_install": install + } + }))?; + Ok(args) + } + + /// Merge 2 JSON objects. But only if the incoming patch value isn't the default value. + /// Inspired by: + pub fn json_merge( + left_in: &mut serde_json::Value, + right_in: serde_json::Value, + maybe_pointer: Option<&String>, + ) -> anyhow::Result<()> { + let defaults = Self::defaults_as_json()?; + + match (left_in, right_in) { + (left @ &mut serde_json::Value::Object(_), serde_json::Value::Object(right)) => { + let left_as_object = left + .as_object_mut() + .context("Unreachable, we've already proved it's an object")?; + for (key, value) in right { + let new_pointer = maybe_pointer.as_ref().map_or_else( + || format!("/{}", key.clone()), + |pointer| format!("{}/{}", pointer, key.clone()), + ); + Self::json_merge( + left_as_object + .entry(key.clone()) + .or_insert(serde_json::Value::Null), + value, + Some(&new_pointer), + )?; + } + } + (left, right) => { + if let Some(pointer) = maybe_pointer { + let default = defaults + .pointer(pointer) + .context(format!("Config `{pointer}` not found in defaults"))?; + if &right != default { + // Only overwrite if the new value differs from the defaults. + *left = right; + } + } + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::io::Write as _; + + #[test_log::test] + fn booleans_from_cli() { + let shader_crate_path = crate::test::shader_crate_test_path(); + + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![ + "gpu".to_owned(), + "build".to_owned(), + "--debug".to_owned(), + "--auto-install-rust-toolchain".to_owned(), + ], + ) + .unwrap(); + assert!(args.build_args.debug); + assert!(args.install.spirv_install.auto_install_rust_toolchain); + } + + #[test_log::test] + fn booleans_from_cargo() { + let shader_crate_path = crate::test::shader_crate_test_path(); + let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "debug = true", + "[package.metadata.rust-gpu.install]", + "auto-install-rust-toolchain = true", + ] + .join("\n") + .as_bytes(), + ) + .unwrap(); + + let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + assert!(args.build_args.debug); + assert!(args.install.spirv_install.auto_install_rust_toolchain); + } + + fn update_cargo_output_dir() -> std::path::PathBuf { + let shader_crate_path = crate::test::shader_crate_test_path(); + let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "output-dir = \"/the/moon\"", + ] + .join("\n") + .as_bytes(), + ) + .unwrap(); + shader_crate_path + } + + #[test_log::test] + fn string_from_cargo() { + let shader_crate_path = update_cargo_output_dir(); + + let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + assert_eq!( + args.build_args.output_dir, + std::path::Path::new("/the/moon") + ); + } + + #[test_log::test] + fn string_from_cargo_overwritten_by_cli() { + let shader_crate_path = update_cargo_output_dir(); + + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![ + "gpu".to_owned(), + "build".to_owned(), + "--output-dir".to_owned(), + "/the/river".to_owned(), + ], + ) + .unwrap(); + assert_eq!( + args.build_args.output_dir, + std::path::Path::new("/the/river") + ); + } + + #[test_log::test] + fn arrays_from_cargo() { + let shader_crate_path = crate::test::shader_crate_test_path(); + let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "capability = [\"AtomicStorage\", \"Matrix\"]", + ] + .join("\n") + .as_bytes(), + ) + .unwrap(); + + let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + assert_eq!( + args.build_args.capability, + vec![ + spirv_builder_cli::spirv::Capability::AtomicStorage, + spirv_builder_cli::spirv::Capability::Matrix + ] + ); + } +} diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index c6e3eefea3..aafc969ea1 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -4,6 +4,7 @@ use std::io::Write as _; use anyhow::Context as _; use crate::{cache_dir, spirv_cli::SpirvCli, spirv_source::SpirvSource, target_spec_dir}; +use spirv_builder_cli::args::InstallArgs; /// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ @@ -19,6 +20,10 @@ const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ "src/lib.rs", include_str!("../../spirv-builder-cli/src/lib.rs"), ), + ( + "src/args.rs", + include_str!("../../spirv-builder-cli/src/args.rs"), + ), ]; /// Metadata for the compile targets supported by `rust-gpu` @@ -86,42 +91,11 @@ const TARGET_SPECS: &[(&str, &str)] = &[ ]; /// `cargo gpu install` -#[derive(clap::Parser, Debug)] +#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] pub struct Install { - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - pub shader_crate: std::path::PathBuf, - - #[expect( - clippy::doc_markdown, - reason = "The URL should appear literally like this. But Clippy wants it to be a in markdown clickable link" - )] - /// Source of `spirv-builder` dependency - /// Eg: "https://github.com/Rust-GPU/rust-gpu" - #[clap(long)] - spirv_builder_source: Option, - - /// 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)] - spirv_builder_version: Option, - - /// Rust toolchain channel to use to build `spirv-builder`. - /// - /// This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - #[clap(long)] - rust_toolchain: Option, - - /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. - #[clap(long)] - force_spirv_cli_rebuild: bool, - - /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. - #[clap(long, action)] - auto_install_rust_toolchain: bool, + /// CLI arguments for installing the Rust toolchain and components + #[clap(flatten)] + pub spirv_install: InstallArgs, } impl Install { @@ -129,16 +103,16 @@ impl Install { fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> anyhow::Result { SpirvCli::new( shader_crate_path, - self.spirv_builder_source.clone(), - self.spirv_builder_version.clone(), - self.rust_toolchain.clone(), - self.auto_install_rust_toolchain, + self.spirv_install.spirv_builder_source.clone(), + self.spirv_install.spirv_builder_version.clone(), + self.spirv_install.rust_toolchain.clone(), + self.spirv_install.auto_install_rust_toolchain, ) } /// Create the `spirv-builder-cli` crate. fn write_source_files(&self) -> anyhow::Result<()> { - let spirv_cli = self.spirv_cli(&self.shader_crate)?; + let spirv_cli = self.spirv_cli(&self.spirv_install.shader_crate)?; let checkout = spirv_cli.cached_checkout_path()?; std::fs::create_dir_all(checkout.join("src"))?; for (filename, contents) in SPIRV_BUILDER_FILES { @@ -187,7 +161,7 @@ impl Install { fn write_target_spec_files(&self) -> anyhow::Result<()> { for (filename, contents) in TARGET_SPECS { let path = target_spec_dir()?.join(filename); - if !path.is_file() || self.force_spirv_cli_rebuild { + if !path.is_file() || self.spirv_install.force_spirv_cli_rebuild { let mut file = std::fs::File::create(&path)?; file.write_all(contents.as_bytes())?; } @@ -196,7 +170,7 @@ impl Install { } /// Install the binary pair and return the paths, (dylib, cli). - pub fn run(&self) -> anyhow::Result<(std::path::PathBuf, std::path::PathBuf)> { + pub fn run(&mut self) -> anyhow::Result { // Ensure the cache dir exists let cache_dir = cache_dir()?; log::info!("cache directory is '{}'", cache_dir.display()); @@ -204,7 +178,7 @@ impl Install { format!("could not create cache directory '{}'", cache_dir.display()) })?; - let spirv_version = self.spirv_cli(&self.shader_crate)?; + let spirv_version = self.spirv_cli(&self.spirv_install.shader_crate)?; spirv_version.ensure_toolchain_and_components_exist()?; let checkout = spirv_version.cached_checkout_path()?; @@ -225,7 +199,10 @@ impl Install { ); } - if dest_dylib_path.is_file() && dest_cli_path.is_file() && !self.force_spirv_cli_rebuild { + if dest_dylib_path.is_file() + && dest_cli_path.is_file() + && !self.spirv_install.force_spirv_cli_rebuild + { log::info!("...and so we are aborting the install step."); } else { log::debug!( @@ -237,7 +214,7 @@ impl Install { crate::user_output!( "Compiling shader-specific `spirv-builder-cli` for {}\n", - self.shader_crate.display() + self.spirv_install.shader_crate.display() ); let mut command = std::process::Command::new("cargo"); @@ -286,7 +263,10 @@ impl Install { anyhow::bail!("spirv-builder-cli build failed"); } } - Ok((dest_dylib_path, dest_cli_path)) + + self.spirv_install.dylib_path = dest_dylib_path; + + Ok(dest_cli_path) } /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index c180973393..d3f906efc0 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -56,14 +56,14 @@ use build::Build; use clap::Parser as _; use install::Install; use show::Show; -use toml::Toml; mod build; +mod config; mod install; +mod metadata; mod show; mod spirv_cli; mod spirv_source; -mod toml; /// Central function to write to the user. #[macro_export] @@ -115,28 +115,33 @@ fn main() { /// Wrappable "main" to catch errors. fn run() -> anyhow::Result<()> { - let args = std::env::args() + let env_args = std::env::args() .filter(|arg| { - // Calling cargo-gpu as the cargo subcommand "cargo gpu" passes "gpu" - // as the first parameter, which we want to ignore. + // Calling our `main()` with the cargo subcommand `cargo gpu` passes "gpu" + // as the first parameter, so we want to ignore it. arg != "gpu" }) .collect::>(); - log::trace!("args: {args:?}"); - let cli = Cli::parse_from(args); + log::trace!("CLI args: {env_args:#?}"); + let cli = Cli::parse_from(env_args.clone()); match cli.command { Command::Install(install) => { - log::debug!("installing with arguments: {install:#?}"); - let (_, _) = install.run()?; + let shader_crate_path = install.spirv_install.shader_crate; + let mut command = + config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; + log::debug!( + "installing with final merged arguments: {:#?}", + command.install + ); + let _: std::path::PathBuf = command.install.run()?; } - Command::Build(mut build) => { - log::debug!("building with arguments: {build:#?}"); - build.run()?; - } - Command::Toml(toml) => { - log::debug!("building by toml file with arguments: {toml:#?}"); - toml.run()?; + Command::Build(build) => { + let shader_crate_path = build.install.spirv_install.shader_crate; + let mut command = + config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; + log::debug!("building with final merged arguments: {command:#?}"); + command.run()?; } Command::Show(show) => show.run()?, Command::DumpUsage => dump_full_usage_for_readme()?, @@ -154,10 +159,6 @@ enum Command { /// Compile a shader crate to SPIR-V. Build(Build), - /// Compile a shader crate according to the `cargo gpu build` parameters - /// found in the given toml file. - Toml(Toml), - /// Show some useful values. Show(Show), @@ -217,26 +218,30 @@ fn dump_full_usage_for_readme() -> anyhow::Result<()> { fn write_help( buffer: &mut impl std::io::Write, cmd: &mut clap::Command, - _depth: usize, + depth: usize, ) -> anyhow::Result<()> { if cmd.get_name() == "help" { return Ok(()); } let mut command = cmd.get_name().to_owned(); + let indent_depth = if depth == 0 || depth == 1 { 0 } else { depth }; + let indent = " ".repeat(indent_depth * 4); writeln!( buffer, - "\n* {}{}", + "\n{}* {}{}", + indent, command.remove(0).to_uppercase(), command )?; - writeln!(buffer)?; - cmd.write_long_help(buffer)?; + + for line in cmd.render_long_help().to_string().lines() { + writeln!(buffer, "{indent} {line}")?; + } for sub in cmd.get_subcommands_mut() { writeln!(buffer)?; - #[expect(clippy::used_underscore_binding, reason = "Used in recursion only")] - write_help(buffer, sub, _depth + 1)?; + write_help(buffer, sub, depth + 1)?; } Ok(()) @@ -258,12 +263,31 @@ fn to_dirname(text: &str) -> String { #[cfg(test)] mod test { use crate::cache_dir; + use std::io::Write as _; pub fn shader_crate_template_path() -> std::path::PathBuf { let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); project_base.join("../shader-crate-template") } + pub fn shader_crate_test_path() -> std::path::PathBuf { + let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); + copy_dir_all(shader_crate_template_path(), shader_crate_path.clone()).unwrap(); + shader_crate_path + } + + pub fn overwrite_shader_cargo_toml(shader_crate_path: &std::path::Path) -> std::fs::File { + let cargo_toml = shader_crate_path.join("Cargo.toml"); + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(cargo_toml) + .unwrap(); + writeln!(file, "[package]").unwrap(); + writeln!(file, "name = \"test\"").unwrap(); + file + } + pub fn tests_teardown() { let cache_dir = cache_dir().unwrap(); if !cache_dir.exists() { @@ -271,4 +295,21 @@ mod test { } std::fs::remove_dir_all(cache_dir).unwrap(); } + + pub fn copy_dir_all( + src: impl AsRef, + dst: impl AsRef, + ) -> anyhow::Result<()> { + std::fs::create_dir_all(&dst)?; + for maybe_entry in std::fs::read_dir(src)? { + let entry = maybe_entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) + } } diff --git a/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs new file mode 100644 index 0000000000..abc16da98b --- /dev/null +++ b/crates/cargo-gpu/src/metadata.rs @@ -0,0 +1,197 @@ +//! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]` + +/// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally +/// ignores so that packages can implement their own behaviour with it. +#[derive(Debug)] +pub struct Metadata; + +impl Metadata { + /// Convert `rust-gpu`-specific sections in `Cargo.toml` to `clap`-compatible arguments. + /// The section in question is: `[package.metadata.rust-gpu.*]`. See the `shader-crate-template` + /// for an example. + /// + /// First we generate the CLI arg defaults as JSON. Then on top of those we merge any config + /// from the workspace `Cargo.toml`, then on top of those we merge any config from the shader + /// crate's `Cargo.toml`. + pub fn as_json(path: &std::path::PathBuf) -> anyhow::Result { + let cargo_json = Self::get_cargo_toml_as_json(path)?; + let config = Self::merge_configs(&cargo_json, path)?; + Ok(config) + } + + /// Convert JSON keys from kebab case to snake case. Eg: `a-b` to `a_b`. + /// + /// Detection of keys for serde deserialization must match the case in the Rust structs. + /// However clap defaults to detecting CLI args in kebab case. So here we do the conversion. + fn keys_to_snake_case(json: &mut serde_json::Value) { + let serde_json::Value::Object(object) = json else { + return; + }; + + *object = core::mem::take(object) + .into_iter() + .map(|(key, mut value)| { + if let serde_json::Value::Object(_) = value { + Self::keys_to_snake_case(&mut value); + } + (key.replace('-', "_"), value) + }) + .collect(); + } + + /// Merge the various source of config: defaults, workspace and shader crate. + fn merge_configs( + cargo_json: &serde_json::Value, + path: &std::path::Path, + ) -> anyhow::Result { + let mut metadata = crate::config::Config::defaults_as_json()?; + crate::config::Config::json_merge( + &mut metadata, + Self::get_workspace_metadata(cargo_json), + None, + )?; + crate::config::Config::json_merge( + &mut metadata, + Self::get_crate_metadata(cargo_json, path)?, + None, + )?; + + Ok(metadata) + } + + /// Convert a `Cargo.toml` to JSON + // + // TODO: reuse for getting the default `rust-gpu` source and toolchain. + fn get_cargo_toml_as_json(path: &std::path::PathBuf) -> anyhow::Result { + let cargo_toml_path = path.join("Cargo.toml"); + if !cargo_toml_path.exists() { + anyhow::bail!("{path:?} must be a shader crate directory"); + } + + log::debug!("Querying Cargo metadata for {cargo_toml_path:?}"); + let output_cargo = std::process::Command::new("cargo") + .args([ + "metadata", + "--no-deps", + "--manifest-path", + cargo_toml_path.display().to_string().as_ref(), + ]) + .output()?; + anyhow::ensure!( + output_cargo.status.success(), + "could not run `cargo metadata` on {cargo_toml_path:?}" + ); + + Ok(serde_json::from_slice(&output_cargo.stdout)?) + } + + /// Get any `rust-gpu` metadata set in the root workspace `Cargo.toml` + fn get_workspace_metadata(json: &serde_json::Value) -> serde_json::Value { + let empty_json_object = serde_json::json!({}); + let mut metadata = json + .pointer("/metadata/rust-gpu") + .unwrap_or(&empty_json_object) + .clone(); + + Self::keys_to_snake_case(&mut metadata); + metadata.clone() + } + + /// Get any `rust-gpu` metadata set in the crate's `Cargo.toml` + fn get_crate_metadata( + json: &serde_json::Value, + path: &std::path::Path, + ) -> anyhow::Result { + let empty_json_object = serde_json::json!({}); + if let Some(serde_json::Value::Array(packages)) = json.pointer("/packages") { + for package in packages { + if let Some(serde_json::Value::String(manifest_path_dirty)) = + package.pointer("/manifest_path") + { + let mut shader_crate_path = std::fs::canonicalize(path)? + .join("Cargo.toml") + .display() + .to_string(); + + // Windows prefixs paths with `\\?\` + shader_crate_path = shader_crate_path.replace(r"\\?\", ""); + let manifest_path = manifest_path_dirty.replace(r"\\?\", ""); + log::debug!("Matching shader crate path with manifest path: {shader_crate_path} == {manifest_path}?"); + if manifest_path == shader_crate_path { + let mut metadata = package + .pointer("/metadata/rust-gpu") + .unwrap_or(&empty_json_object) + .clone(); + Self::keys_to_snake_case(&mut metadata); + return Ok(metadata); + } + } + } + } + Ok(empty_json_object) + } +} + +#[expect( + clippy::indexing_slicing, + reason = "We don't need to be so strict in tests" +)] +#[cfg(test)] +mod test { + use super::*; + + #[test_log::test] + fn generates_defaults() { + let json = serde_json::json!({}); + let configs = Metadata::merge_configs(&json, std::path::Path::new("./")).unwrap(); + assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(false)); + assert_eq!( + configs["install"]["auto_install_rust_toolchain"], + serde_json::Value::Bool(false) + ); + } + + #[test_log::test] + fn can_override_config_from_workspace_toml() { + let json = serde_json::json!( + { "metadata": { "rust-gpu": { + "build": { + "debug": true + }, + "install": { + "auto-install-rust-toolchain": true + } + }}} + ); + let configs = Metadata::merge_configs(&json, std::path::Path::new("./")).unwrap(); + assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(true)); + assert_eq!( + configs["install"]["auto_install_rust_toolchain"], + serde_json::Value::Bool(true) + ); + } + + #[test_log::test] + fn can_override_config_from_crate_toml() { + let marker = std::path::Path::new("./Cargo.toml"); + let json = serde_json::json!( + { "packages": [{ + "metadata": { "rust-gpu": { + "build": { + "debug": true + }, + "install": { + "auto-install-rust-toolchain": true + } + }}, + "manifest_path": std::fs::canonicalize(marker).unwrap() + }]} + ); + let configs = Metadata::merge_configs(&json, marker.parent().unwrap()).unwrap(); + assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(true)); + assert_eq!( + configs["install"]["auto_install_rust_toolchain"], + serde_json::Value::Bool(true) + ); + } +} diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 4e07a735fe..38dfb86900 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -105,7 +105,7 @@ impl SpirvCli { } else { let message = format!("Rust {} with `rustup`", self.channel); self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; - crate::user_output!("Installing {message}"); + crate::user_output!("Installing {message}\n"); let output_toolchain_add = std::process::Command::new("rustup") .args(["toolchain", "add"]) @@ -143,7 +143,7 @@ impl SpirvCli { } else { let message = "toolchain components (rust-src, rustc-dev, llvm-tools) with `rustup`"; self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; - crate::user_output!("Installing {message}"); + crate::user_output!("Installing {message}\n"); let output_component_add = std::process::Command::new("rustup") .args(["component", "add", "--toolchain"]) @@ -193,6 +193,8 @@ mod test { #[test_log::test] fn cached_checkout_dir_sanity() { let shader_template_path = crate::test::shader_crate_template_path(); + // TODO: This downloads the `rust-gpu` repo which slows the test down. Can we avoid that + // just to get the sanity check? let spirv = SpirvCli::new(&shader_template_path, None, None, None, true).unwrap(); let dir = spirv.cached_checkout_path().unwrap(); let name = dir diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index d98fde9df7..498e20ea74 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -320,7 +320,7 @@ impl SpirvSource { self.to_dirname()?.to_string_lossy().as_ref(), ); - crate::user_output!("Cloning `rust-gpu` repo..."); + crate::user_output!("Cloning `rust-gpu` repo...\n"); let output_clone = std::process::Command::new("git") .args([ diff --git a/crates/cargo-gpu/src/toml.rs b/crates/cargo-gpu/src/toml.rs deleted file mode 100644 index c43146776c..0000000000 --- a/crates/cargo-gpu/src/toml.rs +++ /dev/null @@ -1,186 +0,0 @@ -//! Build a shader based on the data in the `[package.metadata.rust-gpu.build.spirv-builder]` section of -//! a shader's `Cargo.toml`. - -use anyhow::Context as _; -use clap::Parser; - -use crate::{Cli, Command}; - -/// `cargo gpu toml` -#[derive(Debug, Parser)] -pub struct Toml { - /// Path to a workspace or package Cargo.toml file. - /// - /// Must include a [[workspace | package].metadata.rust-gpu.build] section where - /// arguments to `cargo gpu build` are listed. - /// - /// Path arguments like `output-dir` and `shader-manifest` must be relative to - /// the location of the Cargo.toml file. - /// - /// Example: - /// - /// ```toml - /// [package.metadata.rust-gpu.build.spirv-builder] - /// git = "https://github.com/Rust-GPU/rust-gpu.git" - /// rev = "0da80f8" - /// - /// [package.metadata.rust-gpu.build] - /// output-dir = "shaders" - /// shader-manifest = "shaders/manifest.json" - /// ``` - /// - /// Calling `cargo gpu toml {path/to/Cargo.toml}` with a Cargo.toml that - /// contains the example above would compile the crate and place the compiled - /// `.spv` files and manifest in a directory "shaders". - #[clap(default_value = "./Cargo.toml", verbatim_doc_comment)] - path: std::path::PathBuf, -} - -impl Toml { - /// Entrypoint - pub fn run(&self) -> anyhow::Result<()> { - let (path, toml) = Self::parse_cargo_toml(self.path.clone())?; - let working_directory = path - .parent() - .context("Couldn't find parent for shader's `Cargo.toml`")?; - - // Determine if this is a workspace's Cargo.toml or a crate's Cargo.toml - let (toml_type, table) = if toml.contains_key("workspace") { - let table = Self::get_metadata_rustgpu_table(&toml, "workspace") - .with_context(|| { - format!( - "toml file '{}' is missing a [workspace.metadata.rust-gpu] table", - path.display() - ) - })? - .clone(); - ("workspace", table) - } else if toml.contains_key("package") { - let mut table = Self::get_metadata_rustgpu_table(&toml, "package") - .with_context(|| { - format!( - "toml file '{}' is missing a [package.metadata.rust-gpu] table", - path.display() - ) - })? - .clone(); - // Ensure the package name is included as the shader-crate parameter - if !table.contains_key("shader-crate") { - table.insert( - "shader-crate".to_owned(), - format!("{}", working_directory.display()).into(), - ); - } - ("package", table) - } else { - anyhow::bail!("toml file '{}' must describe a workspace containing [workspace.metadata.rust-gpu.build] or a describe a crate with [package.metadata.rust-gpu.build]", path.display()); - }; - - log::info!( - "building with [{toml_type}.metadata.rust-gpu.build] section of the toml file at '{}'", - path.display() - ); - log::debug!("table: {table:#?}"); - - log::info!( - "issuing cargo commands from the working directory '{}'", - working_directory.display() - ); - std::env::set_current_dir(working_directory)?; - - let parameters = construct_build_parameters_from_toml_table(toml_type, &table)?; - log::debug!("build parameters: {parameters:#?}"); - if let Cli { - command: Command::Build(mut build), - } = Cli::parse_from(parameters) - { - log::debug!("build: {build:?}"); - build.run()?; - } else { - log::error!("parameters found in [{toml_type}.metadata.rust-gpu.build] were not parameters to `cargo gpu build`"); - anyhow::bail!("could not determin build command"); - } - - Ok(()) - } - - /// Parse the contents of the shader's `Cargo.toml` - pub fn parse_cargo_toml( - mut path: std::path::PathBuf, - ) -> anyhow::Result<(std::path::PathBuf, toml::Table)> { - // Find the path to the toml file to use - let parsed_path = if path.is_file() && path.ends_with(".toml") { - path - } else { - path = path.join("Cargo.toml"); - if path.is_file() { - path - } else { - log::error!("toml file '{}' is not a file", path.display()); - anyhow::bail!("toml file '{}' is not a file", path.display()); - } - }; - - log::info!("using toml file '{}'", parsed_path.display()); - - let contents = std::fs::read_to_string(&parsed_path)?; - let toml: toml::Table = toml::from_str(&contents)?; - - Ok((parsed_path, toml)) - } - - /// Parse the `[package.metadata.rust-gpu]` section. - fn get_metadata_rustgpu_table<'toml>( - toml: &'toml toml::Table, - toml_type: &'static str, - ) -> Option<&'toml toml::Table> { - let workspace = toml.get(toml_type)?.as_table()?; - let metadata = workspace.get("metadata")?.as_table()?; - metadata.get("rust-gpu")?.as_table() - } -} - -/// Construct the cli parameters to run a `cargo gpu build` command from a TOML table. -fn construct_build_parameters_from_toml_table( - toml_type: &str, - table: &toml::map::Map, -) -> Result, anyhow::Error> { - let build_table = table - .get("build") - .with_context(|| "toml is missing the 'build' table")? - .as_table() - .with_context(|| { - format!("toml file's '{toml_type}.metadata.rust-gpu.build' property is not a table") - })?; - let mut parameters: Vec = build_table - .into_iter() - .map(|(key, val)| -> anyhow::Result> { - Ok(match val { - toml::Value::String(string) => vec![format!("--{key}"), string.clone()], - toml::Value::Boolean(truthy) => { - if *truthy { - vec![format!("--{key}")] - } else { - vec![] - } - } - toml::Value::Integer(_) - | toml::Value::Float(_) - | toml::Value::Datetime(_) - | toml::Value::Array(_) - | toml::Value::Table(_) => { - let mut value = String::new(); - let ser = toml::ser::ValueSerializer::new(&mut value); - serde::Serialize::serialize(val, ser)?; - vec![format!("--{key}"), value] - } - }) - }) - .collect::>>>()? - .into_iter() - .flatten() - .collect(); - parameters.insert(0, "cargo-gpu".to_owned()); - parameters.insert(1, "build".to_owned()); - Ok(parameters) -} diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 3ec4841063..d684074429 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -2,7 +2,7 @@ name = "rust-gpu-shader-crate-template" version = "0.1.0" edition = "2021" - + [lib] crate-type = ["rlib", "cdylib"] @@ -15,8 +15,77 @@ spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "82a0f69" } [target.'cfg(target_arch = "spirv")'.dependencies] glam = { version = "0.29", default-features = false, features = ["libm"] } - # Dependencies for CPU code [target.'cfg(not(target_arch = "spirv"))'.dependencies] glam = { version = "0.29", features = ["std"] } +[package.metadata.rust-gpu.build] +# Where to output the compiled shader. Defaults to where `cargo gpu` is called from. +# TODO: Should it default to the root of the shader crate? +output-dir = "./" +# Set shader crate's cargo default-features +no_default_features = false +# Set shader crate's cargo features. +features = [] +# The compile target. +# TODO: `cargo gpu show targets` for all available options. +shader-target = "spirv-unknown-vulkan1.2" +# Treat warnings as errors during compilation. +deny-warnings = false +# Compile shaders in debug mode. +debug = false +# Enables the provided SPIR-V capabilities. +# See: `impl core::str::FromStr for spirv_builder::Capability`. +# TODO: `cargo gpu show capabilities` for all available options. +capability = [] +# Enables the provided SPIR-V extensions. +# See https://github.com/KhronosGroup/SPIRV-Registry for all extensions +# TODO: `cargo gpu show extensions` for all available options. +extension = [] +# Compile one .spv file per shader entry point. +multimodule = false +# Set the level of metadata included in the SPIR-V binary. +# Options: "None", "NameVariables", "Full". +spirv-metadata = "None" +# Allow store from one struct type to a different type with compatible layout and members. +relax-struct-store = false +# Allow allocating an object of a pointer type and returning a pointer value from a function +# in logical addressing mode. +relax-logical-pointer = false +# Enable VK_KHR_relaxed_block_layout when checking standard uniform, storage buffer, and push +# constant layouts. +# This is the default when targeting Vulkan 1.1 or later. +relax-block-layout = false +# Enable VK_KHR_uniform_buffer_standard_layout when checking standard uniform buffer layouts. +uniform-buffer-standard-layout = false +# Enable `VK_EXT_scalar_block_layout` when checking standard uniform, storage buffer, and push +# constant layouts. +# Scalar layout rules are more permissive than relaxed block layout so in effect this will +# override the `relax_block_layout` option. +scalar-block-layout = false +# Skip checking standard uniform/storage buffer layout. +# Overrides `relax_block_layout` and `scalar_block_layout`. +skip-block-layout = false +# Preserve unused descriptor bindings. Useful for reflection. +preserve-bindings = false + +[package.metadata.rust-gpu.install] +# Source of `spirv-builder` dependency +# Eg: "https://github.com/Rust-GPU/rust-gpu" +# spirv_builder_source = "" + +# 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. +# spirv_builder_version = "" + +# Rust toolchain channel to use to build `spirv-builder`. +# Eg: "nightly-2024-04-24" +# rust_toolchain = "" + +# Whether to assume "yes" to the "Install Rust toolchain: [y/n]" prompt. +auto-install-rust-toolchain = false +# Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. +force-spirv-cli-rebuild = false diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index 683b299663..b86b9a264a 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -22,6 +22,55 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + [[package]] name = "ar" version = "0.9.0" @@ -51,6 +100,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "bytemuck" @@ -81,6 +133,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + [[package]] name = "convert_case" version = "0.4.0" @@ -182,6 +280,12 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.4.0" @@ -231,6 +335,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -603,6 +713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ "bitflags 2.6.0", + "serde", ] [[package]] @@ -635,11 +746,13 @@ dependencies = [ name = "spirv-builder-cli" version = "0.1.0" dependencies = [ + "clap", "env_home", "env_logger", "log", "serde", "serde_json", + "spirv 0.3.0+sdk-1.3.268.0", "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", "toml", @@ -669,6 +782,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -740,6 +859,12 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "version_check" version = "0.9.5" diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 6723c5b8a1..2ab9ccc030 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -3,19 +3,14 @@ name = "spirv-builder-cli" version = "0.1.0" edition = "2021" -[lib] -path = "src/lib.rs" - -[[bin]] -name = "spirv-builder-cli" -path = "src/main.rs" - [dependencies] +clap = { version = "4.4.8", features = ["derive"] } env_home = "0.1.0" env_logger = "0.10" log = "0.4" serde = "1.0.214" serde_json = "1.0.132" +spirv = { version = "0.3.0", features = [ "deserialize", "serialize" ] } toml = "0.8.19" [features] @@ -41,7 +36,7 @@ package = "spirv-builder" optional = true git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} rev = "60dcb82" # ${AUTO-REPLACE-VERSION} - + [lints.rust] # This crate is most often run by end users compiling their shaders so it's not so relevant # for them to see warnings. diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs new file mode 100644 index 0000000000..853c06216a --- /dev/null +++ b/crates/spirv-builder-cli/src/args.rs @@ -0,0 +1,165 @@ +use std::str::FromStr as _; + +#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +pub struct AllArgs { + #[clap(flatten)] + pub build: BuildArgs, + + #[clap(flatten)] + pub install: InstallArgs, +} + +/// Options for the `--spirv-metadata` command +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub enum SpirvMetadata { + /// Don't log any metadata (the default) + None, + /// Only log named variables + NameVariables, + /// Log all metadata + Full, +} + +#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +pub struct BuildArgs { + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "./")] + pub output_dir: std::path::PathBuf, + + /// Set shader crate's cargo default-features. + #[clap(long)] + pub no_default_features: bool, + + /// Set shader crate's cargo features. + #[clap(long)] + pub features: Vec, + + /// `rust-gpu` compile target. + /// TODO: deprecate completely + #[arg(hide(true), default_value = "spirv-unknown-vulkan1.2")] + pub target: String, + + /// Shader target. + // TODO: how to list the available options? Would be nice to have a command like: + // `cargo gpu show targets` + #[clap(long, default_value = "spirv-unknown-vulkan1.2")] + pub shader_target: String, + + /// Treat warnings as errors during compilation. + #[arg(long, default_value = "false")] + pub deny_warnings: bool, + + /// Compile shaders in debug mode. + #[arg(long, default_value = "false")] + pub debug: bool, + + /// Enables the provided SPIR-V capabilities. + /// See: `impl core::str::FromStr for spirv_builder::Capability` + #[arg(long, value_parser=Self::spirv_capability)] + pub capability: Vec, + + /// Enables the provided SPIR-V extensions. + /// See for all extensions + #[arg(long)] + pub extension: Vec, + + /// Compile one .spv file per entry point. + #[arg(long, default_value = "false")] + pub multimodule: bool, + + /// Set the level of metadata included in the SPIR-V binary. + #[arg(long, value_parser=Self::spirv_metadata, default_value = "none")] + pub spirv_metadata: SpirvMetadata, + + /// Allow store from one struct type to a different type with compatible layout and members. + #[arg(long, default_value = "false")] + pub relax_struct_store: bool, + + /// Allow allocating an object of a pointer type and returning a pointer value from a function + /// in logical addressing mode. + #[arg(long, default_value = "false")] + pub relax_logical_pointer: bool, + + /// Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, + /// storage buffer, and push constant layouts. + /// This is the default when targeting Vulkan 1.1 or later. + #[arg(long, default_value = "false")] + pub relax_block_layout: bool, + + /// Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer layouts. + #[arg(long, default_value = "false")] + pub uniform_buffer_standard_layout: bool, + + /// Enable `VK_EXT_scalar_block_layout` when checking standard uniform, storage buffer, and push + /// constant layouts. + /// Scalar layout rules are more permissive than relaxed block layout so in effect this will + /// override the --relax-block-layout option. + #[arg(long, default_value = "false")] + pub scalar_block_layout: bool, + + /// Skip checking standard uniform / storage buffer layout. Overrides any --relax-block-layout + /// or --scalar-block-layout option. + #[arg(long, default_value = "false")] + pub skip_block_layout: bool, + + /// Preserve unused descriptor bindings. Useful for reflection. + #[arg(long, default_value = "false")] + pub preserve_bindings: bool, +} + +impl BuildArgs { + /// Clap value parser for `SpirvMetadata`. + fn spirv_metadata(metadata: &str) -> Result { + match metadata { + "none" => Ok(SpirvMetadata::None), + "name-variables" => Ok(SpirvMetadata::NameVariables), + "full" => Ok(SpirvMetadata::Full), + _ => Err(clap::Error::new(clap::error::ErrorKind::InvalidValue)), + } + } + + /// Clap value parser for `Capability`. + fn spirv_capability(capability: &str) -> Result { + spirv::Capability::from_str(capability).map_or_else( + |()| Err(clap::Error::new(clap::error::ErrorKind::InvalidValue)), + Ok, + ) + } +} + +#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +pub struct InstallArgs { + #[clap(long, hide(true), default_value = "INTERNALLY_SET")] + pub dylib_path: std::path::PathBuf, + + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, + + /// Source of `spirv-builder` dependency + /// Eg: "https://github.com/Rust-GPU/rust-gpu" + #[clap(long)] + pub spirv_builder_source: Option, + + /// 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)] + pub spirv_builder_version: Option, + + /// Rust toolchain channel to use to build `spirv-builder`. + /// + /// This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. + #[clap(long)] + pub rust_toolchain: Option, + + /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + pub force_spirv_cli_rebuild: bool, + + /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. + #[clap(long, action)] + pub auto_install_rust_toolchain: bool, +} diff --git a/crates/spirv-builder-cli/src/lib.rs b/crates/spirv-builder-cli/src/lib.rs index b26c7b5928..982f23dc90 100644 --- a/crates/spirv-builder-cli/src/lib.rs +++ b/crates/spirv-builder-cli/src/lib.rs @@ -1,4 +1,6 @@ -//! Wire types for `cargo-gpu` and `spirv-builder-cli`. +pub mod args; + +pub use spirv; /// Shader source and entry point that can be used to create shader linkage. #[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] @@ -28,31 +30,6 @@ impl Linkage { } } -/// `spirv-builder-cli` command line interface. -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Args { - /// Path to rustc_codegen_spirv dylib. - pub dylib_path: std::path::PathBuf, - - /// Directory containing the shader crate to compile. - pub shader_crate: std::path::PathBuf, - - /// Shader target. - pub shader_target: String, - - /// Path to target spec file. - pub path_to_target_spec: std::path::PathBuf, - - /// Set cargo default-features. - pub no_default_features: bool, - - /// Set cargo features. - pub features: Vec, - - /// Path to the output directory for the compiled shaders. - pub output_dir: std::path::PathBuf, -} - /// A built shader entry-point, used in `spirv-builder-cli` to generate /// a `build-manifest.json` used by `cargo-gpu`. #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 496c2cc66a..0390d0c8b0 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -1,5 +1,9 @@ -//! This program builds rust-gpu shader crates and writes generated spv files -//! into the main source repo. +/// NB: For developing this file it will probably help to temporarily move the `"crates/spirv-builder-cli"` +/// line from the `exclude` to `members` section of the root `Cargo.toml` file. This will allow +/// `rust-analyzer` to run on the file. We can't permanently keep it there because each of the +/// `spirv-builder-*` features depends on a different Rust toolchain which `cargo check/clippy` +/// can't build all at once. +pub mod args; #[cfg(feature = "spirv-builder-pre-cli")] use spirv_builder_pre_cli as spirv_builder; @@ -8,8 +12,7 @@ use spirv_builder_pre_cli as spirv_builder; use spirv_builder_0_10 as spirv_builder; use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; - -use spirv_builder_cli::{Args, ShaderModule}; +use spirv_builder_cli::ShaderModule; const RUSTC_NIGHTLY_CHANNEL: &str = "${CHANNEL}"; @@ -39,7 +42,7 @@ fn set_codegen_spirv_location(dylib_path: std::path::PathBuf) { std::env::set_var(env_var, path); } -fn main() { +pub fn main() { env_logger::builder().init(); set_rustup_toolchain(); @@ -49,44 +52,59 @@ fn main() { "running spirv-builder-cli from '{}'", std::env::current_dir().unwrap().display() ); - let args = serde_json::from_str(&args[1]).unwrap(); - log::debug!("compiling with args: {args:#?}"); - let Args { - dylib_path, - shader_crate, - shader_target, - path_to_target_spec, - no_default_features, - features, - output_dir, - } = args; + log::debug!("with args: {args:#?}"); + let args: args::AllArgs = serde_json::from_str(&args[1]).unwrap(); + + let spirv_metadata = match args.build.spirv_metadata { + args::SpirvMetadata::None => spirv_builder::SpirvMetadata::None, + args::SpirvMetadata::NameVariables => spirv_builder::SpirvMetadata::NameVariables, + args::SpirvMetadata::Full => spirv_builder::SpirvMetadata::Full, + }; let CompileResult { entry_points, module, } = { - let mut builder = SpirvBuilder::new(shader_crate, &shader_target) - .print_metadata(MetadataPrintout::None) - .multimodule(true); + let mut builder = SpirvBuilder::new(args.install.shader_crate, &args.build.target) + .deny_warnings(args.build.deny_warnings) + .release(!args.build.debug) + .multimodule(args.build.multimodule) + .spirv_metadata(spirv_metadata) + .relax_struct_store(args.build.relax_struct_store) + .relax_logical_pointer(args.build.relax_logical_pointer) + .relax_block_layout(args.build.relax_block_layout) + .uniform_buffer_standard_layout(args.build.uniform_buffer_standard_layout) + .scalar_block_layout(args.build.scalar_block_layout) + .skip_block_layout(args.build.skip_block_layout) + .preserve_bindings(args.build.preserve_bindings) + .print_metadata(spirv_builder::MetadataPrintout::None); + + for capability in &args.build.capability { + builder = builder.capability(*capability); + } + + for extension in &args.build.extension { + builder = builder.extension(extension); + } #[cfg(feature = "spirv-builder-pre-cli")] { - set_codegen_spirv_location(dylib_path); + set_codegen_spirv_location(args.install.dylib_path); } #[cfg(feature = "spirv-builder-0_10")] { builder = builder - .rustc_codegen_spirv_location(dylib_path) - .target_spec(path_to_target_spec); + .rustc_codegen_spirv_location(args.install.dylib_path) + .target_spec(args.build.shader_target); - if no_default_features { + if args.build.no_default_features { log::info!("setting cargo --no-default-features"); builder = builder.shader_crate_default_features(false); } - if !features.is_empty() { - log::info!("setting --features {features:?}"); - builder = builder.shader_crate_features(features); + if !args.build.features.is_empty() { + log::info!("setting --features {:?}", args.build.features); + builder = builder.shader_crate_features(args.build.features); } } @@ -95,7 +113,7 @@ fn main() { }; log::debug!("found entry points: {entry_points:#?}"); - let dir = output_dir; + let dir = args.build.output_dir; let mut shaders = vec![]; match module { ModuleResult::MultiModule(modules) => { diff --git a/justfile b/justfile index ff42105c05..977b44217e 100644 --- a/justfile +++ b/justfile @@ -1,10 +1,6 @@ [group: 'ci'] build-shader-template: - cargo install --path crates/cargo-gpu - cargo gpu install --shader-crate crates/shader-crate-template --auto-install-rust-toolchain - cargo gpu build --shader-crate crates/shader-crate-template --output-dir test-shaders - ls -lah test-shaders - cat test-shaders/manifest.json + scripts/build_shader_template.sh [group: 'ci'] setup-lints: diff --git a/scripts/build_shader_template.sh b/scripts/build_shader_template.sh new file mode 100755 index 0000000000..55a931ae2c --- /dev/null +++ b/scripts/build_shader_template.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Unix and OSX have different versions of this argument. +SED_INPLACE="-i" +if [ "$(uname)" = "Darwin" ]; then + SED_INPLACE="-i ''" +fi + +# Matching windows paths when they're at root (/) causes problems with how we canoniclaize paths. +TMP_DIR=".$(mktemp --directory)" + +cargo install --path crates/cargo-gpu +cargo gpu install --shader-crate crates/shader-crate-template --auto-install-rust-toolchain + +# We change the output directory in the shader crate's `Cargo.toml` rather than just using the simpler +# `--output-dir` CLI arg, because we want to smoke test that setting config in `Cargo.toml` works. +sed "$SED_INPLACE" "s#^output-dir =.*#output-dir = \"$TMP_DIR\"#" crates/shader-crate-template/Cargo.toml + +cargo gpu build --shader-crate crates/shader-crate-template --force-spirv-cli-rebuild +ls -lah "$TMP_DIR" +cat "$TMP_DIR"/manifest.json From 3a0ec08b0e7a39a88382a9bc375b501c012f9ed0 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Fri, 10 Jan 2025 11:44:09 -0300 Subject: [PATCH 068/162] Add `cargo gpu show capabilities` command --- crates/cargo-gpu/src/show.rs | 21 +++++++++++++++++++++ crates/spirv-builder-cli/src/args.rs | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 3fb8c721e7..985a33f687 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -19,6 +19,8 @@ pub enum Info { SpirvSource(SpirvSourceDep), /// The git commitsh of this cli tool. Commitsh, + /// All the available SPIR-V capabilities that can be set with `--capability` + Capabilities, } /// `cargo gpu show` @@ -53,8 +55,27 @@ impl Show { Info::Commitsh => { println!("{}", std::env!("GIT_HASH")); } + Info::Capabilities => { + println!("All available options to the `cargo gpu build --capability` argument:"); + #[expect( + clippy::use_debug, + reason = "It's easier to just use `Debug` formatting than implementing `Display`" + )] + for capability in Self::capability_variants_iter() { + println!(" {capability:?}"); + } + } } Ok(()) } + + /// Iterator over all `Capability` variants. + fn capability_variants_iter() -> impl Iterator { + // Since spirv::Capability is repr(u32) we can iterate over + // u32s until some maximum + #[expect(clippy::as_conversions, reason = "We know all variants are repr(u32)")] + let last_capability = spirv_builder_cli::spirv::Capability::CacheControlsINTEL as u32; + (0..=last_capability).filter_map(spirv_builder_cli::spirv::Capability::from_u32) + } } diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs index 853c06216a..d90be1594f 100644 --- a/crates/spirv-builder-cli/src/args.rs +++ b/crates/spirv-builder-cli/src/args.rs @@ -54,7 +54,7 @@ pub struct BuildArgs { pub debug: bool, /// Enables the provided SPIR-V capabilities. - /// See: `impl core::str::FromStr for spirv_builder::Capability` + /// See: `cargo gpu show capabilities` #[arg(long, value_parser=Self::spirv_capability)] pub capability: Vec, From 0347ae55d4ee74136776d7ccf3b20d1c02f111ad Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 11 Jan 2025 21:19:53 -0300 Subject: [PATCH 069/162] Feature-gate `gfx-rs/rspirv` dependency Because our `spirv-builder-cli` can modify itself to comply with various versions of `spirv-builder` from `rust-gpu`, then we also need to match the version of `spirv` that we use to get `spirv::Capabilities`. Namely that `rust-gpu <= v0.9.0` uses `spirv = "0.2.0"` and that `rust-gpu >= "v0.9.0"` uses `spirv = "0.3.0". Another solution to this could be to re-export `spirv` from `spirv-builder`. But I'm not sure that would avoid compiling the entirety of `spirv-builder` (which depends on specific Rust nightly versions), and besides, it's not trivial to retroactively add re-exports to already-published version of `rust-gpu`. --- crates/cargo-gpu/Cargo.toml | 2 +- crates/spirv-builder-cli/Cargo.lock | 2 ++ crates/spirv-builder-cli/Cargo.toml | 19 ++++++++++++++++--- crates/spirv-builder-cli/src/args.rs | 6 ++++++ crates/spirv-builder-cli/src/lib.rs | 6 +++++- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index e19a08448b..05c1b33da6 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -11,7 +11,7 @@ build = "build.rs" [dependencies] anyhow.workspace = true -spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false } +spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false, features = ["rspirv-latest"] } clap.workspace = true directories.workspace = true env_logger.workspace = true diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index b86b9a264a..1b1c1d824c 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -704,6 +704,7 @@ checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ "bitflags 1.3.2", "num-traits", + "serde", ] [[package]] @@ -752,6 +753,7 @@ dependencies = [ "log", "serde", "serde_json", + "spirv 0.2.0+1.5.4", "spirv 0.3.0+sdk-1.3.268.0", "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 2ab9ccc030..da2a4e8c44 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -10,16 +10,29 @@ env_logger = "0.10" log = "0.4" serde = "1.0.214" serde_json = "1.0.132" -spirv = { version = "0.3.0", features = [ "deserialize", "serialize" ] } toml = "0.8.19" [features] default = ["spirv-builder-0_10"] # The `spirv-builder` before `cargo gpu` existed. It has an incompatible `SpirvBuilder` interface. -spirv-builder-pre-cli = ["dep:spirv-builder-pre-cli"] +spirv-builder-pre-cli = ["dep:spirv-builder-pre-cli", "dep:spirv_0_2"] # The first version that introduced `cargo gpu`. It has some extra `.builder()` args that make # dynamically changing build dependencies easier. -spirv-builder-0_10 = ["dep:spirv-builder-0_10"] +spirv-builder-0_10 = ["dep:spirv-builder-0_10", "dep:spirv_0_3"] +# +rspirv-latest = ["dep:spirv_0_3"] + +[dependencies.spirv_0_2] +package = "spirv" +version = "0.2.0" +features = [ "deserialize", "serialize" ] +optional = true + +[dependencies.spirv_0_3] +package = "spirv" +version = "0.3.0" +features = [ "deserialize", "serialize" ] +optional = true # NB: All the `${AUTO-REPLACE*}` tokens in each feature get replaced with the same values. # This is because only one feature can ever be used at once and it makes it easier to just diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs index d90be1594f..7cae66c66c 100644 --- a/crates/spirv-builder-cli/src/args.rs +++ b/crates/spirv-builder-cli/src/args.rs @@ -1,3 +1,9 @@ +#[cfg(feature = "spirv-builder-pre-cli")] +use spirv_0_2 as spirv; + +#[cfg(any(feature = "spirv-builder-0_10", feature = "rspirv-latest"))] +use spirv_0_3 as spirv; + use std::str::FromStr as _; #[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] diff --git a/crates/spirv-builder-cli/src/lib.rs b/crates/spirv-builder-cli/src/lib.rs index 982f23dc90..70d83e4b9b 100644 --- a/crates/spirv-builder-cli/src/lib.rs +++ b/crates/spirv-builder-cli/src/lib.rs @@ -1,6 +1,10 @@ pub mod args; -pub use spirv; +#[cfg(feature = "spirv-builder-pre-cli")] +pub use spirv_0_2 as spirv; + +#[cfg(any(feature = "spirv-builder-0_10", feature = "rspirv-latest"))] +pub use spirv_0_3 as spirv; /// Shader source and entry point that can be used to create shader linkage. #[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] From e039e6d0992b133cb0deb2b8a4750399f5a28c14 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sat, 11 Jan 2025 10:39:00 -0300 Subject: [PATCH 070/162] Add `--watch` arg for auto re-compiling on shader changes --- crates/cargo-gpu/src/build.rs | 21 ++-- crates/cargo-gpu/src/main.rs | 11 ++- crates/spirv-builder-cli/Cargo.toml | 2 + crates/spirv-builder-cli/src/args.rs | 10 +- crates/spirv-builder-cli/src/main.rs | 139 ++++++++++++++------------- 5 files changed, 106 insertions(+), 77 deletions(-) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 41b3c19864..913a327cbe 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -1,6 +1,7 @@ //! `cargo gpu build`, analogous to `cargo build` use anyhow::Context as _; +use std::io::Write as _; use crate::{install::Install, target_spec_dir}; use spirv_builder_cli::{args::BuildArgs, Linkage, ShaderModule}; @@ -42,10 +43,12 @@ impl Build { std::env::current_dir()?.display() ); - self.build_args.shader_target = target_spec_dir()? - .join(format!("{}.json", self.build_args.shader_target)) - .display() - .to_string(); + if !self.build_args.watch { + self.build_args.shader_target = target_spec_dir()? + .join(format!("{}.json", self.build_args.shader_target)) + .display() + .to_string(); + } let args_as_json = serde_json::json!({ "install": self.install.spirv_install, @@ -54,10 +57,12 @@ impl Build { let arg = serde_json::to_string_pretty(&args_as_json)?; log::info!("using spirv-builder-cli arg: {arg}"); - crate::user_output!( - "Running `spirv-builder-cli` to compile shader at {}...\n", - self.install.spirv_install.shader_crate.display() - ); + if !self.build_args.watch { + crate::user_output!( + "Running `spirv-builder-cli` to compile shader at {}...\n", + self.install.spirv_install.shader_crate.display() + ); + } // Call spirv-builder-cli to compile the shaders. let output = std::process::Command::new(spirv_builder_cli_path) diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index d3f906efc0..990246c067 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -141,7 +141,16 @@ fn run() -> anyhow::Result<()> { let mut command = config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; log::debug!("building with final merged arguments: {command:#?}"); - command.run()?; + + if command.build_args.watch { + // When watching, do one normal run to setup the `manifest.json` file. + command.build_args.watch = false; + command.run()?; + command.build_args.watch = true; + command.run()?; + } else { + command.run()?; + } } Command::Show(show) => show.run()?, Command::DumpUsage => dump_full_usage_for_readme()?, diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index da2a4e8c44..2bb6680e83 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -40,12 +40,14 @@ optional = true [dependencies.spirv-builder-pre-cli] package = "spirv-builder" +features = [ "watch" ] optional = true git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} rev = "4c633aec" # ${AUTO-REPLACE-VERSION} [dependencies.spirv-builder-0_10] package = "spirv-builder" +features = [ "watch" ] optional = true git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} rev = "60dcb82" # ${AUTO-REPLACE-VERSION} diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs index 7cae66c66c..625c020a81 100644 --- a/crates/spirv-builder-cli/src/args.rs +++ b/crates/spirv-builder-cli/src/args.rs @@ -6,7 +6,7 @@ use spirv_0_3 as spirv; use std::str::FromStr as _; -#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct AllArgs { #[clap(flatten)] pub build: BuildArgs, @@ -26,12 +26,16 @@ pub enum SpirvMetadata { Full, } -#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct BuildArgs { /// Path to the output directory for the compiled shaders. #[clap(long, short, default_value = "./")] pub output_dir: std::path::PathBuf, + /// Watch the shader crate directory and automatically recompile on changes. + #[clap(long, short, action)] + pub watch: bool, + /// Set shader crate's cargo default-features. #[clap(long)] pub no_default_features: bool, @@ -133,7 +137,7 @@ impl BuildArgs { } } -#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct InstallArgs { #[clap(long, hide(true), default_value = "INTERNALLY_SET")] pub dylib_path: std::path::PathBuf, diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index 0390d0c8b0..af3ba3d659 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -42,6 +42,32 @@ fn set_codegen_spirv_location(dylib_path: std::path::PathBuf) { std::env::set_var(env_var, path); } +fn handle_compile_result(result: &CompileResult, args: &args::AllArgs) { + log::debug!("found entry points: {:#?}", result.entry_points); + + let dir = &args.build.output_dir; + let mut shaders = vec![]; + match &result.module { + ModuleResult::MultiModule(modules) => { + assert!(!modules.is_empty(), "No shader modules to compile"); + for (entry, filepath) in modules.clone().into_iter() { + log::debug!("compiled {entry} {}", filepath.display()); + shaders.push(ShaderModule::new(entry, filepath)); + } + } + ModuleResult::SingleModule(filepath) => { + for entry in result.entry_points.clone() { + shaders.push(ShaderModule::new(entry, filepath.clone())); + } + } + } + + use std::io::Write; + let mut file = std::fs::File::create(dir.join("spirv-manifest.json")).unwrap(); + file.write_all(&serde_json::to_vec(&shaders).unwrap()) + .unwrap(); +} + pub fn main() { env_logger::builder().init(); @@ -54,6 +80,7 @@ pub fn main() { ); log::debug!("with args: {args:#?}"); let args: args::AllArgs = serde_json::from_str(&args[1]).unwrap(); + let args_for_result = args.clone(); let spirv_metadata = match args.build.spirv_metadata { args::SpirvMetadata::None => spirv_builder::SpirvMetadata::None, @@ -61,77 +88,59 @@ pub fn main() { args::SpirvMetadata::Full => spirv_builder::SpirvMetadata::Full, }; - let CompileResult { - entry_points, - module, - } = { - let mut builder = SpirvBuilder::new(args.install.shader_crate, &args.build.target) - .deny_warnings(args.build.deny_warnings) - .release(!args.build.debug) - .multimodule(args.build.multimodule) - .spirv_metadata(spirv_metadata) - .relax_struct_store(args.build.relax_struct_store) - .relax_logical_pointer(args.build.relax_logical_pointer) - .relax_block_layout(args.build.relax_block_layout) - .uniform_buffer_standard_layout(args.build.uniform_buffer_standard_layout) - .scalar_block_layout(args.build.scalar_block_layout) - .skip_block_layout(args.build.skip_block_layout) - .preserve_bindings(args.build.preserve_bindings) - .print_metadata(spirv_builder::MetadataPrintout::None); - - for capability in &args.build.capability { - builder = builder.capability(*capability); - } - - for extension in &args.build.extension { - builder = builder.extension(extension); - } - - #[cfg(feature = "spirv-builder-pre-cli")] - { - set_codegen_spirv_location(args.install.dylib_path); - } + let mut builder = SpirvBuilder::new(args.install.shader_crate, &args.build.target) + .deny_warnings(args.build.deny_warnings) + .release(!args.build.debug) + .multimodule(args.build.multimodule) + .spirv_metadata(spirv_metadata) + .relax_struct_store(args.build.relax_struct_store) + .relax_logical_pointer(args.build.relax_logical_pointer) + .relax_block_layout(args.build.relax_block_layout) + .uniform_buffer_standard_layout(args.build.uniform_buffer_standard_layout) + .scalar_block_layout(args.build.scalar_block_layout) + .skip_block_layout(args.build.skip_block_layout) + .preserve_bindings(args.build.preserve_bindings) + .print_metadata(spirv_builder::MetadataPrintout::None); + + for capability in &args.build.capability { + builder = builder.capability(*capability); + } - #[cfg(feature = "spirv-builder-0_10")] - { - builder = builder - .rustc_codegen_spirv_location(args.install.dylib_path) - .target_spec(args.build.shader_target); + for extension in &args.build.extension { + builder = builder.extension(extension); + } - if args.build.no_default_features { - log::info!("setting cargo --no-default-features"); - builder = builder.shader_crate_default_features(false); - } - if !args.build.features.is_empty() { - log::info!("setting --features {:?}", args.build.features); - builder = builder.shader_crate_features(args.build.features); - } - } + #[cfg(feature = "spirv-builder-pre-cli")] + { + set_codegen_spirv_location(args.install.dylib_path); + } - log::debug!("Calling `rust-gpu`'s `spirv-builder` library"); - builder.build().unwrap() - }; - log::debug!("found entry points: {entry_points:#?}"); + #[cfg(feature = "spirv-builder-0_10")] + { + builder = builder + .rustc_codegen_spirv_location(args.install.dylib_path) + .target_spec(args.build.shader_target); - let dir = args.build.output_dir; - let mut shaders = vec![]; - match module { - ModuleResult::MultiModule(modules) => { - assert!(!modules.is_empty(), "No shader modules to compile"); - for (entry, filepath) in modules.into_iter() { - log::debug!("compiled {entry} {}", filepath.display()); - shaders.push(ShaderModule::new(entry, filepath)); - } + if args.build.no_default_features { + log::info!("setting cargo --no-default-features"); + builder = builder.shader_crate_default_features(false); } - ModuleResult::SingleModule(filepath) => { - for entry in entry_points { - shaders.push(ShaderModule::new(entry, filepath.clone())); - } + if !args.build.features.is_empty() { + log::info!("setting --features {:?}", args.build.features); + builder = builder.shader_crate_features(args.build.features); } } - use std::io::Write; - let mut file = std::fs::File::create(dir.join("spirv-manifest.json")).unwrap(); - file.write_all(&serde_json::to_vec(&shaders).unwrap()) - .unwrap(); + log::debug!("Calling `rust-gpu`'s `spirv-builder` library"); + + if args.build.watch { + println!("🦀 Watching and recompiling shader on changes..."); + builder.watch(move |compile_result| { + handle_compile_result(&compile_result, &args_for_result); + }); + std::thread::park(); + } else { + let result = builder.build().unwrap(); + handle_compile_result(&result, &args_for_result); + } } From 08a47d4acebf879c4ff8e21e36b85550c4bcaf05 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Wed, 5 Feb 2025 10:55:59 -0300 Subject: [PATCH 071/162] Include Cargo.lock in when copying spirv-builder-cli Gives us more reliability, especially for integration tests. --- crates/cargo-gpu/src/install.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index aafc969ea1..2d066d541a 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -12,6 +12,10 @@ const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ "Cargo.toml", include_str!("../../spirv-builder-cli/Cargo.toml"), ), + ( + "Cargo.lock", + include_str!("../../spirv-builder-cli/Cargo.lock"), + ), ( "src/main.rs", include_str!("../../spirv-builder-cli/src/main.rs"), From 217388ebd924c184d4dd3d12a865122f5e2551ea Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 14:40:13 +1300 Subject: [PATCH 072/162] fix: run `cargo update` before building spirv-builder-cli --- crates/cargo-gpu/src/config.rs | 7 +- crates/cargo-gpu/src/install.rs | 22 +- crates/cargo-gpu/src/metadata.rs | 15 +- crates/spirv-builder-cli/Cargo.lock | 427 ++++++++++++++++++++++----- crates/spirv-builder-cli/src/main.rs | 2 + 5 files changed, 384 insertions(+), 89 deletions(-) diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index f00ea0b3ea..79a33e5518 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -104,9 +104,10 @@ impl Config { } (left, right) => { if let Some(pointer) = maybe_pointer { - let default = defaults - .pointer(pointer) - .context(format!("Config `{pointer}` not found in defaults"))?; + let default = defaults.pointer(pointer).context(format!( + "Configuration option with path `{pointer}` was not found in the default configuration, \ + which is:\ndefaults: {defaults:#?}" + ))?; if &right != default { // Only overwrite if the new value differs from the defaults. *left = right; diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 2d066d541a..3ceafcb1da 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -221,25 +221,35 @@ impl Install { self.spirv_install.shader_crate.display() ); - let mut command = std::process::Command::new("cargo"); - command + // Run a `cargo update` just in case the cached Cargo.lock we copied over + // is a bit behind what's in rust-gpu + let mut update_command = std::process::Command::new("cargo"); + update_command.current_dir(&checkout).arg("update"); + let update_output = update_command + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output()?; + anyhow::ensure!(update_output.status.success(), "...cargo update error!"); + + let mut build_command = std::process::Command::new("cargo"); + build_command .current_dir(&checkout) .arg(format!("+{}", spirv_version.channel)) .args(["build", "--release"]) .args(["--no-default-features"]); - command.args([ + build_command.args([ "--features", &Self::get_required_spirv_builder_version(spirv_version.date)?, ]); - log::debug!("building artifacts with `{:?}`", command); + log::debug!("building artifacts with `{:?}`", build_command); - let output = command + let build_output = build_command .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) .output()?; - anyhow::ensure!(output.status.success(), "...build error!"); + anyhow::ensure!(build_output.status.success(), "...build error!"); if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); diff --git a/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs index abc16da98b..115770c7e0 100644 --- a/crates/cargo-gpu/src/metadata.rs +++ b/crates/cargo-gpu/src/metadata.rs @@ -47,12 +47,22 @@ impl Metadata { let mut metadata = crate::config::Config::defaults_as_json()?; crate::config::Config::json_merge( &mut metadata, - Self::get_workspace_metadata(cargo_json), + { + log::debug!("looking for workspace metadata"); + let ws_meta = Self::get_workspace_metadata(cargo_json); + log::trace!("workspace_metadata: {ws_meta:#?}"); + ws_meta + }, None, )?; crate::config::Config::json_merge( &mut metadata, - Self::get_crate_metadata(cargo_json, path)?, + { + log::debug!("looking for crate metadata"); + let crate_meta = Self::get_crate_metadata(cargo_json, path)?; + log::trace!("crate_metadata: {crate_meta:#?}"); + crate_meta + }, None, )?; @@ -118,6 +128,7 @@ impl Metadata { let manifest_path = manifest_path_dirty.replace(r"\\?\", ""); log::debug!("Matching shader crate path with manifest path: {shader_crate_path} == {manifest_path}?"); if manifest_path == shader_crate_path { + log::debug!("...matches! Getting metadata"); let mut metadata = package .pointer("/metadata/rust-gpu") .unwrap_or(&empty_json_object) diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index 1b1c1d824c..04e9dc4873 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -63,11 +63,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -97,18 +98,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" dependencies = [ "serde", ] [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -118,9 +119,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.37" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" dependencies = [ "jobserver", "libc", @@ -135,9 +136,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" dependencies = [ "clap_builder", "clap_derive", @@ -145,9 +146,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -157,14 +158,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -185,17 +186,32 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] @@ -206,11 +222,11 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elsa" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" +checksum = "2343daaeabe09879d4ea058bb4f1e63da3fc07dadc6634e01bda1b3d6a9d9d2b" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.1", "stable_deref_trait", ] @@ -239,6 +255,27 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -276,9 +313,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -310,12 +347,32 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", ] [[package]] @@ -326,13 +383,13 @@ checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -352,9 +409,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -365,6 +422,26 @@ dependencies = [ "libc", ] +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -373,15 +450,26 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.8.0", + "libc", + "redox_syscall", +] [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "longest-increasing-subsequence" @@ -395,6 +483,36 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -406,24 +524,24 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -434,6 +552,15 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "regex" version = "1.11.1" @@ -448,9 +575,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -578,9 +705,18 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "sanitize-filename" @@ -594,35 +730,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.98", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -685,7 +821,7 @@ dependencies = [ "bytemuck", "derive_more", "elsa", - "indexmap 2.6.0", + "indexmap 2.7.1", "internal-iterator", "itertools", "lazy_static", @@ -713,7 +849,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "serde", ] @@ -723,6 +859,7 @@ version = "0.9.0" source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" dependencies = [ "memchr", + "notify", "raw-string", "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", @@ -736,6 +873,7 @@ version = "0.9.0" source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" dependencies = [ "memchr", + "notify", "raw-string", "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", @@ -803,9 +941,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -823,9 +961,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", @@ -844,11 +982,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -857,9 +995,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "utf8parse" @@ -873,6 +1011,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -890,11 +1038,20 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -903,7 +1060,37 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -912,28 +1099,64 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -946,24 +1169,72 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -972,9 +1243,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" dependencies = [ "memchr", ] diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index af3ba3d659..f18c3f22ec 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -112,11 +112,13 @@ pub fn main() { #[cfg(feature = "spirv-builder-pre-cli")] { + log::debug!("using spirv-builder-pre-cli"); set_codegen_spirv_location(args.install.dylib_path); } #[cfg(feature = "spirv-builder-0_10")] { + log::debug!("using spirv-builder-0_10"); builder = builder .rustc_codegen_spirv_location(args.install.dylib_path) .target_spec(args.build.shader_target); From 39397c4a3bc872decc4a86f0651364ab7bc9acaf Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 14:51:26 +1300 Subject: [PATCH 073/162] don't run cargo update --- crates/cargo-gpu/src/install.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 3ceafcb1da..505de378a1 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -221,16 +221,6 @@ impl Install { self.spirv_install.shader_crate.display() ); - // Run a `cargo update` just in case the cached Cargo.lock we copied over - // is a bit behind what's in rust-gpu - let mut update_command = std::process::Command::new("cargo"); - update_command.current_dir(&checkout).arg("update"); - let update_output = update_command - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output()?; - anyhow::ensure!(update_output.status.success(), "...cargo update error!"); - let mut build_command = std::process::Command::new("cargo"); build_command .current_dir(&checkout) From b21d8790fe78056652b00536b78a519919b0ae15 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 15:17:16 +1300 Subject: [PATCH 074/162] make crate defined output-dir relative to Cargo.toml it was defined in. Fixes #48 --- crates/cargo-gpu/src/metadata.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs index 115770c7e0..0d6b164cea 100644 --- a/crates/cargo-gpu/src/metadata.rs +++ b/crates/cargo-gpu/src/metadata.rs @@ -1,5 +1,7 @@ //! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]` +use serde_json::Value; + /// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally /// ignores so that packages can implement their own behaviour with it. #[derive(Debug)] @@ -59,8 +61,19 @@ impl Metadata { &mut metadata, { log::debug!("looking for crate metadata"); - let crate_meta = Self::get_crate_metadata(cargo_json, path)?; + let mut crate_meta = Self::get_crate_metadata(cargo_json, path)?; log::trace!("crate_metadata: {crate_meta:#?}"); + if let Some(output_path) = crate_meta.pointer_mut("/build/output_dir") { + log::debug!("found output-dir path in crate metadata: {:?}", output_path); + if let Some(output_dir) = output_path.clone().as_str() { + let new_output_path = path.join(output_dir); + *output_path = Value::String(format!("{}", new_output_path.display())); + log::debug!( + "setting that to be relative to the Cargo.toml it was found in: {}", + new_output_path.display() + ); + } + } crate_meta }, None, From 183da69527cbb11733a84f89f8fd1dd2d11ebfff Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 15:51:38 +1300 Subject: [PATCH 075/162] try to fix tests --- crates/cargo-gpu/src/config.rs | 15 ++- crates/spirv-builder-cli/Cargo.lock | 148 +++++++++++++++------------- 2 files changed, 89 insertions(+), 74 deletions(-) diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 79a33e5518..13ec6f231b 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -185,10 +185,17 @@ mod test { let shader_crate_path = update_cargo_output_dir(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); - assert_eq!( - args.build_args.output_dir, - std::path::Path::new("/the/moon") - ); + if cfg!(target_os = "windows") { + assert_eq!( + args.build_args.output_dir, + std::path::Path::new("C:/the/moon") + ); + } else { + assert_eq!( + args.build_args.output_dir, + std::path::Path::new("/the/moon") + ); + } } #[test_log::test] diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index 04e9dc4873..9c8789ca9e 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -63,12 +63,11 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "once_cell", "windows-sys 0.59.0", ] @@ -98,18 +97,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -119,9 +118,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.13" +version = "1.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" dependencies = [ "jobserver", "libc", @@ -136,9 +135,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.28" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -146,9 +145,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.27" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -158,14 +157,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.87", ] [[package]] @@ -203,15 +202,15 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 2.0.98", + "syn 2.0.87", ] [[package]] @@ -222,11 +221,11 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elsa" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2343daaeabe09879d4ea058bb4f1e63da3fc07dadc6634e01bda1b3d6a9d9d2b" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.6.0", "stable_deref_trait", ] @@ -313,9 +312,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "heck" @@ -347,12 +346,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.1", ] [[package]] @@ -383,13 +382,13 @@ checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" [[package]] name = "is-terminal" -version = "0.4.15" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -409,9 +408,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -450,9 +449,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -460,16 +459,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.6.0", "libc", "redox_syscall", ] [[package]] name = "log" -version = "0.4.25" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "longest-increasing-subsequence" @@ -524,24 +523,24 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.38" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -558,7 +557,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.6.0", ] [[package]] @@ -575,9 +574,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -705,9 +704,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.19" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -730,35 +729,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.25" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.217" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -821,7 +820,7 @@ dependencies = [ "bytemuck", "derive_more", "elsa", - "indexmap 2.7.1", + "indexmap 2.6.0", "internal-iterator", "itertools", "lazy_static", @@ -849,7 +848,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.6.0", "serde", ] @@ -941,9 +940,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -961,9 +960,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -982,11 +981,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -995,9 +994,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.16" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "utf8parse" @@ -1054,6 +1053,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" @@ -1243,9 +1251,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.2" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] From bfdbfdc6a358421862ddb00aa4a3b65bf17f2c48 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 16:58:03 +1300 Subject: [PATCH 076/162] replaced justfile with xtask --- .cargo/config.toml | 3 + .github/workflows/push.yaml | 8 ++- Cargo.lock | 74 +++++++++++++++++++ Cargo.toml | 4 +- clippy.toml | 1 + crates/cargo-gpu/src/build.rs | 2 +- crates/xtask/Cargo.toml | 15 ++++ crates/xtask/src/main.rs | 119 +++++++++++++++++++++++++++++++ justfile | 15 ---- scripts/build_shader_template.sh | 21 ------ 10 files changed, 221 insertions(+), 41 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 crates/xtask/Cargo.toml create mode 100644 crates/xtask/src/main.rs delete mode 100644 justfile delete mode 100755 scripts/build_shader_template.sh diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000000..99d9bb9366 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[alias] +xtask = "run --package xtask --" +build-test-shader = "xtask test-build" diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 26dca5b258..9c41811070 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -35,7 +35,7 @@ jobs: rustup update - run: cargo test - name: Run a full build - run: just build-shader-template + run: cargo xtask test-build lints: @@ -45,5 +45,7 @@ jobs: - uses: moonrepo/setup-rust@v1 - uses: extractions/setup-just@v2 - uses: cargo-bins/cargo-binstall@main - - run: just setup-lints - - run: just lints + - run: cargo binstall cargo-shear + - run: cargo clippy -- --deny warnings + - run: cargo fmt --check + - run: cargo shear diff --git a/Cargo.lock b/Cargo.lock index 64cedc6452..9885f04dbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -276,6 +276,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "getrandom" version = "0.2.15" @@ -510,6 +516,43 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.5.8" @@ -580,6 +623,15 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "rustix" version = "0.38.42" @@ -732,6 +784,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -1086,3 +1148,15 @@ checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "env_logger 0.10.2", + "log", + "tempdir", + "toml", +] diff --git a/Cargo.toml b/Cargo.toml index 5a605381a0..290462a791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ - "crates/cargo-gpu", + "crates/cargo-gpu", + "crates/xtask", ] exclude = [ @@ -30,6 +31,7 @@ relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } serde_json = "1.0.132" toml = "0.8.19" +tempdir = "0.3.7" test-log = "0.2.16" [workspace.lints.rust] diff --git a/clippy.toml b/clippy.toml index f69b4a67f9..5b16b999d1 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,2 +1,3 @@ allow-unwrap-in-tests = true allow-panic-in-tests = true +allow-shadow-reuse = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 913a327cbe..77487dde6c 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -173,7 +173,7 @@ mod test { // For some reason running a full build (`build.run()`) inside tests fails on Windows. // The error is in the `build.rs` step of compiling `spirv-tools-sys`. It is not clear // from the logged error what the problem is. For now we'll just run a full build - // outside the tests environment, see `justfile`'s `build-shader-template`. + // outside the tests environment, see `xtask`'s `test-build`. } else { panic!("was not a build command"); } diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml new file mode 100644 index 0000000000..0573d57610 --- /dev/null +++ b/crates/xtask/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow.workspace = true +clap.workspace = true +env_logger.workspace = true +log.workspace = true +tempdir.workspace = true +toml.workspace = true + +[lints] +workspace = true diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs new file mode 100644 index 0000000000..6ebdf29206 --- /dev/null +++ b/crates/xtask/src/main.rs @@ -0,0 +1,119 @@ +//! Project/repository utilities. + +use anyhow::Context; +use clap::Parser; + +/// Our xtask commands. +#[derive(Debug, clap::Parser)] +enum Cli { + /// Run a test build of the shader-crate-template project. + TestBuild, +} + +fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { + let mut args = args.into_iter(); + let mut cmd = std::process::Command::new(args.next().context("no args")?.as_ref()); + for arg in args { + cmd.arg(arg.as_ref()); + } + + let output = cmd + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .context("cmd failed")?; + anyhow::ensure!(output.status.success()); + + Ok(()) +} + +struct ShaderCrateTemplateCargoTomlWriter { + original_shader_crate_template_str: String, + table: toml::Table, +} + +impl Drop for ShaderCrateTemplateCargoTomlWriter { + fn drop(&mut self) { + log::info!("reverting overwrite of Cargo.toml"); + std::fs::write(Self::PATH, &self.original_shader_crate_template_str).unwrap(); + } +} + +impl ShaderCrateTemplateCargoTomlWriter { + const PATH: &str = "crates/shader-crate-template/Cargo.toml"; + + fn new() -> Self { + let original_shader_crate_template_str = std::fs::read_to_string(Self::PATH).unwrap(); + let table = toml::from_str::(&original_shader_crate_template_str).unwrap(); + Self { + original_shader_crate_template_str, + table, + } + } + + fn replace_output_dir(&mut self, path: impl AsRef) -> anyhow::Result<()> { + let package = self + .table + .get_mut("package") + .unwrap() + .as_table_mut() + .unwrap(); + let metadata = package.get_mut("metadata").unwrap().as_table_mut().unwrap(); + let rust_gpu = metadata + .get_mut("rust-gpu") + .unwrap() + .as_table_mut() + .unwrap(); + let build = rust_gpu.get_mut("build").unwrap().as_table_mut().unwrap(); + let output_dir = build.get_mut("output-dir").unwrap(); + *output_dir = toml::Value::String(format!("{}", path.as_ref().display())); + std::fs::write( + Self::PATH, + toml::to_string_pretty(&self.table).context("could not serialize")?, + ) + .context("could not overwrite path")?; + Ok(()) + } +} + +/// Run the xtask. +fn main() { + env_logger::builder().init(); + + let cli = Cli::parse(); + + match cli { + Cli::TestBuild => { + log::info!("installing cargo gpu"); + cmd(["cargo", "install", "--path", "crates/cargo-gpu"]).unwrap(); + + log::info!("installing cargo gpu artifacts"); + cmd([ + "cargo", + "gpu", + "install", + "--shader-crate", + "crates/shader-crate-template", + "--auto-install-rust-toolchain", + ]) + .unwrap(); + + let dir = tempdir::TempDir::new("test-shader-output").unwrap(); + let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); + overwriter.replace_output_dir(dir.path()).unwrap(); + + cmd([ + "cargo", + "gpu", + "build", + "--shader-crate", + "crates/shader-crate-template", + "--force-spirv-cli-rebuild", + ]) + .unwrap(); + + cmd(["ls", "-lah", dir.path().to_str().unwrap()]).unwrap(); + cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()]).unwrap(); + } + } +} diff --git a/justfile b/justfile deleted file mode 100644 index 977b44217e..0000000000 --- a/justfile +++ /dev/null @@ -1,15 +0,0 @@ -[group: 'ci'] -build-shader-template: - scripts/build_shader_template.sh - -[group: 'ci'] -setup-lints: - cargo binstall cargo-shear - -[group: 'ci'] -lints: - cargo clippy -- --deny warnings - cargo fmt --check - # Look for unused crates - cargo shear - diff --git a/scripts/build_shader_template.sh b/scripts/build_shader_template.sh deleted file mode 100755 index 55a931ae2c..0000000000 --- a/scripts/build_shader_template.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Unix and OSX have different versions of this argument. -SED_INPLACE="-i" -if [ "$(uname)" = "Darwin" ]; then - SED_INPLACE="-i ''" -fi - -# Matching windows paths when they're at root (/) causes problems with how we canoniclaize paths. -TMP_DIR=".$(mktemp --directory)" - -cargo install --path crates/cargo-gpu -cargo gpu install --shader-crate crates/shader-crate-template --auto-install-rust-toolchain - -# We change the output directory in the shader crate's `Cargo.toml` rather than just using the simpler -# `--output-dir` CLI arg, because we want to smoke test that setting config in `Cargo.toml` works. -sed "$SED_INPLACE" "s#^output-dir =.*#output-dir = \"$TMP_DIR\"#" crates/shader-crate-template/Cargo.toml - -cargo gpu build --shader-crate crates/shader-crate-template --force-spirv-cli-rebuild -ls -lah "$TMP_DIR" -cat "$TMP_DIR"/manifest.json From e680ce75863488eb6e72df1885aa933335c84467 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 17:13:30 +1300 Subject: [PATCH 077/162] clippy --- clippy.toml | 1 - crates/cargo-gpu/src/build.rs | 2 ++ crates/xtask/src/main.rs | 13 +++++++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/clippy.toml b/clippy.toml index 5b16b999d1..f69b4a67f9 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,3 +1,2 @@ allow-unwrap-in-tests = true allow-panic-in-tests = true -allow-shadow-reuse = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 77487dde6c..3589d0c231 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -1,3 +1,5 @@ +#![allow(clippy::shadow_reuse, reason = "let's not be silly")] +#![allow(clippy::unwrap_used, reason = "this is basically a test")] //! `cargo gpu build`, analogous to `cargo build` use anyhow::Context as _; diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 6ebdf29206..6d1bd126f9 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -1,7 +1,10 @@ //! Project/repository utilities. +#![allow(clippy::shadow_reuse, reason = "sometimes its nice")] +#![allow(clippy::unwrap_used, reason = "sometimes its good")] +#![allow(clippy::unwrap_in_result, reason = "sometimes that's what you want")] -use anyhow::Context; -use clap::Parser; +use anyhow::Context as _; +use clap::Parser as _; /// Our xtask commands. #[derive(Debug, clap::Parser)] @@ -27,8 +30,11 @@ fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { Ok(()) } +/// Overwrites a toml file's output-dir field, and reverts that on drop. struct ShaderCrateTemplateCargoTomlWriter { + /// Original string original_shader_crate_template_str: String, + /// Parsed toml table table: toml::Table, } @@ -40,8 +46,10 @@ impl Drop for ShaderCrateTemplateCargoTomlWriter { } impl ShaderCrateTemplateCargoTomlWriter { + /// Path to the Cargo.toml const PATH: &str = "crates/shader-crate-template/Cargo.toml"; + /// Create a new one fn new() -> Self { let original_shader_crate_template_str = std::fs::read_to_string(Self::PATH).unwrap(); let table = toml::from_str::(&original_shader_crate_template_str).unwrap(); @@ -51,6 +59,7 @@ impl ShaderCrateTemplateCargoTomlWriter { } } + /// Replace the output-dir fn replace_output_dir(&mut self, path: impl AsRef) -> anyhow::Result<()> { let package = self .table From 21794341bcf1c97e0fab6a2831b95dff5cacb515 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 17:18:32 +1300 Subject: [PATCH 078/162] sheared env_home --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 290462a791..3d16813354 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ clap = { version = "4.4.8", features = ["derive"] } chrono = { version = "0.4.38", default-features = false, features = ["std"] } crossterm = "0.28.1" directories = "5.0.1" -env_home = "0.1.0" env_logger = "0.10" http = "1.2.0" log = "0.4" From 4493eda4b51618582576d139b13f559fb62603c8 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 20:52:20 +1300 Subject: [PATCH 079/162] more logging --- crates/cargo-gpu/src/build.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 3589d0c231..9eb891a1cf 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -22,6 +22,7 @@ pub struct Build { impl Build { /// Entrypoint + #[expect(clippy::too_many_lines, reason = "these lines are fine")] pub fn run(&mut self) -> anyhow::Result<()> { let spirv_builder_cli_path = self.install.run()?; @@ -102,7 +103,13 @@ impl Build { .file_name() .context("Couldn't parse file name from shader module path")?, ); + log::debug!("copying {} to {}", filepath.display(), path.display()); std::fs::copy(&filepath, &path)?; + log::debug!( + "linkage of {} relative to {}", + path.display(), + self.install.spirv_install.shader_crate.display() + ); let path_relative_to_shader_crate = path .relative_to(&self.install.spirv_install.shader_crate)? .to_path(""); From 94e832185b8a4ee437d5d614fb929006ab69ce1e Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 11 Feb 2025 21:10:51 +1300 Subject: [PATCH 080/162] try to determine path relative to shader crate, but don't force it --- crates/cargo-gpu/src/build.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 9eb891a1cf..789e4b7dfc 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -110,10 +110,12 @@ impl Build { path.display(), self.install.spirv_install.shader_crate.display() ); - let path_relative_to_shader_crate = path - .relative_to(&self.install.spirv_install.shader_crate)? - .to_path(""); - Ok(Linkage::new(entry, path_relative_to_shader_crate)) + let spv_path = path + .relative_to(&self.install.spirv_install.shader_crate) + .map_or(path, |path_relative_to_shader_crate| { + path_relative_to_shader_crate.to_path("") + }); + Ok(Linkage::new(entry, spv_path)) }, ) .collect::>>()?; From e08d597df92da48b45b698ae5128244c6b36240c Mon Sep 17 00:00:00 2001 From: Tendsin Mende Date: Fri, 28 Feb 2025 03:15:55 +0100 Subject: [PATCH 081/162] add manifest-file configuration option to BuildArgs (#51) --- crates/cargo-gpu/src/build.rs | 5 ++++- crates/cargo-gpu/src/config.rs | 17 +++++++++++++++++ crates/shader-crate-template/Cargo.toml | 9 ++++++--- crates/spirv-builder-cli/src/args.rs | 4 ++++ crates/xtask/src/main.rs | 1 + 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 789e4b7dfc..3dc97dcb1b 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -121,7 +121,10 @@ impl Build { .collect::>>()?; // Write the shader manifest json file - let manifest_path = self.build_args.output_dir.join("manifest.json"); + let manifest_path = self + .build_args + .output_dir + .join(&self.build_args.manifest_file); // Sort the contents so the output is deterministic linkage.sort(); let json = serde_json::to_string_pretty(&linkage)?; diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 13ec6f231b..15337d353f 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -241,4 +241,21 @@ mod test { ] ); } + + #[test_log::test] + fn rename_manifest_parse() { + let shader_crate_path = crate::test::shader_crate_test_path(); + + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![ + "gpu".to_owned(), + "build".to_owned(), + "--manifest-file".to_owned(), + "mymanifest".to_owned(), + ], + ) + .unwrap(); + assert_eq!(args.build_args.manifest_file, "mymanifest".to_owned()); + } } diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index d684074429..1261d9ff47 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -2,7 +2,7 @@ name = "rust-gpu-shader-crate-template" version = "0.1.0" edition = "2021" - + [lib] crate-type = ["rlib", "cdylib"] @@ -25,7 +25,7 @@ glam = { version = "0.29", features = ["std"] } output-dir = "./" # Set shader crate's cargo default-features no_default_features = false -# Set shader crate's cargo features. +# Set shader crate's cargo features. features = [] # The compile target. # TODO: `cargo gpu show targets` for all available options. @@ -51,7 +51,7 @@ spirv-metadata = "None" relax-struct-store = false # Allow allocating an object of a pointer type and returning a pointer value from a function # in logical addressing mode. -relax-logical-pointer = false +relax-logical-pointer = false # Enable VK_KHR_relaxed_block_layout when checking standard uniform, storage buffer, and push # constant layouts. # This is the default when targeting Vulkan 1.1 or later. @@ -68,6 +68,9 @@ scalar-block-layout = false skip-block-layout = false # Preserve unused descriptor bindings. Useful for reflection. preserve-bindings = false +# Renames the manifest.json file to the given string. Useful if you collect all your SPIR-V fragments +# in one place. +manifest-file = "manifest.json" [package.metadata.rust-gpu.install] # Source of `spirv-builder` dependency diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs index 625c020a81..8ce6a8b6c9 100644 --- a/crates/spirv-builder-cli/src/args.rs +++ b/crates/spirv-builder-cli/src/args.rs @@ -115,6 +115,10 @@ pub struct BuildArgs { /// Preserve unused descriptor bindings. Useful for reflection. #[arg(long, default_value = "false")] pub preserve_bindings: bool, + + ///Renames the manifest.json file to the given name + #[clap(long, short, default_value = "manifest.json")] + pub manifest_file: String, } impl BuildArgs { diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 6d1bd126f9..f486fde4a6 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -122,6 +122,7 @@ fn main() { .unwrap(); cmd(["ls", "-lah", dir.path().to_str().unwrap()]).unwrap(); + //NOTE: manifest.json is the default value here, which should be valid cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()]).unwrap(); } } From 64081883b7c4e10fdbb3a31ea53d12ccd1bb76f4 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Sun, 9 Mar 2025 18:52:23 -0300 Subject: [PATCH 082/162] Support CI tests for old `rust-gpu` versions (#41) Adds `rust-gpu` versions, `0.8.0` and `0.9.0` to the Linux matrix on CI tests. `0.7.0` has a probably minor dependency error, but it's also 18 months old and there probably aren't many users of it. Notes: * Adds a version arg to, eg: `cargo xtask --rust-gpu-version 0.8.0`. * Offers a new CLI arg to workaround a bug where conflicting v3/v4 versions of `Cargo.lock` files (between the shader and workspace) cause a build error. See `force_overwrite_lockfiles_v4_to_v3` arg. --- .github/workflows/push.yaml | 20 +- .gitignore | 5 + Cargo.lock | 31 +-- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 3 +- crates/cargo-gpu/src/install.rs | 3 +- crates/cargo-gpu/src/main.rs | 38 ++-- crates/cargo-gpu/src/spirv_cli.rs | 274 +++++++++++++++++++++++- crates/cargo-gpu/src/spirv_source.rs | 73 ++++--- crates/shader-crate-template/Cargo.lock | 2 +- crates/shader-crate-template/Cargo.toml | 24 ++- crates/spirv-builder-cli/Cargo.lock | 113 +++++----- crates/spirv-builder-cli/Cargo.toml | 5 +- crates/spirv-builder-cli/src/args.rs | 24 +++ crates/xtask/src/main.rs | 106 +++++++-- 15 files changed, 579 insertions(+), 143 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 9c41811070..5a710c97d3 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -19,6 +19,23 @@ jobs: - ubuntu-latest - macos-latest - windows-latest + rust-gpu-version: [latest] + include: + # As well as testing on each OS, we also want to test to make sure we're still supporting + # older versions of `rust-gpu`. However, we can assume that these tests are already okay + # across platforms, so we only need to test on Linux, the chepeast in terms of minutes. + # + # `0.7.0` currently fails building `spirv-builder-cli` with: + # """ + # package `is_terminal_polyfill v1.70.1` cannot be built because it requires rustc + # 1.70.0 or newer, while the currently active rustc version is 1.69.0-nightly + # """ + # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's + # unlikely many users of it? + - os: ubuntu-latest + rust-gpu-version: 0.8.0 + - os: ubuntu-latest + rust-gpu-version: 0.9.0 runs-on: ${{ matrix.os }} defaults: run: @@ -35,9 +52,8 @@ jobs: rustup update - run: cargo test - name: Run a full build - run: cargo xtask test-build + run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} - lints: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index 738d6d1fb3..9f81952cfc 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ flamegraph.svg # Compiled shader assets from running tests crates/shader-crate-template/shaders + +# Build artefacts used by CI tests +tmp/* +crates/shader-crate-template/manifest.json +crates/shader-crate-template/rust_gpu_shader_crate_template.spv diff --git a/Cargo.lock b/Cargo.lock index 9885f04dbc..bd63d763e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,6 +105,7 @@ dependencies = [ "spirv-builder-cli", "test-log", "toml", + "version_check", ] [[package]] @@ -124,9 +125,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -134,9 +135,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -146,9 +147,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -158,9 +159,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -301,9 +302,9 @@ checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "heck" -version = "0.5.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -769,9 +770,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -955,6 +956,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 05c1b33da6..8373ef4a3d 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -23,6 +23,7 @@ toml.workspace = true chrono.workspace = true http.workspace = true crossterm.workspace = true +version_check = "0.9.5" [dev-dependencies] test-log.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 3dc97dcb1b..d32dd24857 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -22,7 +22,7 @@ pub struct Build { impl Build { /// Entrypoint - #[expect(clippy::too_many_lines, reason = "these lines are fine")] + #[expect(clippy::too_many_lines, reason = "It's not too confusing")] pub fn run(&mut self) -> anyhow::Result<()> { let spirv_builder_cli_path = self.install.run()?; @@ -150,7 +150,6 @@ impl Build { ); std::fs::remove_file(spirv_manifest)?; } - Ok(()) } } diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 505de378a1..d6c286bad1 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -104,13 +104,14 @@ pub struct Install { impl Install { /// Returns a [`SpirvCLI`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. - fn spirv_cli(&self, shader_crate_path: &std::path::PathBuf) -> anyhow::Result { + fn spirv_cli(&self, shader_crate_path: &std::path::Path) -> anyhow::Result { SpirvCli::new( shader_crate_path, self.spirv_install.spirv_builder_source.clone(), self.spirv_install.spirv_builder_version.clone(), self.spirv_install.rust_toolchain.clone(), self.spirv_install.auto_install_rust_toolchain, + self.spirv_install.force_overwrite_lockfiles_v4_to_v3, ) } diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 990246c067..b46cf5bdde 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -134,7 +134,7 @@ fn run() -> anyhow::Result<()> { "installing with final merged arguments: {:#?}", command.install ); - let _: std::path::PathBuf = command.install.run()?; + command.install.run()?; } Command::Build(build) => { let shader_crate_path = build.install.spirv_install.shader_crate; @@ -150,7 +150,7 @@ fn run() -> anyhow::Result<()> { command.run()?; } else { command.run()?; - } + }; } Command::Show(show) => show.run()?, Command::DumpUsage => dump_full_usage_for_readme()?, @@ -274,6 +274,23 @@ mod test { use crate::cache_dir; use std::io::Write as _; + fn copy_dir_all( + src: impl AsRef, + dst: impl AsRef, + ) -> anyhow::Result<()> { + std::fs::create_dir_all(&dst)?; + for maybe_entry in std::fs::read_dir(src)? { + let entry = maybe_entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) + } + pub fn shader_crate_template_path() -> std::path::PathBuf { let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); project_base.join("../shader-crate-template") @@ -304,21 +321,4 @@ mod test { } std::fs::remove_dir_all(cache_dir).unwrap(); } - - pub fn copy_dir_all( - src: impl AsRef, - dst: impl AsRef, - ) -> anyhow::Result<()> { - std::fs::create_dir_all(&dst)?; - for maybe_entry in std::fs::read_dir(src)? { - let entry = maybe_entry?; - let ty = entry.file_type()?; - if ty.is_dir() { - copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; - } else { - std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; - } - } - Ok(()) - } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 38dfb86900..abe2e1f4f5 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -1,10 +1,16 @@ //! Query the shader crate to find what version of `rust-gpu` it depends on. //! Then ensure that the relevant Rust toolchain and components are installed. +use std::io::Write as _; + use anyhow::Context as _; use crate::spirv_source::SpirvSource; +/// `Cargo.lock` manifest version 4 became the default in Rust 1.83.0. Conflicting manifest +/// versions between the workspace and the shader crate, can cause problems. +const RUST_VERSION_THAT_USES_V4_CARGO_LOCKS: &str = "1.83.0"; + /// Cargo dependency for `spirv-builder` and the rust toolchain channel. #[derive(Debug, Clone)] pub struct SpirvCli { @@ -23,6 +29,8 @@ pub struct SpirvCli { pub channel: String, /// The date of the pinned version of `rust-gpu` pub date: chrono::NaiveDate, + /// `Cargo.lock`s that have had their manifest versions changed by us and need changing back. + pub cargo_lock_files_with_changed_manifest_versions: Vec, /// Has the user overridden the toolchain consent prompt is_toolchain_install_consent: bool, } @@ -40,15 +48,39 @@ impl core::fmt::Display for SpirvCli { impl SpirvCli { /// Create instance pub fn new( - shader_crate_path: &std::path::PathBuf, + shader_crate_path: &std::path::Path, maybe_rust_gpu_source: Option, maybe_rust_gpu_version: Option, maybe_rust_gpu_channel: Option, is_toolchain_install_consent: bool, + is_force_overwrite_lockfiles_v4_to_v3: bool, ) -> anyhow::Result { + let mut cargo_lock_files_with_changed_manifest_versions = vec![]; + + let maybe_shader_crate_lock = + Self::ensure_workspace_rust_version_doesnt_conflict_with_shader( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + )?; + + if let Some(shader_crate_lock) = maybe_shader_crate_lock { + cargo_lock_files_with_changed_manifest_versions.push(shader_crate_lock); + } + let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path)?; + let maybe_workspace_crate_lock = + Self::ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( + shader_crate_path, + default_rust_gpu_channel.clone(), + is_force_overwrite_lockfiles_v4_to_v3, + )?; + + if let Some(workspace_crate_lock) = maybe_workspace_crate_lock { + cargo_lock_files_with_changed_manifest_versions.push(workspace_crate_lock); + } + let mut maybe_spirv_source: Option = None; if let Some(rust_gpu_version) = maybe_rust_gpu_version { let mut source = SpirvSource::CratesIO(rust_gpu_version.clone()); @@ -66,6 +98,7 @@ impl SpirvCli { channel: maybe_rust_gpu_channel.unwrap_or(default_rust_gpu_channel), date: rust_gpu_date, is_toolchain_install_consent, + cargo_lock_files_with_changed_manifest_versions, }) } @@ -171,7 +204,6 @@ impl SpirvCli { crate::user_output!("{prompt} [y/n]: "); let input = crossterm::event::read()?; crossterm::terminal::disable_raw_mode()?; - crate::user_output!("{:?}\n", input); if let crossterm::event::Event::Key(crossterm::event::KeyEvent { code: crossterm::event::KeyCode::Char('y'), @@ -184,6 +216,242 @@ impl SpirvCli { std::process::exit(0); } } + + /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. + fn ensure_workspace_rust_version_doesnt_conflict_with_shader( + shader_crate_path: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result> { + log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from workspace Rust..."); + let workspace_rust_version = Self::get_rustc_version(None)?; + if version_check::Version::at_least( + &workspace_rust_version, + RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, + ) { + log::debug!( + "user's Rust is v{}, so no v3/v4 conflicts possible.", + workspace_rust_version + ); + return Ok(None); + } + + Self::handle_conflicting_cargo_lock_v4( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + )?; + + if is_force_overwrite_lockfiles_v4_to_v3 { + Ok(Some(shader_crate_path.join("Cargo.lock"))) + } else { + Ok(None) + } + } + + /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. + fn ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( + shader_crate_path: &std::path::Path, + channel: String, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result> { + log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from shader's Rust..."); + let shader_rust_version = Self::get_rustc_version(Some(channel))?; + if version_check::Version::at_least( + &shader_rust_version, + RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, + ) { + log::debug!( + "shader's Rust is v{}, so no v3/v4 conflicts possible.", + shader_rust_version + ); + return Ok(None); + } + + log::debug!( + "shader's Rust is v{}, so checking both shader and workspace `Cargo.lock` manifest versions...", + shader_rust_version + ); + + if shader_crate_path.join("Cargo.lock").exists() { + // Note that we don't return the `Cargo.lock` here (so that it's marked for reversion + // after the build), because we can be sure that updating it now is actually updating it + // to the state it should have been all along. Therefore it doesn't need reverting once + // fixed. + Self::handle_conflicting_cargo_lock_v4( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + )?; + } + + if let Some(workspace_root) = Self::get_workspace_root(shader_crate_path)? { + Self::handle_conflicting_cargo_lock_v4( + workspace_root, + is_force_overwrite_lockfiles_v4_to_v3, + )?; + return Ok(Some(workspace_root.join("Cargo.lock"))); + } + + Ok(None) + } + + /// Get the path to the shader crate's workspace, if it has one. We can't use the traditional + /// `cargo metadata` because if the workspace has a conflicting `Cargo.lock` manifest version + /// then that command won't work. Instead we do an old school recursive file tree walk. + fn get_workspace_root( + shader_crate_path: &std::path::Path, + ) -> anyhow::Result> { + let shader_cargo_toml = std::fs::read_to_string(shader_crate_path.join("Cargo.toml"))?; + if !shader_cargo_toml.contains("workspace = true") { + return Ok(None); + } + + let mut current_path = shader_crate_path; + #[expect(clippy::default_numeric_fallback, reason = "It's just a loop")] + for _ in 0..15 { + if let Some(parent_path) = current_path.parent() { + if parent_path.join("Cargo.lock").exists() { + return Ok(Some(parent_path)); + } + current_path = parent_path; + } else { + break; + } + } + + Ok(None) + } + + /// When Rust < 1.83.0 is being used an error will occur if it tries to parse `Cargo.lock` + /// files that use lockfile manifest version 4. Here we check and handle that. + fn handle_conflicting_cargo_lock_v4( + folder: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result<()> { + let shader_cargo_lock_path = folder.join("Cargo.lock"); + let shader_cargo_lock = std::fs::read_to_string(shader_cargo_lock_path.clone())?; + let third_line = shader_cargo_lock.lines().nth(2).context("")?; + if third_line.contains("version = 4") { + Self::handle_v3v4_conflict( + &shader_cargo_lock_path, + is_force_overwrite_lockfiles_v4_to_v3, + )?; + return Ok(()); + } + if third_line.contains("version = 3") { + return Ok(()); + } + anyhow::bail!( + "Unrecognized `Cargo.lock` manifest version at: {}", + folder.display() + ) + } + + /// Handle conflicting `Cargo.lock` manifest versions by either overwriting the manifest + /// version or exiting with advice on how to handle the conflict. + fn handle_v3v4_conflict( + offending_cargo_lock: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result<()> { + if !is_force_overwrite_lockfiles_v4_to_v3 { + Self::exit_with_v3v4_hack_suggestion(); + } + + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "4", "3")?; + + Ok(()) + } + + /// Once all install and builds have completed put their manifest versions back to how they + /// were. + pub fn revert_cargo_lock_manifest_versions(&self) -> anyhow::Result<()> { + for offending_cargo_lock in &self.cargo_lock_files_with_changed_manifest_versions { + log::debug!("Reverting: {}", offending_cargo_lock.display()); + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "3", "4")?; + } + + Ok(()) + } + + /// Replace the manifest version, eg `version = 4`, in a `Cargo.lock` file. + fn replace_cargo_lock_manifest_version( + offending_cargo_lock: &std::path::Path, + from_version: &str, + to_version: &str, + ) -> anyhow::Result<()> { + log::warn!( + "Replacing manifest version 'version = {}' with 'version = {}' in: {}", + from_version, + to_version, + offending_cargo_lock.display() + ); + let old_contents = std::fs::read_to_string(offending_cargo_lock)?; + let new_contents = old_contents.replace( + &format!("\nversion = {from_version}\n"), + &format!("\nversion = {to_version}\n"), + ); + + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(offending_cargo_lock)?; + file.write_all(new_contents.as_bytes())?; + + Ok(()) + } + + /// Exit and give the user advice on how to deal with the infamous v3/v4 Cargo lockfile version + /// problem. + #[expect(clippy::non_ascii_literal, reason = "It's CLI output")] + fn exit_with_v3v4_hack_suggestion() { + crate::user_output!( + "Conflicting `Cargo.lock` versions detected ⚠️\n\ + Because `cargo gpu` uses a dedicated Rust toolchain for compiling shaders\n\ + it's possible that the `Cargo.lock` manifest version of the shader crate\n\ + does not match the `Cargo.lock` manifest version of the workspace. This is\n\ + due to a change in the defaults introduced in Rust 1.83.0.\n\ + \n\ + One way to resolve this is to force the workspace to use the same version\n\ + of Rust as required by the shader. However that is not often ideal or even\n\ + possible. Another way is to exlude the shader from the workspace. This is\n\ + also not ideal if you have many shaders sharing config from the workspace.\n\ + \n\ + Therefore `cargo gpu build/install` offers a workaround with the argument:\n\ + --force-overwrite-lockfiles-v4-to-v3\n\ + \n\ + See `cargo gpu build --help` for more information.\n\ + " + ); + std::process::exit(1); + } + + /// Get the version of `rustc`. + fn get_rustc_version( + maybe_toolchain: Option, + ) -> anyhow::Result { + let mut maybe_current_env_toolchain: Option = None; + if let Some(toolchain) = maybe_toolchain { + maybe_current_env_toolchain = std::env::var_os("RUSTUP_TOOLCHAIN"); + std::env::set_var("RUSTUP_TOOLCHAIN", toolchain); + } + + let Some(version) = version_check::Version::read() else { + anyhow::bail!("Couldn't get `rustc --version`"); + }; + + if let Some(current_env_toolchain) = maybe_current_env_toolchain { + std::env::set_var("RUSTUP_TOOLCHAIN", current_env_toolchain); + } + + Ok(version) + } +} + +impl Drop for SpirvCli { + fn drop(&mut self) { + let result = self.revert_cargo_lock_manifest_versions(); + if let Err(error) = result { + log::error!("Couldn't revert some or all of the shader `Cargo.lock` files: {error}"); + } + } } #[cfg(test)] @@ -195,7 +463,7 @@ mod test { let shader_template_path = crate::test::shader_crate_template_path(); // TODO: This downloads the `rust-gpu` repo which slows the test down. Can we avoid that // just to get the sanity check? - let spirv = SpirvCli::new(&shader_template_path, None, None, None, true).unwrap(); + let spirv = SpirvCli::new(&shader_template_path, None, None, None, true, false).unwrap(); let dir = spirv.cached_checkout_path().unwrap(); let name = dir .file_name() diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 498e20ea74..ec4526e663 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -50,18 +50,20 @@ impl core::fmt::Display for SpirvSource { impl SpirvSource { /// Look into the shader crate to get the version of `rust-gpu` it's using. - pub fn get_rust_gpu_deps_from_shader( - shader_crate_path: &std::path::PathBuf, + pub fn get_rust_gpu_deps_from_shader>( + shader_crate_path: F, ) -> anyhow::Result<(Self, chrono::NaiveDate, String)> { - let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path)?; - + let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path.as_ref())?; rust_gpu_source.ensure_repo_is_installed()?; rust_gpu_source.checkout()?; let date = rust_gpu_source.get_version_date()?; let channel = Self::get_channel_from_toolchain_toml(&rust_gpu_source.to_dirname()?)?; - log::debug!("Parsed version, date and toolchain channel from shader-defined `rust-gpu`: {rust_gpu_source:?}, {date}, {channel}"); + log::debug!( + "Parsed version, date and toolchain channel from shader-defined `rust-gpu`: \ + {rust_gpu_source:?}, {date}, {channel}" + ); Ok((rust_gpu_source, date, channel)) } @@ -91,6 +93,30 @@ impl SpirvSource { Ok(crate::cache_dir()?.join("rust-gpu-repo").join(dir)) } + /// Make sure shader crate path is absolute and canonical. + fn shader_crate_path_canonical( + shader_crate_path: &mut std::path::PathBuf, + ) -> anyhow::Result<()> { + let cwd = std::env::current_dir().context("no cwd")?; + let mut canonical_path = shader_crate_path.clone(); + + if !canonical_path.is_absolute() { + canonical_path = cwd.join(canonical_path); + } + canonical_path + .canonicalize() + .context("could not get absolute path to shader crate")?; + + if !canonical_path.is_dir() { + log::error!("{shader_crate_path:?} is not a directory, aborting"); + anyhow::bail!("{shader_crate_path:?} is not a directory"); + }; + + *shader_crate_path = canonical_path; + + Ok(()) + } + /// Checkout the `rust-gpu` repo to the requested version. fn checkout(&self) -> anyhow::Result<()> { log::debug!( @@ -171,31 +197,27 @@ impl SpirvSource { Ok(channel.to_string().replace('"', "")) } - /// Get the shader crate's `spirv_std = ...` definition in its `Cargo.toml` + /// Get the shader crate's resolved `spirv_std = ...` definition in its `Cargo.toml`/`Cargo.lock` pub fn get_spirv_std_dep_definition( - shader_crate_path: &std::path::PathBuf, + shader_crate_path: &std::path::Path, ) -> anyhow::Result { - let cwd = std::env::current_dir().context("no cwd")?; - let exec_path = if shader_crate_path.is_absolute() { - shader_crate_path.clone() - } else { - cwd.join(shader_crate_path) - } - .canonicalize() - .context("could not get absolute path to shader crate")?; - if !exec_path.is_dir() { - log::error!("{exec_path:?} is not a directory, aborting"); - anyhow::bail!("{exec_path:?} is not a directory"); - } + let canonical_shader_path = shader_crate_path.to_path_buf(); + Self::shader_crate_path_canonical(&mut canonical_shader_path.clone())?; - log::debug!("Running `cargo tree` on {}", exec_path.display()); + log::debug!( + "Running `cargo tree` on {}", + canonical_shader_path.display() + ); let output_cargo_tree = std::process::Command::new("cargo") - .current_dir(&exec_path) + .current_dir(canonical_shader_path.clone()) .args(["tree", "--workspace", "--prefix", "none"]) .output()?; anyhow::ensure!( output_cargo_tree.status.success(), - "could not query shader's `Cargo.toml` for `spirv-std` dependency" + format!( + "could not query shader's `Cargo.toml` for `spirv-std` dependency: {}", + String::from_utf8(output_cargo_tree.stderr)? + ) ); let cargo_tree_string = String::from_utf8_lossy(&output_cargo_tree.stdout); @@ -205,7 +227,7 @@ impl SpirvSource { log::trace!(" found {maybe_spirv_std_def:?}"); let Some(spirv_std_def) = maybe_spirv_std_def else { - anyhow::bail!("`spirv-std` not found in shader's `Cargo.toml` at {exec_path:?}:\n{cargo_tree_string}"); + anyhow::bail!("`spirv-std` not found in shader's `Cargo.toml` at {canonical_shader_path:?}:\n{cargo_tree_string}"); }; Self::parse_spirv_std_source_and_version(spirv_std_def) @@ -239,8 +261,8 @@ impl SpirvSource { // So here we'll parse the fragment out of the source string by hand let uri = source_string.parse::()?; let maybe_hash = if source_string.contains('#') { - let splits = source_string.split('#'); - splits.last().map(std::borrow::ToOwned::to_owned) + let mut splits = source_string.split('#'); + splits.next_back().map(std::borrow::ToOwned::to_owned) } else { None }; @@ -322,6 +344,7 @@ impl SpirvSource { crate::user_output!("Cloning `rust-gpu` repo...\n"); + // TODO: do something else when testing, to help speed things up. let output_clone = std::process::Command::new("git") .args([ "clone", diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 8a30859684..8a7a320e57 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "autocfg" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 1261d9ff47..fb72e0ee08 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -8,7 +8,7 @@ crate-type = ["rlib", "cdylib"] # Dependencies for CPU and GPU code [dependencies] -# "v0.9" doesn't seem to compile on windows? +# TODO: use a simple crate version once v0.10.0 is released spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "82a0f69" } # Dependencies for GPU code @@ -92,3 +92,25 @@ manifest-file = "manifest.json" auto-install-rust-toolchain = false # Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. force-spirv-cli-rebuild = false +# There is a tricky situation where a shader crate that depends on workspace config can have +# a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can +# prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. +# +# The ideal way to resolve this would be to match the shader crate's toolchain with the +# workspace's toolchain. However, that is not always possible. Another solution is to +# `exclude = [...]` the problematic shader crate from the workspace. This also may not be a +# suitable solution if there are a number of shader crates all sharing similar config and +# you don't want to have to copy/paste and maintain that config across all the shaders. +# +# So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling +# this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also +# only overwrite versions for the duration of a build. It will attempt to return the versions +# to their original values once the build is finished. However, of course, unexpected errors +# can occur and the overwritten values can remain. Hence why this behaviour is not enabled by +# default. +# +# This hack is possible because the change from v3 to v4 only involves a minor change to the +# 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 +force-overwrite-lockfiles-v4-to-v3 = false diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index 9c8789ca9e..ae537474c5 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -63,11 +63,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -97,18 +98,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" dependencies = [ "serde", ] [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -118,9 +119,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.37" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -135,9 +136,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -145,9 +146,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -157,21 +158,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -210,7 +211,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -225,7 +226,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "stable_deref_trait", ] @@ -312,15 +313,15 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" -version = "0.5.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -346,12 +347,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -408,9 +409,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -449,9 +450,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.162" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libredox" @@ -529,18 +530,18 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -574,9 +575,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -729,35 +730,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -820,7 +821,7 @@ dependencies = [ "bytemuck", "derive_more", "elsa", - "indexmap 2.6.0", + "indexmap 2.7.0", "internal-iterator", "itertools", "lazy_static", @@ -848,7 +849,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "serde", ] @@ -923,9 +924,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" -version = "0.11.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -940,9 +941,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -985,7 +986,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -994,9 +995,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "utf8parse" @@ -1251,9 +1252,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml index 2bb6680e83..2cbd135065 100644 --- a/crates/spirv-builder-cli/Cargo.toml +++ b/crates/spirv-builder-cli/Cargo.toml @@ -4,7 +4,10 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = { version = "4.4.8", features = ["derive"] } +# `clap = "=4.4.8"` pin is needed to support older Rust toolchains. +# If `clap` gets too old, then it can be split into 2 versions, gated by a feature, like `spirv` is. +# Or more generally we should think about how to deprecate supporting old version of `rust-gpu`. +clap = { version = "=4.4.8", features = ["derive"] } env_home = "0.1.0" env_logger = "0.10" log = "0.4" diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs index 8ce6a8b6c9..dad50d651d 100644 --- a/crates/spirv-builder-cli/src/args.rs +++ b/crates/spirv-builder-cli/src/args.rs @@ -176,4 +176,28 @@ pub struct InstallArgs { /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. #[clap(long, action)] pub auto_install_rust_toolchain: bool, + + /// There is a tricky situation where a shader crate that depends on workspace config can have + /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can + /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. + /// + /// The ideal way to resolve this would be to match the shader crate's toolchain with the + /// workspace's toolchain. However, that is not always possible. Another solution is to + /// `exclude = [...]` the problematic shader crate from the workspace. This also may not be a + /// suitable solution if there are a number of shader crates all sharing similar config and + /// you don't want to have to copy/paste and maintain that config across all the shaders. + /// + /// So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling + /// this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also + /// only overwrite versions for the duration of a build. It will attempt to return the versions + /// to their original values once the build is finished. However, of course, unexpected errors + /// can occur and the overwritten values can remain. Hence why this behaviour is not enabled by + /// default. + /// + /// This hack is possible because the change from v3 to v4 only involves a minor change to the + /// 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)] + pub force_overwrite_lockfiles_v4_to_v3: bool, } diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index f486fde4a6..3f4d09056a 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -1,16 +1,26 @@ //! Project/repository utilities. -#![allow(clippy::shadow_reuse, reason = "sometimes its nice")] -#![allow(clippy::unwrap_used, reason = "sometimes its good")] -#![allow(clippy::unwrap_in_result, reason = "sometimes that's what you want")] +#![allow( + clippy::shadow_reuse, + clippy::unwrap_used, + clippy::unwrap_in_result, + reason = "This is just a workflow tool" +)] use anyhow::Context as _; use clap::Parser as _; +/// Path to the shader crate +const SHADER_CRATE_PATH: &str = "crates/shader-crate-template"; + /// Our xtask commands. #[derive(Debug, clap::Parser)] enum Cli { /// Run a test build of the shader-crate-template project. - TestBuild, + TestBuild { + /// Build using the specified version of `spirv-std`. + #[clap(long)] + rust_gpu_version: Option, + }, } fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { @@ -34,6 +44,8 @@ fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { struct ShaderCrateTemplateCargoTomlWriter { /// Original string original_shader_crate_template_str: String, + /// Original lockfile + original_shader_crate_lock_file: String, /// Parsed toml table table: toml::Table, } @@ -41,26 +53,46 @@ struct ShaderCrateTemplateCargoTomlWriter { impl Drop for ShaderCrateTemplateCargoTomlWriter { fn drop(&mut self) { log::info!("reverting overwrite of Cargo.toml"); - std::fs::write(Self::PATH, &self.original_shader_crate_template_str).unwrap(); + std::fs::write( + format!("{SHADER_CRATE_PATH}/Cargo.toml"), + &self.original_shader_crate_template_str, + ) + .unwrap(); + log::info!("reverting overwrite of Cargo.lock"); + std::fs::write( + format!("{SHADER_CRATE_PATH}/Cargo.lock"), + &self.original_shader_crate_lock_file, + ) + .unwrap(); } } impl ShaderCrateTemplateCargoTomlWriter { - /// Path to the Cargo.toml - const PATH: &str = "crates/shader-crate-template/Cargo.toml"; - /// Create a new one fn new() -> Self { - let original_shader_crate_template_str = std::fs::read_to_string(Self::PATH).unwrap(); + let original_shader_crate_template_str = + std::fs::read_to_string(format!("{SHADER_CRATE_PATH}/Cargo.toml")).unwrap(); let table = toml::from_str::(&original_shader_crate_template_str).unwrap(); + let original_shader_crate_lock_file = + std::fs::read_to_string(format!("{SHADER_CRATE_PATH}/Cargo.lock")).unwrap(); Self { original_shader_crate_template_str, + original_shader_crate_lock_file, table, } } - /// Replace the output-dir - fn replace_output_dir(&mut self, path: impl AsRef) -> anyhow::Result<()> { + /// Get the `[dependencies]` section of the shader's `Cargo.toml`. + fn get_cargo_dependencies_table(&mut self) -> &mut toml::Table { + self.table + .get_mut("dependencies") + .unwrap() + .as_table_mut() + .unwrap() + } + + /// Get the `[package.metadata.rust-gpu.build]` section of the shader's `Cargo.toml`. + fn get_rust_gpu_table(&mut self) -> &mut toml::Table { let package = self .table .get_mut("package") @@ -68,21 +100,42 @@ impl ShaderCrateTemplateCargoTomlWriter { .as_table_mut() .unwrap(); let metadata = package.get_mut("metadata").unwrap().as_table_mut().unwrap(); - let rust_gpu = metadata + metadata .get_mut("rust-gpu") .unwrap() .as_table_mut() - .unwrap(); - let build = rust_gpu.get_mut("build").unwrap().as_table_mut().unwrap(); - let output_dir = build.get_mut("output-dir").unwrap(); - *output_dir = toml::Value::String(format!("{}", path.as_ref().display())); + .unwrap() + } + + /// Write any temporary changes to the shader crate's `Cargo.toml` that are needed to run e2e + /// tests. + fn write_shader_crate_cargo_toml_changes(&self) -> anyhow::Result<()> { std::fs::write( - Self::PATH, + format!("{SHADER_CRATE_PATH}/Cargo.toml"), toml::to_string_pretty(&self.table).context("could not serialize")?, ) .context("could not overwrite path")?; Ok(()) } + + /// Replace the output-dir + fn replace_output_dir(&mut self, path: impl AsRef) -> anyhow::Result<()> { + let rust_gpu = self.get_rust_gpu_table(); + let build = rust_gpu.get_mut("build").unwrap().as_table_mut().unwrap(); + let output_dir = build.get_mut("output-dir").unwrap(); + *output_dir = toml::Value::String(format!("{}", path.as_ref().display())); + self.write_shader_crate_cargo_toml_changes()?; + Ok(()) + } + + /// Replace the `spirv-std` dependency version + fn replace_spirv_std_version(&mut self, version: String) -> anyhow::Result<()> { + let dependencies = self.get_cargo_dependencies_table(); + let spirv_std = dependencies.get_mut("spirv-std").unwrap(); + *spirv_std = toml::Value::String(version); + self.write_shader_crate_cargo_toml_changes()?; + Ok(()) + } } /// Run the xtask. @@ -92,7 +145,9 @@ fn main() { let cli = Cli::parse(); match cli { - Cli::TestBuild => { + Cli::TestBuild { + rust_gpu_version: maybe_rust_gpu_version, + } => { log::info!("installing cargo gpu"); cmd(["cargo", "install", "--path", "crates/cargo-gpu"]).unwrap(); @@ -102,8 +157,9 @@ fn main() { "gpu", "install", "--shader-crate", - "crates/shader-crate-template", + SHADER_CRATE_PATH, "--auto-install-rust-toolchain", + "--force-overwrite-lockfiles-v4-to-v3", ]) .unwrap(); @@ -111,13 +167,23 @@ fn main() { let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); overwriter.replace_output_dir(dir.path()).unwrap(); + if let Some(rust_gpu_version) = maybe_rust_gpu_version { + if rust_gpu_version != "latest" { + overwriter + .replace_spirv_std_version(rust_gpu_version) + .unwrap(); + } + } + cmd([ "cargo", "gpu", "build", "--shader-crate", - "crates/shader-crate-template", + SHADER_CRATE_PATH, + "--auto-install-rust-toolchain", "--force-spirv-cli-rebuild", + "--force-overwrite-lockfiles-v4-to-v3", ]) .unwrap(); From ea3f5ed1c728b9b0748432c94336550712042ec5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 13 Mar 2025 16:32:12 +1300 Subject: [PATCH 083/162] fix: bumped bytemuck and itoa (#54) --- crates/spirv-builder-cli/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock index ae537474c5..1058571e2f 100644 --- a/crates/spirv-builder-cli/Cargo.lock +++ b/crates/spirv-builder-cli/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "byteorder" @@ -409,9 +409,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" From 924d0ab79d4cdc4d0d7190102510a7eb120f4709 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Nied=C5=BAwied=C5=BA?= Date: Sun, 30 Mar 2025 04:04:02 +0200 Subject: [PATCH 084/162] Ran `cargo fmt` + added some `.context()` calls for non-obvious errors (#56) --- crates/cargo-gpu/src/install.rs | 67 +++++++++++++++++------- crates/cargo-gpu/src/main.rs | 6 +-- crates/cargo-gpu/src/show.rs | 2 +- crates/cargo-gpu/src/spirv_cli.rs | 78 ++++++++++++++++++---------- crates/cargo-gpu/src/spirv_source.rs | 2 +- 5 files changed, 102 insertions(+), 53 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index d6c286bad1..9977227b38 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,4 +1,5 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. + use std::io::Write as _; use anyhow::Context as _; @@ -117,18 +118,24 @@ impl Install { /// Create the `spirv-builder-cli` crate. fn write_source_files(&self) -> anyhow::Result<()> { - let spirv_cli = self.spirv_cli(&self.spirv_install.shader_crate)?; - let checkout = spirv_cli.cached_checkout_path()?; - std::fs::create_dir_all(checkout.join("src"))?; + let spirv_cli = self + .spirv_cli(&self.spirv_install.shader_crate) + .context("running spirv cli")?; + let checkout = spirv_cli + .cached_checkout_path() + .context("getting cached checkout path")?; + std::fs::create_dir_all(checkout.join("src")).context("creating directory for 'src'")?; for (filename, contents) in SPIRV_BUILDER_FILES { log::debug!("writing {filename}"); let path = checkout.join(filename); - let mut file = std::fs::File::create(&path)?; + let mut file = std::fs::File::create(&path) + .with_context(|| format!("creating a file at [{}]", path.display()))?; let mut replaced_contents = contents.replace("${CHANNEL}", &spirv_cli.channel); if filename == &"Cargo.toml" { replaced_contents = Self::update_cargo_toml(&replaced_contents, &spirv_cli.source); } - file.write_all(replaced_contents.as_bytes())?; + file.write_all(replaced_contents.as_bytes()) + .context("writing to file")?; } Ok(()) } @@ -165,10 +172,14 @@ impl Install { /// Add the target spec files to the crate. fn write_target_spec_files(&self) -> anyhow::Result<()> { for (filename, contents) in TARGET_SPECS { - let path = target_spec_dir()?.join(filename); + let path = target_spec_dir() + .context("creating target spec dir")? + .join(filename); if !path.is_file() || self.spirv_install.force_spirv_cli_rebuild { - let mut file = std::fs::File::create(&path)?; - file.write_all(contents.as_bytes())?; + let mut file = std::fs::File::create(&path) + .with_context(|| format!("creating file at [{}]", path.display()))?; + file.write_all(contents.as_bytes()) + .context("writing to file")?; } } Ok(()) @@ -183,10 +194,16 @@ impl Install { format!("could not create cache directory '{}'", cache_dir.display()) })?; - let spirv_version = self.spirv_cli(&self.spirv_install.shader_crate)?; - spirv_version.ensure_toolchain_and_components_exist()?; + let spirv_version = self + .spirv_cli(&self.spirv_install.shader_crate) + .context("running spirv cli")?; + spirv_version + .ensure_toolchain_and_components_exist() + .context("ensuring toolchain and components exist")?; - let checkout = spirv_version.cached_checkout_path()?; + let checkout = spirv_version + .cached_checkout_path() + .context("getting cached checkout path")?; let release = checkout.join("target").join("release"); let dylib_filename = format!( @@ -214,8 +231,9 @@ impl Install { "writing spirv-builder-cli source files into '{}'", checkout.display() ); - self.write_source_files()?; - self.write_target_spec_files()?; + self.write_source_files().context("writing source files")?; + self.write_target_spec_files() + .context("writing target spec files")?; crate::user_output!( "Compiling shader-specific `spirv-builder-cli` for {}\n", @@ -231,20 +249,29 @@ impl Install { build_command.args([ "--features", - &Self::get_required_spirv_builder_version(spirv_version.date)?, + &Self::get_required_spirv_builder_version(spirv_version.date) + .context("getting required spirv builder version")?, ]); log::debug!("building artifacts with `{:?}`", build_command); - let build_output = build_command + build_command .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output()?; - anyhow::ensure!(build_output.status.success(), "...build error!"); + .output() + .context("getting command output") + .and_then(|output| { + if output.status.success() { + Ok(output) + } else { + Err(anyhow::anyhow!("bad status {:?}", output.status)) + } + }) + .context("running build command")?; if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); - std::fs::rename(&dylib_path, &dest_dylib_path)?; + std::fs::rename(&dylib_path, &dest_dylib_path).context("renaming dylib path")?; } else { log::error!("could not find {}", dylib_path.display()); anyhow::bail!("spirv-builder-cli build failed"); @@ -257,11 +284,11 @@ impl Install { }; if cli_path.is_file() { log::info!("successfully built {}", cli_path.display()); - std::fs::rename(&cli_path, &dest_cli_path)?; + std::fs::rename(&cli_path, &dest_cli_path).context("renaming cli path")?; } else { log::error!("could not find {}", cli_path.display()); log::debug!("contents of '{}':", release.display()); - for maybe_entry in std::fs::read_dir(&release)? { + for maybe_entry in std::fs::read_dir(&release).context("reading release dir")? { let entry = maybe_entry?; log::debug!("{}", entry.file_name().to_string_lossy()); } diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index b46cf5bdde..69973861ef 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -110,7 +110,7 @@ fn main() { #[expect(clippy::restriction, reason = "Our central place for safely exiting")] std::process::exit(1); }; - }; + } } /// Wrappable "main" to catch errors. @@ -150,11 +150,11 @@ fn run() -> anyhow::Result<()> { command.run()?; } else { command.run()?; - }; + } } Command::Show(show) => show.run()?, Command::DumpUsage => dump_full_usage_for_readme()?, - }; + } Ok(()) } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 985a33f687..61202cbf0c 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -5,7 +5,7 @@ use crate::cache_dir; /// Show the computed source of the spirv-std dependency. #[derive(Clone, Debug, clap::Parser)] pub struct SpirvSourceDep { - /// The location of the shader-crate to inspect to determine its spirv-std dependency. + /// The location of the shader-crate to inspect to determine its spirv-std dependency. #[clap(long, default_value = "./")] pub shader_crate: std::path::PathBuf, } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index abe2e1f4f5..9dfb7e58ff 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -61,21 +61,24 @@ impl SpirvCli { Self::ensure_workspace_rust_version_doesnt_conflict_with_shader( shader_crate_path, is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("ensure_workspace_rust_version_doesnt_conflict_with_shader")?; if let Some(shader_crate_lock) = maybe_shader_crate_lock { cargo_lock_files_with_changed_manifest_versions.push(shader_crate_lock); } let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = - SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path)?; + SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path) + .context("get_rust_gpu_deps_from_shader")?; let maybe_workspace_crate_lock = Self::ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( shader_crate_path, default_rust_gpu_channel.clone(), is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks")?; if let Some(workspace_crate_lock) = maybe_workspace_crate_lock { cargo_lock_files_with_changed_manifest_versions.push(workspace_crate_lock); @@ -104,12 +107,13 @@ impl SpirvCli { /// Create and/or return the cache directory pub fn cached_checkout_path(&self) -> anyhow::Result { - let checkout_dir = crate::cache_dir()? + let checkout_dir = crate::cache_dir() + .context("reading cache dir")? .join("spirv-builder-cli") .join(crate::to_dirname(self.to_string().as_ref())); - std::fs::create_dir_all(&checkout_dir).with_context(|| { - format!("could not create checkout dir '{}'", checkout_dir.display()) - })?; + std::fs::create_dir_all(&checkout_dir) + .with_context(|| format!("could not create checkout dir '{}'", checkout_dir.display())) + .context("crating directory in cahce dir")?; Ok(checkout_dir) } @@ -124,7 +128,8 @@ impl SpirvCli { // Check for the required toolchain let output_toolchain_list = std::process::Command::new("rustup") .args(["toolchain", "list"]) - .output()?; + .output() + .context("running rustup command")?; anyhow::ensure!( output_toolchain_list.status.success(), "could not list installed toolchains" @@ -145,7 +150,8 @@ impl SpirvCli { .arg(&self.channel) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output()?; + .output() + .context("adding toolchain")?; anyhow::ensure!( output_toolchain_add.status.success(), "could not install required toolchain" @@ -156,7 +162,8 @@ impl SpirvCli { let output_component_list = std::process::Command::new("rustup") .args(["component", "list", "--toolchain"]) .arg(&self.channel) - .output()?; + .output() + .context("getting toolchain list")?; anyhow::ensure!( output_component_list.status.success(), "could not list installed components" @@ -184,7 +191,8 @@ impl SpirvCli { .args(["rust-src", "rustc-dev", "llvm-tools"]) .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) - .output()?; + .output() + .context("adding rustup component")?; anyhow::ensure!( output_component_add.status.success(), "could not install required components" @@ -200,10 +208,10 @@ impl SpirvCli { return Ok(()); } log::debug!("asking for consent to install the required toolchain"); - crossterm::terminal::enable_raw_mode()?; + crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; crate::user_output!("{prompt} [y/n]: "); - let input = crossterm::event::read()?; - crossterm::terminal::disable_raw_mode()?; + let input = crossterm::event::read().context("reading crossterm event")?; + crossterm::terminal::disable_raw_mode().context("disabling raw mode")?; if let crossterm::event::Event::Key(crossterm::event::KeyEvent { code: crossterm::event::KeyCode::Char('y'), @@ -223,7 +231,8 @@ impl SpirvCli { is_force_overwrite_lockfiles_v4_to_v3: bool, ) -> anyhow::Result> { log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from workspace Rust..."); - let workspace_rust_version = Self::get_rustc_version(None)?; + let workspace_rust_version = + Self::get_rustc_version(None).context("reading rustc version")?; if version_check::Version::at_least( &workspace_rust_version, RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, @@ -238,7 +247,8 @@ impl SpirvCli { Self::handle_conflicting_cargo_lock_v4( shader_crate_path, is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("handling v4/v3 conflict")?; if is_force_overwrite_lockfiles_v4_to_v3 { Ok(Some(shader_crate_path.join("Cargo.lock"))) @@ -254,7 +264,8 @@ impl SpirvCli { is_force_overwrite_lockfiles_v4_to_v3: bool, ) -> anyhow::Result> { log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from shader's Rust..."); - let shader_rust_version = Self::get_rustc_version(Some(channel))?; + let shader_rust_version = + Self::get_rustc_version(Some(channel)).context("getting rustc version")?; if version_check::Version::at_least( &shader_rust_version, RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, @@ -279,14 +290,18 @@ impl SpirvCli { Self::handle_conflicting_cargo_lock_v4( shader_crate_path, is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("handling v4/v3 conflict")?; } - if let Some(workspace_root) = Self::get_workspace_root(shader_crate_path)? { + if let Some(workspace_root) = + Self::get_workspace_root(shader_crate_path).context("reading workspace root")? + { Self::handle_conflicting_cargo_lock_v4( workspace_root, is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("handling conflicting cargo v4")?; return Ok(Some(workspace_root.join("Cargo.lock"))); } @@ -299,7 +314,8 @@ impl SpirvCli { fn get_workspace_root( shader_crate_path: &std::path::Path, ) -> anyhow::Result> { - let shader_cargo_toml = std::fs::read_to_string(shader_crate_path.join("Cargo.toml"))?; + let shader_cargo_toml = std::fs::read_to_string(shader_crate_path.join("Cargo.toml")) + .with_context(|| format!("reading Cargo.toml at {}", shader_crate_path.display()))?; if !shader_cargo_toml.contains("workspace = true") { return Ok(None); } @@ -327,13 +343,15 @@ impl SpirvCli { is_force_overwrite_lockfiles_v4_to_v3: bool, ) -> anyhow::Result<()> { let shader_cargo_lock_path = folder.join("Cargo.lock"); - let shader_cargo_lock = std::fs::read_to_string(shader_cargo_lock_path.clone())?; - let third_line = shader_cargo_lock.lines().nth(2).context("")?; + let shader_cargo_lock = std::fs::read_to_string(shader_cargo_lock_path.clone()) + .context("reading shader cargo lock")?; + let third_line = shader_cargo_lock.lines().nth(2).context("no third line")?; if third_line.contains("version = 4") { Self::handle_v3v4_conflict( &shader_cargo_lock_path, is_force_overwrite_lockfiles_v4_to_v3, - )?; + ) + .context("handling v4/v3 conflict")?; return Ok(()); } if third_line.contains("version = 3") { @@ -355,7 +373,8 @@ impl SpirvCli { Self::exit_with_v3v4_hack_suggestion(); } - Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "4", "3")?; + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "4", "3") + .context("replacing version 4 -> 3")?; Ok(()) } @@ -365,7 +384,8 @@ impl SpirvCli { pub fn revert_cargo_lock_manifest_versions(&self) -> anyhow::Result<()> { for offending_cargo_lock in &self.cargo_lock_files_with_changed_manifest_versions { log::debug!("Reverting: {}", offending_cargo_lock.display()); - Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "3", "4")?; + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "3", "4") + .context("replacing version 3 -> 4")?; } Ok(()) @@ -383,7 +403,8 @@ impl SpirvCli { to_version, offending_cargo_lock.display() ); - let old_contents = std::fs::read_to_string(offending_cargo_lock)?; + let old_contents = std::fs::read_to_string(offending_cargo_lock) + .context("reading offending Cargo.lock")?; let new_contents = old_contents.replace( &format!("\nversion = {from_version}\n"), &format!("\nversion = {to_version}\n"), @@ -392,7 +413,8 @@ impl SpirvCli { let mut file = std::fs::OpenOptions::new() .write(true) .truncate(true) - .open(offending_cargo_lock)?; + .open(offending_cargo_lock) + .context("opening offending Cargo.lock")?; file.write_all(new_contents.as_bytes())?; Ok(()) diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index ec4526e663..c1815d62ca 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -110,7 +110,7 @@ impl SpirvSource { if !canonical_path.is_dir() { log::error!("{shader_crate_path:?} is not a directory, aborting"); anyhow::bail!("{shader_crate_path:?} is not a directory"); - }; + } *shader_crate_path = canonical_path; From 2fb1557ea8656431317847e204ddb5cb05063e5d Mon Sep 17 00:00:00 2001 From: bspeice Date: Sun, 30 Mar 2025 15:22:02 -0400 Subject: [PATCH 085/162] Preserve existing paths when adding rustc_codegen_spirv (#61) --- crates/spirv-builder-cli/src/main.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs index f18c3f22ec..2a179380a7 100644 --- a/crates/spirv-builder-cli/src/main.rs +++ b/crates/spirv-builder-cli/src/main.rs @@ -37,7 +37,14 @@ const fn dylib_path_envvar() -> &'static str { fn set_codegen_spirv_location(dylib_path: std::path::PathBuf) { let env_var = dylib_path_envvar(); - let path = dylib_path.parent().unwrap().display().to_string(); + let existing_paths_str = std::env::var(env_var).unwrap(); + let mut dylib_paths = std::env::split_paths(&existing_paths_str).collect::>(); + + let dylib_path = dylib_path.parent().unwrap().to_path_buf(); + dylib_paths.insert(0, dylib_path); + + let path = std::env::join_paths(dylib_paths).unwrap().into_string().unwrap(); + log::debug!("Setting OS-dependent DLL ENV path ({env_var}) to: {path}"); std::env::set_var(env_var, path); } From 76f6f575cbaa43ea8f2abcb494dc028108ebe1a9 Mon Sep 17 00:00:00 2001 From: bspeice Date: Sun, 30 Mar 2025 15:23:51 -0400 Subject: [PATCH 086/162] Update README.md with workspace install path, new template crate (#60) --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 992156a92b..39f303bad9 100644 --- a/README.md +++ b/README.md @@ -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 install --git https://github.com/rust-gpu/cargo-gpu cargo-gpu ``` After that you can use `cargo gpu` to compile your shader crates with: @@ -25,13 +25,13 @@ Use `cargo gpu help` to see other options :) ### Next Steps -You can try this out using the example repo at . -Keep in mind is _not_ yet a cargo generate template, +You can try this out using the example repo at . +Keep in mind is _not_ yet a cargo generate template, it's just a normal repo. ``` -git clone https://github.com/rust-GPU/shader-crate-template -cd shader-crate-template +git clone https://github.com/rust-GPU/cargo-gpu +cd cargo-gpu/crates/shader-crate-template cargo gpu build ``` From 66896f81c6eb702eed66a70aa6baa8a4b473c33b Mon Sep 17 00:00:00 2001 From: bspeice Date: Sun, 30 Mar 2025 19:16:50 -0400 Subject: [PATCH 087/162] Capture initial Enter key release (#59) --- crates/cargo-gpu/src/spirv_cli.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs index 9dfb7e58ff..8a905d15d2 100644 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ b/crates/cargo-gpu/src/spirv_cli.rs @@ -209,8 +209,19 @@ impl SpirvCli { } log::debug!("asking for consent to install the required toolchain"); crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; - crate::user_output!("{prompt} [y/n]: "); - let input = crossterm::event::read().context("reading crossterm event")?; + crate::user_output!("{prompt} [y/n]: \n"); + let mut input = crossterm::event::read().context("reading crossterm event")?; + + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { + code: crossterm::event::KeyCode::Enter, + kind: crossterm::event::KeyEventKind::Release, + .. + }) = input + { + // In Powershell, programs will potentially observe the Enter key release after they started + // (see crossterm#124). If that happens, re-read the input. + input = crossterm::event::read().context("re-reading crossterm event")?; + } crossterm::terminal::disable_raw_mode().context("disabling raw mode")?; if let crossterm::event::Event::Key(crossterm::event::KeyEvent { From 2180d73b3e59e5f0be1c93f1c56b842b94f2c809 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 12 May 2025 23:06:05 +0200 Subject: [PATCH 088/162] refactor: use SpirvBuilder directly, just manage `rustc_backend_spirv` dylibs (#69) * spirv_source minor cleanup * gitignore: .idea * cargo gpu: remove ignored profiles emitting warnings * remove spirv-builder-cli, leave install broken * minor cleanup * adjust install * fix clap and serde errors * working install, build broken * adjust tests to changed names * some clippy fixes * replace cargo tree with cargo metadata * fix local path spirv-std dependency * removed repo cloning, grab toolchain from cargo's checkout * reactive slow test, no longer clones a repo * remove `RUSTC` env var to prevent build script toolchain leaking into cargo gpu This is bandaid fix, it now ignores RUSTC environment variable set from elsewhere, like when shader crate is part of a workspace. As of today, it fails to compile on workspace which uses nightly because an additional restriction was added to target specification json file on nightly. Even though enforcing specific rustc version seems like good idea for the purpose of cargo-gpu, target specification json file should be updated as well if we were to ever bump up required rustc version. * port `mod metadata` to cargo_metadata * split apart spirv_cli into spirv_source, install_toolchain and lockfile * support for local paths, also always build it there instead of our cache * support for old rust-gpu versions on crates.io * adjust build action to use `SpirvBuilder` * don't remove `Cargo.lock` for local paths * use target-specs from spirv-builder * remove unused dependencies * old toolchain support * fix clippy * shorten build dir for windows * watch support, broken on windows * use master rust-gpu * apply suggestions from @tombh * rename mentions of `--capability` to `--capabilities` * update readme's dump-usage * fix typo * ci: speed up old version builds by not building current version * update main docs * remove target dir after successful `rustc_codegen_spirv` build, saves 200MiB * rename `--force-spirv-cli-rebuild` to `--rebuild-codegen` --------- Co-authored-by: tmvkrpxl0 --- .gitignore | 2 + Cargo.lock | 491 ++++--- Cargo.toml | 22 +- README.md | 261 ++-- crates/cargo-gpu/Cargo.toml | 24 +- crates/cargo-gpu/src/args.rs | 106 ++ crates/cargo-gpu/src/build.rs | 159 +-- crates/cargo-gpu/src/config.rs | 14 +- crates/cargo-gpu/src/install.rs | 376 ++--- crates/cargo-gpu/src/install_toolchain.rs | 134 ++ crates/cargo-gpu/src/linkage.rs | 30 + crates/cargo-gpu/src/lockfile.rs | 274 ++++ crates/cargo-gpu/src/main.rs | 71 +- crates/cargo-gpu/src/metadata.rs | 212 ++- crates/cargo-gpu/src/show.rs | 16 +- crates/cargo-gpu/src/spirv_cli.rs | 512 ------- crates/cargo-gpu/src/spirv_source.rs | 524 +++---- .../target-specs/spirv-unknown-opengl4.0.json | 26 - .../target-specs/spirv-unknown-opengl4.1.json | 26 - .../target-specs/spirv-unknown-opengl4.2.json | 26 - .../target-specs/spirv-unknown-opengl4.3.json | 26 - .../target-specs/spirv-unknown-opengl4.5.json | 26 - .../target-specs/spirv-unknown-spv1.0.json | 26 - .../target-specs/spirv-unknown-spv1.1.json | 26 - .../target-specs/spirv-unknown-spv1.2.json | 26 - .../target-specs/spirv-unknown-spv1.3.json | 26 - .../target-specs/spirv-unknown-spv1.4.json | 26 - .../target-specs/spirv-unknown-spv1.5.json | 26 - .../target-specs/spirv-unknown-vulkan1.0.json | 26 - .../target-specs/spirv-unknown-vulkan1.1.json | 26 - .../spirv-unknown-vulkan1.1spv1.4.json | 26 - .../target-specs/spirv-unknown-vulkan1.2.json | 26 - crates/shader-crate-template/Cargo.toml | 18 +- crates/spirv-builder-cli/Cargo.lock | 1260 ----------------- crates/spirv-builder-cli/Cargo.toml | 61 - crates/spirv-builder-cli/README.md | 7 - crates/spirv-builder-cli/rust-toolchain.toml | 5 - crates/spirv-builder-cli/src/args.rs | 203 --- crates/spirv-builder-cli/src/lib.rs | 52 - crates/spirv-builder-cli/src/main.rs | 155 -- crates/xtask/src/main.rs | 16 +- 41 files changed, 1626 insertions(+), 3769 deletions(-) create mode 100644 crates/cargo-gpu/src/args.rs create mode 100644 crates/cargo-gpu/src/install_toolchain.rs create mode 100644 crates/cargo-gpu/src/linkage.rs create mode 100644 crates/cargo-gpu/src/lockfile.rs delete mode 100644 crates/cargo-gpu/src/spirv_cli.rs delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json delete mode 100644 crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json delete mode 100644 crates/spirv-builder-cli/Cargo.lock delete mode 100644 crates/spirv-builder-cli/Cargo.toml delete mode 100644 crates/spirv-builder-cli/README.md delete mode 100644 crates/spirv-builder-cli/rust-toolchain.toml delete mode 100644 crates/spirv-builder-cli/src/args.rs delete mode 100644 crates/spirv-builder-cli/src/lib.rs delete mode 100644 crates/spirv-builder-cli/src/main.rs diff --git a/.gitignore b/.gitignore index 9f81952cfc..1b8b34a36d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ crates/shader-crate-template/shaders tmp/* crates/shader-crate-template/manifest.json crates/shader-crate-template/rust_gpu_shader_crate_template.spv + +.idea diff --git a/Cargo.lock b/Cargo.lock index bd63d763e3..992488f23e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -52,19 +52,20 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "autocfg" @@ -74,60 +75,81 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "2.6.0" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ "serde", ] [[package]] -name = "bytes" -version = "1.9.0" +name = "camino" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] [[package]] name = "cargo-gpu" version = "0.1.0" dependencies = [ "anyhow", - "chrono", + "cargo_metadata", "clap", "crossterm", "directories", "env_logger 0.10.2", - "http", "log", "relative-path", + "semver", "serde", "serde_json", - "spirv-builder-cli", + "spirv-builder", "test-log", - "toml", - "version_check", ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "cargo-platform" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] [[package]] -name = "chrono" -version = "0.4.38" +name = "cargo_metadata" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ - "num-traits", + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 2.0.12", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" -version = "4.4.8" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -135,9 +157,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -147,9 +169,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", @@ -159,9 +181,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -175,7 +197,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags", + "bitflags 2.9.0", "crossterm_winapi", "mio", "parking_lot", @@ -217,19 +239,13 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "env_logger" version = "0.10.2" @@ -245,9 +261,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -257,25 +273,40 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "filetime" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] [[package]] name = "fuchsia-cprng" @@ -285,9 +316,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -296,58 +327,76 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" [[package]] -name = "http" -version = "1.2.0" +name = "humantime" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ - "bytes", - "fnv", - "itoa", + "equivalent", + "hashbrown", ] [[package]] -name = "humantime" -version = "2.1.0" +name = "inotify" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] [[package]] -name = "indexmap" -version = "2.6.0" +name = "inotify-sys" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" dependencies = [ - "equivalent", - "hashbrown", + "libc", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", ] [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -358,9 +407,29 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] [[package]] name = "lazy_static" @@ -370,9 +439,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libredox" @@ -380,15 +449,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.9.0", "libc", + "redox_syscall", ] [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "lock_api" @@ -402,9 +472,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "matchers" @@ -434,29 +504,48 @@ dependencies = [ ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "notify" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" dependencies = [ - "overload", - "winapi", + "bitflags 2.9.0", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.52.0", ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "notify-types" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" dependencies = [ - "autocfg", + "instant", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "option-ext" @@ -495,24 +584,24 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -545,6 +634,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +[[package]] +name = "raw-string" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" + [[package]] name = "rdrand" version = "0.4.0" @@ -556,11 +651,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ - "bitflags", + "bitflags 2.9.0", ] [[package]] @@ -571,7 +666,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -582,7 +677,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -597,9 +692,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -633,13 +728,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "rspirv" +version = "0.12.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" +dependencies = [ + "rustc-hash", + "spirv", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_codegen_spirv-types" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4#6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4" +dependencies = [ + "rspirv", + "serde", + "serde_json", + "spirv", +] + [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -648,9 +770,18 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] [[package]] name = "scopeguard" @@ -658,20 +789,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +dependencies = [ + "serde", +] + [[package]] name = "serde" -version = "1.0.214" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -680,9 +820,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -731,18 +871,18 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" [[package]] name = "spirv" @@ -750,35 +890,37 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags", + "bitflags 2.9.0", "serde", ] [[package]] -name = "spirv-builder-cli" -version = "0.1.0" +name = "spirv-builder" +version = "0.9.0" +source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4#6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4" dependencies = [ "clap", - "env_home", - "env_logger 0.10.2", - "log", + "memchr", + "notify", + "raw-string", + "rustc_codegen_spirv-types", + "semver", "serde", "serde_json", - "spirv", - "toml", + "thiserror 2.0.12", ] [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -806,20 +948,20 @@ dependencies = [ [[package]] name = "test-log" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f" dependencies = [ - "env_logger 0.11.5", + "env_logger 0.11.8", "test-log-macros", "tracing-subscriber", ] [[package]] name = "test-log-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" dependencies = [ "proc-macro2", "quote", @@ -828,18 +970,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", @@ -858,9 +1020,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.19" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -870,26 +1032,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" + [[package]] name = "tracing" version = "0.1.41" @@ -940,9 +1109,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "utf8parse" @@ -952,15 +1121,19 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] -name = "version_check" -version = "0.9.5" +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasi" @@ -1149,9 +1322,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 3d16813354..c266e87598 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,30 +1,24 @@ [workspace] members = [ - "crates/cargo-gpu", - "crates/xtask", + "crates/cargo-gpu", + "crates/xtask", ] exclude = [ - # Can't be included because it depends on a specific Rust toolchain and considering that - # the reason it exists is to prevent Rust toolchain requirements from polluting workspaces - # then let's just not try to workaround it. - "crates/spirv-builder-cli", - - # 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" + # 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" ] resolver = "2" [workspace.dependencies] +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4", default-features = false } anyhow = "1.0.94" -clap = { version = "4.4.8", features = ["derive"] } -chrono = { version = "0.4.38", default-features = false, features = ["std"] } +clap = { version = "4.5.37", features = ["derive"] } crossterm = "0.28.1" directories = "5.0.1" env_logger = "0.10" -http = "1.2.0" log = "0.4" relative-path = "1.9.3" serde = { version = "1.0.214", features = ["derive"] } @@ -32,6 +26,8 @@ serde_json = "1.0.132" toml = "0.8.19" tempdir = "0.3.7" test-log = "0.2.16" +cargo_metadata = "0.19.2" +semver = "1.0.26" [workspace.lints.rust] missing_docs = "warn" diff --git a/README.md b/README.md index 39f303bad9..9065311f7d 100644 --- a/README.md +++ b/README.md @@ -64,159 +64,226 @@ for an example. build Compile a shader crate to SPIR-V show Show some useful values help Print this message or the help of the given subcommand(s) - + Options: -h, --help Print help - + -V, --version Print version * Install Install rust-gpu compiler artifacts - + Usage: cargo-gpu install [OPTIONS] - + Options: --shader-crate Directory containing the shader crate to compile - + [default: ./] - + --spirv-builder-source Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" - + --spirv-builder-version 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. - - --rust-toolchain - Rust toolchain channel to use to build `spirv-builder`. - - This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - - --force-spirv-cli-rebuild - Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt - + + --rebuild-codegen + Force `rustc_codegen_spirv` to be rebuilt + --auto-install-rust-toolchain Assume "yes" to "Install Rust toolchain: [y/n]" prompt - + + --no-clear-target + Clear target dir of `rustc_codegen_spirv` build after a successful build, saves about 200MiB of disk space + + --force-overwrite-lockfiles-v4-to-v3 + There is a tricky situation where a shader crate that depends on workspace config can have + a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can + prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. + + The ideal way to resolve this would be to match the shader crate's toolchain with the + workspace's toolchain. However, that is not always possible. Another solution is to + `exclude = [...]` the problematic shader crate from the workspace. This also may not be a + suitable solution if there are a number of shader crates all sharing similar config and + you don't want to have to copy/paste and maintain that config across all the shaders. + + So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling + this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also + only overwrite versions for the duration of a build. It will attempt to return the versions + to their original values once the build is finished. However, of course, unexpected errors + can occur and the overwritten values can remain. Hence why this behaviour is not enabled by + default. + + This hack is possible because the change from v3 to v4 only involves a minor change to the + way source URLs are encoded. See these PRs for more details: + * + * + -h, --help Print help (see a summary with '-h') * Build Compile a shader crate to SPIR-V - + Usage: cargo-gpu build [OPTIONS] - + Options: --shader-crate Directory containing the shader crate to compile - + [default: ./] - + --spirv-builder-source Source of `spirv-builder` dependency Eg: "https://github.com/Rust-GPU/rust-gpu" - + --spirv-builder-version 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. - - --rust-toolchain - Rust toolchain channel to use to build `spirv-builder`. - - This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - - --force-spirv-cli-rebuild - Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt - + + --rebuild-codegen + Force `rustc_codegen_spirv` to be rebuilt + --auto-install-rust-toolchain Assume "yes" to "Install Rust toolchain: [y/n]" prompt - + + --no-clear-target + Clear target dir of `rustc_codegen_spirv` build after a successful build, saves about 200MiB of disk space + + --force-overwrite-lockfiles-v4-to-v3 + There is a tricky situation where a shader crate that depends on workspace config can have + a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can + prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. + + The ideal way to resolve this would be to match the shader crate's toolchain with the + workspace's toolchain. However, that is not always possible. Another solution is to + `exclude = [...]` the problematic shader crate from the workspace. This also may not be a + suitable solution if there are a number of shader crates all sharing similar config and + you don't want to have to copy/paste and maintain that config across all the shaders. + + So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling + this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also + only overwrite versions for the duration of a build. It will attempt to return the versions + to their original values once the build is finished. However, of course, unexpected errors + can occur and the overwritten values can remain. Hence why this behaviour is not enabled by + default. + + This hack is possible because the change from v3 to v4 only involves a minor change to the + way source URLs are encoded. See these PRs for more details: + * + * + -o, --output-dir Path to the output directory for the compiled shaders - + [default: ./] - - --no-default-features - Set cargo default-features - - --features - Set cargo features - + + -w, --watch + Watch the shader crate directory and automatically recompile on changes + + --debug + Build in release. Defaults to true + --target - `rust-gpu` compile target - + The target triple, eg. `spirv-unknown-vulkan1.2` + [default: spirv-unknown-vulkan1.2] - - --shader-target - Shader target - - [default: spirv-unknown-vulkan1.2] - + + --no-default-features + Set --default-features for the target shader crate + + --features + Set --features for the target shader crate + --deny-warnings - Treat warnings as errors during compilation - - --debug - Compile shaders in debug mode - - --capability - Enables the provided SPIR-V capabilities. See: `impl core::str::FromStr for spirv_builder::Capability` - - --extension - Enables the provided SPIR-V extensions. See for all extensions - + Deny any warnings, as they may never be printed when building within a build script. Defaults to false + --multimodule - Compile one .spv file per entry point - + Splits the resulting SPIR-V file into one module per entry point. This is useful in cases where ecosystem tooling has bugs around multiple entry points per module - having all entry points bundled into a single file is the preferred system + --spirv-metadata - Set the level of metadata included in the SPIR-V binary - + Sets the level of metadata (primarily `OpName` and `OpLine`) included in the SPIR-V binary. Including metadata significantly increases binary size + [default: none] - + + Possible values: + - none: Strip all names and other debug information from SPIR-V output + - name-variables: Only include `OpName`s for public interface variables (uniforms and the like), to allow shader reflection + - full: Include all `OpName`s for everything, and `OpLine`s. Significantly increases binary size + + --capabilities + Adds a capability to the SPIR-V module. Checking if a capability is enabled in code can be done via `#[cfg(target_feature = "TheCapability")]` + + --extensions + Adds an extension to the SPIR-V module. Checking if an extension is enabled in code can be done via `#[cfg(target_feature = "ext:the_extension")]` + --relax-struct-store - Allow store from one struct type to a different type with compatible layout and members - + Record whether or not the validator should relax the rules on types for stores to structs. When relaxed, it will allow a type mismatch as long as the types are structs with the same layout. Two structs have the same layout if + + 1) the members of the structs are either the same type or are structs with same layout, and + + 2) the decorations that affect the memory layout are identical for both types. Other decorations are not relevant. + --relax-logical-pointer - Allow allocating an object of a pointer type and returning a pointer value from a function in logical addressing mode - - --relax-block-layout - Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, storage buffer, and push constant layouts. This is the default when targeting Vulkan 1.1 or later - + Records whether or not the validator should relax the rules on pointer usage in logical addressing mode. + + When relaxed, it will allow the following usage cases of pointers: 1) `OpVariable` allocating an object whose type is a pointer type 2) `OpReturnValue` returning a pointer value + + --relax-block-layout + Records whether the validator should use "relaxed" block layout rules. Relaxed layout rules are described by Vulkan extension `VK_KHR_relaxed_block_layout`, and they affect uniform blocks, storage blocks, and push constants. + + This is enabled by default when targeting Vulkan 1.1 or later. Relaxed layout is more permissive than the default rules in Vulkan 1.0. + + [default: false] + [possible values: true, false] + --uniform-buffer-standard-layout - Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer layouts - + Records whether the validator should use standard block layout rules for uniform blocks + --scalar-block-layout - Enable `VK_EXT_scalar_block_layout` when checking standard uniform, storage buffer, and push constant layouts. Scalar layout rules are more permissive than relaxed block layout so in effect this will override the --relax-block-layout option - + Records whether the validator should use "scalar" block layout rules. Scalar layout rules are more permissive than relaxed block layout. + + See Vulkan extnesion `VK_EXT_scalar_block_layout`. The scalar alignment is defined as follows: - scalar alignment of a scalar is the scalar size - scalar alignment of a vector is the scalar alignment of its component - scalar alignment of a matrix is the scalar alignment of its component - scalar alignment of an array is the scalar alignment of its element - scalar alignment of a struct is the max scalar alignment among its members + + For a struct in Uniform, `StorageClass`, or `PushConstant`: - a member Offset must be a multiple of the member's scalar alignment - `ArrayStride` or `MatrixStride` must be a multiple of the array or matrix scalar alignment + --skip-block-layout - Skip checking standard uniform / storage buffer layout. Overrides any --relax-block-layout or --scalar-block-layout option - + Records whether or not the validator should skip validating standard uniform/storage block layout + --preserve-bindings - Preserve unused descriptor bindings. Useful for reflection - + Records whether all bindings within the module should be preserved + + -m, --manifest-file + Renames the manifest.json file to the given name + + [default: manifest.json] + -h, --help Print help (see a summary with '-h') * Show Show some useful values - + Usage: cargo-gpu show - + Commands: cache-directory Displays the location of the cache directory spirv-source The source location of spirv-std + commitsh The git commitsh of this cli tool + capabilities All the available SPIR-V capabilities that can be set with `--capabilities` help Print this message or the help of the given subcommand(s) - + Options: -h, --help Print help @@ -224,9 +291,9 @@ for an example. * Cache-directory Displays the location of the cache directory - + Usage: cargo-gpu show cache-directory - + Options: -h, --help Print help @@ -234,15 +301,35 @@ for an example. * Spirv-source The source location of spirv-std - + Usage: cargo-gpu show spirv-source [OPTIONS] - + Options: --shader-crate The location of the shader-crate to inspect to determine its spirv-std dependency - + [default: ./] + + -h, --help + Print help + + + * Commitsh + The git commitsh of this cli tool + + Usage: cargo-gpu show commitsh + + Options: + -h, --help + Print help + + * Capabilities + All the available SPIR-V capabilities that can be set with `--capabilities` + + Usage: cargo-gpu show capabilities + + Options: -h, --help Print help ```` diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 8373ef4a3d..49ea8158de 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -7,11 +7,13 @@ repository = "https://github.com/Rust-GPU/cargo-gpu" readme = "../../README.md" keywords = ["gpu", "compiler"] build = "build.rs" +default-run = "cargo-gpu" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +cargo_metadata.workspace = true anyhow.workspace = true -spirv-builder-cli = { path = "../spirv-builder-cli", default-features = false, features = ["rspirv-latest"] } +spirv-builder = { workspace = true, features = ["clap", "watch"] } clap.workspace = true directories.workspace = true env_logger.workspace = true @@ -19,29 +21,11 @@ log.workspace = true relative-path.workspace = true serde.workspace = true serde_json.workspace = true -toml.workspace = true -chrono.workspace = true -http.workspace = true crossterm.workspace = true -version_check = "0.9.5" +semver.workspace = true [dev-dependencies] test-log.workspace = true -# Enable incremental by default in release mode. -[profile.release] -incremental = true -# HACK(eddyb) this is the default but without explicitly specifying it, Cargo -# will treat the identical settings in `[profile.release.build-override]` below -# as different sets of `rustc` flags and will not reuse artifacts between them. -codegen-units = 256 - -# Compile build-dependencies in release mode with the same settings -# as regular dependencies (including the incremental enabled above). -[profile.release.build-override] -opt-level = 3 -incremental = true -codegen-units = 256 - [lints] workspace = true diff --git a/crates/cargo-gpu/src/args.rs b/crates/cargo-gpu/src/args.rs new file mode 100644 index 0000000000..346d857a27 --- /dev/null +++ b/crates/cargo-gpu/src/args.rs @@ -0,0 +1,106 @@ +//! Args for building and installing. + +use spirv_builder::SpirvBuilder; + +/// All args for a build and install +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct AllArgs { + /// build args + #[clap(flatten)] + pub build: BuildArgs, + + /// install args + #[clap(flatten)] + pub install: InstallArgs, +} + +/// Args for just a build +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct BuildArgs { + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "./")] + pub output_dir: std::path::PathBuf, + + /// Watch the shader crate directory and automatically recompile on changes. + #[clap(long, short, action)] + pub watch: bool, + + /// the flattened [`SpirvBuilder`] + #[clap(flatten)] + #[serde(flatten)] + pub spirv_builder: SpirvBuilder, + + ///Renames the manifest.json file to the given name + #[clap(long, short, default_value = "manifest.json")] + pub manifest_file: String, +} + +/// Args for an install +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] +#[expect( + clippy::struct_excessive_bools, + reason = "cmdline args have many bools" +)] +pub struct InstallArgs { + /// path to the `rustc_codegen_spirv` dylib + #[clap(long, hide(true), default_value = "INTERNALLY_SET")] + pub dylib_path: std::path::PathBuf, + + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + pub shader_crate: std::path::PathBuf, + + #[expect( + clippy::doc_markdown, + reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" + )] + /// Source of `spirv-builder` dependency + /// Eg: "https://github.com/Rust-GPU/rust-gpu" + #[clap(long)] + pub spirv_builder_source: Option, + + /// 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)] + pub spirv_builder_version: Option, + + /// Force `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + pub rebuild_codegen: bool, + + /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. + #[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)] + pub clear_target: bool, + + /// There is a tricky situation where a shader crate that depends on workspace config can have + /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can + /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. + /// + /// The ideal way to resolve this would be to match the shader crate's toolchain with the + /// workspace's toolchain. However, that is not always possible. Another solution is to + /// `exclude = [...]` the problematic shader crate from the workspace. This also may not be a + /// suitable solution if there are a number of shader crates all sharing similar config and + /// you don't want to have to copy/paste and maintain that config across all the shaders. + /// + /// So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling + /// this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also + /// only overwrite versions for the duration of a build. It will attempt to return the versions + /// to their original values once the build is finished. However, of course, unexpected errors + /// can occur and the overwritten values can remain. Hence why this behaviour is not enabled by + /// default. + /// + /// This hack is possible because the change from v3 to v4 only involves a minor change to the + /// way source URLs are encoded. See these PRs for more details: + /// * + /// * + #[clap(long, action, verbatim_doc_comment)] + pub force_overwrite_lockfiles_v4_to_v3: bool, +} diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index d32dd24857..b77e5a2eef 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -2,14 +2,16 @@ #![allow(clippy::unwrap_used, reason = "this is basically a test")] //! `cargo gpu build`, analogous to `cargo build` +use crate::args::BuildArgs; +use crate::linkage::Linkage; +use crate::lockfile::LockfileMismatchHandler; +use crate::{install::Install, target_spec_dir}; use anyhow::Context as _; +use spirv_builder::{CompileResult, ModuleResult}; use std::io::Write as _; -use crate::{install::Install, target_spec_dir}; -use spirv_builder_cli::{args::BuildArgs, Linkage, ShaderModule}; - /// `cargo build` subcommands -#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +#[derive(Clone, clap::Parser, Debug, serde::Deserialize, serde::Serialize)] pub struct Build { /// CLI args for install the `rust-gpu` compiler and components #[clap(flatten)] @@ -22,9 +24,25 @@ pub struct Build { impl Build { /// Entrypoint - #[expect(clippy::too_many_lines, reason = "It's not too confusing")] pub fn run(&mut self) -> anyhow::Result<()> { - let spirv_builder_cli_path = self.install.run()?; + let (rustc_codegen_spirv_location, toolchain_channel) = self.install.run()?; + + let _lockfile_mismatch_handler = LockfileMismatchHandler::new( + &self.install.spirv_install.shader_crate, + &toolchain_channel, + self.install + .spirv_install + .force_overwrite_lockfiles_v4_to_v3, + )?; + + let builder = &mut self.build_args.spirv_builder; + builder.rustc_codegen_spirv_location = Some(rustc_codegen_spirv_location); + builder.toolchain_overwrite = Some(toolchain_channel); + builder.path_to_crate = Some(self.install.spirv_install.shader_crate.clone()); + builder.path_to_target_spec = Some(target_spec_dir()?.join(format!( + "{}.json", + builder.target.as_ref().context("expect target to be set")? + ))); // Ensure the shader output dir exists log::debug!( @@ -46,87 +64,74 @@ impl Build { std::env::current_dir()?.display() ); - if !self.build_args.watch { - self.build_args.shader_target = target_spec_dir()? - .join(format!("{}.json", self.build_args.shader_target)) - .display() - .to_string(); - } - - let args_as_json = serde_json::json!({ - "install": self.install.spirv_install, - "build": self.build_args - }); - let arg = serde_json::to_string_pretty(&args_as_json)?; - log::info!("using spirv-builder-cli arg: {arg}"); - - if !self.build_args.watch { + if self.build_args.watch { + let this = self.clone(); + self.build_args + .spirv_builder + .watch(move |result, accept| { + let result1 = this.parse_compilation_result(&result); + if let Some(accept) = accept { + accept.submit(result1); + } + })? + .context("unreachable")??; + std::thread::park(); + } else { crate::user_output!( - "Running `spirv-builder-cli` to compile shader at {}...\n", + "Compiling shaders at {}...\n", self.install.spirv_install.shader_crate.display() ); + let result = self.build_args.spirv_builder.build()?; + self.parse_compilation_result(&result)?; } + Ok(()) + } - // Call spirv-builder-cli to compile the shaders. - let output = std::process::Command::new(spirv_builder_cli_path) - .arg(arg) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output()?; - anyhow::ensure!(output.status.success(), "build failed"); - - let spirv_manifest = self.build_args.output_dir.join("spirv-manifest.json"); - if spirv_manifest.is_file() { - log::debug!( - "successfully built shaders, raw manifest is at '{}'", - spirv_manifest.display() - ); - } else { - log::error!("missing raw manifest '{}'", spirv_manifest.display()); - anyhow::bail!("missing raw manifest"); - } - - let shaders: Vec = - serde_json::from_reader(std::fs::File::open(&spirv_manifest)?)?; - + /// 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) => { + anyhow::ensure!(!modules.is_empty(), "No shader modules were compiled"); + modules.iter().collect::>() + } + ModuleResult::SingleModule(filepath) => result + .entry_points + .iter() + .map(|entry| (entry, filepath)) + .collect::>(), + }; let mut linkage: Vec = shaders .into_iter() - .map( - |ShaderModule { - entry, - path: filepath, - }| - -> anyhow::Result { - use relative_path::PathExt as _; - let path = self.build_args.output_dir.join( - filepath - .file_name() - .context("Couldn't parse file name from shader module path")?, - ); - log::debug!("copying {} to {}", filepath.display(), path.display()); - std::fs::copy(&filepath, &path)?; - log::debug!( - "linkage of {} relative to {}", - path.display(), - self.install.spirv_install.shader_crate.display() - ); - let spv_path = path - .relative_to(&self.install.spirv_install.shader_crate) - .map_or(path, |path_relative_to_shader_crate| { - path_relative_to_shader_crate.to_path("") - }); - Ok(Linkage::new(entry, spv_path)) - }, - ) + .map(|(entry, filepath)| -> anyhow::Result { + use relative_path::PathExt as _; + let path = self.build_args.output_dir.join( + filepath + .file_name() + .context("Couldn't parse file name from shader module path")?, + ); + log::debug!("copying {} to {}", filepath.display(), path.display()); + std::fs::copy(filepath, &path)?; + log::debug!( + "linkage of {} relative to {}", + path.display(), + self.install.spirv_install.shader_crate.display() + ); + let spv_path = path + .relative_to(&self.install.spirv_install.shader_crate) + .map_or(path, |path_relative_to_shader_crate| { + path_relative_to_shader_crate.to_path("") + }); + Ok(Linkage::new(entry, spv_path)) + }) .collect::>>()?; + // Sort the contents so the output is deterministic + linkage.sort(); // Write the shader manifest json file let manifest_path = self .build_args .output_dir .join(&self.build_args.manifest_file); - // Sort the contents so the output is deterministic - linkage.sort(); let json = serde_json::to_string_pretty(&linkage)?; let mut file = std::fs::File::create(&manifest_path).with_context(|| { format!( @@ -142,14 +147,6 @@ impl Build { })?; log::info!("wrote manifest to '{}'", manifest_path.display()); - - if spirv_manifest.is_file() { - log::debug!( - "removing spirv-manifest.json file '{}'", - spirv_manifest.display() - ); - std::fs::remove_file(spirv_manifest)?; - } Ok(()) } } diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 15337d353f..ad8640201f 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -140,7 +140,7 @@ mod test { ], ) .unwrap(); - assert!(args.build_args.debug); + assert!(!args.build_args.spirv_builder.release); assert!(args.install.spirv_install.auto_install_rust_toolchain); } @@ -151,7 +151,7 @@ mod test { file.write_all( [ "[package.metadata.rust-gpu.build]", - "debug = true", + "release = false", "[package.metadata.rust-gpu.install]", "auto-install-rust-toolchain = true", ] @@ -161,7 +161,7 @@ mod test { .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); - assert!(args.build_args.debug); + assert!(!args.build_args.spirv_builder.release); assert!(args.install.spirv_install.auto_install_rust_toolchain); } @@ -225,7 +225,7 @@ mod test { file.write_all( [ "[package.metadata.rust-gpu.build]", - "capability = [\"AtomicStorage\", \"Matrix\"]", + "capabilities = [\"AtomicStorage\", \"Matrix\"]", ] .join("\n") .as_bytes(), @@ -234,10 +234,10 @@ mod test { let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert_eq!( - args.build_args.capability, + args.build_args.spirv_builder.capabilities, vec![ - spirv_builder_cli::spirv::Capability::AtomicStorage, - spirv_builder_cli::spirv::Capability::Matrix + spirv_builder::Capability::AtomicStorage, + spirv_builder::Capability::Matrix ] ); } diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 9977227b38..0b6f5fd55a 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,102 +1,18 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. -use std::io::Write as _; - +use crate::args::InstallArgs; +use crate::spirv_source::{ + get_channel_from_rustc_codegen_spirv_build_script, get_package_from_crate, +}; +use crate::{cache_dir, spirv_source::SpirvSource, target_spec_dir}; use anyhow::Context as _; - -use crate::{cache_dir, spirv_cli::SpirvCli, spirv_source::SpirvSource, target_spec_dir}; -use spirv_builder_cli::args::InstallArgs; - -/// These are the files needed to create the dedicated, per-shader `rust-gpu` builder create. -const SPIRV_BUILDER_FILES: &[(&str, &str)] = &[ - ( - "Cargo.toml", - include_str!("../../spirv-builder-cli/Cargo.toml"), - ), - ( - "Cargo.lock", - include_str!("../../spirv-builder-cli/Cargo.lock"), - ), - ( - "src/main.rs", - include_str!("../../spirv-builder-cli/src/main.rs"), - ), - ( - "src/lib.rs", - include_str!("../../spirv-builder-cli/src/lib.rs"), - ), - ( - "src/args.rs", - include_str!("../../spirv-builder-cli/src/args.rs"), - ), -]; - -/// Metadata for the compile targets supported by `rust-gpu` -const TARGET_SPECS: &[(&str, &str)] = &[ - ( - "spirv-unknown-opengl4.0.json", - include_str!("../target-specs/spirv-unknown-opengl4.0.json"), - ), - ( - "spirv-unknown-opengl4.1.json", - include_str!("../target-specs/spirv-unknown-opengl4.1.json"), - ), - ( - "spirv-unknown-opengl4.2.json", - include_str!("../target-specs/spirv-unknown-opengl4.2.json"), - ), - ( - "spirv-unknown-opengl4.3.json", - include_str!("../target-specs/spirv-unknown-opengl4.3.json"), - ), - ( - "spirv-unknown-opengl4.5.json", - include_str!("../target-specs/spirv-unknown-opengl4.5.json"), - ), - ( - "spirv-unknown-spv1.0.json", - include_str!("../target-specs/spirv-unknown-spv1.0.json"), - ), - ( - "spirv-unknown-spv1.1.json", - include_str!("../target-specs/spirv-unknown-spv1.1.json"), - ), - ( - "spirv-unknown-spv1.2.json", - include_str!("../target-specs/spirv-unknown-spv1.2.json"), - ), - ( - "spirv-unknown-spv1.3.json", - include_str!("../target-specs/spirv-unknown-spv1.3.json"), - ), - ( - "spirv-unknown-spv1.4.json", - include_str!("../target-specs/spirv-unknown-spv1.4.json"), - ), - ( - "spirv-unknown-spv1.5.json", - include_str!("../target-specs/spirv-unknown-spv1.5.json"), - ), - ( - "spirv-unknown-vulkan1.0.json", - include_str!("../target-specs/spirv-unknown-vulkan1.0.json"), - ), - ( - "spirv-unknown-vulkan1.1.json", - include_str!("../target-specs/spirv-unknown-vulkan1.1.json"), - ), - ( - "spirv-unknown-vulkan1.1spv1.4.json", - include_str!("../target-specs/spirv-unknown-vulkan1.1spv1.4.json"), - ), - ( - "spirv-unknown-vulkan1.2.json", - include_str!("../target-specs/spirv-unknown-vulkan1.2.json"), - ), -]; +use log::trace; +use spirv_builder::TARGET_SPECS; +use std::io::Write as _; +use std::path::{Path, PathBuf}; /// `cargo gpu install` -#[derive(clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +#[derive(Clone, clap::Parser, Debug, serde::Deserialize, serde::Serialize)] pub struct Install { /// CLI arguments for installing the Rust toolchain and components #[clap(flatten)] @@ -104,69 +20,57 @@ pub struct Install { } impl Install { - /// Returns a [`SpirvCLI`] instance, responsible for ensuring the right version of the `spirv-builder-cli` crate. - fn spirv_cli(&self, shader_crate_path: &std::path::Path) -> anyhow::Result { - SpirvCli::new( - shader_crate_path, - self.spirv_install.spirv_builder_source.clone(), - self.spirv_install.spirv_builder_version.clone(), - self.spirv_install.rust_toolchain.clone(), - self.spirv_install.auto_install_rust_toolchain, - self.spirv_install.force_overwrite_lockfiles_v4_to_v3, - ) - } - - /// Create the `spirv-builder-cli` crate. - fn write_source_files(&self) -> anyhow::Result<()> { - let spirv_cli = self - .spirv_cli(&self.spirv_install.shader_crate) - .context("running spirv cli")?; - let checkout = spirv_cli - .cached_checkout_path() - .context("getting cached checkout path")?; - std::fs::create_dir_all(checkout.join("src")).context("creating directory for 'src'")?; - for (filename, contents) in SPIRV_BUILDER_FILES { - log::debug!("writing {filename}"); - let path = checkout.join(filename); - let mut file = std::fs::File::create(&path) - .with_context(|| format!("creating a file at [{}]", path.display()))?; - let mut replaced_contents = contents.replace("${CHANNEL}", &spirv_cli.channel); - if filename == &"Cargo.toml" { - replaced_contents = Self::update_cargo_toml(&replaced_contents, &spirv_cli.source); - } - file.write_all(replaced_contents.as_bytes()) - .context("writing to file")?; + /// Create the `rustc_codegen_spirv_dummy` crate that depends on `rustc_codegen_spirv` + fn write_source_files(source: &SpirvSource, checkout: &Path) -> anyhow::Result<()> { + // skip writing a dummy project if we use a local rust-gpu checkout + if matches!(source, SpirvSource::Path { .. }) { + return Ok(()); } - Ok(()) - } - - /// Update the `Cargo.toml` file in the `spirv-builder-cli` crate so that it contains - /// the correct version of `spirv-builder-cli`. - fn update_cargo_toml(contents: &str, spirv_source: &SpirvSource) -> String { - let updated = contents.lines().map(|line| { - if line.contains("${AUTO-REPLACE-SOURCE}") { - let replaced_line = match spirv_source { - SpirvSource::CratesIO(_) => String::new(), - SpirvSource::Git { url, .. } => format!("git = \"{url}\""), - SpirvSource::Path((path, _)) => format!("path = \"{path}\""), - }; - return format!("{replaced_line}\n"); - } - - if line.contains("${AUTO-REPLACE-VERSION}") { - let replaced_line = match spirv_source { - SpirvSource::CratesIO(version) | SpirvSource::Path((_, version)) => { - format!("version = \"{}\"", version.replace('v', "")) - } - SpirvSource::Git { rev, .. } => format!("rev = \"{rev}\""), - }; - return format!("{replaced_line}\n"); - } + log::debug!( + "writing `rustc_codegen_spirv_dummy` source files into '{}'", + checkout.display() + ); - format!("{line}\n") - }); + { + trace!("writing dummy main.rs"); + let main = "fn main() {}"; + let src = checkout.join("src"); + std::fs::create_dir_all(&src).context("creating directory for 'src'")?; + std::fs::write(src.join("main.rs"), main).context("writing 'main.rs'")?; + }; - updated.collect() + { + trace!("writing dummy Cargo.toml"); + let version_spec = match &source { + SpirvSource::CratesIO(version) => { + format!("version = \"{version}\"") + } + SpirvSource::Git { url, rev } => format!("git = \"{url}\"\nrev = \"{rev}\""), + SpirvSource::Path { + rust_gpu_repo_root: rust_gpu_path, + version, + } => { + let mut new_path = rust_gpu_path.to_owned(); + new_path.push("crates/spirv-builder"); + format!("path = \"{new_path}\"\nversion = \"{version}\"") + } + }; + let cargo_toml = format!( + r#" +[package] +name = "rustc_codegen_spirv_dummy" +version = "0.1.0" +edition = "2021" + +[dependencies.spirv-builder] +package = "rustc_codegen_spirv" +{version_spec} + "# + ); + std::fs::write(checkout.join("Cargo.toml"), cargo_toml) + .context("writing 'Cargo.toml'")?; + }; + Ok(()) } /// Add the target spec files to the crate. @@ -175,7 +79,7 @@ impl Install { let path = target_spec_dir() .context("creating target spec dir")? .join(filename); - if !path.is_file() || self.spirv_install.force_spirv_cli_rebuild { + if !path.is_file() || self.spirv_install.rebuild_codegen { let mut file = std::fs::File::create(&path) .with_context(|| format!("creating file at [{}]", path.display()))?; file.write_all(contents.as_bytes()) @@ -185,8 +89,9 @@ impl Install { Ok(()) } - /// Install the binary pair and return the paths, (dylib, cli). - pub fn run(&mut self) -> anyhow::Result { + /// Install the binary pair and return the `(dylib_path, toolchain_channel)`. + #[expect(clippy::too_many_lines, reason = "it's fine")] + pub fn run(&mut self) -> anyhow::Result<(PathBuf, String)> { // Ensure the cache dir exists let cache_dir = cache_dir()?; log::info!("cache directory is '{}'", cache_dir.display()); @@ -194,66 +99,79 @@ impl Install { format!("could not create cache directory '{}'", cache_dir.display()) })?; - let spirv_version = self - .spirv_cli(&self.spirv_install.shader_crate) - .context("running spirv cli")?; - spirv_version - .ensure_toolchain_and_components_exist() - .context("ensuring toolchain and components exist")?; - - let checkout = spirv_version - .cached_checkout_path() - .context("getting cached checkout path")?; - let release = checkout.join("target").join("release"); + let source = SpirvSource::new( + &self.spirv_install.shader_crate, + self.spirv_install.spirv_builder_source.as_deref(), + self.spirv_install.spirv_builder_version.as_deref(), + )?; + let source_is_path = matches!(source, SpirvSource::Path { .. }); + let checkout = source.install_dir()?; let dylib_filename = format!( "{}rustc_codegen_spirv{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_SUFFIX ); - let dylib_path = release.join(&dylib_filename); - let dest_dylib_path = checkout.join(&dylib_filename); - let dest_cli_path = checkout.join("spirv-builder-cli"); - if dest_dylib_path.is_file() && dest_cli_path.is_file() { - log::info!( - "cargo-gpu artifacts are already installed in '{}'", - checkout.display() - ); + + let dest_dylib_path; + if source_is_path { + dest_dylib_path = checkout + .join("target") + .join("release") + .join(&dylib_filename); + } else { + dest_dylib_path = checkout.join(&dylib_filename); + if dest_dylib_path.is_file() { + log::info!( + "cargo-gpu artifacts are already installed in '{}'", + checkout.display() + ); + } } - if dest_dylib_path.is_file() - && dest_cli_path.is_file() - && !self.spirv_install.force_spirv_cli_rebuild - { + let skip_rebuild = + !source_is_path && dest_dylib_path.is_file() && !self.spirv_install.rebuild_codegen; + if skip_rebuild { log::info!("...and so we are aborting the install step."); } else { - log::debug!( - "writing spirv-builder-cli source files into '{}'", - checkout.display() - ); - self.write_source_files().context("writing source files")?; - self.write_target_spec_files() - .context("writing target spec files")?; + Self::write_source_files(&source, &checkout).context("writing source files")?; + } - crate::user_output!( - "Compiling shader-specific `spirv-builder-cli` for {}\n", - self.spirv_install.shader_crate.display() - ); + // TODO cache toolchain channel in a file? + log::debug!("resolving toolchain version to use"); + let rustc_codegen_spirv = get_package_from_crate(&checkout, "rustc_codegen_spirv") + .context("get `rustc_codegen_spirv` metadata")?; + let toolchain_channel = + get_channel_from_rustc_codegen_spirv_build_script(&rustc_codegen_spirv) + .context("read toolchain from `rustc_codegen_spirv`'s build.rs")?; + log::info!("selected toolchain channel `{toolchain_channel:?}`"); + + if !skip_rebuild { + log::debug!("ensure_toolchain_and_components_exist"); + crate::install_toolchain::ensure_toolchain_and_components_exist( + &toolchain_channel, + self.spirv_install.auto_install_rust_toolchain, + ) + .context("ensuring toolchain and components exist")?; + + // to prevent unsupported version errors when using older toolchains + if !source_is_path { + log::debug!("remove Cargo.lock"); + std::fs::remove_file(checkout.join("Cargo.lock")).context("remove Cargo.lock")?; + } + crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source,); let mut build_command = std::process::Command::new("cargo"); build_command .current_dir(&checkout) - .arg(format!("+{}", spirv_version.channel)) + .arg(format!("+{toolchain_channel}")) .args(["build", "--release"]) - .args(["--no-default-features"]); - - build_command.args([ - "--features", - &Self::get_required_spirv_builder_version(spirv_version.date) - .context("getting required spirv builder version")?, - ]); + .env_remove("RUSTC"); + if source_is_path { + build_command.args(["-p", "rustc_codegen_spirv", "--lib"]); + } - log::debug!("building artifacts with `{:?}`", build_command); + log::debug!("building artifacts with `{build_command:?}`"); build_command .stdout(std::process::Stdio::inherit()) @@ -269,54 +187,30 @@ impl Install { }) .context("running build command")?; + let target = checkout.join("target"); + let dylib_path = target.join("release").join(&dylib_filename); if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); - std::fs::rename(&dylib_path, &dest_dylib_path).context("renaming dylib path")?; + if !source_is_path { + std::fs::rename(&dylib_path, &dest_dylib_path) + .context("renaming dylib path")?; + + if self.spirv_install.clear_target { + log::warn!("clearing target dir {}", target.display()); + std::fs::remove_dir_all(&target).context("clearing target dir")?; + } + } } else { log::error!("could not find {}", dylib_path.display()); - anyhow::bail!("spirv-builder-cli build failed"); + anyhow::bail!("`rustc_codegen_spirv` build failed"); } - let cli_path = if cfg!(target_os = "windows") { - release.join("spirv-builder-cli").with_extension("exe") - } else { - release.join("spirv-builder-cli") - }; - if cli_path.is_file() { - log::info!("successfully built {}", cli_path.display()); - std::fs::rename(&cli_path, &dest_cli_path).context("renaming cli path")?; - } else { - log::error!("could not find {}", cli_path.display()); - log::debug!("contents of '{}':", release.display()); - for maybe_entry in std::fs::read_dir(&release).context("reading release dir")? { - let entry = maybe_entry?; - log::debug!("{}", entry.file_name().to_string_lossy()); - } - anyhow::bail!("spirv-builder-cli build failed"); - } + log::debug!("write_target_spec_files"); + self.write_target_spec_files() + .context("writing target spec files")?; } - self.spirv_install.dylib_path = dest_dylib_path; - - Ok(dest_cli_path) - } - - /// The `spirv-builder` crate from the main `rust-gpu` repo hasn't always been setup to - /// interact with `cargo-gpu`. Older versions don't have the same `SpirvBuilder` interface. So - /// here we choose the right Cargo feature to enable/disable code in `spirv-builder-cli`. - /// - /// TODO: - /// * Warn the user that certain `cargo-gpu` features aren't available when building with - /// older versions of `spirv-builder`, eg setting the target spec. - fn get_required_spirv_builder_version(date: chrono::NaiveDate) -> anyhow::Result { - let parse_date = chrono::NaiveDate::parse_from_str; - let pre_cli_date = parse_date("2024-04-24", "%Y-%m-%d")?; - - Ok(if date < pre_cli_date { - "spirv-builder-pre-cli" - } else { - "spirv-builder-0_10" - } - .into()) + self.spirv_install.dylib_path.clone_from(&dest_dylib_path); + Ok((dest_dylib_path, toolchain_channel)) } } diff --git a/crates/cargo-gpu/src/install_toolchain.rs b/crates/cargo-gpu/src/install_toolchain.rs new file mode 100644 index 0000000000..027a90d759 --- /dev/null +++ b/crates/cargo-gpu/src/install_toolchain.rs @@ -0,0 +1,134 @@ +//! toolchain installation logic + +use anyhow::Context as _; + +/// Use `rustup` to install the toolchain and components, if not already installed. +/// +/// Pretty much runs: +/// +/// * rustup toolchain add nightly-2024-04-24 +/// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools +pub fn ensure_toolchain_and_components_exist( + channel: &str, + skip_toolchain_install_consent: bool, +) -> anyhow::Result<()> { + // Check for the required toolchain + let output_toolchain_list = std::process::Command::new("rustup") + .args(["toolchain", "list"]) + .output() + .context("running rustup command")?; + anyhow::ensure!( + output_toolchain_list.status.success(), + "could not list installed toolchains" + ); + let string_toolchain_list = String::from_utf8_lossy(&output_toolchain_list.stdout); + if string_toolchain_list + .split_whitespace() + .any(|toolchain| toolchain.starts_with(channel)) + { + log::debug!("toolchain {channel} is already installed"); + } else { + let message = format!("Rust {channel} with `rustup`"); + get_consent_for_toolchain_install( + format!("Install {message}").as_ref(), + skip_toolchain_install_consent, + )?; + crate::user_output!("Installing {message}\n"); + + let output_toolchain_add = std::process::Command::new("rustup") + .args(["toolchain", "add"]) + .arg(channel) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .context("adding toolchain")?; + anyhow::ensure!( + output_toolchain_add.status.success(), + "could not install required toolchain" + ); + } + + // Check for the required components + let output_component_list = std::process::Command::new("rustup") + .args(["component", "list", "--toolchain"]) + .arg(channel) + .output() + .context("getting toolchain list")?; + anyhow::ensure!( + output_component_list.status.success(), + "could not list installed components" + ); + let string_component_list = String::from_utf8_lossy(&output_component_list.stdout); + let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; + let installed_components = string_component_list.lines().collect::>(); + let all_components_installed = required_components.iter().all(|component| { + installed_components.iter().any(|installed_component| { + let is_component = installed_component.starts_with(component); + let is_installed = installed_component.ends_with("(installed)"); + is_component && is_installed + }) + }); + if all_components_installed { + log::debug!("all required components are installed"); + } else { + let message = "toolchain components [rust-src, rustc-dev, llvm-tools] with `rustup`"; + get_consent_for_toolchain_install( + format!("Install {message}").as_ref(), + skip_toolchain_install_consent, + )?; + crate::user_output!("Installing {message}\n"); + + let output_component_add = std::process::Command::new("rustup") + .args(["component", "add", "--toolchain"]) + .arg(channel) + .args(["rust-src", "rustc-dev", "llvm-tools"]) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .context("adding rustup component")?; + anyhow::ensure!( + output_component_add.status.success(), + "could not install required components" + ); + } + + Ok(()) +} + +/// Prompt user if they want to install a new Rust toolchain. +fn get_consent_for_toolchain_install( + prompt: &str, + skip_toolchain_install_consent: bool, +) -> anyhow::Result<()> { + if skip_toolchain_install_consent { + return Ok(()); + } + log::debug!("asking for consent to install the required toolchain"); + crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; + crate::user_output!("{prompt} [y/n]: \n"); + let mut input = crossterm::event::read().context("reading crossterm event")?; + + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { + code: crossterm::event::KeyCode::Enter, + kind: crossterm::event::KeyEventKind::Release, + .. + }) = input + { + // In Powershell, programs will potentially observe the Enter key release after they started + // (see crossterm#124). If that happens, re-read the input. + input = crossterm::event::read().context("re-reading crossterm event")?; + } + crossterm::terminal::disable_raw_mode().context("disabling raw mode")?; + + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { + code: crossterm::event::KeyCode::Char('y'), + .. + }) = input + { + Ok(()) + } else { + crate::user_output!("Exiting...\n"); + #[expect(clippy::exit, reason = "user requested abort")] + std::process::exit(0); + } +} diff --git a/crates/cargo-gpu/src/linkage.rs b/crates/cargo-gpu/src/linkage.rs new file mode 100644 index 0000000000..346bdaf32c --- /dev/null +++ b/crates/cargo-gpu/src/linkage.rs @@ -0,0 +1,30 @@ +//! Mainly for the Linkage struct, which is written to a json file. + +/// Shader source and entry point that can be used to create shader linkage. +#[derive(serde::Serialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Linkage { + /// File path to the entry point's source file + pub source_path: String, + /// Name of the entry point for spirv and vulkan + pub entry_point: String, + /// Name of the entry point for wgsl, where `::` characters have been removed + pub wgsl_entry_point: String, +} + +impl Linkage { + /// Make a new `Linkage` from an entry point and source path + #[expect(clippy::impl_trait_in_params, reason = "just a struct new")] + pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { + Self { + // Force a forward slash convention here so it works on all OSs + source_path: source_path + .as_ref() + .components() + .map(|comp| comp.as_os_str().to_string_lossy()) + .collect::>() + .join("/"), + wgsl_entry_point: entry_point.as_ref().replace("::", ""), + entry_point: entry_point.as_ref().to_owned(), + } + } +} diff --git a/crates/cargo-gpu/src/lockfile.rs b/crates/cargo-gpu/src/lockfile.rs new file mode 100644 index 0000000000..bce1487aa1 --- /dev/null +++ b/crates/cargo-gpu/src/lockfile.rs @@ -0,0 +1,274 @@ +//! Handles lockfile version conflicts and downgrades. Stable uses lockfile v4, but rust-gpu +//! v0.9.0 uses an old toolchain requiring v3 and will refuse to build with a v4 lockfile being +//! present. This module takes care of warning the user and potentially downgrading the lockfile. + +use anyhow::Context as _; +use semver::Version; +use spirv_builder::query_rustc_version; +use std::io::Write as _; + +/// `Cargo.lock` manifest version 4 became the default in Rust 1.83.0. Conflicting manifest +/// versions between the workspace and the shader crate, can cause problems. +const RUST_VERSION_THAT_USES_V4_CARGO_LOCKS: Version = Version::new(1, 83, 0); + +/// Cargo dependency for `spirv-builder` and the rust toolchain channel. +#[derive(Debug, Clone)] +pub struct LockfileMismatchHandler { + /// `Cargo.lock`s that have had their manifest versions changed by us and need changing back. + pub cargo_lock_files_with_changed_manifest_versions: Vec, +} + +impl LockfileMismatchHandler { + /// Create instance + pub fn new( + shader_crate_path: &std::path::Path, + toolchain_channel: &str, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result { + let mut cargo_lock_files_with_changed_manifest_versions = vec![]; + + let maybe_shader_crate_lock = + Self::ensure_workspace_rust_version_doesnt_conflict_with_shader( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("ensure_workspace_rust_version_doesnt_conflict_with_shader")?; + + if let Some(shader_crate_lock) = maybe_shader_crate_lock { + cargo_lock_files_with_changed_manifest_versions.push(shader_crate_lock); + } + + let maybe_workspace_crate_lock = + Self::ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( + shader_crate_path, + toolchain_channel, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks")?; + + if let Some(workspace_crate_lock) = maybe_workspace_crate_lock { + cargo_lock_files_with_changed_manifest_versions.push(workspace_crate_lock); + } + + Ok(Self { + cargo_lock_files_with_changed_manifest_versions, + }) + } + + /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. + fn ensure_workspace_rust_version_doesnt_conflict_with_shader( + shader_crate_path: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result> { + log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from workspace Rust..."); + let workspace_rust_version = query_rustc_version(None).context("reading rustc version")?; + if workspace_rust_version >= RUST_VERSION_THAT_USES_V4_CARGO_LOCKS { + log::debug!( + "user's Rust is v{workspace_rust_version}, so no v3/v4 conflicts possible." + ); + return Ok(None); + } + + Self::handle_conflicting_cargo_lock_v4( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("handling v4/v3 conflict")?; + + if is_force_overwrite_lockfiles_v4_to_v3 { + Ok(Some(shader_crate_path.join("Cargo.lock"))) + } else { + Ok(None) + } + } + + /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. + fn ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( + shader_crate_path: &std::path::Path, + channel: &str, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result> { + log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from shader's Rust..."); + let shader_rust_version = + query_rustc_version(Some(channel)).context("getting rustc version")?; + if shader_rust_version >= RUST_VERSION_THAT_USES_V4_CARGO_LOCKS { + log::debug!("shader's Rust is v{shader_rust_version}, so no v3/v4 conflicts possible."); + return Ok(None); + } + + log::debug!( + "shader's Rust is v{shader_rust_version}, so checking both shader and workspace `Cargo.lock` manifest versions..." + ); + + if shader_crate_path.join("Cargo.lock").exists() { + // Note that we don't return the `Cargo.lock` here (so that it's marked for reversion + // after the build), because we can be sure that updating it now is actually updating it + // to the state it should have been all along. Therefore it doesn't need reverting once + // fixed. + Self::handle_conflicting_cargo_lock_v4( + shader_crate_path, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("handling v4/v3 conflict")?; + } + + if let Some(workspace_root) = + Self::get_workspace_root(shader_crate_path).context("reading workspace root")? + { + Self::handle_conflicting_cargo_lock_v4( + workspace_root, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("handling conflicting cargo v4")?; + return Ok(Some(workspace_root.join("Cargo.lock"))); + } + + Ok(None) + } + + /// Get the path to the shader crate's workspace, if it has one. We can't use the traditional + /// `cargo metadata` because if the workspace has a conflicting `Cargo.lock` manifest version + /// then that command won't work. Instead we do an old school recursive file tree walk. + fn get_workspace_root( + shader_crate_path: &std::path::Path, + ) -> anyhow::Result> { + let shader_cargo_toml = std::fs::read_to_string(shader_crate_path.join("Cargo.toml")) + .with_context(|| format!("reading Cargo.toml at {}", shader_crate_path.display()))?; + if !shader_cargo_toml.contains("workspace = true") { + return Ok(None); + } + + let mut current_path = shader_crate_path; + #[expect(clippy::default_numeric_fallback, reason = "It's just a loop")] + for _ in 0..15 { + if let Some(parent_path) = current_path.parent() { + if parent_path.join("Cargo.lock").exists() { + return Ok(Some(parent_path)); + } + current_path = parent_path; + } else { + break; + } + } + + Ok(None) + } + + /// When Rust < 1.83.0 is being used an error will occur if it tries to parse `Cargo.lock` + /// files that use lockfile manifest version 4. Here we check and handle that. + fn handle_conflicting_cargo_lock_v4( + folder: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result<()> { + let shader_cargo_lock_path = folder.join("Cargo.lock"); + let shader_cargo_lock = std::fs::read_to_string(shader_cargo_lock_path.clone()) + .context("reading shader cargo lock")?; + let third_line = shader_cargo_lock.lines().nth(2).context("no third line")?; + if third_line.contains("version = 4") { + Self::handle_v3v4_conflict( + &shader_cargo_lock_path, + is_force_overwrite_lockfiles_v4_to_v3, + ) + .context("handling v4/v3 conflict")?; + return Ok(()); + } + if third_line.contains("version = 3") { + return Ok(()); + } + anyhow::bail!( + "Unrecognized `Cargo.lock` manifest version at: {}", + folder.display() + ) + } + + /// Handle conflicting `Cargo.lock` manifest versions by either overwriting the manifest + /// version or exiting with advice on how to handle the conflict. + fn handle_v3v4_conflict( + offending_cargo_lock: &std::path::Path, + is_force_overwrite_lockfiles_v4_to_v3: bool, + ) -> anyhow::Result<()> { + if !is_force_overwrite_lockfiles_v4_to_v3 { + Self::exit_with_v3v4_hack_suggestion(); + } + + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "4", "3") + .context("replacing version 4 -> 3")?; + + Ok(()) + } + + /// Once all install and builds have completed put their manifest versions back to how they + /// were. + pub fn revert_cargo_lock_manifest_versions(&self) -> anyhow::Result<()> { + for offending_cargo_lock in &self.cargo_lock_files_with_changed_manifest_versions { + log::debug!("Reverting: {}", offending_cargo_lock.display()); + Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "3", "4") + .context("replacing version 3 -> 4")?; + } + + Ok(()) + } + + /// Replace the manifest version, eg `version = 4`, in a `Cargo.lock` file. + fn replace_cargo_lock_manifest_version( + offending_cargo_lock: &std::path::Path, + from_version: &str, + to_version: &str, + ) -> anyhow::Result<()> { + log::warn!( + "Replacing manifest version 'version = {}' with 'version = {}' in: {}", + from_version, + to_version, + offending_cargo_lock.display() + ); + let old_contents = std::fs::read_to_string(offending_cargo_lock) + .context("reading offending Cargo.lock")?; + let new_contents = old_contents.replace( + &format!("\nversion = {from_version}\n"), + &format!("\nversion = {to_version}\n"), + ); + + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(offending_cargo_lock) + .context("opening offending Cargo.lock")?; + file.write_all(new_contents.as_bytes())?; + + Ok(()) + } + + /// Exit and give the user advice on how to deal with the infamous v3/v4 Cargo lockfile version + /// problem. + #[expect(clippy::non_ascii_literal, reason = "It's CLI output")] + fn exit_with_v3v4_hack_suggestion() { + crate::user_output!( + "Conflicting `Cargo.lock` versions detected ⚠️\n\ + Because `cargo gpu` uses a dedicated Rust toolchain for compiling shaders\n\ + it's possible that the `Cargo.lock` manifest version of the shader crate\n\ + does not match the `Cargo.lock` manifest version of the workspace. This is\n\ + due to a change in the defaults introduced in Rust 1.83.0.\n\ + \n\ + One way to resolve this is to force the workspace to use the same version\n\ + of Rust as required by the shader. However that is not often ideal or even\n\ + possible. Another way is to exlude the shader from the workspace. This is\n\ + also not ideal if you have many shaders sharing config from the workspace.\n\ + \n\ + Therefore `cargo gpu build/install` offers a workaround with the argument:\n\ + --force-overwrite-lockfiles-v4-to-v3\n\ + \n\ + See `cargo gpu build --help` for more information.\n\ + " + ); + std::process::exit(1); + } +} + +impl Drop for LockfileMismatchHandler { + fn drop(&mut self) { + let result = self.revert_cargo_lock_manifest_versions(); + if let Err(error) = result { + log::error!("Couldn't revert some or all of the shader `Cargo.lock` files: {error}"); + } + } +} diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 69973861ef..852766f078 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -1,50 +1,48 @@ //! Rust GPU shader crate builder. //! -//! This program manages installations of `spirv-builder-cli` and `rustc_codegen_spirv`. -//! It uses these tools to compile Rust code into SPIR-V. +//! This program and library allows you to easily compile your rust-gpu shaders, +//! without requiring you to fix your entire project to a specific toolchain. //! //! # How it works //! -//! In order to build shader crates, we must invoke cargo/rustc with a special backend -//! that performs the SPIR-V code generation. This backend is a dynamic library known -//! by its project name `rustc_codegen_spirv`. The name of the artifact itself is -//! OS-dependent. +//! This program primarily manages installations of `rustc_codegen_spirv`, the +//! codegen backend of rust-gpu to generate SPIR-V shader binaries. The codegen +//! backend builds on internal, ever-changing interfaces of rustc, which requires +//! fixing a version of rust-gpu to a specific version of the rustc compiler. +//! Usually, this would require you to fix your entire project to that specific +//! toolchain, but this project loosens that requirement by managing installations +//! of `rustc_codegen_spirv` and their associated toolchains for you. //! -//! There are a lot of special flags to wrangle and so we use a command line program -//! that wraps `cargo` to perform the building of shader crates. This cli program is -//! called `spirv-builder-cli`, which itself is a cli wrapper around the `spirv-builder` -//! library. +//! We continue to use rust-gpu's `spirv_builder` crate to pass the many additional +//! parameters required to configure rustc and our codegen backend, but provide you +//! with a toolchain agnostic version that you may use from stable rustc. And a +//! `cargo gpu` cmdline utility to simplify shader building even more. //! //! ## Where the binaries are //! -//! `cargo-gpu` maintains different versions `spirv-builder-cli` and `rustc_codegen_spirv` -//! in a cache dir. The location is OS-dependent, for example on macOS it's in -//! `~/Library/Caches/rust-gpu`. Specific versions live inside the cache dir, prefixed -//! by their `spirv-builder` cargo dependency and rust toolchain pair. +//! We store our prebuild `rustc_spirv_builder` binaries in the default cache +//! directory of your OS: +//! * Windows: `C:/users//AppData/Local/rust-gpu` +//! * Mac: `~/Library/Caches/rust-gpu` +//! * Linux: `~/.cache/rust-gpu` //! -//! Building a specific "binary pair" of `spirv-builder-cli` and `rustc_codegen_spirv` -//! happens when there is no existing pair that matches the computed prefix, or if -//! a force rebuild is specified on the command line. +//! ## How we build the backend //! -//! ## Building the "binary pairs" -//! -//! The source of `spirv-builder-cli` lives alongside this source file, in crate that -//! is not included in the workspace. That same source code is also included statically -//! in **this** source file. -//! -//! When `spirv-builder-cli` needs to be built, a new directory is created in the cache -//! where the source to `spirv-builder-cli` is copied into, containing the specific cargo -//! dependency for `spirv-builder` and the matching rust toolchain channel. -//! -//! Then `cargo` is invoked in that cache directory to build the pair of artifacts, which -//! are then put into the top level of that cache directory. -//! -//! This pair of artifacts is then used to build shader crates. +//! * retrieve the version of rust-gpu you want to use based on the version of the +//! `spirv-std` dependency in your shader crate. +//! * create a dummy project at `/codegen//` that depends on +//! `rustc_codegen_spirv` +//! * use `cargo metadata` to `cargo update` the dummy project, which downloads the +//! `rustc_codegen_spirv` crate into cargo's cache, and retrieve the path to the +//! download location. +//! * search for the required toolchain in `build.rs` of `rustc_codegen_spirv` +//! * build it with the required toolchain version +//! * copy out the binary and clean the target dir //! //! ## Building shader crates //! //! `cargo-gpu` takes a path to a shader crate to build, as well as a path to a directory -//! to put the compiled `spv` source files. It also takes a path to an output mainifest +//! to put the compiled `spv` source files. It also takes a path to an output manifest //! file where all shader entry points will be mapped to their `spv` source files. This //! manifest file can be used by build scripts (`build.rs` files) to generate linkage or //! conduct other post-processing, like converting the `spv` files into `wgsl` files, @@ -57,12 +55,15 @@ use clap::Parser as _; use install::Install; use show::Show; +mod args; mod build; mod config; mod install; +mod install_toolchain; +mod linkage; +mod lockfile; mod metadata; mod show; -mod spirv_cli; mod spirv_source; /// Central function to write to the user. @@ -163,10 +164,10 @@ fn run() -> anyhow::Result<()> { #[derive(clap::Subcommand)] enum Command { /// Install rust-gpu compiler artifacts. - Install(Install), + Install(Box), /// Compile a shader crate to SPIR-V. - Build(Build), + Build(Box), /// Show some useful values. Show(Show), diff --git a/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs index 0d6b164cea..0b330fb245 100644 --- a/crates/cargo-gpu/src/metadata.rs +++ b/crates/cargo-gpu/src/metadata.rs @@ -1,5 +1,6 @@ //! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]` +use cargo_metadata::MetadataCommand; use serde_json::Value; /// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally @@ -15,43 +16,23 @@ impl Metadata { /// First we generate the CLI arg defaults as JSON. Then on top of those we merge any config /// from the workspace `Cargo.toml`, then on top of those we merge any config from the shader /// crate's `Cargo.toml`. - pub fn as_json(path: &std::path::PathBuf) -> anyhow::Result { + pub fn as_json(path: &std::path::PathBuf) -> anyhow::Result { let cargo_json = Self::get_cargo_toml_as_json(path)?; let config = Self::merge_configs(&cargo_json, path)?; Ok(config) } - /// Convert JSON keys from kebab case to snake case. Eg: `a-b` to `a_b`. - /// - /// Detection of keys for serde deserialization must match the case in the Rust structs. - /// However clap defaults to detecting CLI args in kebab case. So here we do the conversion. - fn keys_to_snake_case(json: &mut serde_json::Value) { - let serde_json::Value::Object(object) = json else { - return; - }; - - *object = core::mem::take(object) - .into_iter() - .map(|(key, mut value)| { - if let serde_json::Value::Object(_) = value { - Self::keys_to_snake_case(&mut value); - } - (key.replace('-', "_"), value) - }) - .collect(); - } - /// Merge the various source of config: defaults, workspace and shader crate. fn merge_configs( - cargo_json: &serde_json::Value, + cargo_json: &cargo_metadata::Metadata, path: &std::path::Path, - ) -> anyhow::Result { + ) -> anyhow::Result { let mut metadata = crate::config::Config::defaults_as_json()?; crate::config::Config::json_merge( &mut metadata, { log::debug!("looking for workspace metadata"); - let ws_meta = Self::get_workspace_metadata(cargo_json); + let ws_meta = Self::get_rust_gpu_from_metadata(&cargo_json.workspace_metadata); log::trace!("workspace_metadata: {ws_meta:#?}"); ws_meta }, @@ -64,7 +45,7 @@ impl Metadata { let mut crate_meta = Self::get_crate_metadata(cargo_json, path)?; log::trace!("crate_metadata: {crate_meta:#?}"); if let Some(output_path) = crate_meta.pointer_mut("/build/output_dir") { - log::debug!("found output-dir path in crate metadata: {:?}", output_path); + log::debug!("found output-dir path in crate metadata: {output_path:?}"); if let Some(output_dir) = output_path.clone().as_str() { let new_output_path = path.join(output_dir); *output_path = Value::String(format!("{}", new_output_path.display())); @@ -83,76 +64,59 @@ impl Metadata { } /// Convert a `Cargo.toml` to JSON - // - // TODO: reuse for getting the default `rust-gpu` source and toolchain. - fn get_cargo_toml_as_json(path: &std::path::PathBuf) -> anyhow::Result { - let cargo_toml_path = path.join("Cargo.toml"); - if !cargo_toml_path.exists() { - anyhow::bail!("{path:?} must be a shader crate directory"); - } - - log::debug!("Querying Cargo metadata for {cargo_toml_path:?}"); - let output_cargo = std::process::Command::new("cargo") - .args([ - "metadata", - "--no-deps", - "--manifest-path", - cargo_toml_path.display().to_string().as_ref(), - ]) - .output()?; - anyhow::ensure!( - output_cargo.status.success(), - "could not run `cargo metadata` on {cargo_toml_path:?}" - ); - - Ok(serde_json::from_slice(&output_cargo.stdout)?) - } - - /// Get any `rust-gpu` metadata set in the root workspace `Cargo.toml` - fn get_workspace_metadata(json: &serde_json::Value) -> serde_json::Value { - let empty_json_object = serde_json::json!({}); - let mut metadata = json - .pointer("/metadata/rust-gpu") - .unwrap_or(&empty_json_object) - .clone(); - - Self::keys_to_snake_case(&mut metadata); - metadata.clone() + fn get_cargo_toml_as_json( + path: &std::path::PathBuf, + ) -> anyhow::Result { + Ok(MetadataCommand::new().current_dir(path).exec()?) } /// Get any `rust-gpu` metadata set in the crate's `Cargo.toml` fn get_crate_metadata( - json: &serde_json::Value, + json: &cargo_metadata::Metadata, path: &std::path::Path, - ) -> anyhow::Result { - let empty_json_object = serde_json::json!({}); - if let Some(serde_json::Value::Array(packages)) = json.pointer("/packages") { - for package in packages { - if let Some(serde_json::Value::String(manifest_path_dirty)) = - package.pointer("/manifest_path") - { - let mut shader_crate_path = std::fs::canonicalize(path)? - .join("Cargo.toml") - .display() - .to_string(); - - // Windows prefixs paths with `\\?\` - shader_crate_path = shader_crate_path.replace(r"\\?\", ""); - let manifest_path = manifest_path_dirty.replace(r"\\?\", ""); - log::debug!("Matching shader crate path with manifest path: {shader_crate_path} == {manifest_path}?"); - if manifest_path == shader_crate_path { - log::debug!("...matches! Getting metadata"); - let mut metadata = package - .pointer("/metadata/rust-gpu") - .unwrap_or(&empty_json_object) - .clone(); - Self::keys_to_snake_case(&mut metadata); - return Ok(metadata); - } - } + ) -> anyhow::Result { + let shader_crate_path = std::fs::canonicalize(path)?.join("Cargo.toml"); + + for package in &json.packages { + let manifest_path = std::fs::canonicalize(package.manifest_path.as_std_path())?; + log::debug!( + "Matching shader crate path with manifest path: '{}' == '{}'?", + shader_crate_path.display(), + manifest_path.display() + ); + if manifest_path == shader_crate_path { + log::debug!("...matches! Getting metadata"); + return Ok(Self::get_rust_gpu_from_metadata(&package.metadata)); } } - Ok(empty_json_object) + Ok(serde_json::json!({})) + } + + /// Get `rust-gpu` value from some metadata + fn get_rust_gpu_from_metadata(metadata: &Value) -> Value { + Self::keys_to_snake_case( + metadata + .pointer("/rust-gpu") + .cloned() + .unwrap_or(Value::Null), + ) + } + + /// Convert JSON keys from kebab case to snake case. Eg: `a-b` to `a_b`. + /// + /// Detection of keys for serde deserialization must match the case in the Rust structs. + /// However clap defaults to detecting CLI args in kebab case. So here we do the conversion. + #[expect(clippy::wildcard_enum_match_arm, reason = "we only want objects")] + fn keys_to_snake_case(json: Value) -> Value { + match json { + Value::Object(object) => Value::Object( + object + .into_iter() + .map(|(key, value)| (key.replace('-', "_"), Self::keys_to_snake_case(value))) + .collect(), + ), + other => other, + } } } @@ -163,59 +127,73 @@ impl Metadata { #[cfg(test)] mod test { use super::*; + use std::path::Path; #[test_log::test] fn generates_defaults() { - let json = serde_json::json!({}); - let configs = Metadata::merge_configs(&json, std::path::Path::new("./")).unwrap(); - assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(false)); + let mut metadata = MetadataCommand::new() + .current_dir(env!("CARGO_MANIFEST_DIR")) + .exec() + .unwrap(); + metadata.packages.first_mut().unwrap().metadata = serde_json::json!({}); + let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap(); + assert_eq!(configs["build"]["release"], Value::Bool(true)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], - serde_json::Value::Bool(false) + Value::Bool(false) ); } #[test_log::test] fn can_override_config_from_workspace_toml() { - let json = serde_json::json!( - { "metadata": { "rust-gpu": { + let mut metadata = MetadataCommand::new() + .current_dir(env!("CARGO_MANIFEST_DIR")) + .exec() + .unwrap(); + metadata.workspace_metadata = serde_json::json!({ + "rust-gpu": { "build": { - "debug": true + "release": false }, "install": { "auto-install-rust-toolchain": true } - }}} - ); - let configs = Metadata::merge_configs(&json, std::path::Path::new("./")).unwrap(); - assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(true)); + } + }); + let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap(); + assert_eq!(configs["build"]["release"], Value::Bool(false)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], - serde_json::Value::Bool(true) + Value::Bool(true) ); } #[test_log::test] fn can_override_config_from_crate_toml() { - let marker = std::path::Path::new("./Cargo.toml"); - let json = serde_json::json!( - { "packages": [{ - "metadata": { "rust-gpu": { - "build": { - "debug": true - }, - "install": { - "auto-install-rust-toolchain": true - } - }}, - "manifest_path": std::fs::canonicalize(marker).unwrap() - }]} - ); - let configs = Metadata::merge_configs(&json, marker.parent().unwrap()).unwrap(); - assert_eq!(configs["build"]["debug"], serde_json::Value::Bool(true)); + let mut metadata = MetadataCommand::new() + .current_dir(env!("CARGO_MANIFEST_DIR")) + .exec() + .unwrap(); + let cargo_gpu = metadata + .packages + .iter_mut() + .find(|package| package.name.contains("cargo-gpu")) + .unwrap(); + cargo_gpu.metadata = serde_json::json!({ + "rust-gpu": { + "build": { + "release": false + }, + "install": { + "auto-install-rust-toolchain": true + } + } + }); + let configs = Metadata::merge_configs(&metadata, Path::new(".")).unwrap(); + assert_eq!(configs["build"]["release"], Value::Bool(false)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], - serde_json::Value::Bool(true) + Value::Bool(true) ); } } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 61202cbf0c..3b0e2f8891 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -19,7 +19,7 @@ pub enum Info { SpirvSource(SpirvSourceDep), /// The git commitsh of this cli tool. Commitsh, - /// All the available SPIR-V capabilities that can be set with `--capability` + /// All the available SPIR-V capabilities that can be set with `--capabilities` Capabilities, } @@ -47,16 +47,14 @@ impl Show { } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = - crate::spirv_source::SpirvSource::get_spirv_std_dep_definition(&shader_crate)?; - { - println!("{rust_gpu_source}\n"); - } + crate::spirv_source::SpirvSource::get_rust_gpu_deps_from_shader(&shader_crate)?; + println!("{rust_gpu_source}\n"); } Info::Commitsh => { println!("{}", std::env!("GIT_HASH")); } Info::Capabilities => { - println!("All available options to the `cargo gpu build --capability` argument:"); + println!("All available options to the `cargo gpu build --capabilities` argument:"); #[expect( clippy::use_debug, reason = "It's easier to just use `Debug` formatting than implementing `Display`" @@ -71,11 +69,11 @@ impl Show { } /// Iterator over all `Capability` variants. - fn capability_variants_iter() -> impl Iterator { + fn capability_variants_iter() -> impl Iterator { // Since spirv::Capability is repr(u32) we can iterate over // u32s until some maximum #[expect(clippy::as_conversions, reason = "We know all variants are repr(u32)")] - let last_capability = spirv_builder_cli::spirv::Capability::CacheControlsINTEL as u32; - (0..=last_capability).filter_map(spirv_builder_cli::spirv::Capability::from_u32) + let last_capability = spirv_builder::Capability::CacheControlsINTEL as u32; + (0..=last_capability).filter_map(spirv_builder::Capability::from_u32) } } diff --git a/crates/cargo-gpu/src/spirv_cli.rs b/crates/cargo-gpu/src/spirv_cli.rs deleted file mode 100644 index 8a905d15d2..0000000000 --- a/crates/cargo-gpu/src/spirv_cli.rs +++ /dev/null @@ -1,512 +0,0 @@ -//! Query the shader crate to find what version of `rust-gpu` it depends on. -//! Then ensure that the relevant Rust toolchain and components are installed. - -use std::io::Write as _; - -use anyhow::Context as _; - -use crate::spirv_source::SpirvSource; - -/// `Cargo.lock` manifest version 4 became the default in Rust 1.83.0. Conflicting manifest -/// versions between the workspace and the shader crate, can cause problems. -const RUST_VERSION_THAT_USES_V4_CARGO_LOCKS: &str = "1.83.0"; - -/// Cargo dependency for `spirv-builder` and the rust toolchain channel. -#[derive(Debug, Clone)] -pub struct SpirvCli { - #[expect( - clippy::doc_markdown, - reason = "The URL should appear literally like this. But Clippy wants it to be a in markdown clickable link" - )] - /// The source and version of `rust-gpu`. - /// Eg: - /// * From crates.io with version "0.10.0" - /// * From Git with: - /// - a repo of "https://github.com/Rust-GPU/rust-gpu.git" - /// - a revision of "abc213" - pub source: SpirvSource, - /// The toolchain channel that `rust-gpu` uses, eg "nightly-2024-04-24" - pub channel: String, - /// The date of the pinned version of `rust-gpu` - pub date: chrono::NaiveDate, - /// `Cargo.lock`s that have had their manifest versions changed by us and need changing back. - pub cargo_lock_files_with_changed_manifest_versions: Vec, - /// Has the user overridden the toolchain consent prompt - is_toolchain_install_consent: bool, -} - -impl core::fmt::Display for SpirvCli { - #[expect( - clippy::min_ident_chars, - reason = "It's a core library trait implementation" - )] - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - format!("{}+{}", self.source, self.channel).fmt(f) - } -} - -impl SpirvCli { - /// Create instance - pub fn new( - shader_crate_path: &std::path::Path, - maybe_rust_gpu_source: Option, - maybe_rust_gpu_version: Option, - maybe_rust_gpu_channel: Option, - is_toolchain_install_consent: bool, - is_force_overwrite_lockfiles_v4_to_v3: bool, - ) -> anyhow::Result { - let mut cargo_lock_files_with_changed_manifest_versions = vec![]; - - let maybe_shader_crate_lock = - Self::ensure_workspace_rust_version_doesnt_conflict_with_shader( - shader_crate_path, - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("ensure_workspace_rust_version_doesnt_conflict_with_shader")?; - - if let Some(shader_crate_lock) = maybe_shader_crate_lock { - cargo_lock_files_with_changed_manifest_versions.push(shader_crate_lock); - } - - let (default_rust_gpu_source, rust_gpu_date, default_rust_gpu_channel) = - SpirvSource::get_rust_gpu_deps_from_shader(shader_crate_path) - .context("get_rust_gpu_deps_from_shader")?; - - let maybe_workspace_crate_lock = - Self::ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( - shader_crate_path, - default_rust_gpu_channel.clone(), - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks")?; - - if let Some(workspace_crate_lock) = maybe_workspace_crate_lock { - cargo_lock_files_with_changed_manifest_versions.push(workspace_crate_lock); - } - - let mut maybe_spirv_source: Option = None; - if let Some(rust_gpu_version) = maybe_rust_gpu_version { - let mut source = SpirvSource::CratesIO(rust_gpu_version.clone()); - if let Some(rust_gpu_source) = maybe_rust_gpu_source { - source = SpirvSource::Git { - url: rust_gpu_source, - rev: rust_gpu_version, - }; - } - maybe_spirv_source = Some(source); - } - - Ok(Self { - source: maybe_spirv_source.unwrap_or(default_rust_gpu_source), - channel: maybe_rust_gpu_channel.unwrap_or(default_rust_gpu_channel), - date: rust_gpu_date, - is_toolchain_install_consent, - cargo_lock_files_with_changed_manifest_versions, - }) - } - - /// Create and/or return the cache directory - pub fn cached_checkout_path(&self) -> anyhow::Result { - let checkout_dir = crate::cache_dir() - .context("reading cache dir")? - .join("spirv-builder-cli") - .join(crate::to_dirname(self.to_string().as_ref())); - std::fs::create_dir_all(&checkout_dir) - .with_context(|| format!("could not create checkout dir '{}'", checkout_dir.display())) - .context("crating directory in cahce dir")?; - - Ok(checkout_dir) - } - - /// Use `rustup` to install the toolchain and components, if not already installed. - /// - /// Pretty much runs: - /// - /// * rustup toolchain add nightly-2024-04-24 - /// * rustup component add --toolchain nightly-2024-04-24 rust-src rustc-dev llvm-tools - pub fn ensure_toolchain_and_components_exist(&self) -> anyhow::Result<()> { - // Check for the required toolchain - let output_toolchain_list = std::process::Command::new("rustup") - .args(["toolchain", "list"]) - .output() - .context("running rustup command")?; - anyhow::ensure!( - output_toolchain_list.status.success(), - "could not list installed toolchains" - ); - let string_toolchain_list = String::from_utf8_lossy(&output_toolchain_list.stdout); - if string_toolchain_list - .split_whitespace() - .any(|toolchain| toolchain.starts_with(&self.channel)) - { - log::debug!("toolchain {} is already installed", self.channel); - } else { - let message = format!("Rust {} with `rustup`", self.channel); - self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; - crate::user_output!("Installing {message}\n"); - - let output_toolchain_add = std::process::Command::new("rustup") - .args(["toolchain", "add"]) - .arg(&self.channel) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .context("adding toolchain")?; - anyhow::ensure!( - output_toolchain_add.status.success(), - "could not install required toolchain" - ); - } - - // Check for the required components - let output_component_list = std::process::Command::new("rustup") - .args(["component", "list", "--toolchain"]) - .arg(&self.channel) - .output() - .context("getting toolchain list")?; - anyhow::ensure!( - output_component_list.status.success(), - "could not list installed components" - ); - let string_component_list = String::from_utf8_lossy(&output_component_list.stdout); - let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; - let installed_components = string_component_list.lines().collect::>(); - let all_components_installed = required_components.iter().all(|component| { - installed_components.iter().any(|installed_component| { - let is_component = installed_component.starts_with(component); - let is_installed = installed_component.ends_with("(installed)"); - is_component && is_installed - }) - }); - if all_components_installed { - log::debug!("all required components are installed"); - } else { - let message = "toolchain components (rust-src, rustc-dev, llvm-tools) with `rustup`"; - self.get_consent_for_toolchain_install(format!("Install {message}").as_ref())?; - crate::user_output!("Installing {message}\n"); - - let output_component_add = std::process::Command::new("rustup") - .args(["component", "add", "--toolchain"]) - .arg(&self.channel) - .args(["rust-src", "rustc-dev", "llvm-tools"]) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .context("adding rustup component")?; - anyhow::ensure!( - output_component_add.status.success(), - "could not install required components" - ); - } - - Ok(()) - } - - /// Prompt user if they want to install a new Rust toolchain. - fn get_consent_for_toolchain_install(&self, prompt: &str) -> anyhow::Result<()> { - if self.is_toolchain_install_consent { - return Ok(()); - } - log::debug!("asking for consent to install the required toolchain"); - crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; - crate::user_output!("{prompt} [y/n]: \n"); - let mut input = crossterm::event::read().context("reading crossterm event")?; - - if let crossterm::event::Event::Key(crossterm::event::KeyEvent { - code: crossterm::event::KeyCode::Enter, - kind: crossterm::event::KeyEventKind::Release, - .. - }) = input - { - // In Powershell, programs will potentially observe the Enter key release after they started - // (see crossterm#124). If that happens, re-read the input. - input = crossterm::event::read().context("re-reading crossterm event")?; - } - crossterm::terminal::disable_raw_mode().context("disabling raw mode")?; - - if let crossterm::event::Event::Key(crossterm::event::KeyEvent { - code: crossterm::event::KeyCode::Char('y'), - .. - }) = input - { - Ok(()) - } else { - crate::user_output!("Exiting...\n"); - std::process::exit(0); - } - } - - /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. - fn ensure_workspace_rust_version_doesnt_conflict_with_shader( - shader_crate_path: &std::path::Path, - is_force_overwrite_lockfiles_v4_to_v3: bool, - ) -> anyhow::Result> { - log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from workspace Rust..."); - let workspace_rust_version = - Self::get_rustc_version(None).context("reading rustc version")?; - if version_check::Version::at_least( - &workspace_rust_version, - RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, - ) { - log::debug!( - "user's Rust is v{}, so no v3/v4 conflicts possible.", - workspace_rust_version - ); - return Ok(None); - } - - Self::handle_conflicting_cargo_lock_v4( - shader_crate_path, - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("handling v4/v3 conflict")?; - - if is_force_overwrite_lockfiles_v4_to_v3 { - Ok(Some(shader_crate_path.join("Cargo.lock"))) - } else { - Ok(None) - } - } - - /// See docs for `force_overwrite_lockfiles_v4_to_v3` flag for why we do this. - fn ensure_shader_rust_version_doesnt_conflict_with_any_cargo_locks( - shader_crate_path: &std::path::Path, - channel: String, - is_force_overwrite_lockfiles_v4_to_v3: bool, - ) -> anyhow::Result> { - log::debug!("Ensuring no v3/v4 `Cargo.lock` conflicts from shader's Rust..."); - let shader_rust_version = - Self::get_rustc_version(Some(channel)).context("getting rustc version")?; - if version_check::Version::at_least( - &shader_rust_version, - RUST_VERSION_THAT_USES_V4_CARGO_LOCKS, - ) { - log::debug!( - "shader's Rust is v{}, so no v3/v4 conflicts possible.", - shader_rust_version - ); - return Ok(None); - } - - log::debug!( - "shader's Rust is v{}, so checking both shader and workspace `Cargo.lock` manifest versions...", - shader_rust_version - ); - - if shader_crate_path.join("Cargo.lock").exists() { - // Note that we don't return the `Cargo.lock` here (so that it's marked for reversion - // after the build), because we can be sure that updating it now is actually updating it - // to the state it should have been all along. Therefore it doesn't need reverting once - // fixed. - Self::handle_conflicting_cargo_lock_v4( - shader_crate_path, - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("handling v4/v3 conflict")?; - } - - if let Some(workspace_root) = - Self::get_workspace_root(shader_crate_path).context("reading workspace root")? - { - Self::handle_conflicting_cargo_lock_v4( - workspace_root, - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("handling conflicting cargo v4")?; - return Ok(Some(workspace_root.join("Cargo.lock"))); - } - - Ok(None) - } - - /// Get the path to the shader crate's workspace, if it has one. We can't use the traditional - /// `cargo metadata` because if the workspace has a conflicting `Cargo.lock` manifest version - /// then that command won't work. Instead we do an old school recursive file tree walk. - fn get_workspace_root( - shader_crate_path: &std::path::Path, - ) -> anyhow::Result> { - let shader_cargo_toml = std::fs::read_to_string(shader_crate_path.join("Cargo.toml")) - .with_context(|| format!("reading Cargo.toml at {}", shader_crate_path.display()))?; - if !shader_cargo_toml.contains("workspace = true") { - return Ok(None); - } - - let mut current_path = shader_crate_path; - #[expect(clippy::default_numeric_fallback, reason = "It's just a loop")] - for _ in 0..15 { - if let Some(parent_path) = current_path.parent() { - if parent_path.join("Cargo.lock").exists() { - return Ok(Some(parent_path)); - } - current_path = parent_path; - } else { - break; - } - } - - Ok(None) - } - - /// When Rust < 1.83.0 is being used an error will occur if it tries to parse `Cargo.lock` - /// files that use lockfile manifest version 4. Here we check and handle that. - fn handle_conflicting_cargo_lock_v4( - folder: &std::path::Path, - is_force_overwrite_lockfiles_v4_to_v3: bool, - ) -> anyhow::Result<()> { - let shader_cargo_lock_path = folder.join("Cargo.lock"); - let shader_cargo_lock = std::fs::read_to_string(shader_cargo_lock_path.clone()) - .context("reading shader cargo lock")?; - let third_line = shader_cargo_lock.lines().nth(2).context("no third line")?; - if third_line.contains("version = 4") { - Self::handle_v3v4_conflict( - &shader_cargo_lock_path, - is_force_overwrite_lockfiles_v4_to_v3, - ) - .context("handling v4/v3 conflict")?; - return Ok(()); - } - if third_line.contains("version = 3") { - return Ok(()); - } - anyhow::bail!( - "Unrecognized `Cargo.lock` manifest version at: {}", - folder.display() - ) - } - - /// Handle conflicting `Cargo.lock` manifest versions by either overwriting the manifest - /// version or exiting with advice on how to handle the conflict. - fn handle_v3v4_conflict( - offending_cargo_lock: &std::path::Path, - is_force_overwrite_lockfiles_v4_to_v3: bool, - ) -> anyhow::Result<()> { - if !is_force_overwrite_lockfiles_v4_to_v3 { - Self::exit_with_v3v4_hack_suggestion(); - } - - Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "4", "3") - .context("replacing version 4 -> 3")?; - - Ok(()) - } - - /// Once all install and builds have completed put their manifest versions back to how they - /// were. - pub fn revert_cargo_lock_manifest_versions(&self) -> anyhow::Result<()> { - for offending_cargo_lock in &self.cargo_lock_files_with_changed_manifest_versions { - log::debug!("Reverting: {}", offending_cargo_lock.display()); - Self::replace_cargo_lock_manifest_version(offending_cargo_lock, "3", "4") - .context("replacing version 3 -> 4")?; - } - - Ok(()) - } - - /// Replace the manifest version, eg `version = 4`, in a `Cargo.lock` file. - fn replace_cargo_lock_manifest_version( - offending_cargo_lock: &std::path::Path, - from_version: &str, - to_version: &str, - ) -> anyhow::Result<()> { - log::warn!( - "Replacing manifest version 'version = {}' with 'version = {}' in: {}", - from_version, - to_version, - offending_cargo_lock.display() - ); - let old_contents = std::fs::read_to_string(offending_cargo_lock) - .context("reading offending Cargo.lock")?; - let new_contents = old_contents.replace( - &format!("\nversion = {from_version}\n"), - &format!("\nversion = {to_version}\n"), - ); - - let mut file = std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(offending_cargo_lock) - .context("opening offending Cargo.lock")?; - file.write_all(new_contents.as_bytes())?; - - Ok(()) - } - - /// Exit and give the user advice on how to deal with the infamous v3/v4 Cargo lockfile version - /// problem. - #[expect(clippy::non_ascii_literal, reason = "It's CLI output")] - fn exit_with_v3v4_hack_suggestion() { - crate::user_output!( - "Conflicting `Cargo.lock` versions detected ⚠️\n\ - Because `cargo gpu` uses a dedicated Rust toolchain for compiling shaders\n\ - it's possible that the `Cargo.lock` manifest version of the shader crate\n\ - does not match the `Cargo.lock` manifest version of the workspace. This is\n\ - due to a change in the defaults introduced in Rust 1.83.0.\n\ - \n\ - One way to resolve this is to force the workspace to use the same version\n\ - of Rust as required by the shader. However that is not often ideal or even\n\ - possible. Another way is to exlude the shader from the workspace. This is\n\ - also not ideal if you have many shaders sharing config from the workspace.\n\ - \n\ - Therefore `cargo gpu build/install` offers a workaround with the argument:\n\ - --force-overwrite-lockfiles-v4-to-v3\n\ - \n\ - See `cargo gpu build --help` for more information.\n\ - " - ); - std::process::exit(1); - } - - /// Get the version of `rustc`. - fn get_rustc_version( - maybe_toolchain: Option, - ) -> anyhow::Result { - let mut maybe_current_env_toolchain: Option = None; - if let Some(toolchain) = maybe_toolchain { - maybe_current_env_toolchain = std::env::var_os("RUSTUP_TOOLCHAIN"); - std::env::set_var("RUSTUP_TOOLCHAIN", toolchain); - } - - let Some(version) = version_check::Version::read() else { - anyhow::bail!("Couldn't get `rustc --version`"); - }; - - if let Some(current_env_toolchain) = maybe_current_env_toolchain { - std::env::set_var("RUSTUP_TOOLCHAIN", current_env_toolchain); - } - - Ok(version) - } -} - -impl Drop for SpirvCli { - fn drop(&mut self) { - let result = self.revert_cargo_lock_manifest_versions(); - if let Err(error) = result { - log::error!("Couldn't revert some or all of the shader `Cargo.lock` files: {error}"); - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test_log::test] - fn cached_checkout_dir_sanity() { - let shader_template_path = crate::test::shader_crate_template_path(); - // TODO: This downloads the `rust-gpu` repo which slows the test down. Can we avoid that - // just to get the sanity check? - let spirv = SpirvCli::new(&shader_template_path, None, None, None, true, false).unwrap(); - let dir = spirv.cached_checkout_path().unwrap(); - let name = dir - .file_name() - .unwrap() - .to_str() - .map(std::string::ToString::to_string) - .unwrap(); - assert_eq!( - "https___github_com_Rust-GPU_rust-gpu+82a0f69+nightly-2024-04-24", - &name - ); - } -} diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index c1815d62ca..32fde8d94f 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -5,20 +5,28 @@ //! From there we can look at the source code to get the required Rust toolchain. use anyhow::Context as _; - -/// The canonical `rust-gpu` URI -const RUST_GPU_REPO: &str = "https://github.com/Rust-GPU/rust-gpu"; - -/// The various sources that the `rust-gpu` repo can have. -/// Most commonly it will simply be the canonical version on crates.io. But it could also be the -/// Git version, or a fork. +use cargo_metadata::camino::{Utf8Path, Utf8PathBuf}; +use cargo_metadata::semver::Version; +use cargo_metadata::{MetadataCommand, Package}; +use std::fs; +use std::path::{Path, PathBuf}; + +#[expect( + clippy::doc_markdown, + reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" +)] +/// The source and version of `rust-gpu`. +/// Eg: +/// * From crates.io with version "0.10.0" +/// * From Git with: +/// - a repo of "https://github.com/Rust-GPU/rust-gpu.git" +/// - a revision of "abc213" +/// * a local Path #[derive(Eq, PartialEq, Clone, Debug)] pub enum SpirvSource { /// If the shader specifies a simple version like `spirv-std = "0.9.0"` then the source of /// `rust-gpu` is the conventional crates.io version. - /// - /// `String` is the simple version like, "0.9.0" - CratesIO(String), + CratesIO(Version), /// If the shader specifies a version like: /// `spirv-std = { git = "https://github.com..." ... }` /// then the source of `rust-gpu` is `Git`. @@ -31,7 +39,12 @@ pub enum SpirvSource { /// If the shader specifies a version like: /// `spirv-std = { path = "/path/to/rust-gpu" ... }` /// then the source of `rust-gpu` is `Path`. - Path((String, String)), + Path { + /// File path of rust-gpu repository + rust_gpu_repo_root: Utf8PathBuf, + /// Version of specified rust-gpu repository + version: Version, + }, } impl core::fmt::Display for SpirvSource { @@ -41,328 +54,190 @@ impl core::fmt::Display for SpirvSource { )] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::CratesIO(version) => f.write_str(version), - Self::Git { url, rev } => f.write_str(&format!("{url}+{rev}")), - Self::Path((a, b)) => f.write_str(&format!("{a}+{b}")), + Self::CratesIO(version) => version.fmt(f), + Self::Git { url, rev } => { + // shorten rev to 8 chars, prevents windows compile errors due to too long paths... seriously + if let Some(short_rev) = rev.get(..8) { + write!(f, "{url}+{short_rev}") + } else { + write!(f, "{url}+{rev}") + } + } + Self::Path { + rust_gpu_repo_root, + version, + } => write!(f, "{rust_gpu_repo_root}+{version}"), } } } impl SpirvSource { - /// Look into the shader crate to get the version of `rust-gpu` it's using. - pub fn get_rust_gpu_deps_from_shader>( - shader_crate_path: F, - ) -> anyhow::Result<(Self, chrono::NaiveDate, String)> { - let rust_gpu_source = Self::get_spirv_std_dep_definition(shader_crate_path.as_ref())?; - rust_gpu_source.ensure_repo_is_installed()?; - rust_gpu_source.checkout()?; - - let date = rust_gpu_source.get_version_date()?; - let channel = Self::get_channel_from_toolchain_toml(&rust_gpu_source.to_dirname()?)?; + /// Figures out which source of `rust-gpu` to use + pub fn new( + shader_crate_path: &Path, + maybe_rust_gpu_source: Option<&str>, + maybe_rust_gpu_version: Option<&str>, + ) -> anyhow::Result { + let source = if let Some(rust_gpu_version) = maybe_rust_gpu_version { + if let Some(rust_gpu_source) = maybe_rust_gpu_source { + Self::Git { + url: rust_gpu_source.to_owned(), + rev: rust_gpu_version.to_owned(), + } + } else { + Self::CratesIO(Version::parse(rust_gpu_version)?) + } + } else { + Self::get_rust_gpu_deps_from_shader(shader_crate_path) + .context("get_rust_gpu_deps_from_shader")? + }; + Ok(source) + } + /// Look into the shader crate to get the version of `rust-gpu` it's using. + pub fn get_rust_gpu_deps_from_shader(shader_crate_path: &Path) -> anyhow::Result { + let spirv_std_package = get_package_from_crate(shader_crate_path, "spirv-std")?; + let spirv_source = Self::parse_spirv_std_source_and_version(&spirv_std_package)?; log::debug!( - "Parsed version, date and toolchain channel from shader-defined `rust-gpu`: \ - {rust_gpu_source:?}, {date}, {channel}" + "Parsed `SpirvSource` from crate `{}`: \ + {spirv_source:?}", + shader_crate_path.display(), ); - - Ok((rust_gpu_source, date, channel)) - } - - /// Convert the source to just its version. - pub fn to_version(&self) -> String { - match self { - Self::CratesIO(version) | Self::Path((_, version)) => version.to_string(), - Self::Git { rev, .. } => rev.to_string(), - } - } - - /// Convert the source to just its repo or path. - fn to_repo(&self) -> String { - match self { - Self::CratesIO(_) => RUST_GPU_REPO.to_owned(), - Self::Git { url, .. } => url.to_owned(), - Self::Path((path, _)) => path.to_owned(), - } + Ok(spirv_source) } - /// Convert the `rust-gpu` source into a string that can be used as a directory. + /// Convert the `SpirvSource` to a cache directory in which we can build it. /// It needs to be dynamically created because an end-user might want to swap out the source, /// maybe using their own fork for example. - fn to_dirname(&self) -> anyhow::Result { - let dir = crate::to_dirname(self.to_string().as_ref()); - Ok(crate::cache_dir()?.join("rust-gpu-repo").join(dir)) - } - - /// Make sure shader crate path is absolute and canonical. - fn shader_crate_path_canonical( - shader_crate_path: &mut std::path::PathBuf, - ) -> anyhow::Result<()> { - let cwd = std::env::current_dir().context("no cwd")?; - let mut canonical_path = shader_crate_path.clone(); - - if !canonical_path.is_absolute() { - canonical_path = cwd.join(canonical_path); - } - canonical_path - .canonicalize() - .context("could not get absolute path to shader crate")?; - - if !canonical_path.is_dir() { - log::error!("{shader_crate_path:?} is not a directory, aborting"); - anyhow::bail!("{shader_crate_path:?} is not a directory"); + pub fn install_dir(&self) -> anyhow::Result { + match self { + Self::Path { + rust_gpu_repo_root, .. + } => Ok(rust_gpu_repo_root.as_std_path().to_owned()), + Self::CratesIO { .. } | Self::Git { .. } => { + let dir = crate::to_dirname(self.to_string().as_ref()); + Ok(crate::cache_dir()?.join("codegen").join(dir)) + } } - - *shader_crate_path = canonical_path; - - Ok(()) - } - - /// Checkout the `rust-gpu` repo to the requested version. - fn checkout(&self) -> anyhow::Result<()> { - log::debug!( - "Checking out `rust-gpu` repo at {} to {}", - self.to_dirname()?.display(), - self.to_version() - ); - let output_checkout = std::process::Command::new("git") - .current_dir(self.to_dirname()?) - .args(["checkout", self.to_version().as_ref()]) - .output()?; - anyhow::ensure!( - output_checkout.status.success(), - "couldn't checkout revision '{}' of `rust-gpu` at {}", - self.to_version(), - self.to_dirname()?.to_string_lossy() - ); - - Ok(()) - } - - /// Get the date of the version of `rust-gpu` used by the shader. This allows us to know what - /// features we can use in the `spirv-builder` crate. - fn get_version_date(&self) -> anyhow::Result { - let date_format = "%Y-%m-%d"; - - log::debug!( - "Getting `rust-gpu` version date from {}", - self.to_dirname()?.display(), - ); - let output_date = std::process::Command::new("git") - .current_dir(self.to_dirname()?) - .args([ - "show", - "--no-patch", - "--format=%cd", - format!("--date=format:'{date_format}'").as_ref(), - self.to_version().as_ref(), - ]) - .output()?; - anyhow::ensure!( - output_date.status.success(), - "couldn't get `rust-gpu` version date at for {} at {}", - self.to_version(), - self.to_dirname()?.to_string_lossy() - ); - let date_string = String::from_utf8_lossy(&output_date.stdout) - .to_string() - .trim() - .replace('\'', ""); - - log::debug!( - "Parsed date for version {}: {date_string}", - self.to_version() - ); - - Ok(chrono::NaiveDate::parse_from_str( - &date_string, - date_format, - )?) - } - - /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. - fn get_channel_from_toolchain_toml(path: &std::path::PathBuf) -> anyhow::Result { - log::debug!("Parsing `rust-toolchain.toml` at {path:?} for the used toolchain"); - - let contents = std::fs::read_to_string(path.join("rust-toolchain.toml"))?; - let toml: toml::Table = toml::from_str(&contents)?; - let Some(toolchain) = toml.get("toolchain") else { - anyhow::bail!( - "Couldn't find `[toolchain]` section in `rust-toolchain.toml` at {path:?}" - ); - }; - let Some(channel) = toolchain.get("channel") else { - anyhow::bail!("Couldn't find `channel` field in `rust-toolchain.toml` at {path:?}"); - }; - - Ok(channel.to_string().replace('"', "")) - } - - /// Get the shader crate's resolved `spirv_std = ...` definition in its `Cargo.toml`/`Cargo.lock` - pub fn get_spirv_std_dep_definition( - shader_crate_path: &std::path::Path, - ) -> anyhow::Result { - let canonical_shader_path = shader_crate_path.to_path_buf(); - Self::shader_crate_path_canonical(&mut canonical_shader_path.clone())?; - - log::debug!( - "Running `cargo tree` on {}", - canonical_shader_path.display() - ); - let output_cargo_tree = std::process::Command::new("cargo") - .current_dir(canonical_shader_path.clone()) - .args(["tree", "--workspace", "--prefix", "none"]) - .output()?; - anyhow::ensure!( - output_cargo_tree.status.success(), - format!( - "could not query shader's `Cargo.toml` for `spirv-std` dependency: {}", - String::from_utf8(output_cargo_tree.stderr)? - ) - ); - let cargo_tree_string = String::from_utf8_lossy(&output_cargo_tree.stdout); - - let maybe_spirv_std_def = cargo_tree_string - .lines() - .find(|line| line.contains("spirv-std")); - log::trace!(" found {maybe_spirv_std_def:?}"); - - let Some(spirv_std_def) = maybe_spirv_std_def else { - anyhow::bail!("`spirv-std` not found in shader's `Cargo.toml` at {canonical_shader_path:?}:\n{cargo_tree_string}"); - }; - - Self::parse_spirv_std_source_and_version(spirv_std_def) } /// Parse a string like: /// `spirv-std v0.9.0 (https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c) (*)` /// Which would return: /// `SpirvSource::Git("https://github.com/Rust-GPU/rust-gpu", "54f6978c")` - fn parse_spirv_std_source_and_version(spirv_std_def: &str) -> anyhow::Result { - log::trace!("parsing spirv-std source and version from def: '{spirv_std_def}'"); - let parts: Vec = spirv_std_def.split_whitespace().map(String::from).collect(); - let version = parts - .get(1) - .context("Couldn't find `spirv_std` version in shader crate")? - .to_owned(); - let mut source = Self::CratesIO(version.clone()); - - if parts.len() > 2 { - let mut source_string = parts - .get(2) - .context("Couldn't get Uri from dependency string")? + fn parse_spirv_std_source_and_version(spirv_std_package: &Package) -> anyhow::Result { + log::trace!("parsing spirv-std source and version from package: '{spirv_std_package:?}'"); + + let result = if let Some(source) = &spirv_std_package.source { + let is_git = source.repr.starts_with("git+"); + let is_crates_io = source.is_crates_io(); + + match (is_git, is_crates_io) { + (true, true) => anyhow::bail!("parsed both git and crates.io?"), + (true, false) => { + let parse_git = || { + let link = &source.repr.get(4..)?; + let sharp_index = link.find('#')?; + let question_mark_index = link.find('?')?; + let url = link.get(..question_mark_index)?.to_owned(); + let rev = link.get(sharp_index + 1..)?.to_owned(); + Some(Self::Git { url, rev }) + }; + parse_git() + .with_context(|| format!("Failed to parse git url {}", &source.repr))? + } + (false, true) => Self::CratesIO(spirv_std_package.version.clone()), + (false, false) => { + anyhow::bail!("Metadata of spirv-std package uses unknown url format!") + } + } + } else { + let rust_gpu_repo_root = spirv_std_package + .manifest_path // rust-gpu/crates/spirv-std/Cargo.toml + .parent() // rust-gpu/crates/spirv-std + .and_then(Utf8Path::parent) // rust-gpu/crates + .and_then(Utf8Path::parent) // rust-gpu + .context("selecting rust-gpu workspace root dir in local path")? .to_owned(); - source_string = source_string.replace(['(', ')'], ""); - - // Unfortunately Uri ignores the fragment/hash portion of the Uri. - // - // There's been a ticket open for years: - // - // - // So here we'll parse the fragment out of the source string by hand - let uri = source_string.parse::()?; - let maybe_hash = if source_string.contains('#') { - let mut splits = source_string.split('#'); - splits.next_back().map(std::borrow::ToOwned::to_owned) - } else { - None - }; - if uri.scheme().is_some() { - source = Self::parse_git_source(version, &uri, maybe_hash)?; - } else { - source = Self::Path((source_string, version)); + if !rust_gpu_repo_root.is_dir() { + anyhow::bail!("path {rust_gpu_repo_root} is not a directory"); } - } + let version = spirv_std_package.version.clone(); + Self::Path { + rust_gpu_repo_root, + version, + } + }; - log::debug!("Parsed `rust-gpu` source and version: {source:?}"); + log::debug!("Parsed `rust-gpu` source and version: {result:?}"); - Ok(source) + Ok(result) } +} - /// Parse a Git source like: `https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c` - fn parse_git_source( - version: String, - uri: &http::Uri, - fragment: Option, - ) -> anyhow::Result { - log::trace!( - "parsing git source from version: '{version}' and uri: '{uri}' and fragment: {}", - fragment.as_deref().unwrap_or("?") - ); - let repo = format!( - "{}://{}{}", - uri.scheme().context("Couldn't parse scheme from Uri")?, - uri.host().context("Couldn't parse host from Uri")?, - uri.path() - ); - - let rev = Self::parse_git_revision(uri.query(), fragment, version); +/// Make sure shader crate path is absolute and canonical. +fn crate_path_canonical(shader_crate_path: &Path) -> anyhow::Result { + let mut canonical_path = shader_crate_path.to_path_buf(); - Ok(Self::Git { url: repo, rev }) + if !canonical_path.is_absolute() { + let cwd = std::env::current_dir().context("no cwd")?; + canonical_path = cwd.join(canonical_path); } + canonical_path = canonical_path + .canonicalize() + .context("could not get absolute path to shader crate")?; - /// Decide the Git revision to use. - fn parse_git_revision( - maybe_query: Option<&str>, - maybe_fragment: Option, - version: String, - ) -> String { - let marker = "rev="; - let maybe_sane_query = maybe_query.and_then(|query| { - // TODO: This might seem a little crude, but it saves adding a whole query parsing dependency. - let sanity_check = query.contains(marker) && query.split('=').count() == 2; - sanity_check.then_some(query) - }); - - if let Some(query) = maybe_sane_query { - return query.replace(marker, ""); - } - - if let Some(fragment) = maybe_fragment { - return fragment; - } - - version + if !canonical_path.is_dir() { + log::error!("{shader_crate_path:?} is not a directory, aborting"); + anyhow::bail!("{shader_crate_path:?} is not a directory"); } + Ok(canonical_path) +} - /// `git clone` the `rust-gpu` repo. We use it to get the required Rust toolchain to compile - /// the shader. - fn ensure_repo_is_installed(&self) -> anyhow::Result<()> { - if self.to_dirname()?.exists() { - log::debug!( - "Not cloning `rust-gpu` repo ({}) as it already exists at {}", - self.to_repo(), - self.to_dirname()?.to_string_lossy().as_ref(), - ); - return Ok(()); - } - - log::debug!( - "Cloning `rust-gpu` repo {} to {}", - self.to_repo(), - self.to_dirname()?.to_string_lossy().as_ref(), - ); - - crate::user_output!("Cloning `rust-gpu` repo...\n"); - - // TODO: do something else when testing, to help speed things up. - let output_clone = std::process::Command::new("git") - .args([ - "clone", - self.to_repo().as_ref(), - self.to_dirname()?.to_string_lossy().as_ref(), - ]) - .output()?; - - anyhow::ensure!( - output_clone.status.success(), - "couldn't clone `rust-gpu` {} to {}\n{}", - self.to_repo(), - self.to_dirname()?.to_string_lossy(), - String::from_utf8_lossy(&output_clone.stderr) - ); +/// get the Package metadata from some crate +pub fn get_package_from_crate(crate_path: &Path, crate_name: &str) -> anyhow::Result { + let canonical_crate_path = crate_path_canonical(crate_path)?; + + log::debug!( + "Running `cargo metadata` on `{}` to query for package `{crate_name}`", + canonical_crate_path.display() + ); + let metadata = MetadataCommand::new() + .current_dir(&canonical_crate_path) + .exec()?; + + let Some(package) = metadata + .packages + .into_iter() + .find(|package| package.name.eq(crate_name)) + else { + anyhow::bail!("`{crate_name}` not found in `Cargo.toml` at `{canonical_crate_path:?}`"); + }; + log::trace!(" found `{}` version `{}`", package.name, package.version); + Ok(package) +} - Ok(()) - } +/// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. +pub fn get_channel_from_rustc_codegen_spirv_build_script( + rustc_codegen_spirv_package: &Package, +) -> anyhow::Result { + let path = rustc_codegen_spirv_package + .manifest_path + .parent() + .context("finding `rustc_codegen_spirv` crate root")?; + let build_rs = path.join("build.rs"); + + log::debug!("Parsing `build.rs` at {build_rs:?} for the used toolchain"); + let contents = fs::read_to_string(&build_rs)?; + let channel_start = "channel = \""; + let channel_line = contents + .lines() + .find_map(|line| line.strip_prefix(channel_start)) + .context(format!("Can't find `{channel_start}` line in {build_rs:?}"))?; + let channel = channel_line + .get(..channel_line.find('"').context("ending \" missing")?) + .context("can't slice version")?; + Ok(channel.to_owned()) } #[cfg(test)] @@ -372,39 +247,12 @@ mod test { #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { let shader_template_path = crate::test::shader_crate_template_path(); - let source = SpirvSource::get_spirv_std_dep_definition(&shader_template_path).unwrap(); + let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); assert_eq!( source, SpirvSource::Git { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "82a0f69".to_owned() - } - ); - } - - #[test_log::test] - fn parsing_spirv_std_dep_for_git_source() { - let definition = - "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69) (*)"; - let source = SpirvSource::parse_spirv_std_source_and_version(definition).unwrap(); - assert_eq!( - source, - SpirvSource::Git { - url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "82a0f69".to_owned() - } - ); - } - - #[test_log::test] - fn parsing_spirv_std_dep_for_git_source_hash() { - let definition = "spirv-std v9.9.9 (https://github.com/Rust-GPU/rust-gpu#82a0f69) (*)"; - let source = SpirvSource::parse_spirv_std_source_and_version(definition).unwrap(); - assert_eq!( - source, - SpirvSource::Git { - url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "82a0f69".to_owned() + rev: "82a0f69008414f51d59184763146caa6850ac588".to_owned() } ); } @@ -414,4 +262,18 @@ mod test { let path = std::path::PathBuf::from("./"); assert!(path.is_relative()); } + + #[test_log::test] + fn cached_checkout_dir_sanity() { + let shader_template_path = crate::test::shader_crate_template_path(); + let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); + let dir = source.install_dir().unwrap(); + let name = dir + .file_name() + .unwrap() + .to_str() + .map(std::string::ToString::to_string) + .unwrap(); + assert_eq!("https___github_com_Rust-GPU_rust-gpu+82a0f690", &name); + } } diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json deleted file mode 100644 index 9fa58d8558..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.0.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "opengl4.0", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-opengl4.0", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json deleted file mode 100644 index 13d687233c..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.1.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "opengl4.1", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-opengl4.1", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json deleted file mode 100644 index d1312620a2..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.2.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "opengl4.2", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-opengl4.2", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json deleted file mode 100644 index 7a52159432..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.3.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "opengl4.3", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-opengl4.3", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json b/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json deleted file mode 100644 index ba509ed6dd..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-opengl4.5.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "opengl4.5", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-opengl4.5", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json deleted file mode 100644 index d9e2166f5c..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.0.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.0", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.0", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json deleted file mode 100644 index 8fc1bcaf38..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.1.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.1", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.1", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json deleted file mode 100644 index 0037561bee..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.2.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.2", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.2", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json deleted file mode 100644 index 645848caf5..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.3.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.3", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.3", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json deleted file mode 100644 index 43ab248a65..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.4.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.4", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.4", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json b/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json deleted file mode 100644 index e339e11535..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-spv1.5.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "spv1.5", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-spv1.5", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json deleted file mode 100644 index a15b45b6c6..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.0.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "vulkan1.0", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-vulkan1.0", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json deleted file mode 100644 index b71dd7b2fd..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "vulkan1.1", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-vulkan1.1", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json deleted file mode 100644 index 82634e6b85..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.1spv1.4.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "vulkan1.1spv1.4", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-vulkan1.1spv1.4", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json b/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json deleted file mode 100644 index 7952baed9d..0000000000 --- a/crates/cargo-gpu/target-specs/spirv-unknown-vulkan1.2.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "allows-weak-linkage": false, - "arch": "spirv", - "crt-objects-fallback": "false", - "crt-static-allows-dylibs": true, - "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", - "dll-prefix": "", - "dll-suffix": ".spv.json", - "dynamic-linking": true, - "emit-debug-gdb-scripts": false, - "env": "vulkan1.2", - "linker-flavor": "unix", - "linker-is-gnu": false, - "llvm-target": "spirv-unknown-vulkan1.2", - "main-needs-argc-argv": false, - "metadata": { - "description": null, - "host_tools": null, - "std": null, - "tier": null - }, - "os": "unknown", - "panic-strategy": "abort", - "simd-types-indirect": false, - "target-pointer-width": "32" -} diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index fb72e0ee08..faae1f24b7 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -24,24 +24,24 @@ glam = { version = "0.29", features = ["std"] } # TODO: Should it default to the root of the shader crate? output-dir = "./" # Set shader crate's cargo default-features -no_default_features = false +default_features = true # Set shader crate's cargo features. features = [] # The compile target. # TODO: `cargo gpu show targets` for all available options. -shader-target = "spirv-unknown-vulkan1.2" +target = "spirv-unknown-vulkan1.2" # Treat warnings as errors during compilation. deny-warnings = false # Compile shaders in debug mode. -debug = false +release = true # Enables the provided SPIR-V capabilities. # See: `impl core::str::FromStr for spirv_builder::Capability`. # TODO: `cargo gpu show capabilities` for all available options. -capability = [] +capabilities = [] # Enables the provided SPIR-V extensions. # See https://github.com/KhronosGroup/SPIRV-Registry for all extensions # TODO: `cargo gpu show extensions` for all available options. -extension = [] +extensions = [] # Compile one .spv file per shader entry point. multimodule = false # Set the level of metadata included in the SPIR-V binary. @@ -84,14 +84,10 @@ manifest-file = "manifest.json" # as a Git commit hash or a Git tag, therefore anything that `git checkout` can resolve. # spirv_builder_version = "" -# Rust toolchain channel to use to build `spirv-builder`. -# Eg: "nightly-2024-04-24" -# rust_toolchain = "" - # Whether to assume "yes" to the "Install Rust toolchain: [y/n]" prompt. auto-install-rust-toolchain = false -# Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. -force-spirv-cli-rebuild = false +# Force `rustc_codegen_spirv` to be rebuilt. +rebuild_codegen = false # There is a tricky situation where a shader crate that depends on workspace config can have # a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can # prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. diff --git a/crates/spirv-builder-cli/Cargo.lock b/crates/spirv-builder-cli/Cargo.lock deleted file mode 100644 index 1058571e2f..0000000000 --- a/crates/spirv-builder-cli/Cargo.lock +++ /dev/null @@ -1,1260 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" -dependencies = [ - "anstyle", - "once_cell", - "windows-sys 0.59.0", -] - -[[package]] -name = "ar" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" -dependencies = [ - "serde", -] - -[[package]] -name = "bytemuck" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cc" -version = "1.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "4.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "clap_lex" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" - -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.96", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "elsa" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" -dependencies = [ - "indexmap 2.7.0", - "stable_deref_trait", -] - -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", -] - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "internal-iterator" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969ee3fc68ec2e88eb21434ce4d9b7e1600d1ce92ff974560a6c4a304f5124b9" - -[[package]] -name = "is-terminal" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "notify" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" -dependencies = [ - "bitflags 1.3.2", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "mio", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "proc-macro2" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "raw-string" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" - -[[package]] -name = "redox_syscall" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rspirv" -version = "0.11.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba" -dependencies = [ - "fxhash", - "num-traits", - "spirv 0.2.0+1.5.4", -] - -[[package]] -name = "rspirv" -version = "0.12.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" -dependencies = [ - "rustc-hash", - "spirv 0.3.0+sdk-1.3.268.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_codegen_spirv" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" -dependencies = [ - "ar", - "either", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "itertools", - "lazy_static", - "libc", - "num-traits", - "once_cell", - "regex", - "rspirv 0.11.0+1.5.4", - "rustc-demangle", - "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", - "sanitize-filename", - "serde", - "serde_json", - "smallvec", - "spirt 0.3.0", - "spirv-tools", - "syn 1.0.109", -] - -[[package]] -name = "rustc_codegen_spirv" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" -dependencies = [ - "ar", - "either", - "hashbrown 0.11.2", - "indexmap 1.9.3", - "itertools", - "lazy_static", - "libc", - "num-traits", - "once_cell", - "regex", - "rspirv 0.12.0+sdk-1.3.268.0", - "rustc-demangle", - "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", - "sanitize-filename", - "smallvec", - "spirt 0.4.0", - "spirv-tools", - "syn 1.0.109", -] - -[[package]] -name = "rustc_codegen_spirv-types" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" -dependencies = [ - "rspirv 0.11.0+1.5.4", - "serde", -] - -[[package]] -name = "rustc_codegen_spirv-types" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" -dependencies = [ - "rspirv 0.12.0+sdk-1.3.268.0", - "serde", - "serde_json", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "sanitize-filename" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "semver" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" - -[[package]] -name = "serde" -version = "1.0.217" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.217" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "serde_json" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -dependencies = [ - "serde", -] - -[[package]] -name = "spirt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e1f7903720ff818d6da824edf2c4082c6e7a029a99317fd10c39dd7c40c7ff" -dependencies = [ - "arrayvec", - "bytemuck", - "derive_more", - "elsa", - "indexmap 1.9.3", - "internal-iterator", - "itertools", - "lazy_static", - "longest-increasing-subsequence", - "rustc-hash", - "serde", - "serde_json", - "smallvec", -] - -[[package]] -name = "spirt" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d5968bd2a36466468aac637b355776f080edfb0c6f769b2b99b9708260c42a" -dependencies = [ - "arrayvec", - "bytemuck", - "derive_more", - "elsa", - "indexmap 2.7.0", - "internal-iterator", - "itertools", - "lazy_static", - "longest-increasing-subsequence", - "rustc-hash", - "serde", - "serde_json", - "smallvec", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags 1.3.2", - "num-traits", - "serde", -] - -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.7.0", - "serde", -] - -[[package]] -name = "spirv-builder" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec#4c633aec182300d9f85460ffd5a6ba7904ff5f74" -dependencies = [ - "memchr", - "notify", - "raw-string", - "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", - "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", - "serde", - "serde_json", -] - -[[package]] -name = "spirv-builder" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82#60dcb82613b0de4bbcf9701a288b4202d486427f" -dependencies = [ - "memchr", - "notify", - "raw-string", - "rustc_codegen_spirv 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", - "rustc_codegen_spirv-types 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", - "serde", - "serde_json", -] - -[[package]] -name = "spirv-builder-cli" -version = "0.1.0" -dependencies = [ - "clap", - "env_home", - "env_logger", - "log", - "serde", - "serde_json", - "spirv 0.2.0+1.5.4", - "spirv 0.3.0+sdk-1.3.268.0", - "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=4c633aec)", - "spirv-builder 0.9.0 (git+https://github.com/Rust-GPU/rust-gpu?rev=60dcb82)", - "toml", -] - -[[package]] -name = "spirv-tools" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb3b0832881834994b7ec82b709ec5491043ceb4bf8101e27da6b5234b24261" -dependencies = [ - "spirv-tools-sys", -] - -[[package]] -name = "spirv-tools-sys" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e68b55a97aa6856e010a6f2477425875a97873e147bb0232160e73c45bdae7" -dependencies = [ - "cc", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" -dependencies = [ - "memchr", -] diff --git a/crates/spirv-builder-cli/Cargo.toml b/crates/spirv-builder-cli/Cargo.toml deleted file mode 100644 index 2cbd135065..0000000000 --- a/crates/spirv-builder-cli/Cargo.toml +++ /dev/null @@ -1,61 +0,0 @@ -[package] -name = "spirv-builder-cli" -version = "0.1.0" -edition = "2021" - -[dependencies] -# `clap = "=4.4.8"` pin is needed to support older Rust toolchains. -# If `clap` gets too old, then it can be split into 2 versions, gated by a feature, like `spirv` is. -# Or more generally we should think about how to deprecate supporting old version of `rust-gpu`. -clap = { version = "=4.4.8", features = ["derive"] } -env_home = "0.1.0" -env_logger = "0.10" -log = "0.4" -serde = "1.0.214" -serde_json = "1.0.132" -toml = "0.8.19" - -[features] -default = ["spirv-builder-0_10"] -# The `spirv-builder` before `cargo gpu` existed. It has an incompatible `SpirvBuilder` interface. -spirv-builder-pre-cli = ["dep:spirv-builder-pre-cli", "dep:spirv_0_2"] -# The first version that introduced `cargo gpu`. It has some extra `.builder()` args that make -# dynamically changing build dependencies easier. -spirv-builder-0_10 = ["dep:spirv-builder-0_10", "dep:spirv_0_3"] -# -rspirv-latest = ["dep:spirv_0_3"] - -[dependencies.spirv_0_2] -package = "spirv" -version = "0.2.0" -features = [ "deserialize", "serialize" ] -optional = true - -[dependencies.spirv_0_3] -package = "spirv" -version = "0.3.0" -features = [ "deserialize", "serialize" ] -optional = true - -# NB: All the `${AUTO-REPLACE*}` tokens in each feature get replaced with the same values. -# This is because only one feature can ever be used at once and it makes it easier to just -# replace each token rather than figure out to what feature each token belongs. - -[dependencies.spirv-builder-pre-cli] -package = "spirv-builder" -features = [ "watch" ] -optional = true -git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} -rev = "4c633aec" # ${AUTO-REPLACE-VERSION} - -[dependencies.spirv-builder-0_10] -package = "spirv-builder" -features = [ "watch" ] -optional = true -git = "https://github.com/Rust-GPU/rust-gpu" # ${AUTO-REPLACE-SOURCE} -rev = "60dcb82" # ${AUTO-REPLACE-VERSION} - -[lints.rust] -# This crate is most often run by end users compiling their shaders so it's not so relevant -# for them to see warnings. -warnings = "allow" diff --git a/crates/spirv-builder-cli/README.md b/crates/spirv-builder-cli/README.md deleted file mode 100644 index ad609e9134..0000000000 --- a/crates/spirv-builder-cli/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# SPIR-V Builder CLI Template - -> [!CAUTION] -> This may look like a typical crate, but it is in fact more like a crate _template_. -> It is intended to be primarily called by `cargo gpu`, which has these files embedded -> into its binary and so can copy and edit them to automatically compile end-user -> shaders. diff --git a/crates/spirv-builder-cli/rust-toolchain.toml b/crates/spirv-builder-cli/rust-toolchain.toml deleted file mode 100644 index 6148ea9e63..0000000000 --- a/crates/spirv-builder-cli/rust-toolchain.toml +++ /dev/null @@ -1,5 +0,0 @@ -# This is just a placeholder for development. In actual usage the toolchain -# is set dynamically. -[toolchain] -channel = "nightly-2024-04-24" -components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/crates/spirv-builder-cli/src/args.rs b/crates/spirv-builder-cli/src/args.rs deleted file mode 100644 index dad50d651d..0000000000 --- a/crates/spirv-builder-cli/src/args.rs +++ /dev/null @@ -1,203 +0,0 @@ -#[cfg(feature = "spirv-builder-pre-cli")] -use spirv_0_2 as spirv; - -#[cfg(any(feature = "spirv-builder-0_10", feature = "rspirv-latest"))] -use spirv_0_3 as spirv; - -use std::str::FromStr as _; - -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct AllArgs { - #[clap(flatten)] - pub build: BuildArgs, - - #[clap(flatten)] - pub install: InstallArgs, -} - -/// Options for the `--spirv-metadata` command -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] -pub enum SpirvMetadata { - /// Don't log any metadata (the default) - None, - /// Only log named variables - NameVariables, - /// Log all metadata - Full, -} - -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct BuildArgs { - /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "./")] - pub output_dir: std::path::PathBuf, - - /// Watch the shader crate directory and automatically recompile on changes. - #[clap(long, short, action)] - pub watch: bool, - - /// Set shader crate's cargo default-features. - #[clap(long)] - pub no_default_features: bool, - - /// Set shader crate's cargo features. - #[clap(long)] - pub features: Vec, - - /// `rust-gpu` compile target. - /// TODO: deprecate completely - #[arg(hide(true), default_value = "spirv-unknown-vulkan1.2")] - pub target: String, - - /// Shader target. - // TODO: how to list the available options? Would be nice to have a command like: - // `cargo gpu show targets` - #[clap(long, default_value = "spirv-unknown-vulkan1.2")] - pub shader_target: String, - - /// Treat warnings as errors during compilation. - #[arg(long, default_value = "false")] - pub deny_warnings: bool, - - /// Compile shaders in debug mode. - #[arg(long, default_value = "false")] - pub debug: bool, - - /// Enables the provided SPIR-V capabilities. - /// See: `cargo gpu show capabilities` - #[arg(long, value_parser=Self::spirv_capability)] - pub capability: Vec, - - /// Enables the provided SPIR-V extensions. - /// See for all extensions - #[arg(long)] - pub extension: Vec, - - /// Compile one .spv file per entry point. - #[arg(long, default_value = "false")] - pub multimodule: bool, - - /// Set the level of metadata included in the SPIR-V binary. - #[arg(long, value_parser=Self::spirv_metadata, default_value = "none")] - pub spirv_metadata: SpirvMetadata, - - /// Allow store from one struct type to a different type with compatible layout and members. - #[arg(long, default_value = "false")] - pub relax_struct_store: bool, - - /// Allow allocating an object of a pointer type and returning a pointer value from a function - /// in logical addressing mode. - #[arg(long, default_value = "false")] - pub relax_logical_pointer: bool, - - /// Enable `VK_KHR_relaxed_block_layout` when checking standard uniform, - /// storage buffer, and push constant layouts. - /// This is the default when targeting Vulkan 1.1 or later. - #[arg(long, default_value = "false")] - pub relax_block_layout: bool, - - /// Enable `VK_KHR_uniform_buffer_standard_layout` when checking standard uniform buffer layouts. - #[arg(long, default_value = "false")] - pub uniform_buffer_standard_layout: bool, - - /// Enable `VK_EXT_scalar_block_layout` when checking standard uniform, storage buffer, and push - /// constant layouts. - /// Scalar layout rules are more permissive than relaxed block layout so in effect this will - /// override the --relax-block-layout option. - #[arg(long, default_value = "false")] - pub scalar_block_layout: bool, - - /// Skip checking standard uniform / storage buffer layout. Overrides any --relax-block-layout - /// or --scalar-block-layout option. - #[arg(long, default_value = "false")] - pub skip_block_layout: bool, - - /// Preserve unused descriptor bindings. Useful for reflection. - #[arg(long, default_value = "false")] - pub preserve_bindings: bool, - - ///Renames the manifest.json file to the given name - #[clap(long, short, default_value = "manifest.json")] - pub manifest_file: String, -} - -impl BuildArgs { - /// Clap value parser for `SpirvMetadata`. - fn spirv_metadata(metadata: &str) -> Result { - match metadata { - "none" => Ok(SpirvMetadata::None), - "name-variables" => Ok(SpirvMetadata::NameVariables), - "full" => Ok(SpirvMetadata::Full), - _ => Err(clap::Error::new(clap::error::ErrorKind::InvalidValue)), - } - } - - /// Clap value parser for `Capability`. - fn spirv_capability(capability: &str) -> Result { - spirv::Capability::from_str(capability).map_or_else( - |()| Err(clap::Error::new(clap::error::ErrorKind::InvalidValue)), - Ok, - ) - } -} - -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct InstallArgs { - #[clap(long, hide(true), default_value = "INTERNALLY_SET")] - pub dylib_path: std::path::PathBuf, - - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - pub shader_crate: std::path::PathBuf, - - /// Source of `spirv-builder` dependency - /// Eg: "https://github.com/Rust-GPU/rust-gpu" - #[clap(long)] - pub spirv_builder_source: Option, - - /// 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)] - pub spirv_builder_version: Option, - - /// Rust toolchain channel to use to build `spirv-builder`. - /// - /// This must be compatible with the `spirv_builder` argument as defined in the `rust-gpu` repo. - #[clap(long)] - pub rust_toolchain: Option, - - /// Force `spirv-builder-cli` and `rustc_codegen_spirv` to be rebuilt. - #[clap(long)] - pub force_spirv_cli_rebuild: bool, - - /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. - #[clap(long, action)] - pub auto_install_rust_toolchain: bool, - - /// There is a tricky situation where a shader crate that depends on workspace config can have - /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can - /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. - /// - /// The ideal way to resolve this would be to match the shader crate's toolchain with the - /// workspace's toolchain. However, that is not always possible. Another solution is to - /// `exclude = [...]` the problematic shader crate from the workspace. This also may not be a - /// suitable solution if there are a number of shader crates all sharing similar config and - /// you don't want to have to copy/paste and maintain that config across all the shaders. - /// - /// So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling - /// this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also - /// only overwrite versions for the duration of a build. It will attempt to return the versions - /// to their original values once the build is finished. However, of course, unexpected errors - /// can occur and the overwritten values can remain. Hence why this behaviour is not enabled by - /// default. - /// - /// This hack is possible because the change from v3 to v4 only involves a minor change to the - /// 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)] - pub force_overwrite_lockfiles_v4_to_v3: bool, -} diff --git a/crates/spirv-builder-cli/src/lib.rs b/crates/spirv-builder-cli/src/lib.rs deleted file mode 100644 index 70d83e4b9b..0000000000 --- a/crates/spirv-builder-cli/src/lib.rs +++ /dev/null @@ -1,52 +0,0 @@ -pub mod args; - -#[cfg(feature = "spirv-builder-pre-cli")] -pub use spirv_0_2 as spirv; - -#[cfg(any(feature = "spirv-builder-0_10", feature = "rspirv-latest"))] -pub use spirv_0_3 as spirv; - -/// Shader source and entry point that can be used to create shader linkage. -#[derive(serde::Serialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Linkage { - pub source_path: String, - pub entry_point: String, - pub wgsl_entry_point: String, -} - -impl Linkage { - pub fn new(entry_point: impl AsRef, source_path: impl AsRef) -> Self { - Self { - // Force a forward slash convention here so it works on all OSs - source_path: source_path - .as_ref() - .components() - .map(|c| c.as_os_str().to_string_lossy()) - .collect::>() - .join("/"), - wgsl_entry_point: entry_point.as_ref().replace("::", ""), - entry_point: entry_point.as_ref().to_string(), - } - } - - pub fn fn_name(&self) -> &str { - self.entry_point.split("::").last().unwrap() - } -} - -/// A built shader entry-point, used in `spirv-builder-cli` to generate -/// a `build-manifest.json` used by `cargo-gpu`. -#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct ShaderModule { - pub entry: String, - pub path: std::path::PathBuf, -} - -impl ShaderModule { - pub fn new(entry: impl AsRef, path: impl AsRef) -> Self { - Self { - entry: entry.as_ref().into(), - path: path.as_ref().into(), - } - } -} diff --git a/crates/spirv-builder-cli/src/main.rs b/crates/spirv-builder-cli/src/main.rs deleted file mode 100644 index 2a179380a7..0000000000 --- a/crates/spirv-builder-cli/src/main.rs +++ /dev/null @@ -1,155 +0,0 @@ -/// NB: For developing this file it will probably help to temporarily move the `"crates/spirv-builder-cli"` -/// line from the `exclude` to `members` section of the root `Cargo.toml` file. This will allow -/// `rust-analyzer` to run on the file. We can't permanently keep it there because each of the -/// `spirv-builder-*` features depends on a different Rust toolchain which `cargo check/clippy` -/// can't build all at once. -pub mod args; - -#[cfg(feature = "spirv-builder-pre-cli")] -use spirv_builder_pre_cli as spirv_builder; - -#[cfg(feature = "spirv-builder-0_10")] -use spirv_builder_0_10 as spirv_builder; - -use spirv_builder::{CompileResult, MetadataPrintout, ModuleResult, SpirvBuilder}; -use spirv_builder_cli::ShaderModule; - -const RUSTC_NIGHTLY_CHANNEL: &str = "${CHANNEL}"; - -fn set_rustup_toolchain() { - log::trace!( - "setting RUSTUP_TOOLCHAIN = '{}'", - RUSTC_NIGHTLY_CHANNEL.trim_matches('"') - ); - std::env::set_var("RUSTUP_TOOLCHAIN", RUSTC_NIGHTLY_CHANNEL.trim_matches('"')); -} - -/// Get the OS-dependent ENV variable name for the list of paths pointing to .so/.dll files -const fn dylib_path_envvar() -> &'static str { - if cfg!(windows) { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_FALLBACK_LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } -} - -fn set_codegen_spirv_location(dylib_path: std::path::PathBuf) { - let env_var = dylib_path_envvar(); - let existing_paths_str = std::env::var(env_var).unwrap(); - let mut dylib_paths = std::env::split_paths(&existing_paths_str).collect::>(); - - let dylib_path = dylib_path.parent().unwrap().to_path_buf(); - dylib_paths.insert(0, dylib_path); - - let path = std::env::join_paths(dylib_paths).unwrap().into_string().unwrap(); - - log::debug!("Setting OS-dependent DLL ENV path ({env_var}) to: {path}"); - std::env::set_var(env_var, path); -} - -fn handle_compile_result(result: &CompileResult, args: &args::AllArgs) { - log::debug!("found entry points: {:#?}", result.entry_points); - - let dir = &args.build.output_dir; - let mut shaders = vec![]; - match &result.module { - ModuleResult::MultiModule(modules) => { - assert!(!modules.is_empty(), "No shader modules to compile"); - for (entry, filepath) in modules.clone().into_iter() { - log::debug!("compiled {entry} {}", filepath.display()); - shaders.push(ShaderModule::new(entry, filepath)); - } - } - ModuleResult::SingleModule(filepath) => { - for entry in result.entry_points.clone() { - shaders.push(ShaderModule::new(entry, filepath.clone())); - } - } - } - - use std::io::Write; - let mut file = std::fs::File::create(dir.join("spirv-manifest.json")).unwrap(); - file.write_all(&serde_json::to_vec(&shaders).unwrap()) - .unwrap(); -} - -pub fn main() { - env_logger::builder().init(); - - set_rustup_toolchain(); - - let args = std::env::args().collect::>(); - log::debug!( - "running spirv-builder-cli from '{}'", - std::env::current_dir().unwrap().display() - ); - log::debug!("with args: {args:#?}"); - let args: args::AllArgs = serde_json::from_str(&args[1]).unwrap(); - let args_for_result = args.clone(); - - let spirv_metadata = match args.build.spirv_metadata { - args::SpirvMetadata::None => spirv_builder::SpirvMetadata::None, - args::SpirvMetadata::NameVariables => spirv_builder::SpirvMetadata::NameVariables, - args::SpirvMetadata::Full => spirv_builder::SpirvMetadata::Full, - }; - - let mut builder = SpirvBuilder::new(args.install.shader_crate, &args.build.target) - .deny_warnings(args.build.deny_warnings) - .release(!args.build.debug) - .multimodule(args.build.multimodule) - .spirv_metadata(spirv_metadata) - .relax_struct_store(args.build.relax_struct_store) - .relax_logical_pointer(args.build.relax_logical_pointer) - .relax_block_layout(args.build.relax_block_layout) - .uniform_buffer_standard_layout(args.build.uniform_buffer_standard_layout) - .scalar_block_layout(args.build.scalar_block_layout) - .skip_block_layout(args.build.skip_block_layout) - .preserve_bindings(args.build.preserve_bindings) - .print_metadata(spirv_builder::MetadataPrintout::None); - - for capability in &args.build.capability { - builder = builder.capability(*capability); - } - - for extension in &args.build.extension { - builder = builder.extension(extension); - } - - #[cfg(feature = "spirv-builder-pre-cli")] - { - log::debug!("using spirv-builder-pre-cli"); - set_codegen_spirv_location(args.install.dylib_path); - } - - #[cfg(feature = "spirv-builder-0_10")] - { - log::debug!("using spirv-builder-0_10"); - builder = builder - .rustc_codegen_spirv_location(args.install.dylib_path) - .target_spec(args.build.shader_target); - - if args.build.no_default_features { - log::info!("setting cargo --no-default-features"); - builder = builder.shader_crate_default_features(false); - } - if !args.build.features.is_empty() { - log::info!("setting --features {:?}", args.build.features); - builder = builder.shader_crate_features(args.build.features); - } - } - - log::debug!("Calling `rust-gpu`'s `spirv-builder` library"); - - if args.build.watch { - println!("🦀 Watching and recompiling shader on changes..."); - builder.watch(move |compile_result| { - handle_compile_result(&compile_result, &args_for_result); - }); - std::thread::park(); - } else { - let result = builder.build().unwrap(); - handle_compile_result(&result, &args_for_result); - } -} diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 3f4d09056a..d767a2c8cd 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -151,18 +151,7 @@ fn main() { log::info!("installing cargo gpu"); cmd(["cargo", "install", "--path", "crates/cargo-gpu"]).unwrap(); - log::info!("installing cargo gpu artifacts"); - cmd([ - "cargo", - "gpu", - "install", - "--shader-crate", - SHADER_CRATE_PATH, - "--auto-install-rust-toolchain", - "--force-overwrite-lockfiles-v4-to-v3", - ]) - .unwrap(); - + log::info!("setup project"); let dir = tempdir::TempDir::new("test-shader-output").unwrap(); let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); overwriter.replace_output_dir(dir.path()).unwrap(); @@ -175,6 +164,7 @@ fn main() { } } + log::info!("building with auto-install"); cmd([ "cargo", "gpu", @@ -182,7 +172,7 @@ fn main() { "--shader-crate", SHADER_CRATE_PATH, "--auto-install-rust-toolchain", - "--force-spirv-cli-rebuild", + "--rebuild-codegen", "--force-overwrite-lockfiles-v4-to-v3", ]) .unwrap(); From 8087e225e8bcd6688d24be36f7debe136cb29983 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 2 Jun 2025 16:39:36 +0200 Subject: [PATCH 089/162] Updating target json support (#75) * main new clippy fixes * remove internal `InstallArgs::dylib_path` * remove mod args, flatten InstallArgs -> Install and BuildArgs -> Build * add InstalledBackend struct * rename `checkout` to `install_dir` * allow searching multiple packages from one `cargo metadata` query * remove non_exhaustive attribs * add `SpirvSource.is_path()` shortcut * create target-specs folder per installation, pulled from `rustc_codegen_spirv_target_specs`, with legacy fallback * appease clippy --- Cargo.lock | 11 +- Cargo.toml | 5 +- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/args.rs | 106 -------- crates/cargo-gpu/src/build.rs | 102 +++++--- crates/cargo-gpu/src/config.rs | 75 +----- crates/cargo-gpu/src/install.rs | 269 ++++++++++++++++---- crates/cargo-gpu/src/legacy_target_specs.rs | 26 ++ crates/cargo-gpu/src/main.rs | 21 +- crates/cargo-gpu/src/spirv_source.rs | 83 +++--- crates/shader-crate-template/Cargo.lock | 9 +- crates/shader-crate-template/Cargo.toml | 2 +- 12 files changed, 384 insertions(+), 326 deletions(-) delete mode 100644 crates/cargo-gpu/src/args.rs create mode 100644 crates/cargo-gpu/src/legacy_target_specs.rs diff --git a/Cargo.lock b/Cargo.lock index 992488f23e..171421693d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,6 +109,7 @@ dependencies = [ "env_logger 0.10.2", "log", "relative-path", + "rustc_codegen_spirv-target-specs", "semver", "serde", "serde_json", @@ -744,10 +745,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_codegen_spirv-target-specs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" + [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4#6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4" +source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "rspirv", "serde", @@ -897,7 +904,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4#6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4" +source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "clap", "memchr", diff --git a/Cargo.toml b/Cargo.toml index c266e87598..036c97127e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "6d7c1cd6c0920500a3fa8c01c23e7b74302c15c4", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1", default-features = false } anyhow = "1.0.94" clap = { version = "4.5.37", features = ["derive"] } crossterm = "0.28.1" @@ -29,6 +29,9 @@ test-log = "0.2.16" cargo_metadata = "0.19.2" semver = "1.0.26" +# This crate MUST NEVER be upgraded, we need this particular "first" version to support old rust-gpu builds +legacy_target_specs = { package = "rustc_codegen_spirv-target-specs", version = "0.9.0", features = ["include_str"] } + [workspace.lints.rust] missing_docs = "warn" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 49ea8158de..9152876aed 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -14,6 +14,7 @@ default-run = "cargo-gpu" cargo_metadata.workspace = true anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } +legacy_target_specs.workspace = true clap.workspace = true directories.workspace = true env_logger.workspace = true diff --git a/crates/cargo-gpu/src/args.rs b/crates/cargo-gpu/src/args.rs deleted file mode 100644 index 346d857a27..0000000000 --- a/crates/cargo-gpu/src/args.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! Args for building and installing. - -use spirv_builder::SpirvBuilder; - -/// All args for a build and install -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct AllArgs { - /// build args - #[clap(flatten)] - pub build: BuildArgs, - - /// install args - #[clap(flatten)] - pub install: InstallArgs, -} - -/// Args for just a build -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct BuildArgs { - /// Path to the output directory for the compiled shaders. - #[clap(long, short, default_value = "./")] - pub output_dir: std::path::PathBuf, - - /// Watch the shader crate directory and automatically recompile on changes. - #[clap(long, short, action)] - pub watch: bool, - - /// the flattened [`SpirvBuilder`] - #[clap(flatten)] - #[serde(flatten)] - pub spirv_builder: SpirvBuilder, - - ///Renames the manifest.json file to the given name - #[clap(long, short, default_value = "manifest.json")] - pub manifest_file: String, -} - -/// Args for an install -#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] -#[expect( - clippy::struct_excessive_bools, - reason = "cmdline args have many bools" -)] -pub struct InstallArgs { - /// path to the `rustc_codegen_spirv` dylib - #[clap(long, hide(true), default_value = "INTERNALLY_SET")] - pub dylib_path: std::path::PathBuf, - - /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] - pub shader_crate: std::path::PathBuf, - - #[expect( - clippy::doc_markdown, - reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" - )] - /// Source of `spirv-builder` dependency - /// Eg: "https://github.com/Rust-GPU/rust-gpu" - #[clap(long)] - pub spirv_builder_source: Option, - - /// 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)] - pub spirv_builder_version: Option, - - /// Force `rustc_codegen_spirv` to be rebuilt. - #[clap(long)] - pub rebuild_codegen: bool, - - /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. - #[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)] - pub clear_target: bool, - - /// There is a tricky situation where a shader crate that depends on workspace config can have - /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can - /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. - /// - /// The ideal way to resolve this would be to match the shader crate's toolchain with the - /// workspace's toolchain. However, that is not always possible. Another solution is to - /// `exclude = [...]` the problematic shader crate from the workspace. This also may not be a - /// suitable solution if there are a number of shader crates all sharing similar config and - /// you don't want to have to copy/paste and maintain that config across all the shaders. - /// - /// So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling - /// this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also - /// only overwrite versions for the duration of a build. It will attempt to return the versions - /// to their original values once the build is finished. However, of course, unexpected errors - /// can occur and the overwritten values can remain. Hence why this behaviour is not enabled by - /// default. - /// - /// This hack is possible because the change from v3 to v4 only involves a minor change to the - /// way source URLs are encoded. See these PRs for more details: - /// * - /// * - #[clap(long, action, verbatim_doc_comment)] - pub force_overwrite_lockfiles_v4_to_v3: bool, -} diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index b77e5a2eef..1bb50788a8 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -2,13 +2,46 @@ #![allow(clippy::unwrap_used, reason = "this is basically a test")] //! `cargo gpu build`, analogous to `cargo build` -use crate::args::BuildArgs; +use crate::install::Install; use crate::linkage::Linkage; use crate::lockfile::LockfileMismatchHandler; -use crate::{install::Install, target_spec_dir}; use anyhow::Context as _; -use spirv_builder::{CompileResult, ModuleResult}; +use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder}; use std::io::Write as _; +use std::path::PathBuf; + +/// Args for just a build +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct BuildArgs { + /// Path to the output directory for the compiled shaders. + #[clap(long, short, default_value = "./")] + pub output_dir: PathBuf, + + /// Watch the shader crate directory and automatically recompile on changes. + #[clap(long, short, action)] + pub watch: bool, + + /// the flattened [`SpirvBuilder`] + #[clap(flatten)] + #[serde(flatten)] + pub spirv_builder: SpirvBuilder, + + ///Renames the manifest.json file to the given name + #[clap(long, short, default_value = "manifest.json")] + pub manifest_file: String, +} + +impl Default for BuildArgs { + #[inline] + fn default() -> Self { + Self { + output_dir: PathBuf::from("./"), + watch: false, + spirv_builder: SpirvBuilder::default(), + manifest_file: String::from("manifest.json"), + } + } +} /// `cargo build` subcommands #[derive(Clone, clap::Parser, Debug, serde::Deserialize, serde::Serialize)] @@ -19,54 +52,46 @@ pub struct Build { /// CLI args for configuring the build of the shader #[clap(flatten)] - pub build_args: BuildArgs, + pub build: BuildArgs, } impl Build { /// Entrypoint pub fn run(&mut self) -> anyhow::Result<()> { - let (rustc_codegen_spirv_location, toolchain_channel) = self.install.run()?; + let installed_backend = self.install.run()?; let _lockfile_mismatch_handler = LockfileMismatchHandler::new( - &self.install.spirv_install.shader_crate, - &toolchain_channel, - self.install - .spirv_install - .force_overwrite_lockfiles_v4_to_v3, + &self.install.shader_crate, + &installed_backend.toolchain_channel, + self.install.force_overwrite_lockfiles_v4_to_v3, )?; - let builder = &mut self.build_args.spirv_builder; - builder.rustc_codegen_spirv_location = Some(rustc_codegen_spirv_location); - builder.toolchain_overwrite = Some(toolchain_channel); - builder.path_to_crate = Some(self.install.spirv_install.shader_crate.clone()); - builder.path_to_target_spec = Some(target_spec_dir()?.join(format!( - "{}.json", - builder.target.as_ref().context("expect target to be set")? - ))); + let builder = &mut self.build.spirv_builder; + builder.path_to_crate = Some(self.install.shader_crate.clone()); + installed_backend.configure_spirv_builder(builder)?; // Ensure the shader output dir exists log::debug!( "ensuring output-dir '{}' exists", - self.build_args.output_dir.display() + self.build.output_dir.display() ); - std::fs::create_dir_all(&self.build_args.output_dir)?; - let canonicalized = self.build_args.output_dir.canonicalize()?; - log::debug!("canonicalized output dir: {canonicalized:?}"); - self.build_args.output_dir = canonicalized; + std::fs::create_dir_all(&self.build.output_dir)?; + let canonicalized = self.build.output_dir.canonicalize()?; + log::debug!("canonicalized output dir: {}", canonicalized.display()); + self.build.output_dir = canonicalized; // Ensure the shader crate exists - self.install.spirv_install.shader_crate = - self.install.spirv_install.shader_crate.canonicalize()?; + self.install.shader_crate = self.install.shader_crate.canonicalize()?; anyhow::ensure!( - self.install.spirv_install.shader_crate.exists(), + self.install.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", - self.install.spirv_install.shader_crate.display(), + self.install.shader_crate.display(), std::env::current_dir()?.display() ); - if self.build_args.watch { + if self.build.watch { let this = self.clone(); - self.build_args + self.build .spirv_builder .watch(move |result, accept| { let result1 = this.parse_compilation_result(&result); @@ -79,9 +104,9 @@ impl Build { } else { crate::user_output!( "Compiling shaders at {}...\n", - self.install.spirv_install.shader_crate.display() + self.install.shader_crate.display() ); - let result = self.build_args.spirv_builder.build()?; + let result = self.build.spirv_builder.build()?; self.parse_compilation_result(&result)?; } Ok(()) @@ -104,7 +129,7 @@ impl Build { .into_iter() .map(|(entry, filepath)| -> anyhow::Result { use relative_path::PathExt as _; - let path = self.build_args.output_dir.join( + let path = self.build.output_dir.join( filepath .file_name() .context("Couldn't parse file name from shader module path")?, @@ -114,10 +139,10 @@ impl Build { log::debug!( "linkage of {} relative to {}", path.display(), - self.install.spirv_install.shader_crate.display() + self.install.shader_crate.display() ); let spv_path = path - .relative_to(&self.install.spirv_install.shader_crate) + .relative_to(&self.install.shader_crate) .map_or(path, |path_relative_to_shader_crate| { path_relative_to_shader_crate.to_path("") }); @@ -128,10 +153,7 @@ impl Build { linkage.sort(); // Write the shader manifest json file - let manifest_path = self - .build_args - .output_dir - .join(&self.build_args.manifest_file); + let manifest_path = self.build.output_dir.join(&self.build.manifest_file); let json = serde_json::to_string_pretty(&linkage)?; let mut file = std::fs::File::create(&manifest_path).with_context(|| { format!( @@ -176,8 +198,8 @@ mod test { command: Command::Build(build), } = Cli::parse_from(args) { - assert_eq!(shader_crate_path, build.install.spirv_install.shader_crate); - assert_eq!(output_dir, build.build_args.output_dir); + assert_eq!(shader_crate_path, build.install.shader_crate); + assert_eq!(output_dir, build.build.output_dir); // TODO: // For some reason running a full build (`build.run()`) inside tests fails on Windows. diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index ad8640201f..f1a67fa9cb 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -14,28 +14,9 @@ impl Config { /// Convert CLI args to their serde JSON representation. fn cli_args_to_json(env_args: Vec) -> anyhow::Result { - let mut cli_args_json = serde_json::to_value(crate::build::Build::parse_from(env_args))?; - - // Move `/install/spirv_install` to `/install` - let spirv_install = cli_args_json - .pointer("/install/spirv_install") - .context("`/install/spirv_install` not found in config")? - .clone(); - *cli_args_json - .get_mut("install") - .context("`/install` not found in config")? = spirv_install; - - let build = cli_args_json - .pointer("/build_args") - .context("`/build_args` not found in config")? - .clone(); - - // Move `/build_args` to `/build` - let object = cli_args_json.as_object_mut().context("!")?; - object.remove("build_args"); - object.insert("build".to_owned(), build); - - Ok(cli_args_json) + Ok(serde_json::to_value(crate::build::Build::parse_from( + env_args, + ))?) } /// Config for the `cargo gpu build` and `cargo gpu install` can be set in the shader crate's @@ -47,30 +28,11 @@ impl Config { ) -> anyhow::Result { let mut config = crate::metadata::Metadata::as_json(shader_crate_path)?; - env_args = env_args - .into_iter() - .filter(|arg| !(arg == "build" || arg == "install")) - .collect::>(); + env_args.retain(|arg| !(arg == "build" || arg == "install")); let cli_args_json = Self::cli_args_to_json(env_args)?; - Self::json_merge(&mut config, cli_args_json, None)?; - let build = config - .get("build") - .context("`build` not found in merged configs")? - .clone(); - - let install = config - .get("install") - .context("`install` not found in merged configs")? - .clone(); - - let args = serde_json::from_value::(serde_json::json!({ - "build_args": build, - "install": { - "spirv_install": install - } - }))?; + let args = serde_json::from_value::(config)?; Ok(args) } @@ -140,8 +102,8 @@ mod test { ], ) .unwrap(); - assert!(!args.build_args.spirv_builder.release); - assert!(args.install.spirv_install.auto_install_rust_toolchain); + assert!(!args.build.spirv_builder.release); + assert!(args.install.auto_install_rust_toolchain); } #[test_log::test] @@ -161,8 +123,8 @@ mod test { .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); - assert!(!args.build_args.spirv_builder.release); - assert!(args.install.spirv_install.auto_install_rust_toolchain); + assert!(!args.build.spirv_builder.release); + assert!(args.install.auto_install_rust_toolchain); } fn update_cargo_output_dir() -> std::path::PathBuf { @@ -186,15 +148,9 @@ mod test { let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); if cfg!(target_os = "windows") { - assert_eq!( - args.build_args.output_dir, - std::path::Path::new("C:/the/moon") - ); + assert_eq!(args.build.output_dir, std::path::Path::new("C:/the/moon")); } else { - assert_eq!( - args.build_args.output_dir, - std::path::Path::new("/the/moon") - ); + assert_eq!(args.build.output_dir, std::path::Path::new("/the/moon")); } } @@ -212,10 +168,7 @@ mod test { ], ) .unwrap(); - assert_eq!( - args.build_args.output_dir, - std::path::Path::new("/the/river") - ); + assert_eq!(args.build.output_dir, std::path::Path::new("/the/river")); } #[test_log::test] @@ -234,7 +187,7 @@ mod test { let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert_eq!( - args.build_args.spirv_builder.capabilities, + args.build.spirv_builder.capabilities, vec![ spirv_builder::Capability::AtomicStorage, spirv_builder::Capability::Matrix @@ -256,6 +209,6 @@ mod test { ], ) .unwrap(); - assert_eq!(args.build_args.manifest_file, "mymanifest".to_owned()); + assert_eq!(args.build.manifest_file, "mymanifest".to_owned()); } } diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 0b6f5fd55a..bd08e6d13f 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,29 +1,126 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. -use crate::args::InstallArgs; +use crate::legacy_target_specs::write_legacy_target_specs; use crate::spirv_source::{ - get_channel_from_rustc_codegen_spirv_build_script, get_package_from_crate, + get_channel_from_rustc_codegen_spirv_build_script, query_metadata, FindPackage as _, }; -use crate::{cache_dir, spirv_source::SpirvSource, target_spec_dir}; +use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; -use log::trace; -use spirv_builder::TARGET_SPECS; -use std::io::Write as _; +use cargo_metadata::Metadata; +use log::{info, trace}; +use spirv_builder::SpirvBuilder; use std::path::{Path, PathBuf}; -/// `cargo gpu install` -#[derive(Clone, clap::Parser, Debug, serde::Deserialize, serde::Serialize)] +/// Args for an install +#[expect( + clippy::struct_excessive_bools, + reason = "cmdline args have many bools" +)] +#[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct Install { - /// CLI arguments for installing the Rust toolchain and components - #[clap(flatten)] - pub spirv_install: InstallArgs, + /// Directory containing the shader crate to compile. + #[clap(long, default_value = "./")] + pub shader_crate: PathBuf, + + #[expect( + clippy::doc_markdown, + reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" + )] + /// Source of `spirv-builder` dependency + /// Eg: "https://github.com/Rust-GPU/rust-gpu" + #[clap(long)] + pub spirv_builder_source: Option, + + /// 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)] + pub spirv_builder_version: Option, + + /// Force `rustc_codegen_spirv` to be rebuilt. + #[clap(long)] + pub rebuild_codegen: bool, + + /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. + #[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)] + pub clear_target: bool, + + /// There is a tricky situation where a shader crate that depends on workspace config can have + /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can + /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. + /// + /// The ideal way to resolve this would be to match the shader crate's toolchain with the + /// workspace's toolchain. However, that is not always possible. Another solution is to + /// `exclude = [...]` the problematic shader crate from the workspace. This also may not be a + /// suitable solution if there are a number of shader crates all sharing similar config and + /// you don't want to have to copy/paste and maintain that config across all the shaders. + /// + /// So a somewhat hacky workaround is to have `cargo gpu` overwrite lockfile versions. Enabling + /// this flag will only come into effect if there are a mix of v3/v4 lockfiles. It will also + /// only overwrite versions for the duration of a build. It will attempt to return the versions + /// to their original values once the build is finished. However, of course, unexpected errors + /// can occur and the overwritten values can remain. Hence why this behaviour is not enabled by + /// default. + /// + /// This hack is possible because the change from v3 to v4 only involves a minor change to the + /// way source URLs are encoded. See these PRs for more details: + /// * + /// * + #[clap(long, action, verbatim_doc_comment)] + pub force_overwrite_lockfiles_v4_to_v3: bool, +} + +/// Represents a functional backend installation, whether it was cached or just installed. +#[derive(Clone, Debug)] +pub struct InstalledBackend { + /// path to the `rustc_codegen_spirv` dylib + pub rustc_codegen_spirv_location: PathBuf, + /// toolchain channel name + pub toolchain_channel: String, + /// directory with target-specs json files + pub target_spec_dir: PathBuf, +} + +impl InstalledBackend { + /// Configures the supplied [`SpirvBuilder`]. `SpirvBuilder.target` must be set and must not change after calling this function. + pub fn configure_spirv_builder(&self, builder: &mut SpirvBuilder) -> anyhow::Result<()> { + builder.rustc_codegen_spirv_location = Some(self.rustc_codegen_spirv_location.clone()); + builder.toolchain_overwrite = Some(self.toolchain_channel.clone()); + builder.path_to_target_spec = Some(self.target_spec_dir.join(format!( + "{}.json", + builder.target.as_ref().context("expect target to be set")? + ))); + Ok(()) + } +} + +impl Default for Install { + #[inline] + fn default() -> Self { + Self { + shader_crate: PathBuf::from("./"), + spirv_builder_source: None, + spirv_builder_version: None, + rebuild_codegen: false, + auto_install_rust_toolchain: false, + clear_target: true, + force_overwrite_lockfiles_v4_to_v3: false, + } + } } impl Install { /// Create the `rustc_codegen_spirv_dummy` crate that depends on `rustc_codegen_spirv` fn write_source_files(source: &SpirvSource, checkout: &Path) -> anyhow::Result<()> { // skip writing a dummy project if we use a local rust-gpu checkout - if matches!(source, SpirvSource::Path { .. }) { + if source.is_path() { return Ok(()); } log::debug!( @@ -47,10 +144,12 @@ impl Install { } SpirvSource::Git { url, rev } => format!("git = \"{url}\"\nrev = \"{rev}\""), SpirvSource::Path { - rust_gpu_repo_root: rust_gpu_path, + rust_gpu_repo_root, version, } => { - let mut new_path = rust_gpu_path.to_owned(); + // this branch is currently unreachable, as we just build `rustc_codegen_spirv` directly, + // since we don't need the `dummy` crate to make cargo download it for us + let mut new_path = rust_gpu_repo_root.to_owned(); new_path.push("crates/spirv-builder"); format!("path = \"{new_path}\"\nversion = \"{version}\"") } @@ -73,25 +172,75 @@ package = "rustc_codegen_spirv" Ok(()) } - /// Add the target spec files to the crate. - fn write_target_spec_files(&self) -> anyhow::Result<()> { - for (filename, contents) in TARGET_SPECS { - let path = target_spec_dir() - .context("creating target spec dir")? - .join(filename); - if !path.is_file() || self.spirv_install.rebuild_codegen { - let mut file = std::fs::File::create(&path) - .with_context(|| format!("creating file at [{}]", path.display()))?; - file.write_all(contents.as_bytes()) - .context("writing to file")?; + /// Copy spec files from one dir to another, assuming no subdirectories + fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> { + info!( + "Copy target specs from {:?} to {:?}", + src.display(), + dst.display() + ); + std::fs::create_dir_all(dst)?; + let dir = std::fs::read_dir(src)?; + for dir_entry in dir { + let file = dir_entry?; + let file_path = file.path(); + if file_path.is_file() { + std::fs::copy(file_path, dst.join(file.file_name()))?; } } Ok(()) } + /// Add the target spec files to the crate. + fn update_spec_files( + &self, + source: &SpirvSource, + install_dir: &Path, + dummy_metadata: &Metadata, + skip_rebuild: bool, + ) -> anyhow::Result { + let mut target_specs_dst = install_dir.join("target-specs"); + if !skip_rebuild { + if let Ok(target_specs) = + dummy_metadata.find_package("rustc_codegen_spirv-target-specs") + { + let target_specs_src = target_specs + .manifest_path + .as_std_path() + .parent() + .and_then(|root| { + let src = root.join("target-specs"); + src.is_dir().then_some(src) + }) + .context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?; + if source.is_path() { + // skip copy + target_specs_dst = target_specs_src; + } else { + // copy over the target-specs + Self::copy_spec_files(&target_specs_src, &target_specs_dst) + .context("copying target-specs json files")?; + } + } else { + // use legacy target specs bundled with cargo gpu + if source.is_path() { + // This is a stupid situation: + // * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`) + // * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout + // -> do what the old cargo gpu did, one global dir for all target specs + // and hope parallel runs don't shred each other + target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout"); + } + write_legacy_target_specs(&target_specs_dst, self.rebuild_codegen)?; + } + } + + Ok(target_specs_dst) + } + /// Install the binary pair and return the `(dylib_path, toolchain_channel)`. #[expect(clippy::too_many_lines, reason = "it's fine")] - pub fn run(&mut self) -> anyhow::Result<(PathBuf, String)> { + pub fn run(&self) -> anyhow::Result { // Ensure the cache dir exists let cache_dir = cache_dir()?; log::info!("cache directory is '{}'", cache_dir.display()); @@ -100,12 +249,11 @@ package = "rustc_codegen_spirv" })?; let source = SpirvSource::new( - &self.spirv_install.shader_crate, - self.spirv_install.spirv_builder_source.as_deref(), - self.spirv_install.spirv_builder_version.as_deref(), + &self.shader_crate, + self.spirv_builder_source.as_deref(), + self.spirv_builder_version.as_deref(), )?; - let source_is_path = matches!(source, SpirvSource::Path { .. }); - let checkout = source.install_dir()?; + let install_dir = source.install_dir()?; let dylib_filename = format!( "{}rustc_codegen_spirv{}", @@ -114,60 +262,70 @@ package = "rustc_codegen_spirv" ); let dest_dylib_path; - if source_is_path { - dest_dylib_path = checkout + if source.is_path() { + dest_dylib_path = install_dir .join("target") .join("release") .join(&dylib_filename); } else { - dest_dylib_path = checkout.join(&dylib_filename); + dest_dylib_path = install_dir.join(&dylib_filename); if dest_dylib_path.is_file() { log::info!( "cargo-gpu artifacts are already installed in '{}'", - checkout.display() + install_dir.display() ); } } - let skip_rebuild = - !source_is_path && dest_dylib_path.is_file() && !self.spirv_install.rebuild_codegen; + // if `source` is a path, always rebuild + let skip_rebuild = !source.is_path() && dest_dylib_path.is_file() && !self.rebuild_codegen; if skip_rebuild { log::info!("...and so we are aborting the install step."); } else { - Self::write_source_files(&source, &checkout).context("writing source files")?; + Self::write_source_files(&source, &install_dir).context("writing source files")?; } // TODO cache toolchain channel in a file? log::debug!("resolving toolchain version to use"); - let rustc_codegen_spirv = get_package_from_crate(&checkout, "rustc_codegen_spirv") - .context("get `rustc_codegen_spirv` metadata")?; + let dummy_metadata = query_metadata(&install_dir) + .context("resolving toolchain version: get `rustc_codegen_spirv_dummy` metadata")?; + let rustc_codegen_spirv = dummy_metadata.find_package("rustc_codegen_spirv").context( + "resolving toolchain version: expected a dependency on `rustc_codegen_spirv`", + )?; let toolchain_channel = - get_channel_from_rustc_codegen_spirv_build_script(&rustc_codegen_spirv) - .context("read toolchain from `rustc_codegen_spirv`'s build.rs")?; + get_channel_from_rustc_codegen_spirv_build_script(rustc_codegen_spirv).context( + "resolving toolchain version: read toolchain from `rustc_codegen_spirv`'s build.rs", + )?; log::info!("selected toolchain channel `{toolchain_channel:?}`"); + log::debug!("update_spec_files"); + let target_spec_dir = self + .update_spec_files(&source, &install_dir, &dummy_metadata, skip_rebuild) + .context("writing target spec files")?; + if !skip_rebuild { log::debug!("ensure_toolchain_and_components_exist"); crate::install_toolchain::ensure_toolchain_and_components_exist( &toolchain_channel, - self.spirv_install.auto_install_rust_toolchain, + self.auto_install_rust_toolchain, ) .context("ensuring toolchain and components exist")?; // to prevent unsupported version errors when using older toolchains - if !source_is_path { + if !source.is_path() { log::debug!("remove Cargo.lock"); - std::fs::remove_file(checkout.join("Cargo.lock")).context("remove Cargo.lock")?; + std::fs::remove_file(install_dir.join("Cargo.lock")) + .context("remove Cargo.lock")?; } crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source,); let mut build_command = std::process::Command::new("cargo"); build_command - .current_dir(&checkout) + .current_dir(&install_dir) .arg(format!("+{toolchain_channel}")) .args(["build", "--release"]) .env_remove("RUSTC"); - if source_is_path { + if source.is_path() { build_command.args(["-p", "rustc_codegen_spirv", "--lib"]); } @@ -187,15 +345,15 @@ package = "rustc_codegen_spirv" }) .context("running build command")?; - let target = checkout.join("target"); + let target = install_dir.join("target"); let dylib_path = target.join("release").join(&dylib_filename); if dylib_path.is_file() { log::info!("successfully built {}", dylib_path.display()); - if !source_is_path { + if !source.is_path() { std::fs::rename(&dylib_path, &dest_dylib_path) .context("renaming dylib path")?; - if self.spirv_install.clear_target { + if self.clear_target { log::warn!("clearing target dir {}", target.display()); std::fs::remove_dir_all(&target).context("clearing target dir")?; } @@ -204,13 +362,12 @@ package = "rustc_codegen_spirv" log::error!("could not find {}", dylib_path.display()); anyhow::bail!("`rustc_codegen_spirv` build failed"); } - - log::debug!("write_target_spec_files"); - self.write_target_spec_files() - .context("writing target spec files")?; } - self.spirv_install.dylib_path.clone_from(&dest_dylib_path); - Ok((dest_dylib_path, toolchain_channel)) + Ok(InstalledBackend { + rustc_codegen_spirv_location: dest_dylib_path, + toolchain_channel, + target_spec_dir, + }) } } diff --git a/crates/cargo-gpu/src/legacy_target_specs.rs b/crates/cargo-gpu/src/legacy_target_specs.rs new file mode 100644 index 0000000000..cabcdec63e --- /dev/null +++ b/crates/cargo-gpu/src/legacy_target_specs.rs @@ -0,0 +1,26 @@ +//! Legacy target specs are spec jsons for versions before `rustc_codegen_spirv-target-specs` +//! came bundled with them. Instead, cargo gpu needs to bundle these legacy spec files. Luckily, +//! they are the same for all versions, as bundling target specs with the codegen backend was +//! introduced before the first target spec update. + +use anyhow::Context as _; +use log::info; +use std::path::Path; + +/// Extract legacy target specs from our executable into some directory +pub fn write_legacy_target_specs(target_spec_dir: &Path, rebuild: bool) -> anyhow::Result<()> { + info!( + "Writing legacy target specs to {}", + target_spec_dir.display() + ); + std::fs::create_dir_all(target_spec_dir)?; + for (filename, contents) in legacy_target_specs::TARGET_SPECS { + let path = target_spec_dir.join(filename); + if !path.is_file() || rebuild { + std::fs::write(&path, contents.as_bytes()).with_context(|| { + format!("writing legacy target spec file at [{}]", path.display()) + })?; + } + } + Ok(()) +} diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 852766f078..9aae856144 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -55,11 +55,11 @@ use clap::Parser as _; use install::Install; use show::Show; -mod args; mod build; mod config; mod install; mod install_toolchain; +mod legacy_target_specs; mod linkage; mod lockfile; mod metadata; @@ -128,8 +128,8 @@ fn run() -> anyhow::Result<()> { match cli.command { Command::Install(install) => { - let shader_crate_path = install.spirv_install.shader_crate; - let mut command = + let shader_crate_path = install.shader_crate; + let command = config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; log::debug!( "installing with final merged arguments: {:#?}", @@ -138,16 +138,16 @@ fn run() -> anyhow::Result<()> { command.install.run()?; } Command::Build(build) => { - let shader_crate_path = build.install.spirv_install.shader_crate; + let shader_crate_path = build.install.shader_crate; let mut command = config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; log::debug!("building with final merged arguments: {command:#?}"); - if command.build_args.watch { + if command.build.watch { // When watching, do one normal run to setup the `manifest.json` file. - command.build_args.watch = false; + command.build.watch = false; command.run()?; - command.build_args.watch = true; + command.build.watch = true; command.run()?; } else { command.run()?; @@ -202,13 +202,6 @@ fn cache_dir() -> anyhow::Result { }) } -/// Location of the target spec metadata files -fn target_spec_dir() -> anyhow::Result { - let dir = cache_dir()?.join("target-specs"); - std::fs::create_dir_all(&dir)?; - Ok(dir) -} - /// Convenience function for internal use. Dumps all the CLI usage instructions. Useful for /// updating the README. fn dump_full_usage_for_readme() -> anyhow::Result<()> { diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 32fde8d94f..28e93bd3c1 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -7,7 +7,7 @@ use anyhow::Context as _; use cargo_metadata::camino::{Utf8Path, Utf8PathBuf}; use cargo_metadata::semver::Version; -use cargo_metadata::{MetadataCommand, Package}; +use cargo_metadata::{Metadata, MetadataCommand, Package}; use std::fs; use std::path::{Path, PathBuf}; @@ -96,8 +96,9 @@ impl SpirvSource { /// Look into the shader crate to get the version of `rust-gpu` it's using. pub fn get_rust_gpu_deps_from_shader(shader_crate_path: &Path) -> anyhow::Result { - let spirv_std_package = get_package_from_crate(shader_crate_path, "spirv-std")?; - let spirv_source = Self::parse_spirv_std_source_and_version(&spirv_std_package)?; + let crate_metadata = query_metadata(shader_crate_path)?; + let spirv_std_package = crate_metadata.find_package("spirv-std")?; + let spirv_source = Self::parse_spirv_std_source_and_version(spirv_std_package)?; log::debug!( "Parsed `SpirvSource` from crate `{}`: \ {spirv_source:?}", @@ -121,6 +122,11 @@ impl SpirvSource { } } + /// Returns true if self is a Path + pub const fn is_path(&self) -> bool { + matches!(self, Self::Path { .. }) + } + /// Parse a string like: /// `spirv-std v0.9.0 (https://github.com/Rust-GPU/rust-gpu?rev=54f6978c#54f6978c) (*)` /// Which would return: @@ -175,46 +181,41 @@ impl SpirvSource { } } -/// Make sure shader crate path is absolute and canonical. -fn crate_path_canonical(shader_crate_path: &Path) -> anyhow::Result { - let mut canonical_path = shader_crate_path.to_path_buf(); - - if !canonical_path.is_absolute() { - let cwd = std::env::current_dir().context("no cwd")?; - canonical_path = cwd.join(canonical_path); - } - canonical_path = canonical_path - .canonicalize() - .context("could not get absolute path to shader crate")?; - - if !canonical_path.is_dir() { - log::error!("{shader_crate_path:?} is not a directory, aborting"); - anyhow::bail!("{shader_crate_path:?} is not a directory"); - } - Ok(canonical_path) -} - /// get the Package metadata from some crate -pub fn get_package_from_crate(crate_path: &Path, crate_name: &str) -> anyhow::Result { - let canonical_crate_path = crate_path_canonical(crate_path)?; - - log::debug!( - "Running `cargo metadata` on `{}` to query for package `{crate_name}`", - canonical_crate_path.display() - ); +pub fn query_metadata(crate_path: &Path) -> anyhow::Result { + log::debug!("Running `cargo metadata` on `{}`", crate_path.display()); let metadata = MetadataCommand::new() - .current_dir(&canonical_crate_path) + .current_dir( + &crate_path + .canonicalize() + .context("could not get absolute path to shader crate")?, + ) .exec()?; + Ok(metadata) +} + +/// implements [`Self::find_package`] +pub trait FindPackage { + /// Search for a package or return a nice error + fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package>; +} - let Some(package) = metadata - .packages - .into_iter() - .find(|package| package.name.eq(crate_name)) - else { - anyhow::bail!("`{crate_name}` not found in `Cargo.toml` at `{canonical_crate_path:?}`"); - }; - log::trace!(" found `{}` version `{}`", package.name, package.version); - Ok(package) +impl FindPackage for Metadata { + fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package> { + if let Some(package) = self + .packages + .iter() + .find(|package| package.name.eq(crate_name)) + { + log::trace!(" found `{}` version `{}`", package.name, package.version); + Ok(package) + } else { + anyhow::bail!( + "`{crate_name}` not found in `Cargo.toml` at `{:?}`", + self.workspace_root + ); + } + } } /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. @@ -252,7 +253,7 @@ mod test { source, SpirvSource::Git { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "82a0f69008414f51d59184763146caa6850ac588".to_owned() + rev: "86fc48032c4cd4afb74f1d81ae859711d20386a1".to_owned() } ); } @@ -274,6 +275,6 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - assert_eq!("https___github_com_Rust-GPU_rust-gpu+82a0f690", &name); + assert_eq!("https___github_com_Rust-GPU_rust-gpu+86fc4803", &name); } } diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 8a7a320e57..89add75e22 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" @@ -68,10 +68,11 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "bitflags", "glam", + "libm", "num-traits", "spirv-std-macros", "spirv-std-types", @@ -80,7 +81,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "proc-macro2", "quote", @@ -91,7 +92,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=82a0f69#82a0f69008414f51d59184763146caa6850ac588" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" [[package]] name = "syn" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index faae1f24b7..9ed5a5a615 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["rlib", "cdylib"] # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released -spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "82a0f69" } +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1" } # Dependencies for GPU code [target.'cfg(target_arch = "spirv")'.dependencies] From b4972342b9331c4925783dc3ae0ab5e2b87fd66a Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 2 Jun 2025 17:41:53 +0200 Subject: [PATCH 090/162] Make cargo-gpu a library, usable from build scripts (#71) * build script: move Command run logic to `.run()` * move usage dumping for readme to `mod dump_usage` * move testing utilities to `mod test` * turn cargo-gpu into a pure library * recreate the binary and main function * fix clippy warnings * make Install usable from a lib * fix clippy * make dummy a library, skip linking an executable binary * add logging on target-specs writing * deduplicate cargo cloning rust-gpu due to slightly different url * change unreachable Err handling * make `Install` and `InstalledBackend` `#[non_exhaustive]` --- Cargo.lock | 4 +- Cargo.toml | 2 +- crates/cargo-gpu/src/dump_usage.rs | 51 ++++ crates/cargo-gpu/src/install.rs | 133 +++++---- crates/cargo-gpu/src/legacy_target_specs.rs | 14 +- crates/cargo-gpu/src/lib.rs | 202 ++++++++++++++ crates/cargo-gpu/src/main.rs | 285 +------------------- crates/cargo-gpu/src/show.rs | 8 +- crates/cargo-gpu/src/test.rs | 53 ++++ 9 files changed, 406 insertions(+), 346 deletions(-) create mode 100644 crates/cargo-gpu/src/dump_usage.rs create mode 100644 crates/cargo-gpu/src/lib.rs create mode 100644 crates/cargo-gpu/src/test.rs diff --git a/Cargo.lock b/Cargo.lock index 171421693d..fbc2f16fb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -754,7 +754,7 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "rspirv", "serde", @@ -904,7 +904,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu.git?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" dependencies = [ "clap", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 036c97127e..78a6b5261e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu.git", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1", default-features = false } anyhow = "1.0.94" clap = { version = "4.5.37", features = ["derive"] } crossterm = "0.28.1" diff --git a/crates/cargo-gpu/src/dump_usage.rs b/crates/cargo-gpu/src/dump_usage.rs new file mode 100644 index 0000000000..d53941419f --- /dev/null +++ b/crates/cargo-gpu/src/dump_usage.rs @@ -0,0 +1,51 @@ +//! Convenience function for internal use. Dumps all the CLI usage instructions. Useful for +//! updating the README. + +use crate::{user_output, Cli}; + +/// main dump usage function +pub fn dump_full_usage_for_readme() -> anyhow::Result<()> { + use clap::CommandFactory as _; + let mut command = Cli::command(); + + let mut buffer: Vec = Vec::default(); + command.build(); + + write_help(&mut buffer, &mut command, 0)?; + user_output!("{}", String::from_utf8(buffer)?); + + Ok(()) +} + +/// Recursive function to print the usage instructions for each subcommand. +fn write_help( + buffer: &mut impl std::io::Write, + cmd: &mut clap::Command, + depth: usize, +) -> anyhow::Result<()> { + if cmd.get_name() == "help" { + return Ok(()); + } + + let mut command = cmd.get_name().to_owned(); + let indent_depth = if depth == 0 || depth == 1 { 0 } else { depth }; + let indent = " ".repeat(indent_depth * 4); + writeln!( + buffer, + "\n{}* {}{}", + indent, + command.remove(0).to_uppercase(), + command + )?; + + for line in cmd.render_long_help().to_string().lines() { + writeln!(buffer, "{indent} {line}")?; + } + + for sub in cmd.get_subcommands_mut() { + writeln!(buffer)?; + write_help(buffer, sub, depth + 1)?; + } + + Ok(()) +} diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index bd08e6d13f..50a34e0d8b 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -7,16 +7,63 @@ use crate::spirv_source::{ use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; use cargo_metadata::Metadata; -use log::{info, trace}; use spirv_builder::SpirvBuilder; use std::path::{Path, PathBuf}; +/// Represents a functional backend installation, whether it was cached or just installed. +#[derive(Clone, Debug)] +#[non_exhaustive] +pub struct InstalledBackend { + /// path to the `rustc_codegen_spirv` dylib + pub rustc_codegen_spirv_location: PathBuf, + /// toolchain channel name + pub toolchain_channel: String, + /// directory with target-specs json files + pub target_spec_dir: PathBuf, +} + +impl InstalledBackend { + /// Creates a new `SpirvBuilder` configured to use this installed backend. + #[expect( + clippy::unreachable, + reason = "it's unreachable, no need to return a Result" + )] + #[expect(clippy::impl_trait_in_params, reason = "forwarding spirv-builder API")] + #[inline] + pub fn to_spirv_builder( + &self, + path_to_crate: impl AsRef, + target: impl Into, + ) -> SpirvBuilder { + let mut builder = SpirvBuilder::new(path_to_crate, target); + self.configure_spirv_builder(&mut builder) + .unwrap_or_else(|_| unreachable!("we set target before calling this function")); + builder + } + + /// Configures the supplied [`SpirvBuilder`]. `SpirvBuilder.target` must be set and must not change after calling this function. + /// + /// # Errors + /// if `SpirvBuilder.target` is not set + #[inline] + pub fn configure_spirv_builder(&self, builder: &mut SpirvBuilder) -> anyhow::Result<()> { + builder.rustc_codegen_spirv_location = Some(self.rustc_codegen_spirv_location.clone()); + builder.toolchain_overwrite = Some(self.toolchain_channel.clone()); + builder.path_to_target_spec = Some(self.target_spec_dir.join(format!( + "{}.json", + builder.target.as_ref().context("expect target to be set")? + ))); + Ok(()) + } +} + /// Args for an install #[expect( clippy::struct_excessive_bools, reason = "cmdline args have many bools" )] #[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] +#[non_exhaustive] pub struct Install { /// Directory containing the shader crate to compile. #[clap(long, default_value = "./")] @@ -44,6 +91,8 @@ pub struct Install { pub rebuild_codegen: bool, /// Assume "yes" to "Install Rust toolchain: [y/n]" prompt. + /// + /// Defaults to `false` in cli, `true` in [`Default`] #[clap(long, action)] pub auto_install_rust_toolchain: bool, @@ -77,46 +126,22 @@ pub struct Install { pub force_overwrite_lockfiles_v4_to_v3: bool, } -/// Represents a functional backend installation, whether it was cached or just installed. -#[derive(Clone, Debug)] -pub struct InstalledBackend { - /// path to the `rustc_codegen_spirv` dylib - pub rustc_codegen_spirv_location: PathBuf, - /// toolchain channel name - pub toolchain_channel: String, - /// directory with target-specs json files - pub target_spec_dir: PathBuf, -} - -impl InstalledBackend { - /// Configures the supplied [`SpirvBuilder`]. `SpirvBuilder.target` must be set and must not change after calling this function. - pub fn configure_spirv_builder(&self, builder: &mut SpirvBuilder) -> anyhow::Result<()> { - builder.rustc_codegen_spirv_location = Some(self.rustc_codegen_spirv_location.clone()); - builder.toolchain_overwrite = Some(self.toolchain_channel.clone()); - builder.path_to_target_spec = Some(self.target_spec_dir.join(format!( - "{}.json", - builder.target.as_ref().context("expect target to be set")? - ))); - Ok(()) - } -} - -impl Default for Install { +impl Install { + /// Create a default install for a shader crate of some path #[inline] - fn default() -> Self { + #[must_use] + pub const fn from_shader_crate(shader_crate: PathBuf) -> Self { Self { - shader_crate: PathBuf::from("./"), + shader_crate, spirv_builder_source: None, spirv_builder_version: None, rebuild_codegen: false, - auto_install_rust_toolchain: false, + auto_install_rust_toolchain: true, clear_target: true, force_overwrite_lockfiles_v4_to_v3: false, } } -} -impl Install { /// Create the `rustc_codegen_spirv_dummy` crate that depends on `rustc_codegen_spirv` fn write_source_files(source: &SpirvSource, checkout: &Path) -> anyhow::Result<()> { // skip writing a dummy project if we use a local rust-gpu checkout @@ -129,15 +154,14 @@ impl Install { ); { - trace!("writing dummy main.rs"); - let main = "fn main() {}"; + log::trace!("writing dummy lib.rs"); let src = checkout.join("src"); - std::fs::create_dir_all(&src).context("creating directory for 'src'")?; - std::fs::write(src.join("main.rs"), main).context("writing 'main.rs'")?; + std::fs::create_dir_all(&src).context("creating 'src' directory")?; + std::fs::File::create(src.join("lib.rs")).context("creating 'src/lib.rs'")?; }; { - trace!("writing dummy Cargo.toml"); + log::trace!("writing dummy Cargo.toml"); let version_spec = match &source { SpirvSource::CratesIO(version) => { format!("version = \"{version}\"") @@ -174,11 +198,6 @@ package = "rustc_codegen_spirv" /// Copy spec files from one dir to another, assuming no subdirectories fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> { - info!( - "Copy target specs from {:?} to {:?}", - src.display(), - dst.display() - ); std::fs::create_dir_all(dst)?; let dir = std::fs::read_dir(src)?; for dir_entry in dir { @@ -193,7 +212,6 @@ package = "rustc_codegen_spirv" /// Add the target spec files to the crate. fn update_spec_files( - &self, source: &SpirvSource, install_dir: &Path, dummy_metadata: &Metadata, @@ -204,6 +222,11 @@ package = "rustc_codegen_spirv" if let Ok(target_specs) = dummy_metadata.find_package("rustc_codegen_spirv-target-specs") { + log::info!( + "target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`", + target_specs.manifest_path + ); + let target_specs_src = target_specs .manifest_path .as_std_path() @@ -215,9 +238,17 @@ package = "rustc_codegen_spirv" .context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?; if source.is_path() { // skip copy + log::info!( + "target-specs: source is local path, use target-specs from `{}`", + target_specs_src.display() + ); target_specs_dst = target_specs_src; } else { // copy over the target-specs + log::info!( + "target-specs: Copy target specs from `{}`", + target_specs_src.display() + ); Self::copy_spec_files(&target_specs_src, &target_specs_dst) .context("copying target-specs json files")?; } @@ -231,14 +262,22 @@ package = "rustc_codegen_spirv" // and hope parallel runs don't shred each other target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout"); } - write_legacy_target_specs(&target_specs_dst, self.rebuild_codegen)?; + log::info!( + "target-specs: Writing legacy target specs to `{}`", + target_specs_dst.display() + ); + write_legacy_target_specs(&target_specs_dst)?; } } Ok(target_specs_dst) } - /// Install the binary pair and return the `(dylib_path, toolchain_channel)`. + /// Install the binary pair and return the [`InstalledBackend`], from which you can create [`SpirvBuilder`] instances. + /// + /// # Errors + /// If the installation somehow fails. + #[inline] #[expect(clippy::too_many_lines, reason = "it's fine")] pub fn run(&self) -> anyhow::Result { // Ensure the cache dir exists @@ -299,9 +338,9 @@ package = "rustc_codegen_spirv" log::info!("selected toolchain channel `{toolchain_channel:?}`"); log::debug!("update_spec_files"); - let target_spec_dir = self - .update_spec_files(&source, &install_dir, &dummy_metadata, skip_rebuild) - .context("writing target spec files")?; + let target_spec_dir = + Self::update_spec_files(&source, &install_dir, &dummy_metadata, skip_rebuild) + .context("writing target spec files")?; if !skip_rebuild { log::debug!("ensure_toolchain_and_components_exist"); diff --git a/crates/cargo-gpu/src/legacy_target_specs.rs b/crates/cargo-gpu/src/legacy_target_specs.rs index cabcdec63e..796b0e3182 100644 --- a/crates/cargo-gpu/src/legacy_target_specs.rs +++ b/crates/cargo-gpu/src/legacy_target_specs.rs @@ -4,23 +4,15 @@ //! introduced before the first target spec update. use anyhow::Context as _; -use log::info; use std::path::Path; /// Extract legacy target specs from our executable into some directory -pub fn write_legacy_target_specs(target_spec_dir: &Path, rebuild: bool) -> anyhow::Result<()> { - info!( - "Writing legacy target specs to {}", - target_spec_dir.display() - ); +pub fn write_legacy_target_specs(target_spec_dir: &Path) -> anyhow::Result<()> { std::fs::create_dir_all(target_spec_dir)?; for (filename, contents) in legacy_target_specs::TARGET_SPECS { let path = target_spec_dir.join(filename); - if !path.is_file() || rebuild { - std::fs::write(&path, contents.as_bytes()).with_context(|| { - format!("writing legacy target spec file at [{}]", path.display()) - })?; - } + std::fs::write(&path, contents.as_bytes()) + .with_context(|| format!("writing legacy target spec file at [{}]", path.display()))?; } Ok(()) } diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs new file mode 100644 index 0000000000..b3adabf00f --- /dev/null +++ b/crates/cargo-gpu/src/lib.rs @@ -0,0 +1,202 @@ +#![expect(clippy::pub_use, reason = "pub use for build scripts")] + +//! Rust GPU shader crate builder. +//! +//! This program and library allows you to easily compile your rust-gpu shaders, +//! without requiring you to fix your entire project to a specific toolchain. +//! +//! # How it works +//! +//! This program primarily manages installations of `rustc_codegen_spirv`, the +//! codegen backend of rust-gpu to generate SPIR-V shader binaries. The codegen +//! backend builds on internal, ever-changing interfaces of rustc, which requires +//! fixing a version of rust-gpu to a specific version of the rustc compiler. +//! Usually, this would require you to fix your entire project to that specific +//! toolchain, but this project loosens that requirement by managing installations +//! of `rustc_codegen_spirv` and their associated toolchains for you. +//! +//! We continue to use rust-gpu's `spirv_builder` crate to pass the many additional +//! parameters required to configure rustc and our codegen backend, but provide you +//! with a toolchain agnostic version that you may use from stable rustc. And a +//! `cargo gpu` cmdline utility to simplify shader building even more. +//! +//! ## Where the binaries are +//! +//! We store our prebuild `rustc_spirv_builder` binaries in the default cache +//! directory of your OS: +//! * Windows: `C:/users//AppData/Local/rust-gpu` +//! * Mac: `~/Library/Caches/rust-gpu` +//! * Linux: `~/.cache/rust-gpu` +//! +//! ## How we build the backend +//! +//! * retrieve the version of rust-gpu you want to use based on the version of the +//! `spirv-std` dependency in your shader crate. +//! * create a dummy project at `/codegen//` that depends on +//! `rustc_codegen_spirv` +//! * use `cargo metadata` to `cargo update` the dummy project, which downloads the +//! `rustc_codegen_spirv` crate into cargo's cache, and retrieve the path to the +//! download location. +//! * search for the required toolchain in `build.rs` of `rustc_codegen_spirv` +//! * build it with the required toolchain version +//! * copy out the binary and clean the target dir +//! +//! ## Building shader crates +//! +//! `cargo-gpu` takes a path to a shader crate to build, as well as a path to a directory +//! to put the compiled `spv` source files. It also takes a path to an output manifest +//! file where all shader entry points will be mapped to their `spv` source files. This +//! manifest file can be used by build scripts (`build.rs` files) to generate linkage or +//! conduct other post-processing, like converting the `spv` files into `wgsl` files, +//! for example. + +use anyhow::Context as _; + +use crate::dump_usage::dump_full_usage_for_readme; +use build::Build; +use show::Show; + +mod build; +mod config; +mod dump_usage; +mod install; +mod install_toolchain; +mod legacy_target_specs; +mod linkage; +mod lockfile; +mod metadata; +mod show; +mod spirv_source; +mod test; + +pub use install::*; +pub use spirv_builder; + +/// Central function to write to the user. +#[macro_export] +macro_rules! user_output { + ($($args: tt)*) => { + #[allow( + clippy::allow_attributes, + clippy::useless_attribute, + unused_imports, + reason = "`std::io::Write` is only sometimes called??" + )] + use std::io::Write as _; + + #[expect( + clippy::non_ascii_literal, + reason = "CRAB GOOD. CRAB IMPORTANT." + )] + { + print!("🦀 "); + } + print!($($args)*); + std::io::stdout().flush().unwrap(); + } +} + +/// All of the available subcommands for `cargo gpu` +#[derive(clap::Subcommand)] +#[non_exhaustive] +pub enum Command { + /// Install rust-gpu compiler artifacts. + Install(Box), + + /// Compile a shader crate to SPIR-V. + Build(Box), + + /// Show some useful values. + Show(Show), + + /// A hidden command that can be used to recursively print out all the subcommand help messages: + /// `cargo gpu dump-usage` + /// Useful for updating the README. + #[clap(hide(true))] + DumpUsage, +} + +impl Command { + /// Runs the command + /// + /// # Errors + /// Any errors during execution, usually printed to the user + #[inline] + pub fn run(&self, env_args: Vec) -> anyhow::Result<()> { + match &self { + Self::Install(install) => { + let shader_crate_path = &install.shader_crate; + let command = + config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?; + log::debug!( + "installing with final merged arguments: {:#?}", + command.install + ); + command.install.run()?; + } + Self::Build(build) => { + let shader_crate_path = &build.install.shader_crate; + let mut command = + config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?; + log::debug!("building with final merged arguments: {command:#?}"); + + if command.build.watch { + // When watching, do one normal run to setup the `manifest.json` file. + command.build.watch = false; + command.run()?; + command.build.watch = true; + command.run()?; + } else { + command.run()?; + } + } + Self::Show(show) => show.run()?, + Self::DumpUsage => dump_full_usage_for_readme()?, + } + + Ok(()) + } +} + +/// the Cli struct representing the main cli +#[derive(clap::Parser)] +#[clap(author, version, about, subcommand_required = true)] +#[non_exhaustive] +pub struct Cli { + /// The command to run. + #[clap(subcommand)] + pub command: Command, +} + +/// The central cache directory of cargo gpu +/// +/// # Errors +/// may fail if we can't find the user home directory +#[inline] +pub fn cache_dir() -> anyhow::Result { + let dir = directories::BaseDirs::new() + .with_context(|| "could not find the user home directory")? + .cache_dir() + .join("rust-gpu"); + + Ok(if cfg!(test) { + let thread_id = std::thread::current().id(); + let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); + dir.join("tests").join(id) + } else { + dir + }) +} + +/// Returns a string suitable to use as a directory. +/// +/// Created from the spirv-builder source dep and the rustc channel. +fn to_dirname(text: &str) -> String { + text.replace( + [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], + "_", + ) + .split(['{', '}', ' ', '\n', '"', '\'']) + .collect::>() + .concat() +} diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 9aae856144..f40e3c6e4e 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -1,94 +1,6 @@ -//! Rust GPU shader crate builder. -//! -//! This program and library allows you to easily compile your rust-gpu shaders, -//! without requiring you to fix your entire project to a specific toolchain. -//! -//! # How it works -//! -//! This program primarily manages installations of `rustc_codegen_spirv`, the -//! codegen backend of rust-gpu to generate SPIR-V shader binaries. The codegen -//! backend builds on internal, ever-changing interfaces of rustc, which requires -//! fixing a version of rust-gpu to a specific version of the rustc compiler. -//! Usually, this would require you to fix your entire project to that specific -//! toolchain, but this project loosens that requirement by managing installations -//! of `rustc_codegen_spirv` and their associated toolchains for you. -//! -//! We continue to use rust-gpu's `spirv_builder` crate to pass the many additional -//! parameters required to configure rustc and our codegen backend, but provide you -//! with a toolchain agnostic version that you may use from stable rustc. And a -//! `cargo gpu` cmdline utility to simplify shader building even more. -//! -//! ## Where the binaries are -//! -//! We store our prebuild `rustc_spirv_builder` binaries in the default cache -//! directory of your OS: -//! * Windows: `C:/users//AppData/Local/rust-gpu` -//! * Mac: `~/Library/Caches/rust-gpu` -//! * Linux: `~/.cache/rust-gpu` -//! -//! ## How we build the backend -//! -//! * retrieve the version of rust-gpu you want to use based on the version of the -//! `spirv-std` dependency in your shader crate. -//! * create a dummy project at `/codegen//` that depends on -//! `rustc_codegen_spirv` -//! * use `cargo metadata` to `cargo update` the dummy project, which downloads the -//! `rustc_codegen_spirv` crate into cargo's cache, and retrieve the path to the -//! download location. -//! * search for the required toolchain in `build.rs` of `rustc_codegen_spirv` -//! * build it with the required toolchain version -//! * copy out the binary and clean the target dir -//! -//! ## Building shader crates -//! -//! `cargo-gpu` takes a path to a shader crate to build, as well as a path to a directory -//! to put the compiled `spv` source files. It also takes a path to an output manifest -//! file where all shader entry points will be mapped to their `spv` source files. This -//! manifest file can be used by build scripts (`build.rs` files) to generate linkage or -//! conduct other post-processing, like converting the `spv` files into `wgsl` files, -//! for example. - -use anyhow::Context as _; - -use build::Build; +//! main executable of cargo gpu +use cargo_gpu::Cli; use clap::Parser as _; -use install::Install; -use show::Show; - -mod build; -mod config; -mod install; -mod install_toolchain; -mod legacy_target_specs; -mod linkage; -mod lockfile; -mod metadata; -mod show; -mod spirv_source; - -/// Central function to write to the user. -#[macro_export] -macro_rules! user_output { - ($($args: tt)*) => { - #[allow( - clippy::allow_attributes, - clippy::useless_attribute, - unused_imports, - reason = "`std::io::Write` is only sometimes called??" - )] - use std::io::Write as _; - - #[expect( - clippy::non_ascii_literal, - reason = "CRAB GOOD. CRAB IMPORTANT." - )] - { - print!("🦀 "); - } - print!($($args)*); - std::io::stdout().flush().unwrap(); - } -} fn main() { #[cfg(debug_assertions)] @@ -124,195 +36,6 @@ fn run() -> anyhow::Result<()> { }) .collect::>(); log::trace!("CLI args: {env_args:#?}"); - let cli = Cli::parse_from(env_args.clone()); - - match cli.command { - Command::Install(install) => { - let shader_crate_path = install.shader_crate; - let command = - config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; - log::debug!( - "installing with final merged arguments: {:#?}", - command.install - ); - command.install.run()?; - } - Command::Build(build) => { - let shader_crate_path = build.install.shader_crate; - let mut command = - config::Config::clap_command_with_cargo_config(&shader_crate_path, env_args)?; - log::debug!("building with final merged arguments: {command:#?}"); - - if command.build.watch { - // When watching, do one normal run to setup the `manifest.json` file. - command.build.watch = false; - command.run()?; - command.build.watch = true; - command.run()?; - } else { - command.run()?; - } - } - Command::Show(show) => show.run()?, - Command::DumpUsage => dump_full_usage_for_readme()?, - } - - Ok(()) -} - -/// All of the available subcommands for `cargo gpu` -#[derive(clap::Subcommand)] -enum Command { - /// Install rust-gpu compiler artifacts. - Install(Box), - - /// Compile a shader crate to SPIR-V. - Build(Box), - - /// Show some useful values. - Show(Show), - - /// A hidden command that can be used to recursively print out all the subcommand help messages: - /// `cargo gpu dump-usage` - /// Useful for updating the README. - #[clap(hide(true))] - DumpUsage, -} - -#[derive(clap::Parser)] -#[clap(author, version, about, subcommand_required = true)] -pub(crate) struct Cli { - /// The command to run. - #[clap(subcommand)] - command: Command, -} - -fn cache_dir() -> anyhow::Result { - let dir = directories::BaseDirs::new() - .with_context(|| "could not find the user home directory")? - .cache_dir() - .join("rust-gpu"); - - Ok(if cfg!(test) { - let thread_id = std::thread::current().id(); - let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); - dir.join("tests").join(id) - } else { - dir - }) -} - -/// Convenience function for internal use. Dumps all the CLI usage instructions. Useful for -/// updating the README. -fn dump_full_usage_for_readme() -> anyhow::Result<()> { - use clap::CommandFactory as _; - let mut command = Cli::command(); - - let mut buffer: Vec = Vec::default(); - command.build(); - - write_help(&mut buffer, &mut command, 0)?; - user_output!("{}", String::from_utf8(buffer)?); - - Ok(()) -} - -/// Recursive function to print the usage instructions for each subcommand. -fn write_help( - buffer: &mut impl std::io::Write, - cmd: &mut clap::Command, - depth: usize, -) -> anyhow::Result<()> { - if cmd.get_name() == "help" { - return Ok(()); - } - - let mut command = cmd.get_name().to_owned(); - let indent_depth = if depth == 0 || depth == 1 { 0 } else { depth }; - let indent = " ".repeat(indent_depth * 4); - writeln!( - buffer, - "\n{}* {}{}", - indent, - command.remove(0).to_uppercase(), - command - )?; - - for line in cmd.render_long_help().to_string().lines() { - writeln!(buffer, "{indent} {line}")?; - } - - for sub in cmd.get_subcommands_mut() { - writeln!(buffer)?; - write_help(buffer, sub, depth + 1)?; - } - - Ok(()) -} - -/// Returns a string suitable to use as a directory. -/// -/// Created from the spirv-builder source dep and the rustc channel. -fn to_dirname(text: &str) -> String { - text.replace( - [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], - "_", - ) - .split(['{', '}', ' ', '\n', '"', '\'']) - .collect::>() - .concat() -} - -#[cfg(test)] -mod test { - use crate::cache_dir; - use std::io::Write as _; - - fn copy_dir_all( - src: impl AsRef, - dst: impl AsRef, - ) -> anyhow::Result<()> { - std::fs::create_dir_all(&dst)?; - for maybe_entry in std::fs::read_dir(src)? { - let entry = maybe_entry?; - let ty = entry.file_type()?; - if ty.is_dir() { - copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; - } else { - std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; - } - } - Ok(()) - } - - pub fn shader_crate_template_path() -> std::path::PathBuf { - let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); - project_base.join("../shader-crate-template") - } - - pub fn shader_crate_test_path() -> std::path::PathBuf { - let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); - copy_dir_all(shader_crate_template_path(), shader_crate_path.clone()).unwrap(); - shader_crate_path - } - - pub fn overwrite_shader_cargo_toml(shader_crate_path: &std::path::Path) -> std::fs::File { - let cargo_toml = shader_crate_path.join("Cargo.toml"); - let mut file = std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(cargo_toml) - .unwrap(); - writeln!(file, "[package]").unwrap(); - writeln!(file, "name = \"test\"").unwrap(); - file - } - - pub fn tests_teardown() { - let cache_dir = cache_dir().unwrap(); - if !cache_dir.exists() { - return; - } - std::fs::remove_dir_all(cache_dir).unwrap(); - } + let cli = Cli::parse_from(&env_args); + cli.command.run(env_args) } diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 3b0e2f8891..265b1269b9 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -33,7 +33,7 @@ pub struct Show { impl Show { /// Entrypoint - pub fn run(self) -> anyhow::Result<()> { + pub fn run(&self) -> anyhow::Result<()> { log::info!("{:?}: ", self.command); #[expect( @@ -41,17 +41,17 @@ impl Show { reason = "The output of this command could potentially be used in a script, \ so we _don't_ want to use `crate::user_output`, as that prefixes a crab." )] - match self.command { + match &self.command { Info::CacheDirectory => { println!("{}\n", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { let rust_gpu_source = - crate::spirv_source::SpirvSource::get_rust_gpu_deps_from_shader(&shader_crate)?; + crate::spirv_source::SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?; println!("{rust_gpu_source}\n"); } Info::Commitsh => { - println!("{}", std::env!("GIT_HASH")); + println!("{}", env!("GIT_HASH")); } Info::Capabilities => { println!("All available options to the `cargo gpu build --capabilities` argument:"); diff --git a/crates/cargo-gpu/src/test.rs b/crates/cargo-gpu/src/test.rs new file mode 100644 index 0000000000..c9ee93aa0d --- /dev/null +++ b/crates/cargo-gpu/src/test.rs @@ -0,0 +1,53 @@ +//! utilities for tests +#![cfg(test)] + +use crate::cache_dir; +use std::io::Write as _; + +fn copy_dir_all( + src: impl AsRef, + dst: impl AsRef, +) -> anyhow::Result<()> { + std::fs::create_dir_all(&dst)?; + for maybe_entry in std::fs::read_dir(src)? { + let entry = maybe_entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} + +pub fn shader_crate_template_path() -> std::path::PathBuf { + let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + project_base.join("../shader-crate-template") +} + +pub fn shader_crate_test_path() -> std::path::PathBuf { + let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); + copy_dir_all(shader_crate_template_path(), shader_crate_path.clone()).unwrap(); + shader_crate_path +} + +pub fn overwrite_shader_cargo_toml(shader_crate_path: &std::path::Path) -> std::fs::File { + let cargo_toml = shader_crate_path.join("Cargo.toml"); + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(cargo_toml) + .unwrap(); + writeln!(file, "[package]").unwrap(); + writeln!(file, "name = \"test\"").unwrap(); + file +} + +pub fn tests_teardown() { + let cache_dir = cache_dir().unwrap(); + if !cache_dir.exists() { + return; + } + std::fs::remove_dir_all(cache_dir).unwrap(); +} From 32d297a6d9881a9af9be7115b3a31080d5b7dcad Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Wed, 4 Jun 2025 09:41:34 +0200 Subject: [PATCH 091/162] ci: ensure lockfile is up-to-date (#78) --- .github/workflows/push.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 5a710c97d3..df17c6b594 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -50,6 +50,12 @@ jobs: run: | rustup default stable rustup update + - name: Fetch root dependencies + run: cargo fetch --locked + - name: Fetch shader-crate-template dependencies + run: | + cd ./crates/shader-crate-template + cargo fetch --locked - run: cargo test - name: Run a full build run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} From 91ade614bb010038be9eb9dd64f06b4e6c02e110 Mon Sep 17 00:00:00 2001 From: Jer Date: Sat, 7 Jun 2025 03:54:53 +1000 Subject: [PATCH 092/162] show-targets #36 (#79) * show-targets comments * TARGET_SPECS has them all at comp time * Update methodology of retrieving targets. use the `cache_dir`, but fallback on the legacy const as it's known to be there, currently the cache_dir's presence is not guaranteed. * filter earlier on to do less hashing. * check dir exists earlier on. * use same error conventions as already in codebase (anyhow) * docs, cleanups * chore: silence clippy * create `mod target_specs` and move all related code there * refactor `update_spec_files` to allow querying `target_specs` dir without updating * make `show targets` use new `target_specs` path querying * fix clippy * update docs on target specs --------- Co-authored-by: Firestar99 --- crates/cargo-gpu/src/install.rs | 85 +----------- crates/cargo-gpu/src/legacy_target_specs.rs | 18 --- crates/cargo-gpu/src/lib.rs | 2 +- crates/cargo-gpu/src/show.rs | 46 ++++++- crates/cargo-gpu/src/target_specs.rs | 135 ++++++++++++++++++++ 5 files changed, 183 insertions(+), 103 deletions(-) delete mode 100644 crates/cargo-gpu/src/legacy_target_specs.rs create mode 100644 crates/cargo-gpu/src/target_specs.rs diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 50a34e0d8b..d7a6894b33 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -1,12 +1,11 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. -use crate::legacy_target_specs::write_legacy_target_specs; use crate::spirv_source::{ get_channel_from_rustc_codegen_spirv_build_script, query_metadata, FindPackage as _, }; +use crate::target_specs::update_target_specs_files; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; -use cargo_metadata::Metadata; use spirv_builder::SpirvBuilder; use std::path::{Path, PathBuf}; @@ -196,83 +195,6 @@ package = "rustc_codegen_spirv" Ok(()) } - /// Copy spec files from one dir to another, assuming no subdirectories - fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> { - std::fs::create_dir_all(dst)?; - let dir = std::fs::read_dir(src)?; - for dir_entry in dir { - let file = dir_entry?; - let file_path = file.path(); - if file_path.is_file() { - std::fs::copy(file_path, dst.join(file.file_name()))?; - } - } - Ok(()) - } - - /// Add the target spec files to the crate. - fn update_spec_files( - source: &SpirvSource, - install_dir: &Path, - dummy_metadata: &Metadata, - skip_rebuild: bool, - ) -> anyhow::Result { - let mut target_specs_dst = install_dir.join("target-specs"); - if !skip_rebuild { - if let Ok(target_specs) = - dummy_metadata.find_package("rustc_codegen_spirv-target-specs") - { - log::info!( - "target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`", - target_specs.manifest_path - ); - - let target_specs_src = target_specs - .manifest_path - .as_std_path() - .parent() - .and_then(|root| { - let src = root.join("target-specs"); - src.is_dir().then_some(src) - }) - .context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?; - if source.is_path() { - // skip copy - log::info!( - "target-specs: source is local path, use target-specs from `{}`", - target_specs_src.display() - ); - target_specs_dst = target_specs_src; - } else { - // copy over the target-specs - log::info!( - "target-specs: Copy target specs from `{}`", - target_specs_src.display() - ); - Self::copy_spec_files(&target_specs_src, &target_specs_dst) - .context("copying target-specs json files")?; - } - } else { - // use legacy target specs bundled with cargo gpu - if source.is_path() { - // This is a stupid situation: - // * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`) - // * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout - // -> do what the old cargo gpu did, one global dir for all target specs - // and hope parallel runs don't shred each other - target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout"); - } - log::info!( - "target-specs: Writing legacy target specs to `{}`", - target_specs_dst.display() - ); - write_legacy_target_specs(&target_specs_dst)?; - } - } - - Ok(target_specs_dst) - } - /// Install the binary pair and return the [`InstalledBackend`], from which you can create [`SpirvBuilder`] instances. /// /// # Errors @@ -338,9 +260,8 @@ package = "rustc_codegen_spirv" log::info!("selected toolchain channel `{toolchain_channel:?}`"); log::debug!("update_spec_files"); - let target_spec_dir = - Self::update_spec_files(&source, &install_dir, &dummy_metadata, skip_rebuild) - .context("writing target spec files")?; + let target_spec_dir = update_target_specs_files(&source, &dummy_metadata, !skip_rebuild) + .context("writing target spec files")?; if !skip_rebuild { log::debug!("ensure_toolchain_and_components_exist"); diff --git a/crates/cargo-gpu/src/legacy_target_specs.rs b/crates/cargo-gpu/src/legacy_target_specs.rs deleted file mode 100644 index 796b0e3182..0000000000 --- a/crates/cargo-gpu/src/legacy_target_specs.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Legacy target specs are spec jsons for versions before `rustc_codegen_spirv-target-specs` -//! came bundled with them. Instead, cargo gpu needs to bundle these legacy spec files. Luckily, -//! they are the same for all versions, as bundling target specs with the codegen backend was -//! introduced before the first target spec update. - -use anyhow::Context as _; -use std::path::Path; - -/// Extract legacy target specs from our executable into some directory -pub fn write_legacy_target_specs(target_spec_dir: &Path) -> anyhow::Result<()> { - std::fs::create_dir_all(target_spec_dir)?; - for (filename, contents) in legacy_target_specs::TARGET_SPECS { - let path = target_spec_dir.join(filename); - std::fs::write(&path, contents.as_bytes()) - .with_context(|| format!("writing legacy target spec file at [{}]", path.display()))?; - } - Ok(()) -} diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index b3adabf00f..323743b4b0 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -61,12 +61,12 @@ mod config; mod dump_usage; mod install; mod install_toolchain; -mod legacy_target_specs; mod linkage; mod lockfile; mod metadata; mod show; mod spirv_source; +mod target_specs; mod test; pub use install::*; diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 265b1269b9..b7eb19b2ff 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -1,6 +1,11 @@ //! Display various information about `cargo gpu`, eg its cache directory. use crate::cache_dir; +use crate::spirv_source::{query_metadata, SpirvSource}; +use crate::target_specs::update_target_specs_files; +use anyhow::bail; +use std::fs; +use std::path::Path; /// Show the computed source of the spirv-std dependency. #[derive(Clone, Debug, clap::Parser)] @@ -21,6 +26,9 @@ pub enum Info { Commitsh, /// All the available SPIR-V capabilities that can be set with `--capabilities` Capabilities, + + /// All available SPIR-V targets + Targets(SpirvSourceDep), } /// `cargo gpu show` @@ -46,8 +54,7 @@ impl Show { println!("{}\n", cache_dir()?.display()); } Info::SpirvSource(SpirvSourceDep { shader_crate }) => { - let rust_gpu_source = - crate::spirv_source::SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?; + let rust_gpu_source = SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?; println!("{rust_gpu_source}\n"); } Info::Commitsh => { @@ -63,6 +70,13 @@ impl Show { println!(" {capability:?}"); } } + Info::Targets(SpirvSourceDep { shader_crate }) => { + let (source, targets) = Self::available_spirv_targets_iter(shader_crate)?; + println!("All available targets for rust-gpu version '{source}':"); + for target in targets { + println!("{target}"); + } + } } Ok(()) @@ -76,4 +90,32 @@ impl Show { let last_capability = spirv_builder::Capability::CacheControlsINTEL as u32; (0..=last_capability).filter_map(spirv_builder::Capability::from_u32) } + + /// List all available spirv targets, note: the targets from compile time of cargo-gpu and those + /// in the cache-directory will be picked up. + fn available_spirv_targets_iter( + shader_crate: &Path, + ) -> anyhow::Result<(SpirvSource, impl Iterator)> { + let source = SpirvSource::new(shader_crate, None, None)?; + let install_dir = source.install_dir()?; + if !install_dir.is_dir() { + bail!("rust-gpu version {} is not installed", source); + } + let dummy_metadata = query_metadata(&install_dir)?; + let target_specs_dir = update_target_specs_files(&source, &dummy_metadata, false)?; + + let mut targets = fs::read_dir(target_specs_dir)? + .filter_map(|entry| { + let file = entry.ok()?; + if file.path().is_file() { + if let Some(target) = file.file_name().to_string_lossy().strip_suffix(".json") { + return Some(target.to_owned()); + } + } + None + }) + .collect::>(); + targets.sort(); + Ok((source, targets.into_iter())) + } } diff --git a/crates/cargo-gpu/src/target_specs.rs b/crates/cargo-gpu/src/target_specs.rs new file mode 100644 index 0000000000..00deeef667 --- /dev/null +++ b/crates/cargo-gpu/src/target_specs.rs @@ -0,0 +1,135 @@ +//! This module deals with target specs, which are json metadata files that need to be passed to +//! rustc to add foreign targets such as `spirv_unknown_vulkan1.2`. +//! +//! There are 4 version ranges of `rustc_codegen_spirv` and they all need different handling of +//! their target specs: +//! * "ancient" versions such as 0.9.0 or earlier do not need target specs, just passing the target +//! string (`spirv-unknown-vulkan1.2`) directly is sufficient. We still prep target-specs for them +//! like the "legacy" variant below, spirv-builder +//! [will just ignore it](https://github.com/Rust-GPU/rust-gpu/blob/369122e1703c0c32d3d46f46fa11ccf12667af03/crates/spirv-builder/src/lib.rs#L987) +//! * "legacy" versions require target specs to compile, which is a requirement introduced by some +//! rustc version. Back then it was decided that cargo gpu would ship them, as they'd probably +//! never change, right? So now we're stuck with having to ship these "legacy" target specs with +//! cargo gpu *forever*. These are the symbol `legacy_target_specs::TARGET_SPECS`, with +//! `legacy_target_specs` being a **fixed** version of `rustc_codegen_spirv-target-specs`, +//! which must **never** update. +//! * As of [PR 256](https://github.com/Rust-GPU/rust-gpu/pull/256), `rustc_codegen_spirv` now has +//! a direct dependency on `rustc_codegen_spirv-target-specs`, allowing cargo gpu to pull the +//! required target specs directly from that dependency. At this point, the target specs are +//! still the same as the legacy target specs. +//! * The [edition 2024 PR](https://github.com/Rust-GPU/rust-gpu/pull/249) must update the +//! target specs to comply with newly added validation within rustc. This is why the new system +//! was implemented, so we can support both old and new target specs without having to worry +//! which version of cargo gpu you are using. It'll "just work". + +use crate::cache_dir; +use crate::spirv_source::{FindPackage as _, SpirvSource}; +use anyhow::Context as _; +use cargo_metadata::Metadata; +use std::path::{Path, PathBuf}; + +/// Extract legacy target specs from our executable into some directory +pub fn write_legacy_target_specs(target_spec_dir: &Path) -> anyhow::Result<()> { + std::fs::create_dir_all(target_spec_dir)?; + for (filename, contents) in legacy_target_specs::TARGET_SPECS { + let path = target_spec_dir.join(filename); + std::fs::write(&path, contents.as_bytes()) + .with_context(|| format!("writing legacy target spec file at [{}]", path.display()))?; + } + Ok(()) +} + +/// Copy spec files from one dir to another, assuming no subdirectories +fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> { + std::fs::create_dir_all(dst)?; + let dir = std::fs::read_dir(src)?; + for dir_entry in dir { + let file = dir_entry?; + let file_path = file.path(); + if file_path.is_file() { + std::fs::copy(file_path, dst.join(file.file_name()))?; + } + } + Ok(()) +} + +/// Computes the `target-specs` directory to use and updates the target spec files, if enabled. +pub fn update_target_specs_files( + source: &SpirvSource, + dummy_metadata: &Metadata, + update_files: bool, +) -> anyhow::Result { + log::info!( + "target-specs: Resolving target specs `{}`", + if update_files { + "and update them" + } else { + "without updating" + } + ); + + let mut target_specs_dst = source.install_dir()?.join("target-specs"); + if let Ok(target_specs) = dummy_metadata.find_package("rustc_codegen_spirv-target-specs") { + log::info!( + "target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`", + target_specs.manifest_path + ); + + let target_specs_src = target_specs + .manifest_path + .as_std_path() + .parent() + .and_then(|root| { + let src = root.join("target-specs"); + src.is_dir().then_some(src) + }) + .context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?; + log::info!( + "target-specs: found `rustc_codegen_spirv-target-specs` with `target-specs` directory `{}`", + target_specs_dst.display() + ); + + if source.is_path() { + // skip copy + log::info!( + "target-specs resolution: source is local path, use target-specs directly from `{}`", + target_specs_dst.display() + ); + target_specs_dst = target_specs_src; + } else { + // copy over the target-specs + log::info!( + "target-specs resolution: coping target-specs from `{}`{}", + target_specs_dst.display(), + if update_files { "" } else { " was skipped" } + ); + if update_files { + copy_spec_files(&target_specs_src, &target_specs_dst) + .context("copying target-specs json files")?; + } + } + } else { + // use legacy target specs bundled with cargo gpu + if source.is_path() { + // This is a stupid situation: + // * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`) + // * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout + // -> do what the old cargo gpu did, one global dir for all target specs + // and hope parallel runs don't shred each other + target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout"); + } + log::info!( + "target-specs resolution: legacy target specs in directory `{}`", + target_specs_dst.display() + ); + if update_files { + log::info!( + "target-specs: Writing legacy target specs into `{}`", + target_specs_dst.display() + ); + write_legacy_target_specs(&target_specs_dst)?; + } + } + + Ok(target_specs_dst) +} From d097aa1cdcabb2f78b634f39614287b269000df4 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 6 Jun 2025 19:55:57 +0200 Subject: [PATCH 093/162] make cargo-gpu specify Apache and MIT licence, same as rust-gpu (#82) --- LICENSE | 21 ---- LICENSE-APACHE | 201 ++++++++++++++++++++++++++++++++++++ LICENSE-MIT | 23 +++++ crates/cargo-gpu/Cargo.toml | 4 +- 4 files changed, 226 insertions(+), 23 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-MIT diff --git a/LICENSE b/LICENSE deleted file mode 100644 index a0a8cb4ae5..0000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 Rust GPU - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000000..11069edd79 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 9152876aed..2bbde3b2b7 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" description = "Generates shader .spv files from rust-gpu shader crates" repository = "https://github.com/Rust-GPU/cargo-gpu" readme = "../../README.md" -keywords = ["gpu", "compiler"] -build = "build.rs" +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 From e5744605020d9a94931519a17815e027db5fba01 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Wed, 25 Jun 2025 17:38:07 +0200 Subject: [PATCH 094/162] Various small fixes for Graphite (#80) * report path of shader crate when it can't be found * fix git parsing with no `?` in url * update spirv-builder * install: remove RUSTFLAGS env var --- Cargo.lock | 84 +++++++++++++++++++++++++++- Cargo.toml | 2 +- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/install.rs | 3 +- crates/cargo-gpu/src/spirv_source.rs | 59 +++++++++++++++++-- 5 files changed, 141 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbc2f16fb4..d1dad73b3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -134,6 +134,7 @@ checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", + "derive_builder", "semver", "serde", "serde_json", @@ -217,6 +218,72 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "directories" version = "5.0.1" @@ -300,6 +367,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -350,6 +423,12 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "2.9.0" @@ -754,7 +833,7 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e6d017d5504c4441a84edcc27f4eca61de6fc8cf#e6d017d5504c4441a84edcc27f4eca61de6fc8cf" dependencies = [ "rspirv", "serde", @@ -904,8 +983,9 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e6d017d5504c4441a84edcc27f4eca61de6fc8cf#e6d017d5504c4441a84edcc27f4eca61de6fc8cf" dependencies = [ + "cargo_metadata", "clap", "memchr", "notify", diff --git a/Cargo.toml b/Cargo.toml index 78a6b5261e..6ef4f03bfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e6d017d5504c4441a84edcc27f4eca61de6fc8cf", default-features = false } anyhow = "1.0.94" clap = { version = "4.5.37", features = ["derive"] } crossterm = "0.28.1" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 2bbde3b2b7..302b9d2f41 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -27,6 +27,7 @@ semver.workspace = true [dev-dependencies] test-log.workspace = true +cargo_metadata = { workspace = true, features = ["builder"] } [lints] workspace = true diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index d7a6894b33..50cfa13528 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -284,7 +284,8 @@ package = "rustc_codegen_spirv" .current_dir(&install_dir) .arg(format!("+{toolchain_channel}")) .args(["build", "--release"]) - .env_remove("RUSTC"); + .env_remove("RUSTC") + .env_remove("RUSTFLAGS"); if source.is_path() { build_command.args(["-p", "rustc_codegen_spirv", "--lib"]); } diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 28e93bd3c1..e21a075e67 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -88,8 +88,12 @@ impl SpirvSource { Self::CratesIO(Version::parse(rust_gpu_version)?) } } else { - Self::get_rust_gpu_deps_from_shader(shader_crate_path) - .context("get_rust_gpu_deps_from_shader")? + Self::get_rust_gpu_deps_from_shader(shader_crate_path).with_context(|| { + format!( + "get spirv-std dependency from shader crate '{}'", + shader_crate_path.display() + ) + })? }; Ok(source) } @@ -144,8 +148,8 @@ impl SpirvSource { let parse_git = || { let link = &source.repr.get(4..)?; let sharp_index = link.find('#')?; - let question_mark_index = link.find('?')?; - let url = link.get(..question_mark_index)?.to_owned(); + let url_end = link.find('?').unwrap_or(sharp_index); + let url = link.get(..url_end)?.to_owned(); let rev = link.get(sharp_index + 1..)?.to_owned(); Some(Self::Git { url, rev }) }; @@ -244,6 +248,7 @@ pub fn get_channel_from_rustc_codegen_spirv_build_script( #[cfg(test)] mod test { use super::*; + use cargo_metadata::{PackageBuilder, PackageId, Source}; #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { @@ -277,4 +282,50 @@ mod test { .unwrap(); assert_eq!("https___github_com_Rust-GPU_rust-gpu+86fc4803", &name); } + + #[test_log::test] + fn parse_git_with_rev() { + let source = parse_git( + "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc4803", + ); + assert_eq!( + source, + SpirvSource::Git { + url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), + rev: "86fc4803".to_owned(), + } + ) + } + + #[test_log::test] + fn parse_git_no_question_mark() { + // taken directly from Graphite + let source = parse_git( + "git+https://github.com/Rust-GPU/rust-gpu.git#6e2c84d4fe64e32df4c060c5a7f3e35a32e45421", + ); + assert_eq!( + source, + SpirvSource::Git { + url: "https://github.com/Rust-GPU/rust-gpu.git".to_owned(), + rev: "6e2c84d4fe64e32df4c060c5a7f3e35a32e45421".to_owned(), + } + ) + } + + fn parse_git(source: &str) -> SpirvSource { + let package = PackageBuilder::new( + "spirv-std", + Version::new(0, 9, 0), + PackageId { + repr: "".to_owned(), + }, + "", + ) + .source(Some(Source { + repr: source.to_owned(), + })) + .build() + .unwrap(); + SpirvSource::parse_spirv_std_source_and_version(&package).unwrap() + } } From 6a192d824ffa8fc4aa7870c957077fd647d3369b Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 4 Jul 2025 13:36:45 +0200 Subject: [PATCH 095/162] prevent env vars leaking into install (#97) * prevent env vars from leaking into install * fix clippy * fix clippy in test code --- crates/cargo-gpu/src/install.rs | 30 ++++++++++++++++++++-------- crates/cargo-gpu/src/spirv_source.rs | 6 +++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 50cfa13528..48e1ab8b1e 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -7,6 +7,7 @@ use crate::target_specs::update_target_specs_files; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; use spirv_builder::SpirvBuilder; +use std::env; use std::path::{Path, PathBuf}; /// Represents a functional backend installation, whether it was cached or just installed. @@ -279,20 +280,33 @@ package = "rustc_codegen_spirv" } crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source,); - let mut build_command = std::process::Command::new("cargo"); - build_command + let mut cargo = std::process::Command::new("cargo"); + cargo .current_dir(&install_dir) .arg(format!("+{toolchain_channel}")) - .args(["build", "--release"]) - .env_remove("RUSTC") - .env_remove("RUSTFLAGS"); + .args(["build", "--release"]); if source.is_path() { - build_command.args(["-p", "rustc_codegen_spirv", "--lib"]); + cargo.args(["-p", "rustc_codegen_spirv", "--lib"]); } - log::debug!("building artifacts with `{build_command:?}`"); + // Clear Cargo environment variables that we don't want to leak into the + // inner invocation of Cargo and mess with our `rustc_codegen_spirv` build. + for (key, _) in env::vars_os() { + let remove = key.to_str().is_some_and(|st| { + st.starts_with("CARGO_FEATURES_") || st.starts_with("CARGO_CFG_") + }); + if remove { + cargo.env_remove(key); + } + } + cargo + .env_remove("RUSTC") + .env_remove("RUSTFLAGS") + // ignore any externally supplied target dir, we want to build it in our cache dir + .env_remove("CARGO_TARGET_DIR"); - build_command + log::debug!("building artifacts with `{cargo:?}`"); + cargo .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) .output() diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index e21a075e67..6bbcdb5369 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -294,7 +294,7 @@ mod test { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), rev: "86fc4803".to_owned(), } - ) + ); } #[test_log::test] @@ -309,7 +309,7 @@ mod test { url: "https://github.com/Rust-GPU/rust-gpu.git".to_owned(), rev: "6e2c84d4fe64e32df4c060c5a7f3e35a32e45421".to_owned(), } - ) + ); } fn parse_git(source: &str) -> SpirvSource { @@ -317,7 +317,7 @@ mod test { "spirv-std", Version::new(0, 9, 0), PackageId { - repr: "".to_owned(), + repr: String::new(), }, "", ) From 7fc4560ab7664bc69220e059e2785a9c85631f73 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Mon, 7 Jul 2025 06:40:07 -0300 Subject: [PATCH 096/162] fix: better output when consent is required without at a TTY (#98) Fixes #95 --- crates/cargo-gpu/src/install_toolchain.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/install_toolchain.rs b/crates/cargo-gpu/src/install_toolchain.rs index 027a90d759..98d35d59ab 100644 --- a/crates/cargo-gpu/src/install_toolchain.rs +++ b/crates/cargo-gpu/src/install_toolchain.rs @@ -1,6 +1,9 @@ //! toolchain installation logic use anyhow::Context as _; +use crossterm::tty::IsTty as _; + +use crate::user_output; /// Use `rustup` to install the toolchain and components, if not already installed. /// @@ -103,9 +106,17 @@ fn get_consent_for_toolchain_install( if skip_toolchain_install_consent { return Ok(()); } + + if !std::io::stdout().is_tty() { + user_output!("No TTY detected so can't ask for consent to install Rust toolchain."); + log::error!("Attempted to ask for consent when there's no TTY"); + #[expect(clippy::exit, reason = "can't ask for user consent if there's no TTY")] + std::process::exit(1); + } + log::debug!("asking for consent to install the required toolchain"); crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; - crate::user_output!("{prompt} [y/n]: \n"); + crate::user_output!("{prompt} [y/n]: "); let mut input = crossterm::event::read().context("reading crossterm event")?; if let crossterm::event::Event::Key(crossterm::event::KeyEvent { From 98931f8b9aa7471c3f0691f87174f4b478d86bc8 Mon Sep 17 00:00:00 2001 From: Timur Tugushev Date: Tue, 22 Jul 2025 19:04:14 +0300 Subject: [PATCH 097/162] Fix cargo-gpu in build script failing when called by Miri or Clippy (#101) * Remove `RUSTC_WRAPPER` env * use new CargoCmd from spirv-builder to handle env vars centrally * Update spirv-builder --------- Co-authored-by: Firestar99 --- Cargo.lock | 5 +++-- Cargo.toml | 2 +- crates/cargo-gpu/src/install.rs | 23 +++-------------------- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1dad73b3f..7cf3ee45ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -833,7 +833,7 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e6d017d5504c4441a84edcc27f4eca61de6fc8cf#e6d017d5504c4441a84edcc27f4eca61de6fc8cf" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850#3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850" dependencies = [ "rspirv", "serde", @@ -983,10 +983,11 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e6d017d5504c4441a84edcc27f4eca61de6fc8cf#e6d017d5504c4441a84edcc27f4eca61de6fc8cf" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850#3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850" dependencies = [ "cargo_metadata", "clap", + "log", "memchr", "notify", "raw-string", diff --git a/Cargo.toml b/Cargo.toml index 6ef4f03bfe..02b1eadf9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e6d017d5504c4441a84edcc27f4eca61de6fc8cf", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850", default-features = false } anyhow = "1.0.94" clap = { version = "4.5.37", features = ["derive"] } crossterm = "0.28.1" diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 48e1ab8b1e..cfbfdfb00a 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -7,7 +7,6 @@ use crate::target_specs::update_target_specs_files; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; use spirv_builder::SpirvBuilder; -use std::env; use std::path::{Path, PathBuf}; /// Represents a functional backend installation, whether it was cached or just installed. @@ -279,8 +278,8 @@ package = "rustc_codegen_spirv" .context("remove Cargo.lock")?; } - crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source,); - let mut cargo = std::process::Command::new("cargo"); + crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source); + let mut cargo = spirv_builder::cargo_cmd::CargoCmd::new(); cargo .current_dir(&install_dir) .arg(format!("+{toolchain_channel}")) @@ -289,23 +288,7 @@ package = "rustc_codegen_spirv" cargo.args(["-p", "rustc_codegen_spirv", "--lib"]); } - // Clear Cargo environment variables that we don't want to leak into the - // inner invocation of Cargo and mess with our `rustc_codegen_spirv` build. - for (key, _) in env::vars_os() { - let remove = key.to_str().is_some_and(|st| { - st.starts_with("CARGO_FEATURES_") || st.starts_with("CARGO_CFG_") - }); - if remove { - cargo.env_remove(key); - } - } - cargo - .env_remove("RUSTC") - .env_remove("RUSTFLAGS") - // ignore any externally supplied target dir, we want to build it in our cache dir - .env_remove("CARGO_TARGET_DIR"); - - log::debug!("building artifacts with `{cargo:?}`"); + log::debug!("building artifacts with `{cargo}`"); cargo .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) From a2ad3574dd32142ff661994e0d79448a45d18f47 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Thu, 24 Jul 2025 21:40:15 +0300 Subject: [PATCH 098/162] Update direct dependencies --- Cargo.lock | 732 ++++++++++++++++++++------- Cargo.toml | 21 +- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/spirv_source.rs | 5 +- 4 files changed, 577 insertions(+), 182 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cf3ee45ef..d9e1d728a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,11 +102,12 @@ name = "cargo-gpu" version = "0.1.0" dependencies = [ "anyhow", - "cargo_metadata", + "cargo-util-schemas", + "cargo_metadata 0.21.0", "clap", "crossterm", "directories", - "env_logger 0.10.2", + "env_logger", "log", "relative-path", "rustc_codegen_spirv-target-specs", @@ -126,6 +127,31 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo-platform" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-util-schemas" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830" +dependencies = [ + "semver", + "serde", + "serde-untagged", + "serde-value", + "thiserror", + "toml 0.8.22", + "unicode-xid", + "url", +] + [[package]] name = "cargo_metadata" version = "0.19.2" @@ -133,12 +159,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", - "cargo-platform", + "cargo-platform 0.1.9", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cargo_metadata" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868" +dependencies = [ + "camino", + "cargo-platform 0.2.0", + "cargo-util-schemas", "derive_builder", "semver", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror", ] [[package]] @@ -193,14 +234,25 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "crossterm" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ "bitflags 2.9.0", "crossterm_winapi", + "derive_more", + "document-features", "mio", "parking_lot", "rustix", @@ -284,47 +336,76 @@ dependencies = [ "syn", ] +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] -name = "env_filter" -version = "0.1.3" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "log", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "env_logger" -version = "0.10.2" +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + +[[package]] +name = "env_filter" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ - "humantime", - "is-terminal", "log", "regex", - "termcolor", ] [[package]] @@ -336,6 +417,7 @@ dependencies = [ "anstream", "anstyle", "env_filter", + "jiff", "log", ] @@ -345,6 +427,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "erased-serde" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +dependencies = [ + "serde", + "typeid", +] + [[package]] name = "errno" version = "0.3.11" @@ -373,6 +465,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -412,16 +513,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hermit-abi" -version = "0.5.0" +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] [[package]] -name = "humantime" -version = "2.2.0" +name = "icu_normalizer" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] [[package]] name = "ident_case" @@ -429,6 +604,27 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indexmap" version = "2.9.0" @@ -468,17 +664,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -491,6 +676,30 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "kqueue" version = "1.0.8" @@ -536,9 +745,21 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.15" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "lock_api" @@ -621,6 +842,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -633,6 +863,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -659,15 +898,45 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -740,13 +1009,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -795,9 +1064,12 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "relative-path" -version = "1.9.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0" +dependencies = [ + "serde", +] [[package]] name = "remove_dir_all" @@ -843,9 +1115,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.44" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.9.0", "errno", @@ -893,6 +1165,27 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-untagged" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" +dependencies = [ + "erased-serde", + "serde", + "typeid", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -906,9 +1199,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -925,6 +1218,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +dependencies = [ + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -985,7 +1287,7 @@ name = "spirv-builder" version = "0.9.0" source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850#3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850" dependencies = [ - "cargo_metadata", + "cargo_metadata 0.19.2", "clap", "log", "memchr", @@ -995,9 +1297,15 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -1016,73 +1324,55 @@ dependencies = [ ] [[package]] -name = "tempdir" -version = "0.3.7" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "rand", - "remove_dir_all", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "tempdir" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" dependencies = [ - "winapi-util", + "rand", + "remove_dir_all", ] [[package]] name = "test-log" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f46083d221181166e5b6f6b1e5f1d499f3a76888826e6cb1d057554157cd0f" +checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b" dependencies = [ - "env_logger 0.11.8", + "env_logger", "test-log-macros", "tracing-subscriber", ] [[package]] name = "test-log-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888d0c3c6db53c0fdab160d2ed5e12ba745383d3e85813f2ea0f2b1475ab553f" +checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" dependencies = [ "proc-macro2", "quote", "syn", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1106,6 +1396,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "toml" version = "0.8.22" @@ -1113,11 +1413,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.8", + "toml_datetime 0.6.9", "toml_edit", ] +[[package]] +name = "toml" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac" +dependencies = [ + "indexmap", + "serde", + "serde_spanned 1.0.0", + "toml_datetime 0.7.0", + "toml_parser", + "toml_writer", + "winnow", +] + [[package]] name = "toml_datetime" version = "0.6.9" @@ -1127,6 +1442,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +dependencies = [ + "serde", +] + [[package]] name = "toml_edit" version = "0.22.26" @@ -1135,18 +1459,33 @@ checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.8", + "toml_datetime 0.6.9", "toml_write", "winnow", ] +[[package]] +name = "toml_parser" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +dependencies = [ + "winnow", +] + [[package]] name = "toml_write" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +[[package]] +name = "toml_writer" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" + [[package]] name = "tracing" version = "0.1.41" @@ -1195,12 +1534,47 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1260,22 +1634,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -1284,22 +1649,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -1308,46 +1658,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1360,48 +1692,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1410,21 +1718,105 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.7.7" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "xtask" version = "0.1.0" dependencies = [ "anyhow", "clap", - "env_logger 0.10.2", + "env_logger", "log", "tempdir", - "toml", + "toml 0.9.2", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 02b1eadf9e..c3a8ccc3f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,19 +14,20 @@ resolver = "2" [workspace.dependencies] spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850", default-features = false } -anyhow = "1.0.94" +anyhow = "1.0.98" clap = { version = "4.5.37", features = ["derive"] } -crossterm = "0.28.1" -directories = "5.0.1" -env_logger = "0.10" +crossterm = "0.29.0" +directories = "6.0.0" +env_logger = "0.11.8" log = "0.4" -relative-path = "1.9.3" -serde = { version = "1.0.214", features = ["derive"] } -serde_json = "1.0.132" -toml = "0.8.19" +relative-path = "2.0.1" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.141" +toml = "0.9.2" tempdir = "0.3.7" -test-log = "0.2.16" -cargo_metadata = "0.19.2" +test-log = "0.2.18" +cargo_metadata = "0.21.0" +cargo-util-schemas = "0.8.2" semver = "1.0.26" # This crate MUST NEVER be upgraded, we need this particular "first" version to support old rust-gpu builds diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 302b9d2f41..8ef4a6c3a1 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -28,6 +28,7 @@ semver.workspace = true [dev-dependencies] test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } +cargo-util-schemas = "0.8.2" [lints] workspace = true diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 6bbcdb5369..4c095e0886 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -209,7 +209,7 @@ impl FindPackage for Metadata { if let Some(package) = self .packages .iter() - .find(|package| package.name.eq(crate_name)) + .find(|package| package.name.as_str() == crate_name) { log::trace!(" found `{}` version `{}`", package.name, package.version); Ok(package) @@ -249,6 +249,7 @@ pub fn get_channel_from_rustc_codegen_spirv_build_script( mod test { use super::*; use cargo_metadata::{PackageBuilder, PackageId, Source}; + use cargo_util_schemas::manifest::PackageName; #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { @@ -314,7 +315,7 @@ mod test { fn parse_git(source: &str) -> SpirvSource { let package = PackageBuilder::new( - "spirv-std", + PackageName::new("spirv-std".to_owned()).unwrap(), Version::new(0, 9, 0), PackageId { repr: String::new(), From 39b238f25b7652ba79d153626e252321942cb558 Mon Sep 17 00:00:00 2001 From: Nazar Mokrynskyi Date: Mon, 28 Jul 2025 15:20:28 +0300 Subject: [PATCH 099/162] Update rust-gpu dependency (#107) --- Cargo.lock | 186 ++++++++++++++++++++++++++++++----------------------- Cargo.toml | 4 +- 2 files changed, 107 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9e1d728a8..9b68563623 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,7 +103,7 @@ version = "0.1.0" dependencies = [ "anyhow", "cargo-util-schemas", - "cargo_metadata 0.21.0", + "cargo_metadata", "clap", "crossterm", "directories", @@ -118,15 +118,6 @@ dependencies = [ "test-log", ] -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - [[package]] name = "cargo-platform" version = "0.2.0" @@ -152,20 +143,6 @@ dependencies = [ "url", ] -[[package]] -name = "cargo_metadata" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" -dependencies = [ - "camino", - "cargo-platform 0.1.9", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cargo_metadata" version = "0.21.0" @@ -173,7 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868" dependencies = [ "camino", - "cargo-platform 0.2.0", + "cargo-platform", "cargo-util-schemas", "derive_builder", "semver", @@ -190,9 +167,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.37" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -200,9 +177,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -212,9 +189,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", @@ -447,18 +424,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "fnv" version = "1.0.7" @@ -637,11 +602,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.0", "inotify-sys", "libc", ] @@ -655,15 +620,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -702,9 +658,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" dependencies = [ "kqueue-sys", "libc", @@ -740,7 +696,6 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.9.0", "libc", - "redox_syscall", ] [[package]] @@ -806,12 +761,11 @@ dependencies = [ [[package]] name = "notify" -version = "7.0.0" +version = "8.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" +checksum = "3163f59cd3fa0e9ef8c32f242966a7b9994fd7378366099593e0e73077cd8c97" dependencies = [ "bitflags 2.9.0", - "filetime", "fsevent-sys", "inotify", "kqueue", @@ -820,17 +774,14 @@ dependencies = [ "mio", "notify-types", "walkdir", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "notify-types" -version = "1.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" -dependencies = [ - "instant", -] +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" [[package]] name = "nu-ansi-term" @@ -898,7 +849,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1105,7 +1056,7 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850#3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3df836eb9d7b01344f52737bf9a310d1fb5a0c26#3df836eb9d7b01344f52737bf9a310d1fb5a0c26" dependencies = [ "rspirv", "serde", @@ -1285,9 +1236,9 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850#3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3df836eb9d7b01344f52737bf9a310d1fb5a0c26#3df836eb9d7b01344f52737bf9a310d1fb5a0c26" dependencies = [ - "cargo_metadata 0.19.2", + "cargo_metadata", "clap", "log", "memchr", @@ -1640,7 +1591,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1649,7 +1600,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", ] [[package]] @@ -1658,14 +1618,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -1674,48 +1650,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.7.12" diff --git a/Cargo.toml b/Cargo.toml index c3a8ccc3f0..75d67998ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,9 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3e89e6cc7b32b51db51d75b5f558ccd7ecf5b850", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3df836eb9d7b01344f52737bf9a310d1fb5a0c26", default-features = false } anyhow = "1.0.98" -clap = { version = "4.5.37", features = ["derive"] } +clap = { version = "4.5.41", features = ["derive"] } crossterm = "0.29.0" directories = "6.0.0" env_logger = "0.11.8" From 91286dd92ddadaa8f3992cca964f3928ca896402 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Sat, 30 Aug 2025 15:06:08 +0200 Subject: [PATCH 100/162] Implement `Default` for `InstalledBackend` (#108) --- crates/cargo-gpu/src/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index cfbfdfb00a..e5f7359411 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -10,7 +10,7 @@ use spirv_builder::SpirvBuilder; use std::path::{Path, PathBuf}; /// Represents a functional backend installation, whether it was cached or just installed. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] #[non_exhaustive] pub struct InstalledBackend { /// path to the `rustc_codegen_spirv` dylib From 265bba797cfee3b313bbc4b49e3bb73a7eacc2a6 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 18 Sep 2025 12:16:32 +1200 Subject: [PATCH 101/162] feature: use --package and -p as an alias for --shader-crate (#109) --- crates/cargo-gpu/src/install.rs | 3 ++- crates/cargo-gpu/src/target_specs.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index e5f7359411..95ff906531 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -65,7 +65,8 @@ impl InstalledBackend { #[non_exhaustive] pub struct Install { /// Directory containing the shader crate to compile. - #[clap(long, default_value = "./")] + #[clap(long, alias("package"), short_alias('p'), default_value = "./")] + #[serde(alias = "package")] pub shader_crate: PathBuf, #[expect( diff --git a/crates/cargo-gpu/src/target_specs.rs b/crates/cargo-gpu/src/target_specs.rs index 00deeef667..eef8dca9c0 100644 --- a/crates/cargo-gpu/src/target_specs.rs +++ b/crates/cargo-gpu/src/target_specs.rs @@ -99,7 +99,7 @@ pub fn update_target_specs_files( } else { // copy over the target-specs log::info!( - "target-specs resolution: coping target-specs from `{}`{}", + "target-specs resolution: copying target-specs from `{}`{}", target_specs_dst.display(), if update_files { "" } else { " was skipped" } ); @@ -124,7 +124,7 @@ pub fn update_target_specs_files( ); if update_files { log::info!( - "target-specs: Writing legacy target specs into `{}`", + "target-specs: writing legacy target specs into `{}`", target_specs_dst.display() ); write_legacy_target_specs(&target_specs_dst)?; From e3c0cd135f90e3f9a1706b4e6bddcb1bd00444cf Mon Sep 17 00:00:00 2001 From: Timur Tugushev Date: Fri, 19 Sep 2025 00:32:29 +0300 Subject: [PATCH 102/162] Fix differing path display on Windows (#111) --- Cargo.lock | 11 +++++++++-- Cargo.toml | 1 + crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b68563623..64a9410448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,7 @@ dependencies = [ "clap", "crossterm", "directories", + "dunce", "env_logger", "log", "relative-path", @@ -352,7 +353,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -375,6 +376,12 @@ dependencies = [ "litrs", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "env_filter" version = "0.1.3" @@ -1074,7 +1081,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 75d67998ca..656c071167 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ test-log = "0.2.18" cargo_metadata = "0.21.0" cargo-util-schemas = "0.8.2" semver = "1.0.26" +dunce = "1.0.5" # This crate MUST NEVER be upgraded, we need this particular "first" version to support old rust-gpu builds legacy_target_specs = { package = "rustc_codegen_spirv-target-specs", version = "0.9.0", features = ["include_str"] } diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 8ef4a6c3a1..8de68b2c8f 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -24,6 +24,7 @@ serde.workspace = true serde_json.workspace = true crossterm.workspace = true semver.workspace = true +dunce.workspace = true [dev-dependencies] test-log.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 1bb50788a8..2a7f1586be 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -76,12 +76,12 @@ impl Build { self.build.output_dir.display() ); std::fs::create_dir_all(&self.build.output_dir)?; - let canonicalized = self.build.output_dir.canonicalize()?; + let canonicalized = dunce::canonicalize(&self.build.output_dir)?; log::debug!("canonicalized output dir: {}", canonicalized.display()); self.build.output_dir = canonicalized; // Ensure the shader crate exists - self.install.shader_crate = self.install.shader_crate.canonicalize()?; + self.install.shader_crate = dunce::canonicalize(&self.install.shader_crate)?; anyhow::ensure!( self.install.shader_crate.exists(), "shader crate '{}' does not exist. (Current dir is '{}')", From 970c9bbede4884e843c079558bac8e7ce74a33d5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 21:41:24 +1200 Subject: [PATCH 103/162] fix: ensure toolchain components are installed, even if artifacts exist (#114) --- crates/cargo-gpu/src/install.rs | 14 +++++++------- crates/cargo-gpu/src/lib.rs | 4 +--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 95ff906531..aa3dfa14aa 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -264,14 +264,14 @@ package = "rustc_codegen_spirv" let target_spec_dir = update_target_specs_files(&source, &dummy_metadata, !skip_rebuild) .context("writing target spec files")?; - if !skip_rebuild { - log::debug!("ensure_toolchain_and_components_exist"); - crate::install_toolchain::ensure_toolchain_and_components_exist( - &toolchain_channel, - self.auto_install_rust_toolchain, - ) - .context("ensuring toolchain and components exist")?; + log::debug!("ensure_toolchain_and_components_exist"); + crate::install_toolchain::ensure_toolchain_and_components_exist( + &toolchain_channel, + self.auto_install_rust_toolchain, + ) + .context("ensuring toolchain and components exist")?; + if !skip_rebuild { // to prevent unsupported version errors when using older toolchains if !source.is_path() { log::debug!("remove Cargo.lock"); diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 323743b4b0..1be7abb234 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -145,10 +145,8 @@ impl Command { command.build.watch = false; command.run()?; command.build.watch = true; - command.run()?; - } else { - command.run()?; } + command.run()?; } Self::Show(show) => show.run()?, Self::DumpUsage => dump_full_usage_for_readme()?, From 9561c1641a8cdd8fb59b65dde1c3d150337b7d11 Mon Sep 17 00:00:00 2001 From: Timur Tugushev Date: Sun, 21 Sep 2025 22:48:23 +0300 Subject: [PATCH 104/162] Replace `tempdir` with `tempfile` by RUSTSEC-2018-0017 (#115) --- Cargo.lock | 113 +++++++++++++++++++-------------------- Cargo.toml | 2 +- crates/xtask/Cargo.toml | 2 +- crates/xtask/src/main.rs | 2 +- 4 files changed, 59 insertions(+), 60 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64a9410448..d42db1259a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -431,6 +431,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "fnv" version = "1.0.7" @@ -456,20 +462,26 @@ dependencies = [ ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] @@ -762,7 +774,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -914,32 +926,10 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_core" -version = "0.3.1" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "raw-string" @@ -947,15 +937,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.5.11" @@ -971,7 +952,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom", + "getrandom 0.2.16", "libredox", "thiserror", ] @@ -1029,15 +1010,6 @@ dependencies = [ "serde", ] -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rspirv" version = "0.12.0+sdk-1.3.268.0" @@ -1293,13 +1265,16 @@ dependencies = [ ] [[package]] -name = "tempdir" -version = "0.3.7" +name = "tempfile" +version = "3.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" dependencies = [ - "rand", - "remove_dir_all", + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.60.2", ] [[package]] @@ -1561,6 +1536,24 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1756,6 +1749,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + [[package]] name = "writeable" version = "0.6.1" @@ -1770,7 +1769,7 @@ dependencies = [ "clap", "env_logger", "log", - "tempdir", + "tempfile", "toml 0.9.2", ] diff --git a/Cargo.toml b/Cargo.toml index 656c071167..62ca2eca20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ relative-path = "2.0.1" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.141" toml = "0.9.2" -tempdir = "0.3.7" +tempfile = "3.22" test-log = "0.2.18" cargo_metadata = "0.21.0" cargo-util-schemas = "0.8.2" diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index 0573d57610..afe0178a53 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -8,7 +8,7 @@ anyhow.workspace = true clap.workspace = true env_logger.workspace = true log.workspace = true -tempdir.workspace = true +tempfile.workspace = true toml.workspace = true [lints] diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index d767a2c8cd..8eec0beb14 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -152,7 +152,7 @@ fn main() { cmd(["cargo", "install", "--path", "crates/cargo-gpu"]).unwrap(); log::info!("setup project"); - let dir = tempdir::TempDir::new("test-shader-output").unwrap(); + let dir = tempfile::TempDir::with_prefix("test-shader-output").unwrap(); let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); overwriter.replace_output_dir(dir.path()).unwrap(); From 0cbd863017f3f65e4f544e4a34e79afc2c4afc9f Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 1 Oct 2025 15:19:33 +0200 Subject: [PATCH 105/162] ci: use github provided rustup --- .github/workflows/push.yaml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index df17c6b594..82929b56c5 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -43,13 +43,7 @@ jobs: env: RUST_LOG: debug steps: - - uses: actions/checkout@v2 - - uses: moonrepo/setup-rust@v1 - - uses: extractions/setup-just@v2 - - name: Install Rust toolchain - run: | - rustup default stable - rustup update + - uses: actions/checkout@v4 - name: Fetch root dependencies run: cargo fetch --locked - name: Fetch shader-crate-template dependencies @@ -63,11 +57,11 @@ jobs: lints: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: moonrepo/setup-rust@v1 - - uses: extractions/setup-just@v2 + - uses: actions/checkout@v4 - uses: cargo-bins/cargo-binstall@main - - run: cargo binstall cargo-shear + - name: Install cargo-shear + run: cargo binstall cargo-shear + - run: cargo fetch --locked - run: cargo clippy -- --deny warnings - run: cargo fmt --check - run: cargo shear From 09829681cbe3866b6d1fc2ee0eae83aa77855b3e Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Wed, 8 Oct 2025 17:37:47 +0200 Subject: [PATCH 106/162] Increase resilience towards partial cache clears (#119) --- crates/cargo-gpu/src/install.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index aa3dfa14aa..2aa7bde7d6 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -223,24 +223,26 @@ package = "rustc_codegen_spirv" std::env::consts::DLL_SUFFIX ); - let dest_dylib_path; - if source.is_path() { - dest_dylib_path = install_dir - .join("target") - .join("release") - .join(&dylib_filename); + let (dest_dylib_path, skip_rebuild) = if source.is_path() { + ( + install_dir + .join("target") + .join("release") + .join(&dylib_filename), + // if `source` is a path, always rebuild + false, + ) } else { - dest_dylib_path = install_dir.join(&dylib_filename); - if dest_dylib_path.is_file() { - log::info!( - "cargo-gpu artifacts are already installed in '{}'", - install_dir.display() - ); + let dest_dylib_path = install_dir.join(&dylib_filename); + let artifacts_found = dest_dylib_path.is_file() + && install_dir.join("Cargo.toml").is_file() + && install_dir.join("src").join("lib.rs").is_file(); + if artifacts_found { + log::info!("cargo-gpu artifacts found in '{}'", install_dir.display()); } - } + (dest_dylib_path, artifacts_found && !self.rebuild_codegen) + }; - // if `source` is a path, always rebuild - let skip_rebuild = !source.is_path() && dest_dylib_path.is_file() && !self.rebuild_codegen; if skip_rebuild { log::info!("...and so we are aborting the install step."); } else { From eb5f8dbe3aef5a8d94886194fb3ba14caae80e2f Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 7 Nov 2025 13:30:01 +0100 Subject: [PATCH 107/162] Add `TestEnv` for Nextest support (#120) * template: remove glam, use spirv-std reexport selecting the correct glam version manually when testing various spirv-std versions is hard * Update `shader-crate-template`'s `spirv-std` otherwise I can't build it * Tests: Add `TestEnv`, to manage temp dir creation and cleanup, nextest compatible * Tests: fix clippy * Tests: fix windows test failing on CI * Tests: document `TestEnv` --- Cargo.lock | 1 + Cargo.toml | 4 +- crates/cargo-gpu/Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 2 - crates/cargo-gpu/src/config.rs | 100 ++++++++++++--------- crates/cargo-gpu/src/lib.rs | 20 ++--- crates/cargo-gpu/src/spirv_source.rs | 6 +- crates/cargo-gpu/src/test.rs | 113 ++++++++++++++++++------ crates/shader-crate-template/Cargo.lock | 11 ++- crates/shader-crate-template/Cargo.toml | 10 +-- crates/shader-crate-template/src/lib.rs | 2 +- 11 files changed, 167 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d42db1259a..f7c2b207a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,6 +116,7 @@ dependencies = [ "serde", "serde_json", "spirv-builder", + "tempfile", "test-log", ] diff --git a/Cargo.toml b/Cargo.toml index 62ca2eca20..32cd239567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,9 @@ members = [ 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" + "crates/shader-crate-template", + # Testing infra may copy the `shader-crate-template` into subdirs of target + "target", ] resolver = "2" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 8de68b2c8f..ba883834e2 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -27,6 +27,7 @@ semver.workspace = true dunce.workspace = true [dev-dependencies] +tempfile.workspace = true test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } cargo-util-schemas = "0.8.2" diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index 2a7f1586be..aa89fe2265 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -181,8 +181,6 @@ mod test { #[test_log::test] fn builder_from_params() { - crate::test::tests_teardown(); - let shader_crate_path = crate::test::shader_crate_template_path(); let output_dir = shader_crate_path.join("shaders"); diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index f1a67fa9cb..44a7de773a 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -86,11 +86,13 @@ impl Config { mod test { use super::*; + use crate::test::TestEnv; use std::io::Write as _; #[test_log::test] fn booleans_from_cli() { - let shader_crate_path = crate::test::shader_crate_test_path(); + let _env = TestEnv::new(); + let shader_crate_path = _env.setup_shader_crate().unwrap(); let args = Config::clap_command_with_cargo_config( &shader_crate_path, @@ -108,47 +110,57 @@ mod test { #[test_log::test] fn booleans_from_cargo() { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "release = false", - "[package.metadata.rust-gpu.install]", - "auto-install-rust-toolchain = true", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); + let _env = TestEnv::new(); + let shader_crate_path = _env + .setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "release = false", + "[package.metadata.rust-gpu.install]", + "auto-install-rust-toolchain = true", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert!(!args.build.spirv_builder.release); assert!(args.install.auto_install_rust_toolchain); } - fn update_cargo_output_dir() -> std::path::PathBuf { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "output-dir = \"/the/moon\"", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); - shader_crate_path + fn update_cargo_output_dir(_env: &TestEnv) -> std::path::PathBuf { + _env.setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "output-dir = \"/the/moon\"", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap() } #[test_log::test] fn string_from_cargo() { - let shader_crate_path = update_cargo_output_dir(); + let _env = TestEnv::new(); + let shader_crate_path = update_cargo_output_dir(&_env); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); if cfg!(target_os = "windows") { - assert_eq!(args.build.output_dir, std::path::Path::new("C:/the/moon")); + assert!( + args.build + .output_dir + .to_str() + .unwrap() + .ends_with("/the/moon"), + "Actual: {:?}", + args.build.output_dir + ); } else { assert_eq!(args.build.output_dir, std::path::Path::new("/the/moon")); } @@ -156,7 +168,8 @@ mod test { #[test_log::test] fn string_from_cargo_overwritten_by_cli() { - let shader_crate_path = update_cargo_output_dir(); + let _env = TestEnv::new(); + let shader_crate_path = update_cargo_output_dir(&_env); let args = Config::clap_command_with_cargo_config( &shader_crate_path, @@ -173,17 +186,19 @@ mod test { #[test_log::test] fn arrays_from_cargo() { - let shader_crate_path = crate::test::shader_crate_test_path(); - let mut file = crate::test::overwrite_shader_cargo_toml(&shader_crate_path); - file.write_all( - [ - "[package.metadata.rust-gpu.build]", - "capabilities = [\"AtomicStorage\", \"Matrix\"]", - ] - .join("\n") - .as_bytes(), - ) - .unwrap(); + let _env = TestEnv::new(); + let shader_crate_path = _env + .setup_shader_crate_with_cargo_toml(|file| { + file.write_all( + [ + "[package.metadata.rust-gpu.build]", + "capabilities = [\"AtomicStorage\", \"Matrix\"]", + ] + .join("\n") + .as_bytes(), + ) + }) + .unwrap(); let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); assert_eq!( @@ -197,7 +212,8 @@ mod test { #[test_log::test] fn rename_manifest_parse() { - let shader_crate_path = crate::test::shader_crate_test_path(); + let _env = TestEnv::new(); + let shader_crate_path = _env.setup_shader_crate().unwrap(); let args = Config::clap_command_with_cargo_config( &shader_crate_path, diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 1be7abb234..ff8c1b9c14 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -50,8 +50,6 @@ //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. -use anyhow::Context as _; - use crate::dump_usage::dump_full_usage_for_readme; use build::Build; use show::Show; @@ -171,21 +169,19 @@ pub struct Cli { /// # Errors /// may fail if we can't find the user home directory #[inline] +#[cfg(not(test))] +#[expect(clippy::cfg_not_test, reason = "tests use different cache_dir")] pub fn cache_dir() -> anyhow::Result { - let dir = directories::BaseDirs::new() + use anyhow::Context as _; + Ok(directories::BaseDirs::new() .with_context(|| "could not find the user home directory")? .cache_dir() - .join("rust-gpu"); - - Ok(if cfg!(test) { - let thread_id = std::thread::current().id(); - let id = format!("{thread_id:?}").replace('(', "-").replace(')', ""); - dir.join("tests").join(id) - } else { - dir - }) + .join("rust-gpu")) } +#[cfg(test)] +pub use test::test_cache_dir as cache_dir; + /// Returns a string suitable to use as a directory. /// /// Created from the spirv-builder source dep and the rustc channel. diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index 4c095e0886..f33c2839f4 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -248,6 +248,7 @@ pub fn get_channel_from_rustc_codegen_spirv_build_script( #[cfg(test)] mod test { use super::*; + use crate::test::TestEnv; use cargo_metadata::{PackageBuilder, PackageId, Source}; use cargo_util_schemas::manifest::PackageName; @@ -259,7 +260,7 @@ mod test { source, SpirvSource::Git { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "86fc48032c4cd4afb74f1d81ae859711d20386a1".to_owned() + rev: "2aa4d4f8a8ba73103501562cfca17b8163e5a887".to_owned() } ); } @@ -272,6 +273,7 @@ mod test { #[test_log::test] fn cached_checkout_dir_sanity() { + let _env = TestEnv::new(); let shader_template_path = crate::test::shader_crate_template_path(); let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); let dir = source.install_dir().unwrap(); @@ -281,7 +283,7 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - assert_eq!("https___github_com_Rust-GPU_rust-gpu+86fc4803", &name); + assert_eq!("https___github_com_Rust-GPU_rust-gpu+2aa4d4f8", &name); } #[test_log::test] diff --git a/crates/cargo-gpu/src/test.rs b/crates/cargo-gpu/src/test.rs index c9ee93aa0d..4fb6a8dab8 100644 --- a/crates/cargo-gpu/src/test.rs +++ b/crates/cargo-gpu/src/test.rs @@ -1,8 +1,90 @@ //! utilities for tests #![cfg(test)] -use crate::cache_dir; +use anyhow::Context; +use std::cell::RefCell; +use std::fs::File; use std::io::Write as _; +use std::path::PathBuf; +use tempfile::TempDir; + +/// `TestEnv` sets up a temp dir in `./target/cargo-gpu-test/` that is used as the cache dir. Not initializing a +/// `TestEnv` and asking for the cache dir will panic, to ensure you set it up. Calling [`Self::setup_shader_crate`] +/// or [`Self::setup_shader_crate_with_cargo_toml`] will copy the `shader_crate_template` into the temp dir and return +/// you the path to it, so each test now has it's unique copy and won't race to change the template in the repo. +/// Dropping `TestEnv` will clean up the dir, except when panic unwinding, so you can debug failures. +#[must_use] +pub struct TestEnv(TempDir); + +impl TestEnv { + /// Create a new [`TestEnv`] + pub fn new() -> Self { + let target_dir = cargo_metadata::MetadataCommand::new() + .exec() + .unwrap() + .target_directory + .into_std_path_buf(); + let tests_dir = target_dir.join("cargo-gpu-test"); + std::fs::create_dir_all(&tests_dir).ok(); + let test_dir = TempDir::new_in(tests_dir).unwrap(); + + let had_old = TESTDIR + .replace(Some(test_dir.path().to_path_buf())) + .is_some(); + if had_old { + panic!("TestEnv is not reentrant!") + } + + TestEnv(test_dir) + } + + /// Copies the `shader_crate_template` to the temp dir and returns the path to the directory. + pub fn setup_shader_crate(&self) -> anyhow::Result { + let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); + copy_dir_all(shader_crate_template_path(), &shader_crate_path)?; + Ok(shader_crate_path) + } + + /// Like [`Self::setup_shader_crate`], copies the `shader_crate_template` to the temp dir and returns the path to + /// the directory. Additionally, takes a closure to allow you to overwrite the contents of the `Cargo.toml`. + /// This function will write the bare minimum for a valid crate, that is, give it a package name. + pub fn setup_shader_crate_with_cargo_toml( + &self, + f: impl FnOnce(&mut File) -> std::io::Result<()>, + ) -> anyhow::Result { + let shader_crate_path = self.setup_shader_crate()?; + let cargo_toml = shader_crate_path.join("Cargo.toml"); + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(true) + .open(cargo_toml)?; + writeln!(file, "[package]")?; + writeln!(file, "name = \"test\"")?; + f(&mut file)?; + Ok(shader_crate_path) + } +} + +impl Drop for TestEnv { + fn drop(&mut self) { + TESTDIR.replace(None).unwrap(); + // when a test fails, keep directory + if std::thread::panicking() { + self.0.disable_cleanup(true); + } + } +} + +thread_local! { + static TESTDIR: RefCell> = RefCell::new(None); +} + +/// [`crate::cache_dir`] for testing, see [`TestEnv`] +pub fn test_cache_dir() -> anyhow::Result { + Ok(TESTDIR.with_borrow(|a| a.clone()).context( + "TestEnv is not initialized! Add `let _env = TestEnv::new();` to the beginning of your test", + )?) +} fn copy_dir_all( src: impl AsRef, @@ -21,33 +103,8 @@ fn copy_dir_all( Ok(()) } -pub fn shader_crate_template_path() -> std::path::PathBuf { +/// Path to the `shader-crate-template` for copying or querying data +pub fn shader_crate_template_path() -> PathBuf { let project_base = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); project_base.join("../shader-crate-template") } - -pub fn shader_crate_test_path() -> std::path::PathBuf { - let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); - copy_dir_all(shader_crate_template_path(), shader_crate_path.clone()).unwrap(); - shader_crate_path -} - -pub fn overwrite_shader_cargo_toml(shader_crate_path: &std::path::Path) -> std::fs::File { - let cargo_toml = shader_crate_path.join("Cargo.toml"); - let mut file = std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(cargo_toml) - .unwrap(); - writeln!(file, "[package]").unwrap(); - writeln!(file, "name = \"test\"").unwrap(); - file -} - -pub fn tests_teardown() { - let cache_dir = cache_dir().unwrap(); - if !cache_dir.exists() { - return; - } - std::fs::remove_dir_all(cache_dir).unwrap(); -} diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 89add75e22..29a1a182ce 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "glam" -version = "0.29.2" +version = "0.30.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" +checksum = "e12d847aeb25f41be4c0ec9587d624e9cd631bc007a8fd7ce3f5851e064c6460" dependencies = [ "libm", ] @@ -61,14 +61,13 @@ dependencies = [ name = "rust-gpu-shader-crate-template" version = "0.1.0" dependencies = [ - "glam", "spirv-std", ] [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" dependencies = [ "bitflags", "glam", @@ -81,7 +80,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" dependencies = [ "proc-macro2", "quote", @@ -92,7 +91,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc48032c4cd4afb74f1d81ae859711d20386a1" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" [[package]] name = "syn" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 9ed5a5a615..18fb6783ac 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -9,15 +9,7 @@ crate-type = ["rlib", "cdylib"] # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released -spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "86fc48032c4cd4afb74f1d81ae859711d20386a1" } - -# Dependencies for GPU code -[target.'cfg(target_arch = "spirv")'.dependencies] -glam = { version = "0.29", default-features = false, features = ["libm"] } - -# Dependencies for CPU code -[target.'cfg(not(target_arch = "spirv"))'.dependencies] -glam = { version = "0.29", features = ["std"] } +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "2aa4d4f8a8ba73103501562cfca17b8163e5a887" } [package.metadata.rust-gpu.build] # Where to output the compiled shader. Defaults to where `cargo gpu` is called from. diff --git a/crates/shader-crate-template/src/lib.rs b/crates/shader-crate-template/src/lib.rs index e12c0ff2bb..eb547f4719 100644 --- a/crates/shader-crate-template/src/lib.rs +++ b/crates/shader-crate-template/src/lib.rs @@ -2,7 +2,7 @@ //! //! Contains an example vertex shader, fragment shader. #![no_std] -use glam::{Vec2, Vec4}; +use spirv_std::glam::{Vec2, Vec4}; use spirv_std::spirv; pub const CLIP_SPACE_COORD_QUAD_CCW: [Vec4; 6] = { From bf24eb6060e0c7b0013eceddd23b5d7cee68f4cc Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 18 Nov 2025 11:06:31 +1300 Subject: [PATCH 108/162] fix: cargo build/install -p resolves target to shader crate (#122) * added logging * remove -p as alias for --shader-crate * add --package and -p as its own clap option * resolve package to shader crate * cache cargo metadata * fix or allow clippy lints --- Cargo.toml | 1 + crates/cargo-gpu/src/build.rs | 5 ++ crates/cargo-gpu/src/config.rs | 31 ++++++++++-- crates/cargo-gpu/src/install.rs | 12 ++++- crates/cargo-gpu/src/lib.rs | 21 ++++++-- crates/cargo-gpu/src/main.rs | 3 +- crates/cargo-gpu/src/metadata.rs | 87 ++++++++++++++++++++++++++++---- 7 files changed, 136 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 32cd239567..cab77d3bfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,3 +59,4 @@ partial_pub_fields = { level = "allow", priority = 1 } pattern_type_mismatch = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } arbitrary_source_item_ordering = { level = "allow", priority = 1 } +missing_inline_in_public_items = { level = "allow", priority = 1 } diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index aa89fe2265..b9e15ae9dd 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -59,6 +59,11 @@ impl Build { /// Entrypoint pub fn run(&mut self) -> anyhow::Result<()> { let installed_backend = self.install.run()?; + let mut metadata = crate::metadata::MetadataCache::default(); + + if let Some(package) = self.install.package.as_ref() { + self.install.shader_crate = metadata.resolve_package_to_shader_crate(package)?; + } let _lockfile_mismatch_handler = LockfileMismatchHandler::new( &self.install.shader_crate, diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 44a7de773a..3c3d66777d 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -2,6 +2,8 @@ use anyhow::Context as _; use clap::Parser as _; +use crate::metadata::MetadataCache; + /// Config pub struct Config; @@ -23,10 +25,11 @@ impl Config { /// `Cargo.toml`, so here we load that config first as the base config, and the CLI arguments can /// then later override it. pub fn clap_command_with_cargo_config( - shader_crate_path: &std::path::PathBuf, + shader_crate_path: &std::path::Path, mut env_args: Vec, + metadata: &mut MetadataCache, ) -> anyhow::Result { - let mut config = crate::metadata::Metadata::as_json(shader_crate_path)?; + let mut config = metadata.as_json(shader_crate_path)?; env_args.retain(|arg| !(arg == "build" || arg == "install")); let cli_args_json = Self::cli_args_to_json(env_args)?; @@ -102,6 +105,7 @@ mod test { "--debug".to_owned(), "--auto-install-rust-toolchain".to_owned(), ], + &mut MetadataCache::default(), ) .unwrap(); assert!(!args.build.spirv_builder.release); @@ -126,7 +130,12 @@ mod test { }) .unwrap(); - let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![], + &mut MetadataCache::default(), + ) + .unwrap(); assert!(!args.build.spirv_builder.release); assert!(args.install.auto_install_rust_toolchain); } @@ -150,7 +159,12 @@ mod test { let _env = TestEnv::new(); let shader_crate_path = update_cargo_output_dir(&_env); - let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![], + &mut MetadataCache::default(), + ) + .unwrap(); if cfg!(target_os = "windows") { assert!( args.build @@ -179,6 +193,7 @@ mod test { "--output-dir".to_owned(), "/the/river".to_owned(), ], + &mut MetadataCache::default(), ) .unwrap(); assert_eq!(args.build.output_dir, std::path::Path::new("/the/river")); @@ -200,7 +215,12 @@ mod test { }) .unwrap(); - let args = Config::clap_command_with_cargo_config(&shader_crate_path, vec![]).unwrap(); + let args = Config::clap_command_with_cargo_config( + &shader_crate_path, + vec![], + &mut MetadataCache::default(), + ) + .unwrap(); assert_eq!( args.build.spirv_builder.capabilities, vec![ @@ -223,6 +243,7 @@ mod test { "--manifest-file".to_owned(), "mymanifest".to_owned(), ], + &mut MetadataCache::default(), ) .unwrap(); assert_eq!(args.build.manifest_file, "mymanifest".to_owned()); diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 2aa7bde7d6..2cf362089b 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -64,9 +64,16 @@ impl InstalledBackend { #[derive(clap::Parser, Debug, Clone, serde::Deserialize, serde::Serialize)] #[non_exhaustive] pub struct Install { + /// Cargo target to compile. + /// + /// Conflicts with `--shader-crate`. + #[clap(short, long, conflicts_with("shader_crate"))] + pub package: Option, + /// Directory containing the shader crate to compile. - #[clap(long, alias("package"), short_alias('p'), default_value = "./")] - #[serde(alias = "package")] + /// + /// Conflicts with `--package` or `-p`. + #[clap(long, default_value = "./", conflicts_with("package"))] pub shader_crate: PathBuf, #[expect( @@ -132,6 +139,7 @@ impl Install { #[must_use] pub const fn from_shader_crate(shader_crate: PathBuf) -> Self { Self { + package: None, shader_crate, spirv_builder_source: None, spirv_builder_version: None, diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index ff8c1b9c14..d7b99a1f69 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -68,6 +68,7 @@ mod target_specs; mod test; pub use install::*; +pub use metadata::MetadataCache; pub use spirv_builder; /// Central function to write to the user. @@ -120,12 +121,19 @@ impl Command { /// # Errors /// Any errors during execution, usually printed to the user #[inline] - pub fn run(&self, env_args: Vec) -> anyhow::Result<()> { + pub fn run( + &self, + env_args: Vec, + metadata_cache: &mut metadata::MetadataCache, + ) -> anyhow::Result<()> { match &self { Self::Install(install) => { let shader_crate_path = &install.shader_crate; - let command = - config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?; + let command = config::Config::clap_command_with_cargo_config( + shader_crate_path, + env_args, + metadata_cache, + )?; log::debug!( "installing with final merged arguments: {:#?}", command.install @@ -134,8 +142,11 @@ impl Command { } Self::Build(build) => { let shader_crate_path = &build.install.shader_crate; - let mut command = - config::Config::clap_command_with_cargo_config(shader_crate_path, env_args)?; + let mut command = config::Config::clap_command_with_cargo_config( + shader_crate_path, + env_args, + metadata_cache, + )?; log::debug!("building with final merged arguments: {command:#?}"); if command.build.watch { diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index f40e3c6e4e..449aa700d7 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -37,5 +37,6 @@ fn run() -> anyhow::Result<()> { .collect::>(); log::trace!("CLI args: {env_args:#?}"); let cli = Cli::parse_from(&env_args); - cli.command.run(env_args) + let mut metadata_cache = cargo_gpu::MetadataCache::default(); + cli.command.run(env_args, &mut metadata_cache) } diff --git a/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs index 0b330fb245..00aeea13ac 100644 --- a/crates/cargo-gpu/src/metadata.rs +++ b/crates/cargo-gpu/src/metadata.rs @@ -1,14 +1,73 @@ //! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]` +use std::collections::HashMap; + +use anyhow::Context as _; use cargo_metadata::MetadataCommand; use serde_json::Value; -/// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally +/// A cache of metadata from various `Cargo.toml` files. +/// +/// "Metadata" refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally /// ignores so that packages can implement their own behaviour with it. -#[derive(Debug)] -pub struct Metadata; +#[derive(Debug, Default)] +pub struct MetadataCache { + /// Cached result of `MetadataCommand::new().exec()`. + inner: HashMap, +} + +impl MetadataCache { + /// Return the cached cargo metadata for the Cargo.toml at the given path, + /// or find it, populate the cache with it and return it. + fn get_metadata( + &mut self, + maybe_path_to_manifest_dir: Option<&std::path::Path>, + ) -> anyhow::Result<&cargo_metadata::Metadata> { + let path = if let Some(path) = maybe_path_to_manifest_dir { + path.to_path_buf() + } else { + std::env::current_dir().context("cannot determine the current working directory")? + }; + + if !self.inner.contains_key(&path) { + let metadata = MetadataCommand::new().current_dir(&path).exec()?; + self.inner.insert(path.clone(), metadata); + } + + self.inner.get(&path).context("unreachable") + } + + /// Resolve a package name to a crate directory. + /// + /// ## Errors + /// * if fetching cargo metadata fails. + /// * if no packages are listed in the cargo metadata. + /// * if the manifest path has no parent. + pub fn resolve_package_to_shader_crate( + &mut self, + package: &str, + ) -> anyhow::Result { + log::debug!("resolving package '{package}' to shader crate"); + let metadata = self.get_metadata(None)?; + + let meta_package = metadata + .packages + .iter() + .find(|pkg| pkg.name.as_str() == package) + .context("Package not found in metadata")?; + let shader_crate_path: std::path::PathBuf = meta_package + .manifest_path + .parent() + .context("manifest is missing a parent directory")? + .to_path_buf() + .into(); + log::debug!( + " determined shader crate path to be '{}'", + shader_crate_path.display() + ); + Ok(shader_crate_path) + } -impl Metadata { /// Convert `rust-gpu`-specific sections in `Cargo.toml` to `clap`-compatible arguments. /// The section in question is: `[package.metadata.rust-gpu.*]`. See the `shader-crate-template` /// for an example. @@ -16,8 +75,12 @@ impl Metadata { /// First we generate the CLI arg defaults as JSON. Then on top of those we merge any config /// from the workspace `Cargo.toml`, then on top of those we merge any config from the shader /// crate's `Cargo.toml`. - pub fn as_json(path: &std::path::PathBuf) -> anyhow::Result { - let cargo_json = Self::get_cargo_toml_as_json(path)?; + /// + /// ## Errors + /// Errors if cargo metadata cannot be found or if it cannot be operated on. + pub fn as_json(&mut self, path: &std::path::Path) -> anyhow::Result { + log::debug!("reading package metadata from {}", path.display()); + let cargo_json = self.get_cargo_toml_as_json(path)?; let config = Self::merge_configs(&cargo_json, path)?; Ok(config) } @@ -27,6 +90,7 @@ impl Metadata { cargo_json: &cargo_metadata::Metadata, path: &std::path::Path, ) -> anyhow::Result { + log::debug!("merging cargo metadata from {}", path.display()); let mut metadata = crate::config::Config::defaults_as_json()?; crate::config::Config::json_merge( &mut metadata, @@ -65,9 +129,10 @@ impl Metadata { /// Convert a `Cargo.toml` to JSON fn get_cargo_toml_as_json( - path: &std::path::PathBuf, + &mut self, + path: &std::path::Path, ) -> anyhow::Result { - Ok(MetadataCommand::new().current_dir(path).exec()?) + self.get_metadata(Some(path)).cloned() } /// Get any `rust-gpu` metadata set in the crate's `Cargo.toml` @@ -136,7 +201,7 @@ mod test { .exec() .unwrap(); metadata.packages.first_mut().unwrap().metadata = serde_json::json!({}); - let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap(); + let configs = MetadataCache::merge_configs(&metadata, Path::new("./")).unwrap(); assert_eq!(configs["build"]["release"], Value::Bool(true)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], @@ -160,7 +225,7 @@ mod test { } } }); - let configs = Metadata::merge_configs(&metadata, Path::new("./")).unwrap(); + let configs = MetadataCache::merge_configs(&metadata, Path::new("./")).unwrap(); assert_eq!(configs["build"]["release"], Value::Bool(false)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], @@ -189,7 +254,7 @@ mod test { } } }); - let configs = Metadata::merge_configs(&metadata, Path::new(".")).unwrap(); + let configs = MetadataCache::merge_configs(&metadata, Path::new(".")).unwrap(); assert_eq!(configs["build"]["release"], Value::Bool(false)); assert_eq!( configs["install"]["auto_install_rust_toolchain"], From 816b3f63dea4e3244069d6b36176f509e8b21d7a Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 4 Dec 2025 14:58:53 +0100 Subject: [PATCH 109/162] fix clippy lints from stable updates --- crates/cargo-gpu/src/spirv_source.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu/src/spirv_source.rs index f33c2839f4..1775a99765 100644 --- a/crates/cargo-gpu/src/spirv_source.rs +++ b/crates/cargo-gpu/src/spirv_source.rs @@ -48,10 +48,6 @@ pub enum SpirvSource { } impl core::fmt::Display for SpirvSource { - #[expect( - clippy::min_ident_chars, - reason = "It's a core library trait implementation" - )] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Self::CratesIO(version) => version.fmt(f), From 5926363c2d4484ea0c30e4186ea71db70c01c04c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 4 Dec 2025 14:54:29 +0100 Subject: [PATCH 110/162] update spirv-builder --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/cargo-gpu/src/build.rs | 27 ++++++++++++++++----------- crates/cargo-gpu/src/install.rs | 2 +- crates/cargo-gpu/src/lib.rs | 4 ++-- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7c2b207a3..c5c4082a6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1036,7 +1036,7 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3df836eb9d7b01344f52737bf9a310d1fb5a0c26#3df836eb9d7b01344f52737bf9a310d1fb5a0c26" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e97524f6b4816056b3edaa70c3e0e0c656392c05#e97524f6b4816056b3edaa70c3e0e0c656392c05" dependencies = [ "rspirv", "serde", @@ -1216,7 +1216,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=3df836eb9d7b01344f52737bf9a310d1fb5a0c26#3df836eb9d7b01344f52737bf9a310d1fb5a0c26" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e97524f6b4816056b3edaa70c3e0e0c656392c05#e97524f6b4816056b3edaa70c3e0e0c656392c05" dependencies = [ "cargo_metadata", "clap", diff --git a/Cargo.toml b/Cargo.toml index cab77d3bfe..de7d918b7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "3df836eb9d7b01344f52737bf9a310d1fb5a0c26", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e97524f6b4816056b3edaa70c3e0e0c656392c05", default-features = false } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } crossterm = "0.29.0" diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index b9e15ae9dd..e8e620cba9 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -6,7 +6,7 @@ use crate::install::Install; use crate::linkage::Linkage; use crate::lockfile::LockfileMismatchHandler; use anyhow::Context as _; -use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder}; +use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder, SpirvBuilderError}; use std::io::Write as _; use std::path::PathBuf; @@ -95,17 +95,22 @@ impl Build { ); if self.build.watch { - let this = self.clone(); - self.build - .spirv_builder - .watch(move |result, accept| { - let result1 = this.parse_compilation_result(&result); - if let Some(accept) = accept { - accept.submit(result1); + let mut watcher = self.build.spirv_builder.clone().watch()?; + loop { + // if the build fails "regularly", eg. `cargo build` fails and nothing else, just retry + crate::user_output!( + "Compiling shaders at {}...\n", + self.install.shader_crate.display() + ); + match watcher.recv() { + Ok(result) => { + self.parse_compilation_result(&result)?; + crate::user_output!("Build successful!\n"); } - })? - .context("unreachable")??; - std::thread::park(); + Err(SpirvBuilderError::BuildFailed) => crate::user_output!("Build failed!\n"), + Err(err) => return Err(anyhow::Error::from(err)), + } + } } else { crate::user_output!( "Compiling shaders at {}...\n", diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index 2cf362089b..c66c6b6556 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -299,7 +299,7 @@ package = "rustc_codegen_spirv" cargo.args(["-p", "rustc_codegen_spirv", "--lib"]); } - log::debug!("building artifacts with `{cargo}`"); + log::debug!("building artifacts with `{cargo:?}`"); cargo .stdout(std::process::Stdio::inherit()) .stderr(std::process::Stdio::inherit()) diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index d7b99a1f69..cd16561f3e 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -74,7 +74,7 @@ pub use spirv_builder; /// Central function to write to the user. #[macro_export] macro_rules! user_output { - ($($args: tt)*) => { + ($($args: tt)*) => { { #[allow( clippy::allow_attributes, clippy::useless_attribute, @@ -92,7 +92,7 @@ macro_rules! user_output { } print!($($args)*); std::io::stdout().flush().unwrap(); - } + } } } /// All of the available subcommands for `cargo gpu` From d661fb5787810fffee8e1688848a5981e9c18dca Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 12:14:56 +0100 Subject: [PATCH 111/162] ci: split main test between `test-os` and `test-rust-gpu-versions` jobs --- .github/workflows/push.yaml | 55 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 82929b56c5..8e02875270 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -5,13 +5,14 @@ on: branches: - main pull_request: + workflow_dispatch: env: # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: - install-and-build-shaders: + test-os: strategy: fail-fast: false matrix: @@ -19,49 +20,59 @@ jobs: - ubuntu-latest - macos-latest - windows-latest - rust-gpu-version: [latest] - include: + runs-on: ${{ matrix.os }} + env: + RUST_LOG: debug + steps: + - uses: actions/checkout@v4 + - uses: cargo-bins/cargo-binstall@main + - run: cargo binstall cargo-nextest + - run: cargo fetch --locked + - name: shader-crate-template cargo fetch --locked + run: | + cd ./crates/shader-crate-template + cargo fetch --locked + - run: cargo nextest run + - name: Run a full build + run: cargo xtask test-build + + test-rust-gpu-releases: + strategy: + fail-fast: false + matrix: + rust-gpu-version: # As well as testing on each OS, we also want to test to make sure we're still supporting # older versions of `rust-gpu`. However, we can assume that these tests are already okay # across platforms, so we only need to test on Linux, the chepeast in terms of minutes. # # `0.7.0` currently fails building `spirv-builder-cli` with: # """ - # package `is_terminal_polyfill v1.70.1` cannot be built because it requires rustc + # package `is_terminal_polyfill v1.70.1` cannot be built because it requires rustc # 1.70.0 or newer, while the currently active rustc version is 1.69.0-nightly # """ # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's # unlikely many users of it? - - os: ubuntu-latest - rust-gpu-version: 0.8.0 - - os: ubuntu-latest - rust-gpu-version: 0.9.0 - runs-on: ${{ matrix.os }} - defaults: - run: - shell: bash + - 0.8.0 + - 0.9.0 + runs-on: ubuntu-latest env: RUST_LOG: debug steps: - uses: actions/checkout@v4 - - name: Fetch root dependencies - run: cargo fetch --locked - - name: Fetch shader-crate-template dependencies - run: | - cd ./crates/shader-crate-template - cargo fetch --locked - - run: cargo test - name: Run a full build run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} - + lints: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: cargo-bins/cargo-binstall@main - - name: Install cargo-shear - run: cargo binstall cargo-shear + - run: cargo binstall cargo-shear - run: cargo fetch --locked - run: cargo clippy -- --deny warnings - run: cargo fmt --check - run: cargo shear + +defaults: + run: + shell: bash From cc8f32214368ea1c4a3ffa26e25054233b5e999c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 12:32:15 +0100 Subject: [PATCH 112/162] ci: add `test_success` job --- .github/workflows/push.yaml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 8e02875270..3f0bd481a6 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -62,7 +62,7 @@ jobs: - name: Run a full build run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} - lints: + lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -73,6 +73,21 @@ jobs: - run: cargo fmt --check - run: cargo shear + # This allows us to have a single job we can branch protect on, rather than needing + # to update the branch protection rules when the test matrix changes + test_success: + runs-on: ubuntu-24.04 + needs: [test-os, test-rust-gpu-releases, lint] + # Hack for buggy GitHub Actions behavior with skipped checks: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + if: ${{ always() }} + steps: + # Another hack is to actually check the status of the dependencies or else it'll fall through + - run: | + echo "Checking statuses..." + [[ "${{ needs.test-os.result }}" == "success" ]] || exit 1 + [[ "${{ needs.test-rust-gpu-releases.result }}" == "success" ]] || exit 1 + [[ "${{ needs.lint.result }}" == "success" ]] || exit 1 + defaults: run: shell: bash From 16ea3693f3d76f760da4fc7b78c8405078c5a52c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 7 Nov 2025 13:32:14 +0100 Subject: [PATCH 113/162] xtask: support git revs for `rust_gpu_version` arg --- crates/xtask/src/main.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 8eec0beb14..90abe02e12 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -132,7 +132,19 @@ impl ShaderCrateTemplateCargoTomlWriter { fn replace_spirv_std_version(&mut self, version: String) -> anyhow::Result<()> { let dependencies = self.get_cargo_dependencies_table(); let spirv_std = dependencies.get_mut("spirv-std").unwrap(); - *spirv_std = toml::Value::String(version); + if version.contains('.') { + // semver + *spirv_std = toml::Value::String(version); + } else { + // git rev + *spirv_std = toml::Value::Table(toml::Table::from_iter([ + ( + "git".to_owned(), + toml::Value::String("https://github.com/Rust-GPU/rust-gpu".to_owned()), + ), + ("rev".to_owned(), toml::Value::String(version)), + ])); + } self.write_shader_crate_cargo_toml_changes()?; Ok(()) } From 0efaf65f0bc9b8f0bd9433d852eccbcbc4992ba7 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 14:56:23 +0100 Subject: [PATCH 114/162] xtask: allow setting glam version --- crates/xtask/src/main.rs | 133 ++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 35 deletions(-) diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 90abe02e12..84ddec9dec 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -20,6 +20,9 @@ enum Cli { /// Build using the specified version of `spirv-std`. #[clap(long)] rust_gpu_version: Option, + /// The version of glam to use + #[clap(long)] + glam_version: Option, }, } @@ -128,52 +131,112 @@ impl ShaderCrateTemplateCargoTomlWriter { Ok(()) } + /// Add or replace a dependency in the shader-crate-template + fn set_dependency( + &mut self, + package: String, + version: &DependencyVersion, + ) -> anyhow::Result<()> { + if let Some(version) = version.to_toml() { + let dependencies = self.get_cargo_dependencies_table(); + dependencies.insert(package, version); + self.write_shader_crate_cargo_toml_changes()?; + } + Ok(()) + } + /// Replace the `spirv-std` dependency version - fn replace_spirv_std_version(&mut self, version: String) -> anyhow::Result<()> { - let dependencies = self.get_cargo_dependencies_table(); - let spirv_std = dependencies.get_mut("spirv-std").unwrap(); - if version.contains('.') { - // semver - *spirv_std = toml::Value::String(version); + fn set_spirv_std_version(&mut self, version: &str) -> anyhow::Result<()> { + self.set_dependency( + "spirv-std".into(), + &DependencyVersion::parse( + version.into(), + Some("https://github.com/Rust-GPU/rust-gpu".into()), + )?, + ) + } + + /// Replace the `glam` dependency version + fn set_dependency_glam(&mut self, version: &str) -> anyhow::Result<()> { + self.set_dependency( + "glam".into(), + &DependencyVersion::parse( + version.into(), + Some("https://github.com/bitshifter/glam-rs".into()), + )?, + ) + } +} + +/// The version of a dependency +#[non_exhaustive] +pub enum DependencyVersion { + /// Don't change anything, don't replace the dependency nor add it when it's not there. + Latest, + /// A version dependency for crates.io + Crates(String), + /// A git dependency on a specific rev + Git { + /// git repo + git: String, + /// git commit revision + rev: String, + }, +} + +impl DependencyVersion { + /// Try to parse a version from a string + /// + /// # Errors + /// if `version` is a commit rev, `git` must be specified + pub fn parse(version: String, git: Option) -> anyhow::Result { + if version == "latest" { + Ok(Self::Latest) + } else if version.contains('.') { + Ok(Self::Crates(version)) } else { - // git rev - *spirv_std = toml::Value::Table(toml::Table::from_iter([ - ( - "git".to_owned(), - toml::Value::String("https://github.com/Rust-GPU/rust-gpu".to_owned()), - ), - ("rev".to_owned(), toml::Value::String(version)), - ])); + Ok(Self::Git { + git: git.context("specifying a revision requires a git repo")?, + rev: version, + }) + } + } + + /// Convert this version to a toml value, may fail if we want the latest version + #[must_use] + pub fn to_toml(&self) -> Option { + match self { + Self::Latest => None, + Self::Crates(version) => Some(toml::Value::String(version.clone())), + Self::Git { git, rev } => Some(toml::Value::Table(toml::Table::from_iter([ + ("git".to_owned(), toml::Value::String(git.clone())), + ("rev".to_owned(), toml::Value::String(rev.clone())), + ]))), } - self.write_shader_crate_cargo_toml_changes()?; - Ok(()) } } /// Run the xtask. -fn main() { +fn main() -> anyhow::Result<()> { env_logger::builder().init(); - let cli = Cli::parse(); - - match cli { + match &cli { Cli::TestBuild { - rust_gpu_version: maybe_rust_gpu_version, + rust_gpu_version, + glam_version, } => { log::info!("installing cargo gpu"); - cmd(["cargo", "install", "--path", "crates/cargo-gpu"]).unwrap(); + cmd(["cargo", "install", "--path", "crates/cargo-gpu"])?; log::info!("setup project"); - let dir = tempfile::TempDir::with_prefix("test-shader-output").unwrap(); let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); - overwriter.replace_output_dir(dir.path()).unwrap(); - - if let Some(rust_gpu_version) = maybe_rust_gpu_version { - if rust_gpu_version != "latest" { - overwriter - .replace_spirv_std_version(rust_gpu_version) - .unwrap(); - } + let dir = tempfile::TempDir::with_prefix("test-shader-output")?; + overwriter.replace_output_dir(dir.path())?; + if let Some(rust_gpu_version) = rust_gpu_version.as_ref() { + overwriter.set_spirv_std_version(rust_gpu_version)?; + } + if let Some(glam_version) = glam_version.as_ref() { + overwriter.set_dependency_glam(glam_version)?; } log::info!("building with auto-install"); @@ -186,12 +249,12 @@ fn main() { "--auto-install-rust-toolchain", "--rebuild-codegen", "--force-overwrite-lockfiles-v4-to-v3", - ]) - .unwrap(); + ])?; - cmd(["ls", "-lah", dir.path().to_str().unwrap()]).unwrap(); + cmd(["ls", "-lah", dir.path().to_str().unwrap()])?; //NOTE: manifest.json is the default value here, which should be valid - cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()]).unwrap(); + cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()])?; } } + Ok(()) } From e6ea752999d953e9ba1eb0a037a3a15049fa146b Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 15:08:16 +0100 Subject: [PATCH 115/162] xtask: add `xtask set-dependency [--git link]` --- .github/workflows/push.yaml | 11 ++++++++--- crates/xtask/src/main.rs | 38 +++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 3f0bd481a6..fb217a136b 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -40,7 +40,7 @@ jobs: strategy: fail-fast: false matrix: - rust-gpu-version: + include: # As well as testing on each OS, we also want to test to make sure we're still supporting # older versions of `rust-gpu`. However, we can assume that these tests are already okay # across platforms, so we only need to test on Linux, the chepeast in terms of minutes. @@ -52,13 +52,18 @@ jobs: # """ # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's # unlikely many users of it? - - 0.8.0 - - 0.9.0 + - rust-gpu-version: 0.8.0 + glam-version: 0.24.2 + - rust-gpu-version: 0.9.0 + glam-version: 0.24.2 runs-on: ubuntu-latest env: RUST_LOG: debug steps: - uses: actions/checkout@v4 + - if: ${{ matrix.glam-version }} + name: set glam version + run: cargo xtask set-dependency glam ${{ matrix.glam-version }} - name: Run a full build run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 84ddec9dec..0561b758eb 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -24,6 +24,16 @@ enum Cli { #[clap(long)] glam_version: Option, }, + /// Set a dependency in the shader-crate-template to some version + SetDependency { + /// the dependency to modify + package: String, + /// the version to set it to + version: String, + /// the git repo to use, if version is a commit rev + #[clap(long)] + git: Option, + }, } fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { @@ -51,10 +61,16 @@ struct ShaderCrateTemplateCargoTomlWriter { original_shader_crate_lock_file: String, /// Parsed toml table table: toml::Table, + /// false will reset Cargo.toml when this is dropped + persistent: bool, } impl Drop for ShaderCrateTemplateCargoTomlWriter { fn drop(&mut self) { + if self.persistent { + return; + } + log::info!("reverting overwrite of Cargo.toml"); std::fs::write( format!("{SHADER_CRATE_PATH}/Cargo.toml"), @@ -70,9 +86,15 @@ impl Drop for ShaderCrateTemplateCargoTomlWriter { } } +impl Default for ShaderCrateTemplateCargoTomlWriter { + fn default() -> Self { + Self::new(false) + } +} + impl ShaderCrateTemplateCargoTomlWriter { /// Create a new one - fn new() -> Self { + fn new(persistent: bool) -> Self { let original_shader_crate_template_str = std::fs::read_to_string(format!("{SHADER_CRATE_PATH}/Cargo.toml")).unwrap(); let table = toml::from_str::(&original_shader_crate_template_str).unwrap(); @@ -82,6 +104,7 @@ impl ShaderCrateTemplateCargoTomlWriter { original_shader_crate_template_str, original_shader_crate_lock_file, table, + persistent, } } @@ -229,7 +252,7 @@ fn main() -> anyhow::Result<()> { cmd(["cargo", "install", "--path", "crates/cargo-gpu"])?; log::info!("setup project"); - let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(); + let mut overwriter = ShaderCrateTemplateCargoTomlWriter::default(); let dir = tempfile::TempDir::with_prefix("test-shader-output")?; overwriter.replace_output_dir(dir.path())?; if let Some(rust_gpu_version) = rust_gpu_version.as_ref() { @@ -255,6 +278,17 @@ fn main() -> anyhow::Result<()> { //NOTE: manifest.json is the default value here, which should be valid cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()])?; } + Cli::SetDependency { + package, + version, + git, + } => { + let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(true); + overwriter.set_dependency( + package.clone(), + &DependencyVersion::parse(version.clone(), git.clone())?, + )?; + } } Ok(()) } From 88f173fb3fa413660667394c13bf25296bdb392e Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 16:13:02 +0100 Subject: [PATCH 116/162] xtask: copy over features and default-features when setting version --- crates/shader-crate-template/Cargo.lock | 1 + crates/shader-crate-template/Cargo.toml | 1 + crates/xtask/src/main.rs | 49 +++++++++++++++++-------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 29a1a182ce..a61d1e83a4 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -61,6 +61,7 @@ dependencies = [ name = "rust-gpu-shader-crate-template" version = "0.1.0" dependencies = [ + "glam", "spirv-std", ] diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 18fb6783ac..a3363f4a62 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["rlib", "cdylib"] [dependencies] # TODO: use a simple crate version once v0.10.0 is released spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "2aa4d4f8a8ba73103501562cfca17b8163e5a887" } +glam = { version = "0.30.8", default-features = false } [package.metadata.rust-gpu.build] # Where to output the compiled shader. Defaults to where `cargo gpu` is called from. diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 0561b758eb..076c57c1b6 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -155,23 +155,21 @@ impl ShaderCrateTemplateCargoTomlWriter { } /// Add or replace a dependency in the shader-crate-template - fn set_dependency( - &mut self, - package: String, - version: &DependencyVersion, - ) -> anyhow::Result<()> { - if let Some(version) = version.to_toml() { - let dependencies = self.get_cargo_dependencies_table(); - dependencies.insert(package, version); + fn set_dependency(&mut self, package: &str, version: &DependencyVersion) -> anyhow::Result<()> { + let dependencies = self.get_cargo_dependencies_table(); + if let Some(value) = dependencies.get_mut(package) { + version.modify_toml(value); self.write_shader_crate_cargo_toml_changes()?; + Ok(()) + } else { + anyhow::bail!("Crate `{package}` not found") } - Ok(()) } /// Replace the `spirv-std` dependency version fn set_spirv_std_version(&mut self, version: &str) -> anyhow::Result<()> { self.set_dependency( - "spirv-std".into(), + "spirv-std", &DependencyVersion::parse( version.into(), Some("https://github.com/Rust-GPU/rust-gpu".into()), @@ -182,7 +180,7 @@ impl ShaderCrateTemplateCargoTomlWriter { /// Replace the `glam` dependency version fn set_dependency_glam(&mut self, version: &str) -> anyhow::Result<()> { self.set_dependency( - "glam".into(), + "glam", &DependencyVersion::parse( version.into(), Some("https://github.com/bitshifter/glam-rs".into()), @@ -227,14 +225,33 @@ impl DependencyVersion { /// Convert this version to a toml value, may fail if we want the latest version #[must_use] - pub fn to_toml(&self) -> Option { + pub fn to_toml(&self) -> Option { match self { Self::Latest => None, - Self::Crates(version) => Some(toml::Value::String(version.clone())), - Self::Git { git, rev } => Some(toml::Value::Table(toml::Table::from_iter([ + Self::Crates(version) => Some(toml::Table::from_iter([( + "version".to_owned(), + toml::Value::String(version.clone()), + )])), + Self::Git { git, rev } => Some(toml::Table::from_iter([ ("git".to_owned(), toml::Value::String(git.clone())), ("rev".to_owned(), toml::Value::String(rev.clone())), - ]))), + ])), + } + } + + /// Convert this version to a toml value, may fail if we want the latest version + pub fn modify_toml(&self, toml: &mut toml::Value) { + if let Some(mut table) = self.to_toml() { + let mut copy = |key: &str| { + if let Some(src_table) = toml.as_table_mut() { + if let Some(value) = src_table.remove(key) { + table.insert(key.to_owned(), value); + } + } + }; + copy("default-features"); + copy("features"); + *toml = toml::Value::Table(table); } } } @@ -285,7 +302,7 @@ fn main() -> anyhow::Result<()> { } => { let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(true); overwriter.set_dependency( - package.clone(), + package, &DependencyVersion::parse(version.clone(), git.clone())?, )?; } From 48c75114e2962e2f368b35006a35487b3f23ba5d Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 12:27:21 +0100 Subject: [PATCH 117/162] ci: test interesting revs: target spec changes, glam semver breakage (by us) --- .github/workflows/push.yaml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index fb217a136b..5bdadff13d 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -56,6 +56,41 @@ jobs: glam-version: 0.24.2 - rust-gpu-version: 0.9.0 glam-version: 0.24.2 + + # target spec introduction + # last version before + # * fails: compiler too old, `serde` using `#[diagnostic]` +# - rust-gpu-version: cc752312c3de6813a41189e46476d5c1be5e0bbe +# glam-version: 0.30.7 + # first version requiring target specs + # * fails: target spec mismatch! + # * resolution: Since this is just a few commits, I'd be fine ignoring it. +# - rust-gpu-version: 02cefd101014f66b79dffb20a2c2b5b7c9038401 +# glam-version: 0.30.7 + # target specs change again just a few commits later + # * fails: compiler too old, `proc-macro2` using `Literal::byte_character`. + # * resolution: want to support, can't be bothered to hack in old proc-macro2 versions +# - rust-gpu-version: bbb61f58b3d24f3f64745050eb214b90bf6dcce9 +# glam-version: 0.30.7 + + # testing rustc 1.5 months later + - rust-gpu-version: eea8998df9dc2fd8e7a65c5b5b7ae20c238a665a + glam-version: 0.29.3 + + # just after target specs v2 refactor, we updated to rustc 1.85 and needed to change them again + # before + - rust-gpu-version: a547c6e45266d613d9fec673e869d7a96181e47b + glam-version: =0.30.7 + # after + - rust-gpu-version: 2326b87fe1542eeb898065e36ac949307b55386d + glam-version: =0.30.7 + + # glam semver breakage due to vector type refactor + # before, glam was fixed to <=0.30.7 in this commit + - rust-gpu-version: f79c4181a5dc2d37303947b113f190930c6c1ce6 + glam-version: =0.30.7 + # after, glam >0.30.8 + - rust-gpu-version: e767f24f2565baf1a71bbaf84d453d181cab2417 runs-on: ubuntu-latest env: RUST_LOG: debug From bb74342b90066ce8b7d50ba8e058df356a54acf4 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 16 Dec 2025 10:53:36 +0100 Subject: [PATCH 118/162] ci: shorten job name to `test-rust-gpu` --- .github/workflows/push.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 5bdadff13d..e48fea0d74 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -36,7 +36,7 @@ jobs: - name: Run a full build run: cargo xtask test-build - test-rust-gpu-releases: + test-rust-gpu: strategy: fail-fast: false matrix: @@ -117,7 +117,7 @@ jobs: # to update the branch protection rules when the test matrix changes test_success: runs-on: ubuntu-24.04 - needs: [test-os, test-rust-gpu-releases, lint] + needs: [test-os, test-rust-gpu, lint] # Hack for buggy GitHub Actions behavior with skipped checks: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks if: ${{ always() }} steps: @@ -125,7 +125,7 @@ jobs: - run: | echo "Checking statuses..." [[ "${{ needs.test-os.result }}" == "success" ]] || exit 1 - [[ "${{ needs.test-rust-gpu-releases.result }}" == "success" ]] || exit 1 + [[ "${{ needs.test-rust-gpu.result }}" == "success" ]] || exit 1 [[ "${{ needs.lint.result }}" == "success" ]] || exit 1 defaults: From 7d721b70d0e7ef9be54a0c4386c07519e492574c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 16:17:38 +0100 Subject: [PATCH 119/162] target-spec: update spirv-builder --- Cargo.lock | 6 ++++-- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5c4082a6b..2c2e2bece8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1036,12 +1036,14 @@ checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e97524f6b4816056b3edaa70c3e0e0c656392c05#e97524f6b4816056b3edaa70c3e0e0c656392c05" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=a30bd43db45f2bfe260051f44141e5eaffcbb4b0#a30bd43db45f2bfe260051f44141e5eaffcbb4b0" dependencies = [ "rspirv", + "semver", "serde", "serde_json", "spirv", + "thiserror", ] [[package]] @@ -1216,7 +1218,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e97524f6b4816056b3edaa70c3e0e0c656392c05#e97524f6b4816056b3edaa70c3e0e0c656392c05" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=a30bd43db45f2bfe260051f44141e5eaffcbb4b0#a30bd43db45f2bfe260051f44141e5eaffcbb4b0" dependencies = [ "cargo_metadata", "clap", diff --git a/Cargo.toml b/Cargo.toml index de7d918b7e..c4f1e0b253 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ exclude = [ resolver = "2" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e97524f6b4816056b3edaa70c3e0e0c656392c05", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "a30bd43db45f2bfe260051f44141e5eaffcbb4b0", default-features = false } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } crossterm = "0.29.0" From 782807907c357396df90888b87318d4b10813d4a Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 16:20:13 +0100 Subject: [PATCH 120/162] target-spec: remove target spec handling and `show targets` --- crates/cargo-gpu/src/install.rs | 12 --- crates/cargo-gpu/src/lib.rs | 1 - crates/cargo-gpu/src/show.rs | 44 +-------- crates/cargo-gpu/src/target_specs.rs | 135 --------------------------- 4 files changed, 1 insertion(+), 191 deletions(-) delete mode 100644 crates/cargo-gpu/src/target_specs.rs diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu/src/install.rs index c66c6b6556..c9ea0eceba 100644 --- a/crates/cargo-gpu/src/install.rs +++ b/crates/cargo-gpu/src/install.rs @@ -3,7 +3,6 @@ use crate::spirv_source::{ get_channel_from_rustc_codegen_spirv_build_script, query_metadata, FindPackage as _, }; -use crate::target_specs::update_target_specs_files; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; use spirv_builder::SpirvBuilder; @@ -17,8 +16,6 @@ pub struct InstalledBackend { pub rustc_codegen_spirv_location: PathBuf, /// toolchain channel name pub toolchain_channel: String, - /// directory with target-specs json files - pub target_spec_dir: PathBuf, } impl InstalledBackend { @@ -48,10 +45,6 @@ impl InstalledBackend { pub fn configure_spirv_builder(&self, builder: &mut SpirvBuilder) -> anyhow::Result<()> { builder.rustc_codegen_spirv_location = Some(self.rustc_codegen_spirv_location.clone()); builder.toolchain_overwrite = Some(self.toolchain_channel.clone()); - builder.path_to_target_spec = Some(self.target_spec_dir.join(format!( - "{}.json", - builder.target.as_ref().context("expect target to be set")? - ))); Ok(()) } } @@ -270,10 +263,6 @@ package = "rustc_codegen_spirv" )?; log::info!("selected toolchain channel `{toolchain_channel:?}`"); - log::debug!("update_spec_files"); - let target_spec_dir = update_target_specs_files(&source, &dummy_metadata, !skip_rebuild) - .context("writing target spec files")?; - log::debug!("ensure_toolchain_and_components_exist"); crate::install_toolchain::ensure_toolchain_and_components_exist( &toolchain_channel, @@ -336,7 +325,6 @@ package = "rustc_codegen_spirv" Ok(InstalledBackend { rustc_codegen_spirv_location: dest_dylib_path, toolchain_channel, - target_spec_dir, }) } } diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index cd16561f3e..d4822781ff 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -64,7 +64,6 @@ mod lockfile; mod metadata; mod show; mod spirv_source; -mod target_specs; mod test; pub use install::*; diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index b7eb19b2ff..1e318c4845 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -1,11 +1,7 @@ //! Display various information about `cargo gpu`, eg its cache directory. use crate::cache_dir; -use crate::spirv_source::{query_metadata, SpirvSource}; -use crate::target_specs::update_target_specs_files; -use anyhow::bail; -use std::fs; -use std::path::Path; +use crate::spirv_source::SpirvSource; /// Show the computed source of the spirv-std dependency. #[derive(Clone, Debug, clap::Parser)] @@ -26,9 +22,6 @@ pub enum Info { Commitsh, /// All the available SPIR-V capabilities that can be set with `--capabilities` Capabilities, - - /// All available SPIR-V targets - Targets(SpirvSourceDep), } /// `cargo gpu show` @@ -70,13 +63,6 @@ impl Show { println!(" {capability:?}"); } } - Info::Targets(SpirvSourceDep { shader_crate }) => { - let (source, targets) = Self::available_spirv_targets_iter(shader_crate)?; - println!("All available targets for rust-gpu version '{source}':"); - for target in targets { - println!("{target}"); - } - } } Ok(()) @@ -90,32 +76,4 @@ impl Show { let last_capability = spirv_builder::Capability::CacheControlsINTEL as u32; (0..=last_capability).filter_map(spirv_builder::Capability::from_u32) } - - /// List all available spirv targets, note: the targets from compile time of cargo-gpu and those - /// in the cache-directory will be picked up. - fn available_spirv_targets_iter( - shader_crate: &Path, - ) -> anyhow::Result<(SpirvSource, impl Iterator)> { - let source = SpirvSource::new(shader_crate, None, None)?; - let install_dir = source.install_dir()?; - if !install_dir.is_dir() { - bail!("rust-gpu version {} is not installed", source); - } - let dummy_metadata = query_metadata(&install_dir)?; - let target_specs_dir = update_target_specs_files(&source, &dummy_metadata, false)?; - - let mut targets = fs::read_dir(target_specs_dir)? - .filter_map(|entry| { - let file = entry.ok()?; - if file.path().is_file() { - if let Some(target) = file.file_name().to_string_lossy().strip_suffix(".json") { - return Some(target.to_owned()); - } - } - None - }) - .collect::>(); - targets.sort(); - Ok((source, targets.into_iter())) - } } diff --git a/crates/cargo-gpu/src/target_specs.rs b/crates/cargo-gpu/src/target_specs.rs deleted file mode 100644 index eef8dca9c0..0000000000 --- a/crates/cargo-gpu/src/target_specs.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! This module deals with target specs, which are json metadata files that need to be passed to -//! rustc to add foreign targets such as `spirv_unknown_vulkan1.2`. -//! -//! There are 4 version ranges of `rustc_codegen_spirv` and they all need different handling of -//! their target specs: -//! * "ancient" versions such as 0.9.0 or earlier do not need target specs, just passing the target -//! string (`spirv-unknown-vulkan1.2`) directly is sufficient. We still prep target-specs for them -//! like the "legacy" variant below, spirv-builder -//! [will just ignore it](https://github.com/Rust-GPU/rust-gpu/blob/369122e1703c0c32d3d46f46fa11ccf12667af03/crates/spirv-builder/src/lib.rs#L987) -//! * "legacy" versions require target specs to compile, which is a requirement introduced by some -//! rustc version. Back then it was decided that cargo gpu would ship them, as they'd probably -//! never change, right? So now we're stuck with having to ship these "legacy" target specs with -//! cargo gpu *forever*. These are the symbol `legacy_target_specs::TARGET_SPECS`, with -//! `legacy_target_specs` being a **fixed** version of `rustc_codegen_spirv-target-specs`, -//! which must **never** update. -//! * As of [PR 256](https://github.com/Rust-GPU/rust-gpu/pull/256), `rustc_codegen_spirv` now has -//! a direct dependency on `rustc_codegen_spirv-target-specs`, allowing cargo gpu to pull the -//! required target specs directly from that dependency. At this point, the target specs are -//! still the same as the legacy target specs. -//! * The [edition 2024 PR](https://github.com/Rust-GPU/rust-gpu/pull/249) must update the -//! target specs to comply with newly added validation within rustc. This is why the new system -//! was implemented, so we can support both old and new target specs without having to worry -//! which version of cargo gpu you are using. It'll "just work". - -use crate::cache_dir; -use crate::spirv_source::{FindPackage as _, SpirvSource}; -use anyhow::Context as _; -use cargo_metadata::Metadata; -use std::path::{Path, PathBuf}; - -/// Extract legacy target specs from our executable into some directory -pub fn write_legacy_target_specs(target_spec_dir: &Path) -> anyhow::Result<()> { - std::fs::create_dir_all(target_spec_dir)?; - for (filename, contents) in legacy_target_specs::TARGET_SPECS { - let path = target_spec_dir.join(filename); - std::fs::write(&path, contents.as_bytes()) - .with_context(|| format!("writing legacy target spec file at [{}]", path.display()))?; - } - Ok(()) -} - -/// Copy spec files from one dir to another, assuming no subdirectories -fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> { - std::fs::create_dir_all(dst)?; - let dir = std::fs::read_dir(src)?; - for dir_entry in dir { - let file = dir_entry?; - let file_path = file.path(); - if file_path.is_file() { - std::fs::copy(file_path, dst.join(file.file_name()))?; - } - } - Ok(()) -} - -/// Computes the `target-specs` directory to use and updates the target spec files, if enabled. -pub fn update_target_specs_files( - source: &SpirvSource, - dummy_metadata: &Metadata, - update_files: bool, -) -> anyhow::Result { - log::info!( - "target-specs: Resolving target specs `{}`", - if update_files { - "and update them" - } else { - "without updating" - } - ); - - let mut target_specs_dst = source.install_dir()?.join("target-specs"); - if let Ok(target_specs) = dummy_metadata.find_package("rustc_codegen_spirv-target-specs") { - log::info!( - "target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`", - target_specs.manifest_path - ); - - let target_specs_src = target_specs - .manifest_path - .as_std_path() - .parent() - .and_then(|root| { - let src = root.join("target-specs"); - src.is_dir().then_some(src) - }) - .context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?; - log::info!( - "target-specs: found `rustc_codegen_spirv-target-specs` with `target-specs` directory `{}`", - target_specs_dst.display() - ); - - if source.is_path() { - // skip copy - log::info!( - "target-specs resolution: source is local path, use target-specs directly from `{}`", - target_specs_dst.display() - ); - target_specs_dst = target_specs_src; - } else { - // copy over the target-specs - log::info!( - "target-specs resolution: copying target-specs from `{}`{}", - target_specs_dst.display(), - if update_files { "" } else { " was skipped" } - ); - if update_files { - copy_spec_files(&target_specs_src, &target_specs_dst) - .context("copying target-specs json files")?; - } - } - } else { - // use legacy target specs bundled with cargo gpu - if source.is_path() { - // This is a stupid situation: - // * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`) - // * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout - // -> do what the old cargo gpu did, one global dir for all target specs - // and hope parallel runs don't shred each other - target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout"); - } - log::info!( - "target-specs resolution: legacy target specs in directory `{}`", - target_specs_dst.display() - ); - if update_files { - log::info!( - "target-specs: writing legacy target specs into `{}`", - target_specs_dst.display() - ); - write_legacy_target_specs(&target_specs_dst)?; - } - } - - Ok(target_specs_dst) -} From e2d64f443135ff0ca1a1f9ba416b167790ff79bd Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 12 Dec 2025 17:06:26 +0100 Subject: [PATCH 121/162] target-spec: remove `legacy_target_specs` dep --- Cargo.lock | 7 ------- Cargo.toml | 3 --- crates/cargo-gpu/Cargo.toml | 1 - 3 files changed, 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c2e2bece8..eb9af06aec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,7 +111,6 @@ dependencies = [ "env_logger", "log", "relative-path", - "rustc_codegen_spirv-target-specs", "semver", "serde", "serde_json", @@ -1027,12 +1026,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_codegen_spirv-target-specs" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c89eaf493b3dfc730cda42a77014aad65e03213992c7afe0dff60a9f7d3dd94" - [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index c4f1e0b253..baa11507ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,9 +33,6 @@ cargo-util-schemas = "0.8.2" semver = "1.0.26" dunce = "1.0.5" -# This crate MUST NEVER be upgraded, we need this particular "first" version to support old rust-gpu builds -legacy_target_specs = { package = "rustc_codegen_spirv-target-specs", version = "0.9.0", features = ["include_str"] } - [workspace.lints.rust] missing_docs = "warn" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index ba883834e2..81c8a87db1 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -14,7 +14,6 @@ default-run = "cargo-gpu" cargo_metadata.workspace = true anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } -legacy_target_specs.workspace = true clap.workspace = true directories.workspace = true env_logger.workspace = true From b3b507365b106cadc5d39275e0dc817a414f784e Mon Sep 17 00:00:00 2001 From: firestar99 Date: Mon, 22 Dec 2025 10:13:01 +0100 Subject: [PATCH 122/162] clippy: add `cargo gpu clippy` --- crates/cargo-gpu/src/build.rs | 22 ++++++++++++++++++---- crates/cargo-gpu/src/config.rs | 2 +- crates/cargo-gpu/src/lib.rs | 9 ++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index e8e620cba9..c00f8ccf1e 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -21,14 +21,19 @@ pub struct BuildArgs { #[clap(long, short, action)] pub watch: bool, - /// the flattened [`SpirvBuilder`] + /// The flattened [`SpirvBuilder`] #[clap(flatten)] #[serde(flatten)] pub spirv_builder: SpirvBuilder, - ///Renames the manifest.json file to the given name + /// Renames the `manifest.json` file to the given name #[clap(long, short, default_value = "manifest.json")] pub manifest_file: String, + + /// When building fails with [`SpirvBuilderError::NoArtifactProduced`], count it as a success anyway. + /// Used for e.g. `clippy`, which doesn't produce any artifacts. Defaults to false. + #[clap(skip)] + pub allow_no_artifacts: bool, } impl Default for BuildArgs { @@ -39,6 +44,7 @@ impl Default for BuildArgs { watch: false, spirv_builder: SpirvBuilder::default(), manifest_file: String::from("manifest.json"), + allow_no_artifacts: false, } } } @@ -116,8 +122,16 @@ impl Build { "Compiling shaders at {}...\n", self.install.shader_crate.display() ); - let result = self.build.spirv_builder.build()?; - self.parse_compilation_result(&result)?; + let result = self.build.spirv_builder.build(); + match result { + Ok(result) => { + self.parse_compilation_result(&result)?; + } + // conditionally ignore NoArtifactProduced + Err(SpirvBuilderError::NoArtifactProduced { .. }) + if self.build.allow_no_artifacts => {} + Err(err) => return Err(err.into()), + } } Ok(()) } diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 3c3d66777d..2d9696b7b8 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -31,7 +31,7 @@ impl Config { ) -> anyhow::Result { let mut config = metadata.as_json(shader_crate_path)?; - env_args.retain(|arg| !(arg == "build" || arg == "install")); + env_args.retain(|arg| !(arg == "build" || arg == "install" || arg == "clippy")); let cli_args_json = Self::cli_args_to_json(env_args)?; Self::json_merge(&mut config, cli_args_json, None)?; diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index d4822781ff..949bcb9fb6 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -104,6 +104,9 @@ pub enum Command { /// Compile a shader crate to SPIR-V. Build(Box), + /// Run clippy on a shader crate with a SPIR-V target + Clippy(Box), + /// Show some useful values. Show(Show), @@ -139,13 +142,17 @@ impl Command { ); command.install.run()?; } - Self::Build(build) => { + Self::Build(build) | Self::Clippy(build) => { let shader_crate_path = &build.install.shader_crate; let mut command = config::Config::clap_command_with_cargo_config( shader_crate_path, env_args, metadata_cache, )?; + if let Self::Clippy(_) = self { + command.build.spirv_builder.cargo_cmd = Some("clippy".into()); + command.build.allow_no_artifacts = true; + } log::debug!("building with final merged arguments: {command:#?}"); if command.build.watch { From 54d9060f57969f9d7302caeb3dd14378c74007ef Mon Sep 17 00:00:00 2001 From: firestar99 Date: Mon, 22 Dec 2025 13:22:13 +0100 Subject: [PATCH 123/162] template: add `unexpected_cfgs` for spirv --- crates/shader-crate-template/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index a3363f4a62..96f0422851 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" [lib] crate-type = ["rlib", "cdylib"] +[lints.rust] +unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } + # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released From 8df8515bc3b756c7056b8c71e2851e961c146678 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 17:49:53 +0100 Subject: [PATCH 124/162] clippy: add `cargo gpu check` --- crates/cargo-gpu/src/config.rs | 4 +++- crates/cargo-gpu/src/lib.rs | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index 2d9696b7b8..c8df371242 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -31,7 +31,9 @@ impl Config { ) -> anyhow::Result { let mut config = metadata.as_json(shader_crate_path)?; - env_args.retain(|arg| !(arg == "build" || arg == "install" || arg == "clippy")); + env_args.retain(|arg| { + !(arg == "build" || arg == "install" || arg == "check" || arg == "clippy") + }); let cli_args_json = Self::cli_args_to_json(env_args)?; Self::json_merge(&mut config, cli_args_json, None)?; diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index 949bcb9fb6..cc81dce90f 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -104,6 +104,9 @@ pub enum Command { /// Compile a shader crate to SPIR-V. Build(Box), + /// Run `cargo check` on the shader crate with a SPIR-V target without building the actual shaders + Check(Box), + /// Run clippy on a shader crate with a SPIR-V target Clippy(Box), @@ -142,16 +145,24 @@ impl Command { ); command.install.run()?; } - Self::Build(build) | Self::Clippy(build) => { + Self::Build(build) | Self::Check(build) | Self::Clippy(build) => { let shader_crate_path = &build.install.shader_crate; let mut command = config::Config::clap_command_with_cargo_config( shader_crate_path, env_args, metadata_cache, )?; - if let Self::Clippy(_) = self { - command.build.spirv_builder.cargo_cmd = Some("clippy".into()); - command.build.allow_no_artifacts = true; + #[expect(clippy::wildcard_enum_match_arm, reason = "unreachable")] + match self { + Self::Check(_) => { + command.build.spirv_builder.cargo_cmd = Some("check".into()); + command.build.allow_no_artifacts = true; + } + Self::Clippy(_) => { + command.build.spirv_builder.cargo_cmd = Some("clippy".into()); + command.build.allow_no_artifacts = true; + } + _ => {} } log::debug!("building with final merged arguments: {command:#?}"); From 98cd1193425ab023bf6a1b6f2c3a70c58efaff91 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:06:12 +0100 Subject: [PATCH 125/162] install-crate: move crate properties (version, edition) to workspace --- Cargo.toml | 8 ++++++++ crates/cargo-gpu/Cargo.toml | 12 ++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index baa11507ba..4d3c46c1d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,14 @@ exclude = [ resolver = "2" +[workspace.package] +version = "0.1.0" +edition = "2021" +repository = "https://github.com/Rust-GPU/cargo-gpu" +readme = "./README.md" +keywords = ["gpu", "compiler", "rust-gpu"] +license = "MIT OR Apache-2.0" + [workspace.dependencies] spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "a30bd43db45f2bfe260051f44141e5eaffcbb4b0", default-features = false } anyhow = "1.0.98" diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 81c8a87db1..d451396a47 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "cargo-gpu" -version = "0.1.0" -edition = "2021" +version.workspace = true +edition.workspace = true description = "Generates shader .spv files from rust-gpu shader crates" -repository = "https://github.com/Rust-GPU/cargo-gpu" -readme = "../../README.md" -keywords = ["gpu", "compiler", "rust-gpu"] -license = "MIT OR Apache-2.0" +repository.workspace = true +readme.workspace = true +keywords.workspace = true +license.workspace = true default-run = "cargo-gpu" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html From d033a545a240ed186b9a1703564a6ef316170795 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:18:03 +0100 Subject: [PATCH 126/162] install-crate: move install action to new `cargo-gpu-install` crate --- Cargo.lock | 23 +++++ Cargo.toml | 2 + crates/cargo-gpu-install/Cargo.toml | 36 ++++++++ crates/cargo-gpu-install/README.md | 43 ++++++++++ .../src/install.rs | 0 .../src/install_toolchain.rs | 0 crates/cargo-gpu-install/src/lib.rs | 64 ++++++++++++++ .../src/spirv_source.rs | 0 .../src/test.rs | 2 +- crates/cargo-gpu/Cargo.toml | 2 + crates/cargo-gpu/src/lib.rs | 84 +++---------------- 11 files changed, 182 insertions(+), 74 deletions(-) create mode 100644 crates/cargo-gpu-install/Cargo.toml create mode 100644 crates/cargo-gpu-install/README.md rename crates/{cargo-gpu => cargo-gpu-install}/src/install.rs (100%) rename crates/{cargo-gpu => cargo-gpu-install}/src/install_toolchain.rs (100%) create mode 100644 crates/cargo-gpu-install/src/lib.rs rename crates/{cargo-gpu => cargo-gpu-install}/src/spirv_source.rs (100%) rename crates/{cargo-gpu => cargo-gpu-install}/src/test.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index eb9af06aec..47600777f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,29 @@ dependencies = [ [[package]] name = "cargo-gpu" version = "0.1.0" +dependencies = [ + "anyhow", + "cargo-gpu-install", + "cargo-util-schemas", + "cargo_metadata", + "clap", + "crossterm", + "directories", + "dunce", + "env_logger", + "log", + "relative-path", + "semver", + "serde", + "serde_json", + "spirv-builder", + "tempfile", + "test-log", +] + +[[package]] +name = "cargo-gpu-install" +version = "0.1.0" dependencies = [ "anyhow", "cargo-util-schemas", diff --git a/Cargo.toml b/Cargo.toml index 4d3c46c1d1..1af71b3b51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "crates/cargo-gpu", + "crates/cargo-gpu-install", "crates/xtask", ] @@ -24,6 +25,7 @@ license = "MIT OR Apache-2.0" [workspace.dependencies] spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "a30bd43db45f2bfe260051f44141e5eaffcbb4b0", default-features = false } +cargo-gpu-install = { path = "./crates/cargo-gpu-install" } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } crossterm = "0.29.0" diff --git a/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml new file mode 100644 index 0000000000..d7d34075d2 --- /dev/null +++ b/crates/cargo-gpu-install/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "cargo-gpu-install" +version.workspace = true +edition.workspace = true +description = "Install rust-gpu and it's required toolchain automatically" +repository.workspace = true +readme.workspace = true +keywords.workspace = true +license.workspace = true + +[features] +test = ["dep:tempfile"] + +[dependencies] +cargo_metadata.workspace = true +anyhow.workspace = true +spirv-builder = { workspace = true, features = ["clap", "watch"] } +clap.workspace = true +directories.workspace = true +env_logger.workspace = true +log.workspace = true +relative-path.workspace = true +serde.workspace = true +serde_json.workspace = true +crossterm.workspace = true +semver.workspace = true +dunce.workspace = true +tempfile = { workspace = true, optional = true } + +[dev-dependencies] +test-log.workspace = true +cargo_metadata = { workspace = true, features = ["builder"] } +cargo-util-schemas = "0.8.2" + +[lints] +workspace = true diff --git a/crates/cargo-gpu-install/README.md b/crates/cargo-gpu-install/README.md new file mode 100644 index 0000000000..5068029c29 --- /dev/null +++ b/crates/cargo-gpu-install/README.md @@ -0,0 +1,43 @@ +# cargo-gpu-install + +`cargo-gpu-install` is the install action of `cargo-gpu`, separated into its own crate. It's intended to be used +by build scripts and other binaries that need automated installation of rust-gpu and it's required toolchain, +without having to pull all the other cli dependencies of the full `cargo-gpu` (like clap). + +## Example + +This is an example build script meant to be placed in your "main" std crate, to build a secondary no-std "shader" crate. +But you can just as well use this in your executable directly, with some minor adjustments. +```rust,no_run +# use std::path::PathBuf; +# use cargo_gpu_install::install::Install; +# use cargo_gpu_install::spirv_builder::SpirvMetadata; + +pub fn main() -> Result<(), Box> { + // path to your shader crate + let shader_crate = PathBuf::from("./shaders"); + + // install the toolchain and build the `rustc_codegen_spirv` codegen backend with it + let backend = Install::from_shader_crate(shader_crate.clone()).run()?; + + // build the shader crate + let mut builder = backend.to_spirv_builder(shader_crate, "spirv-unknown-vulkan1.2"); + // set to true when you're in a build script, false when outside one + builder.build_script.defaults = true; + // enable debug information in the shaders + builder.spirv_metadata = SpirvMetadata::Full; + let spv_result = builder.build()?; + let path_to_spv = spv_result.module.unwrap_single(); + + // emit path to the artifact into env var, use it anywhere in your crate like: + // > include_str!(env!("MY_SHADER_PATH")) + println!( + "cargo::rustc-env=MY_SHADER_PATH={}", + path_to_spv.display() + ); + + // you could also generate some rust source code into the `std::env::var("OUT_DIR")` dir + // and use `include!(concat!(env!("OUT_DIR"), "/shader_symbols.rs"));` to include it + Ok(()) +} +``` diff --git a/crates/cargo-gpu/src/install.rs b/crates/cargo-gpu-install/src/install.rs similarity index 100% rename from crates/cargo-gpu/src/install.rs rename to crates/cargo-gpu-install/src/install.rs diff --git a/crates/cargo-gpu/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs similarity index 100% rename from crates/cargo-gpu/src/install_toolchain.rs rename to crates/cargo-gpu-install/src/install_toolchain.rs diff --git a/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs new file mode 100644 index 0000000000..e9b28891f8 --- /dev/null +++ b/crates/cargo-gpu-install/src/lib.rs @@ -0,0 +1,64 @@ +#![expect(clippy::pub_use, reason = "pub use for build scripts")] +#![doc = include_str!("../README.md")] + +pub mod install; +mod install_toolchain; +pub mod spirv_source; +pub mod test; + +pub use spirv_builder; + +/// Central function to write to the user. +#[macro_export] +macro_rules! user_output { + ($($args: tt)*) => { { + #[allow( + clippy::allow_attributes, + clippy::useless_attribute, + unused_imports, + reason = "`std::io::Write` is only sometimes called??" + )] + use std::io::Write as _; + + #[expect( + clippy::non_ascii_literal, + reason = "CRAB GOOD. CRAB IMPORTANT." + )] + { + print!("🦀 "); + } + print!($($args)*); + std::io::stdout().flush().unwrap(); + } } +} + +/// The central cache directory of cargo gpu +/// +/// # Errors +/// may fail if we can't find the user home directory +#[inline] +#[cfg(not(test))] +#[expect(clippy::cfg_not_test, reason = "tests use different cache_dir")] +pub fn cache_dir() -> anyhow::Result { + use anyhow::Context as _; + Ok(directories::BaseDirs::new() + .with_context(|| "could not find the user home directory")? + .cache_dir() + .join("rust-gpu")) +} + +#[cfg(test)] +pub use test::test_cache_dir as cache_dir; + +/// Returns a string suitable to use as a directory. +/// +/// Created from the spirv-builder source dep and the rustc channel. +fn to_dirname(text: &str) -> String { + text.replace( + [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], + "_", + ) + .split(['{', '}', ' ', '\n', '"', '\'']) + .collect::>() + .concat() +} diff --git a/crates/cargo-gpu/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs similarity index 100% rename from crates/cargo-gpu/src/spirv_source.rs rename to crates/cargo-gpu-install/src/spirv_source.rs diff --git a/crates/cargo-gpu/src/test.rs b/crates/cargo-gpu-install/src/test.rs similarity index 99% rename from crates/cargo-gpu/src/test.rs rename to crates/cargo-gpu-install/src/test.rs index 4fb6a8dab8..8cdc5cf841 100644 --- a/crates/cargo-gpu/src/test.rs +++ b/crates/cargo-gpu-install/src/test.rs @@ -1,5 +1,5 @@ //! utilities for tests -#![cfg(test)] +#![cfg(any(feature = "test", test))] use anyhow::Context; use std::cell::RefCell; diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index d451396a47..40a29de7a6 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -14,6 +14,7 @@ default-run = "cargo-gpu" cargo_metadata.workspace = true anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } +cargo-gpu-install.workspace = true clap.workspace = true directories.workspace = true env_logger.workspace = true @@ -26,6 +27,7 @@ semver.workspace = true dunce.workspace = true [dev-dependencies] +cargo-gpu-install = { workspace = true, features = ["test"] } tempfile.workspace = true test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } diff --git a/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs index cc81dce90f..eadde1c8d8 100644 --- a/crates/cargo-gpu/src/lib.rs +++ b/crates/cargo-gpu/src/lib.rs @@ -1,4 +1,4 @@ -#![expect(clippy::pub_use, reason = "pub use for build scripts")] +#![expect(clippy::pub_use, reason = "reexports from cargo_gpu_install crate")] //! Rust GPU shader crate builder. //! @@ -50,68 +50,37 @@ //! conduct other post-processing, like converting the `spv` files into `wgsl` files, //! for example. -use crate::dump_usage::dump_full_usage_for_readme; -use build::Build; -use show::Show; +#[cfg(test)] +pub use cargo_gpu_install::test; +pub use cargo_gpu_install::{cache_dir, install, spirv_builder, spirv_source, user_output}; +pub use metadata::MetadataCache; mod build; mod config; mod dump_usage; -mod install; -mod install_toolchain; mod linkage; mod lockfile; mod metadata; mod show; -mod spirv_source; -mod test; - -pub use install::*; -pub use metadata::MetadataCache; -pub use spirv_builder; - -/// Central function to write to the user. -#[macro_export] -macro_rules! user_output { - ($($args: tt)*) => { { - #[allow( - clippy::allow_attributes, - clippy::useless_attribute, - unused_imports, - reason = "`std::io::Write` is only sometimes called??" - )] - use std::io::Write as _; - - #[expect( - clippy::non_ascii_literal, - reason = "CRAB GOOD. CRAB IMPORTANT." - )] - { - print!("🦀 "); - } - print!($($args)*); - std::io::stdout().flush().unwrap(); - } } -} /// All of the available subcommands for `cargo gpu` #[derive(clap::Subcommand)] #[non_exhaustive] pub enum Command { /// Install rust-gpu compiler artifacts. - Install(Box), + Install(Box), /// Compile a shader crate to SPIR-V. - Build(Box), + Build(Box), /// Run `cargo check` on the shader crate with a SPIR-V target without building the actual shaders - Check(Box), + Check(Box), /// Run clippy on a shader crate with a SPIR-V target - Clippy(Box), + Clippy(Box), /// Show some useful values. - Show(Show), + Show(show::Show), /// A hidden command that can be used to recursively print out all the subcommand help messages: /// `cargo gpu dump-usage` @@ -175,7 +144,7 @@ impl Command { command.run()?; } Self::Show(show) => show.run()?, - Self::DumpUsage => dump_full_usage_for_readme()?, + Self::DumpUsage => dump_usage::dump_full_usage_for_readme()?, } Ok(()) @@ -191,34 +160,3 @@ pub struct Cli { #[clap(subcommand)] pub command: Command, } - -/// The central cache directory of cargo gpu -/// -/// # Errors -/// may fail if we can't find the user home directory -#[inline] -#[cfg(not(test))] -#[expect(clippy::cfg_not_test, reason = "tests use different cache_dir")] -pub fn cache_dir() -> anyhow::Result { - use anyhow::Context as _; - Ok(directories::BaseDirs::new() - .with_context(|| "could not find the user home directory")? - .cache_dir() - .join("rust-gpu")) -} - -#[cfg(test)] -pub use test::test_cache_dir as cache_dir; - -/// Returns a string suitable to use as a directory. -/// -/// Created from the spirv-builder source dep and the rustc channel. -fn to_dirname(text: &str) -> String { - text.replace( - [std::path::MAIN_SEPARATOR, '\\', '/', '.', ':', '@', '='], - "_", - ) - .split(['{', '}', ' ', '\n', '"', '\'']) - .collect::>() - .concat() -} From 64a1e4ed64eef6af074f236b208bfc461a883bcd Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:58:19 +0100 Subject: [PATCH 127/162] install-crate: fix clippy --- crates/cargo-gpu-install/src/lib.rs | 7 ++++++- crates/cargo-gpu-install/src/spirv_source.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs index e9b28891f8..5b9fc1bcb6 100644 --- a/crates/cargo-gpu-install/src/lib.rs +++ b/crates/cargo-gpu-install/src/lib.rs @@ -1,5 +1,10 @@ #![expect(clippy::pub_use, reason = "pub use for build scripts")] -#![doc = include_str!("../README.md")] +#![expect( + missing_docs, + clippy::missing_docs_in_private_items, + reason = "crate docs are cfg'ed out" +)] +#![cfg_attr(doc, doc = include_str!("../README.md"))] pub mod install; mod install_toolchain; diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index 1775a99765..d0ae054ffd 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -22,6 +22,7 @@ use std::path::{Path, PathBuf}; /// - a repo of "https://github.com/Rust-GPU/rust-gpu.git" /// - a revision of "abc213" /// * a local Path +#[non_exhaustive] #[derive(Eq, PartialEq, Clone, Debug)] pub enum SpirvSource { /// If the shader specifies a simple version like `spirv-std = "0.9.0"` then the source of @@ -69,6 +70,9 @@ impl core::fmt::Display for SpirvSource { impl SpirvSource { /// Figures out which source of `rust-gpu` to use + /// + /// # Errors + /// Crate may not depend on `spirv-std` or is otherwise malformed pub fn new( shader_crate_path: &Path, maybe_rust_gpu_source: Option<&str>, @@ -95,6 +99,9 @@ impl SpirvSource { } /// Look into the shader crate to get the version of `rust-gpu` it's using. + /// + /// # Errors + /// Crate may not depend on `spirv-std` or is otherwise malformed pub fn get_rust_gpu_deps_from_shader(shader_crate_path: &Path) -> anyhow::Result { let crate_metadata = query_metadata(shader_crate_path)?; let spirv_std_package = crate_metadata.find_package("spirv-std")?; @@ -110,6 +117,9 @@ impl SpirvSource { /// Convert the `SpirvSource` to a cache directory in which we can build it. /// It needs to be dynamically created because an end-user might want to swap out the source, /// maybe using their own fork for example. + /// + /// # Errors + /// [`crate::cache_dir`] may fail pub fn install_dir(&self) -> anyhow::Result { match self { Self::Path { @@ -123,6 +133,7 @@ impl SpirvSource { } /// Returns true if self is a Path + #[must_use] pub const fn is_path(&self) -> bool { matches!(self, Self::Path { .. }) } @@ -182,6 +193,9 @@ impl SpirvSource { } /// get the Package metadata from some crate +/// +/// # Errors +/// metadata query may fail pub fn query_metadata(crate_path: &Path) -> anyhow::Result { log::debug!("Running `cargo metadata` on `{}`", crate_path.display()); let metadata = MetadataCommand::new() @@ -197,6 +211,9 @@ pub fn query_metadata(crate_path: &Path) -> anyhow::Result { /// implements [`Self::find_package`] pub trait FindPackage { /// Search for a package or return a nice error + /// + /// # Errors + /// package may not be found or crate may be malformed fn find_package(&self, crate_name: &str) -> anyhow::Result<&Package>; } @@ -219,6 +236,9 @@ impl FindPackage for Metadata { } /// Parse the `rust-toolchain.toml` in the working tree of the checked-out version of the `rust-gpu` repo. +/// +/// # Errors +/// parsing may fail pub fn get_channel_from_rustc_codegen_spirv_build_script( rustc_codegen_spirv_package: &Package, ) -> anyhow::Result { From 922e8f3243573657508ac5a458db1c024ea22f1e Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:21:06 +0100 Subject: [PATCH 128/162] install-crate: cargo shear --- Cargo.lock | 9 --------- crates/cargo-gpu-install/Cargo.toml | 5 ----- crates/cargo-gpu/Cargo.toml | 4 ---- 3 files changed, 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47600777f7..3e63107518 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,11 +103,8 @@ version = "0.1.0" dependencies = [ "anyhow", "cargo-gpu-install", - "cargo-util-schemas", "cargo_metadata", "clap", - "crossterm", - "directories", "dunce", "env_logger", "log", @@ -116,7 +113,6 @@ dependencies = [ "serde", "serde_json", "spirv-builder", - "tempfile", "test-log", ] @@ -130,13 +126,8 @@ dependencies = [ "clap", "crossterm", "directories", - "dunce", - "env_logger", "log", - "relative-path", - "semver", "serde", - "serde_json", "spirv-builder", "tempfile", "test-log", diff --git a/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml index d7d34075d2..108e44d00d 100644 --- a/crates/cargo-gpu-install/Cargo.toml +++ b/crates/cargo-gpu-install/Cargo.toml @@ -17,14 +17,9 @@ anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } clap.workspace = true directories.workspace = true -env_logger.workspace = true log.workspace = true -relative-path.workspace = true serde.workspace = true -serde_json.workspace = true crossterm.workspace = true -semver.workspace = true -dunce.workspace = true tempfile = { workspace = true, optional = true } [dev-dependencies] diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 40a29de7a6..3fee0877e9 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -16,22 +16,18 @@ anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } cargo-gpu-install.workspace = true clap.workspace = true -directories.workspace = true env_logger.workspace = true log.workspace = true relative-path.workspace = true serde.workspace = true serde_json.workspace = true -crossterm.workspace = true semver.workspace = true dunce.workspace = true [dev-dependencies] cargo-gpu-install = { workspace = true, features = ["test"] } -tempfile.workspace = true test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } -cargo-util-schemas = "0.8.2" [lints] workspace = true From b705e15c6fb9f050994a02aafdb5136befc35606 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:26:01 +0100 Subject: [PATCH 129/162] install-crate: clap and watch feature for optional deps --- crates/cargo-gpu-install/Cargo.toml | 6 ++++-- crates/cargo-gpu-install/src/install.rs | 22 +++++++++++++--------- crates/cargo-gpu/Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml index 108e44d00d..5aa026169a 100644 --- a/crates/cargo-gpu-install/Cargo.toml +++ b/crates/cargo-gpu-install/Cargo.toml @@ -9,13 +9,15 @@ keywords.workspace = true license.workspace = true [features] +clap = ["dep:clap", "spirv-builder/clap"] +watch = ["spirv-builder/watch"] test = ["dep:tempfile"] [dependencies] cargo_metadata.workspace = true anyhow.workspace = true -spirv-builder = { workspace = true, features = ["clap", "watch"] } -clap.workspace = true +spirv-builder.workspace = true +clap = { workspace = true, optional = true } directories.workspace = true log.workspace = true serde.workspace = true diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index c9ea0eceba..0de94036b1 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -54,19 +54,23 @@ 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 { /// Cargo target to compile. /// /// Conflicts with `--shader-crate`. - #[clap(short, long, conflicts_with("shader_crate"))] + #[cfg_attr(feature = "clap", clap(short, long, conflicts_with("shader_crate")))] pub package: Option, /// Directory containing the shader crate to compile. /// /// Conflicts with `--package` or `-p`. - #[clap(long, default_value = "./", conflicts_with("package"))] + #[cfg_attr( + feature = "clap", + clap(long, default_value = "./", conflicts_with("package")) + )] pub shader_crate: PathBuf, #[expect( @@ -75,7 +79,7 @@ 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, /// Version of `spirv-builder` dependency. @@ -83,22 +87,22 @@ pub struct Install { /// 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, /// 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 @@ -122,7 +126,7 @@ pub struct Install { /// way source URLs are encoded. See these PRs for more details: /// * /// * - #[clap(long, action, verbatim_doc_comment)] + #[cfg_attr(feature = "clap", clap(long, action, verbatim_doc_comment))] pub force_overwrite_lockfiles_v4_to_v3: bool, } diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 3fee0877e9..edf04cc36e 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -14,7 +14,7 @@ default-run = "cargo-gpu" cargo_metadata.workspace = true anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } -cargo-gpu-install.workspace = true +cargo-gpu-install = { workspace = true, features = ["clap", "watch"] } clap.workspace = true env_logger.workspace = true log.workspace = true From 5d2d9a48da214502c14214f56a5bde44d683aa20 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:40:33 +0100 Subject: [PATCH 130/162] install-crate: tty feature to make crossterm and user output optional --- Cargo.lock | 49 +++---------------- Cargo.toml | 2 +- crates/cargo-gpu-install/Cargo.toml | 3 +- .../src/install_toolchain.rs | 27 ++++++++-- crates/cargo-gpu-install/src/lib.rs | 8 +++ crates/cargo-gpu/Cargo.toml | 2 +- 6 files changed, 41 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e63107518..20b8e95f29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,15 +226,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "convert_case" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "crossterm" version = "0.29.0" @@ -243,7 +234,6 @@ checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ "bitflags 2.9.0", "crossterm_winapi", - "derive_more", "document-features", "mio", "parking_lot", @@ -328,27 +318,6 @@ dependencies = [ "syn", ] -[[package]] -name = "derive_more" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "directories" version = "6.0.0" @@ -1178,9 +1147,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ "libc", "signal-hook-registry", @@ -1188,9 +1157,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -1199,9 +1168,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.5" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ "libc", ] @@ -1489,12 +1458,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - [[package]] name = "unicode-xid" version = "0.2.6" diff --git a/Cargo.toml b/Cargo.toml index 1af71b3b51..c65bc291d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "a30bd43db cargo-gpu-install = { path = "./crates/cargo-gpu-install" } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } -crossterm = "0.29.0" +crossterm = { version = "0.29.0", default-features = false, features = ["events", "windows"] } directories = "6.0.0" env_logger = "0.11.8" log = "0.4" diff --git a/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml index 5aa026169a..8a914c7072 100644 --- a/crates/cargo-gpu-install/Cargo.toml +++ b/crates/cargo-gpu-install/Cargo.toml @@ -12,6 +12,7 @@ license.workspace = true clap = ["dep:clap", "spirv-builder/clap"] watch = ["spirv-builder/watch"] test = ["dep:tempfile"] +tty = ["dep:crossterm"] [dependencies] cargo_metadata.workspace = true @@ -21,7 +22,7 @@ clap = { workspace = true, optional = true } directories.workspace = true log.workspace = true serde.workspace = true -crossterm.workspace = true +crossterm = { workspace = true, optional = true } tempfile = { workspace = true, optional = true } [dev-dependencies] diff --git a/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs index 98d35d59ab..300ddb83cd 100644 --- a/crates/cargo-gpu-install/src/install_toolchain.rs +++ b/crates/cargo-gpu-install/src/install_toolchain.rs @@ -1,6 +1,7 @@ //! toolchain installation logic use anyhow::Context as _; +#[cfg(feature = "tty")] use crossterm::tty::IsTty as _; use crate::user_output; @@ -98,6 +99,20 @@ pub fn ensure_toolchain_and_components_exist( Ok(()) } +#[cfg(not(feature = "tty"))] +/// Prompt user if they want to install a new Rust toolchain. +fn get_consent_for_toolchain_install( + _prompt: &str, + skip_toolchain_install_consent: bool, +) -> anyhow::Result<()> { + if skip_toolchain_install_consent { + Ok(()) + } else { + no_tty() + } +} + +#[cfg(feature = "tty")] /// Prompt user if they want to install a new Rust toolchain. fn get_consent_for_toolchain_install( prompt: &str, @@ -108,10 +123,7 @@ fn get_consent_for_toolchain_install( } if !std::io::stdout().is_tty() { - user_output!("No TTY detected so can't ask for consent to install Rust toolchain."); - log::error!("Attempted to ask for consent when there's no TTY"); - #[expect(clippy::exit, reason = "can't ask for user consent if there's no TTY")] - std::process::exit(1); + no_tty() } log::debug!("asking for consent to install the required toolchain"); @@ -143,3 +155,10 @@ fn get_consent_for_toolchain_install( std::process::exit(0); } } + +fn no_tty() -> ! { + user_output!("No TTY detected so can't ask for consent to install Rust toolchain."); + log::error!("Attempted to ask for consent when there's no TTY"); + #[expect(clippy::exit, reason = "can't ask for user consent if there's no TTY")] + std::process::exit(1); +} diff --git a/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs index 5b9fc1bcb6..f59d39c5d0 100644 --- a/crates/cargo-gpu-install/src/lib.rs +++ b/crates/cargo-gpu-install/src/lib.rs @@ -15,6 +15,7 @@ pub use spirv_builder; /// Central function to write to the user. #[macro_export] +#[cfg(feature = "tty")] macro_rules! user_output { ($($args: tt)*) => { { #[allow( @@ -37,6 +38,13 @@ macro_rules! user_output { } } } +/// Central function to write to the user. +#[macro_export] +#[cfg(not(feature = "tty"))] +macro_rules! user_output { + ($($args: tt)*) => {{}}; +} + /// The central cache directory of cargo gpu /// /// # Errors diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index edf04cc36e..41c8dc38e8 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -14,7 +14,7 @@ default-run = "cargo-gpu" cargo_metadata.workspace = true anyhow.workspace = true spirv-builder = { workspace = true, features = ["clap", "watch"] } -cargo-gpu-install = { workspace = true, features = ["clap", "watch"] } +cargo-gpu-install = { workspace = true, features = ["clap", "watch", "tty"] } clap.workspace = true env_logger.workspace = true log.workspace = true From 671450e7fe1b8e4f45a1db0154af87c7dc29ef61 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 12:41:53 +0100 Subject: [PATCH 131/162] install-crate: remove spirv-builder direct dep in cargo-gpu --- Cargo.lock | 1 - crates/cargo-gpu/Cargo.toml | 1 - crates/cargo-gpu/src/build.rs | 2 +- crates/cargo-gpu/src/config.rs | 6 ++---- crates/cargo-gpu/src/lockfile.rs | 2 +- crates/cargo-gpu/src/show.rs | 7 ++++--- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20b8e95f29..6d539d3fec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,7 +112,6 @@ dependencies = [ "semver", "serde", "serde_json", - "spirv-builder", "test-log", ] diff --git a/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml index 41c8dc38e8..951e88451a 100644 --- a/crates/cargo-gpu/Cargo.toml +++ b/crates/cargo-gpu/Cargo.toml @@ -13,7 +13,6 @@ default-run = "cargo-gpu" [dependencies] cargo_metadata.workspace = true anyhow.workspace = true -spirv-builder = { workspace = true, features = ["clap", "watch"] } cargo-gpu-install = { workspace = true, features = ["clap", "watch", "tty"] } clap.workspace = true env_logger.workspace = true diff --git a/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs index c00f8ccf1e..ed1e9736f3 100644 --- a/crates/cargo-gpu/src/build.rs +++ b/crates/cargo-gpu/src/build.rs @@ -5,8 +5,8 @@ use crate::install::Install; use crate::linkage::Linkage; use crate::lockfile::LockfileMismatchHandler; +use crate::spirv_builder::{CompileResult, ModuleResult, SpirvBuilder, SpirvBuilderError}; use anyhow::Context as _; -use spirv_builder::{CompileResult, ModuleResult, SpirvBuilder, SpirvBuilderError}; use std::io::Write as _; use std::path::PathBuf; diff --git a/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs index c8df371242..37bcd84bf0 100644 --- a/crates/cargo-gpu/src/config.rs +++ b/crates/cargo-gpu/src/config.rs @@ -91,6 +91,7 @@ impl Config { mod test { use super::*; + use crate::spirv_builder::Capability; use crate::test::TestEnv; use std::io::Write as _; @@ -225,10 +226,7 @@ mod test { .unwrap(); assert_eq!( args.build.spirv_builder.capabilities, - vec![ - spirv_builder::Capability::AtomicStorage, - spirv_builder::Capability::Matrix - ] + vec![Capability::AtomicStorage, Capability::Matrix] ); } diff --git a/crates/cargo-gpu/src/lockfile.rs b/crates/cargo-gpu/src/lockfile.rs index bce1487aa1..89aaad6f02 100644 --- a/crates/cargo-gpu/src/lockfile.rs +++ b/crates/cargo-gpu/src/lockfile.rs @@ -2,9 +2,9 @@ //! v0.9.0 uses an old toolchain requiring v3 and will refuse to build with a v4 lockfile being //! present. This module takes care of warning the user and potentially downgrading the lockfile. +use crate::spirv_builder::query_rustc_version; use anyhow::Context as _; use semver::Version; -use spirv_builder::query_rustc_version; use std::io::Write as _; /// `Cargo.lock` manifest version 4 became the default in Rust 1.83.0. Conflicting manifest diff --git a/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs index 1e318c4845..491550cd94 100644 --- a/crates/cargo-gpu/src/show.rs +++ b/crates/cargo-gpu/src/show.rs @@ -1,6 +1,7 @@ //! Display various information about `cargo gpu`, eg its cache directory. use crate::cache_dir; +use crate::spirv_builder::Capability; use crate::spirv_source::SpirvSource; /// Show the computed source of the spirv-std dependency. @@ -69,11 +70,11 @@ impl Show { } /// Iterator over all `Capability` variants. - fn capability_variants_iter() -> impl Iterator { + fn capability_variants_iter() -> impl Iterator { // Since spirv::Capability is repr(u32) we can iterate over // u32s until some maximum #[expect(clippy::as_conversions, reason = "We know all variants are repr(u32)")] - let last_capability = spirv_builder::Capability::CacheControlsINTEL as u32; - (0..=last_capability).filter_map(spirv_builder::Capability::from_u32) + let last_capability = Capability::CacheControlsINTEL as u32; + (0..=last_capability).filter_map(Capability::from_u32) } } From 7445a7a70385e4ee0e6cb88cfbb1a50f966a060d Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 15:11:16 +0100 Subject: [PATCH 132/162] install-crate: fix test instability unintentionally started sharing the cache dir between tests --- crates/cargo-gpu-install/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs index f59d39c5d0..d7b2210156 100644 --- a/crates/cargo-gpu-install/src/lib.rs +++ b/crates/cargo-gpu-install/src/lib.rs @@ -50,7 +50,7 @@ macro_rules! user_output { /// # Errors /// may fail if we can't find the user home directory #[inline] -#[cfg(not(test))] +#[cfg(not(any(feature = "test", test)))] #[expect(clippy::cfg_not_test, reason = "tests use different cache_dir")] pub fn cache_dir() -> anyhow::Result { use anyhow::Context as _; @@ -60,7 +60,7 @@ pub fn cache_dir() -> anyhow::Result { .join("rust-gpu")) } -#[cfg(test)] +#[cfg(any(feature = "test", test))] pub use test::test_cache_dir as cache_dir; /// Returns a string suitable to use as a directory. From b41f50fe4389be09f0157be0f3d38460c0702561 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 14:58:53 +0100 Subject: [PATCH 133/162] readme: final goal readme --- README.md | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9065311f7d..8e73fafeba 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,54 @@ # cargo-gpu -Command line tool for building Rust shaders using rust-gpu. +`cargo-gpu` is an installation manager and command line tool for [rust-gpu](https://github.com/Rust-GPU/rust-gpu/). `cargo-gpu` is not an essential requirement, it should just make working with `rust-gpu` easier. -## Getting Started +There are 2 ways to use it: +1. Through a CLI, ie `cargo gpu ...` +2. As a crate included in your build scripts or executables -### Installation +## 1. CLI Quickstart -To install the tool ensure you have `rustup`. Then run: +To install the command line tool, ensure you are using `rustup`. Then run: ``` cargo install --git https://github.com/rust-gpu/cargo-gpu cargo-gpu ``` -After that you can use `cargo gpu` to compile your shader crates with: +You can then use `cargo gpu` to compile your shader crates or use any of the other commands you're used to: ``` cargo gpu build +cargo gpu check +cargo gpu clippy ``` -This plain invocation will compile the crate in the current directory and -place the compiled shaders in the current directory. +### Example project -Use `cargo gpu help` to see other options :) +To create an example project from our [templates](https://github.com/Rust-GPU/rust-gpu-template), use the command below: +``` +cargo gpu new +# choose any template you want, then select cargo-gpu cmdline integration +# you may have to adjust the crate name +cargo gpu build -p mygraphics-shaders +``` -### Next Steps +This plain invocation will compile the crate in the current directory and place the compiled shaders in the current directory. -You can try this out using the example repo at . -Keep in mind is _not_ yet a cargo generate template, -it's just a normal repo. +Use `cargo gpu help` to see more options :) +## 2. Crate Quickstart + +Add `cargo-gpu-install` as a regular or build dependency to your project, and use it like this: + +```rust,no_run +let shader_crate = PathBuf::from("./shaders"); +let backend = cargo_gpu_install::Install::from_shader_crate(shader_crate.clone()).run()?; +let mut builder = backend.to_spirv_builder(shader_crate, "spirv-unknown-vulkan1.2"); +// configure the builder... +let spv_result = builder.build()?; ``` -git clone https://github.com/rust-GPU/cargo-gpu -cd cargo-gpu/crates/shader-crate-template -cargo gpu build -``` + +For more detail, see the [readme of `cargo-gpu-install`](crates/cargo-gpu-install/README.md) or use any of our [templates](https://github.com/Rust-GPU/rust-gpu-template) as reference and choosing the `cargo-gpu-install` integration. ## How it works @@ -52,7 +67,7 @@ the usage instructions the backend and nightly Rust version are referred to as " > workspace might use a newer `Cargo.lock` layout not supported by the pinned version of the shader crate's custom codegen backend. The solution to > this is to either exclude the shader from the workspace, or upgrade the shader's `spirv-std` dependency to the latest. -## Usage +## CLI Usage All the following arguments for the `build` and `install` commands can also be set in the shader crate's `Cargo.toml` file. In general usage that would be the recommended way to set config. See `crates/shader-crate-template/Cargo.toml` From 2d36589d9d3515e68064f38ad65cb79ada5696ef Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 17:30:07 +0100 Subject: [PATCH 134/162] readme: revert when `cargo gpu new` is done --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e73fafeba..4cb0c12681 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ cargo gpu clippy To create an example project from our [templates](https://github.com/Rust-GPU/rust-gpu-template), use the command below: ``` -cargo gpu new +cargo install cargo-generate +cargo generate --git https://github.com/Rust-GPU/rust-gpu-template # choose any template you want, then select cargo-gpu cmdline integration # you may have to adjust the crate name cargo gpu build -p mygraphics-shaders From 70160693564611ca85e17a3c441da93ee642d29a Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 23 Dec 2025 17:31:31 +0100 Subject: [PATCH 135/162] readme: revert when rust-gpu-template supports `cargo-gpu-install` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cb0c12681..e37f4e210f 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ let mut builder = backend.to_spirv_builder(shader_crate, "spirv-unknown-vulkan1. let spv_result = builder.build()?; ``` -For more detail, see the [readme of `cargo-gpu-install`](crates/cargo-gpu-install/README.md) or use any of our [templates](https://github.com/Rust-GPU/rust-gpu-template) as reference and choosing the `cargo-gpu-install` integration. +For more detail, see the [readme of `cargo-gpu-install`](crates/cargo-gpu-install/README.md) or use any of our [templates](https://github.com/Rust-GPU/rust-gpu-template) as reference and choosing the `cargo-gpu` integration. ## How it works From af070fff30919fe1bf926851a9608f4d4f39d8ff Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 15:56:01 +0100 Subject: [PATCH 136/162] ci: drop testing for `0.8.0` --- .github/workflows/push.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index e48fea0d74..40e18db5eb 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -52,8 +52,10 @@ jobs: # """ # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's # unlikely many users of it? - - rust-gpu-version: 0.8.0 - glam-version: 0.24.2 + + # 0.8.0 started failing as well due to `zmij v1.0.20` requiring rustc 1.71 or newer +# - rust-gpu-version: 0.8.0 +# glam-version: 0.24.2 - rust-gpu-version: 0.9.0 glam-version: 0.24.2 From 3dc9770b756010ee5b1dba2edcaa9bb2b61b58f1 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 15:10:45 +0100 Subject: [PATCH 137/162] fix clippy --- Cargo.toml | 1 + crates/xtask/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index c65bc291d7..8ea70da11d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,3 +67,4 @@ pattern_type_mismatch = { level = "allow", priority = 1 } std_instead_of_alloc = { level = "allow", priority = 1 } arbitrary_source_item_ordering = { level = "allow", priority = 1 } missing_inline_in_public_items = { level = "allow", priority = 1 } +doc_paragraphs_missing_punctuation = { level = "allow", priority = 1 } diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 076c57c1b6..c596e93cb7 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -36,6 +36,7 @@ enum Cli { }, } +/// run some cmd fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { let mut args = args.into_iter(); let mut cmd = std::process::Command::new(args.next().context("no args")?.as_ref()); From b265ae05c645c9d26035a55fd9d5adb7f223505d Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 15:28:30 +0100 Subject: [PATCH 138/162] copy less strict lint config from rust-gpu --- Cargo.toml | 96 ++++++++++++++++++++++++++++-------- crates/cargo-gpu/src/main.rs | 4 -- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8ea70da11d..26aeba36f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,28 +43,82 @@ cargo-util-schemas = "0.8.2" semver = "1.0.26" dunce = "1.0.5" + + [workspace.lints.rust] missing_docs = "warn" +# copied from rust-gpu +future_incompatible = "warn" +nonstandard_style = "warn" +rust_2018_idioms = "warn" [workspace.lints.clippy] -all = { level = "warn", priority = 0 } -pedantic = { level = "warn", priority = 0 } -nursery = { level = "warn", priority = 0 } -cargo = { level = "warn", priority = 0 } -restriction = { level = "warn", priority = 0 } -blanket_clippy_restriction_lints = { level = "allow", priority = 1 } - -arithmetic_side_effects = { level = "allow", priority = 1 } -absolute_paths = { level = "allow", priority = 1 } -cargo_common_metadata = { level = "allow", priority = 1 } -implicit_return = { level = "allow", priority = 1 } -single_call_fn = { level = "allow", priority = 1 } -question_mark_used = { level = "allow", priority = 1 } -multiple_crate_versions = { level = "allow", priority = 1 } -pub_with_shorthand = { level = "allow", priority = 1 } -partial_pub_fields = { level = "allow", priority = 1 } -pattern_type_mismatch = { level = "allow", priority = 1 } -std_instead_of_alloc = { level = "allow", priority = 1 } -arbitrary_source_item_ordering = { level = "allow", priority = 1 } -missing_inline_in_public_items = { level = "allow", priority = 1 } -doc_paragraphs_missing_punctuation = { level = "allow", priority = 1 } +print_stdout = "deny" +print_stderr = "deny" +exit = "deny" +# copied from rust-gpu +all = { level = "warn", priority = -1 } +await_holding_lock = "warn" +char_lit_as_u8 = "warn" +checked_conversions = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" +doc_markdown = "warn" +empty_enums = "warn" +enum_glob_use = "warn" +#exit = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_let_mutex = "warn" +implicit_clone = "warn" +imprecise_flops = "warn" +inefficient_to_string = "warn" +invalid_upcast_comparisons = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +let_unit_value = "warn" +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +manual_ok_or = "warn" +map_err_ignore = "warn" +map_flatten = "warn" +map_unwrap_or = "warn" +match_same_arms = "warn" +match_wild_err_arm = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +missing_enforced_import_renames = "warn" +mut_mut = "warn" +mutex_integer = "warn" +needless_borrow = "warn" +needless_continue = "warn" +needless_for_each = "warn" +option_option = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +same_functions_in_if_condition = "warn" +semicolon_if_nothing_returned = "warn" +single_match_else = "warn" +string_add_assign = "warn" +string_add = "warn" +string_lit_as_bytes = "warn" +todo = "warn" +trait_duplication_in_bounds = "warn" +unimplemented = "warn" +unnested_or_patterns = "warn" +unused_self = "warn" +useless_transmute = "warn" +verbose_file_reads = "warn" +zero_sized_map_values = "warn" diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 449aa700d7..82151f2eda 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -17,10 +17,6 @@ fn main() { )] { eprintln!("Error: {error}"); - - // `clippy::exit` seems to be a false positive in `main()`. - // See: https://github.com/rust-lang/rust-clippy/issues/13518 - #[expect(clippy::restriction, reason = "Our central place for safely exiting")] std::process::exit(1); }; } From 5b8748dbc77130f4880e7513c287d7adaddeb414 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 13:39:17 +0100 Subject: [PATCH 139/162] toolchain: refactor, check installed components, install everything as one cmd --- .../src/install_toolchain.rs | 197 +++++++++++------- 1 file changed, 125 insertions(+), 72 deletions(-) diff --git a/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs index 300ddb83cd..6eb4f29af4 100644 --- a/crates/cargo-gpu-install/src/install_toolchain.rs +++ b/crates/cargo-gpu-install/src/install_toolchain.rs @@ -1,10 +1,16 @@ //! toolchain installation logic +use crate::user_output; use anyhow::Context as _; #[cfg(feature = "tty")] use crossterm::tty::IsTty as _; +use std::collections::HashSet; +use std::process::Command; +use std::string::FromUtf8Error; -use crate::user_output; +/// list of required rustup components +pub const REQUIRED_COMPONENTS: &[&str] = + ["rust-src", "rustc-dev", "llvm-tools", "clippy"].as_slice(); /// Use `rustup` to install the toolchain and components, if not already installed. /// @@ -16,87 +22,134 @@ pub fn ensure_toolchain_and_components_exist( channel: &str, skip_toolchain_install_consent: bool, ) -> anyhow::Result<()> { - // Check for the required toolchain - let output_toolchain_list = std::process::Command::new("rustup") - .args(["toolchain", "list"]) - .output() - .context("running rustup command")?; - anyhow::ensure!( - output_toolchain_list.status.success(), - "could not list installed toolchains" - ); - let string_toolchain_list = String::from_utf8_lossy(&output_toolchain_list.stdout); - if string_toolchain_list - .split_whitespace() - .any(|toolchain| toolchain.starts_with(channel)) - { - log::debug!("toolchain {channel} is already installed"); - } else { - let message = format!("Rust {channel} with `rustup`"); + // While our channel may be `nightly-2024-04-24`, it'll be resolved to the full toolchain name of e.g. + // `nightly-2024-04-24-aarch64-unknown-linux-gnu` and that's also what `rustup toolchain list` will print. + // Only checking whether the toolchain starts with the channel name may incorrectly pass if you have a toolchain + // installed that you're not able to run on your system via `rustup toolchain install --force-non-host ...`. + // CMD: `rustc --print host-tuple` + // TODO: What if the user has no toolchain installed? You can't query this with rustup sady. + let (host_tuple, _) = run_cmd(Command::new("rustc").args(["--print", "host-tuple"]))?; + let host_tuple = host_tuple.trim_ascii(); + let toolchain = format!("{channel}-{host_tuple}"); + + if !is_toolchain_installed(&toolchain, host_tuple)? { + let message = format!( + "toolchain {channel} with components {}", + intersperse(", ", REQUIRED_COMPONENTS.iter().copied()) + ); get_consent_for_toolchain_install( format!("Install {message}").as_ref(), skip_toolchain_install_consent, )?; - crate::user_output!("Installing {message}\n"); - - let output_toolchain_add = std::process::Command::new("rustup") - .args(["toolchain", "add"]) - .arg(channel) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .context("adding toolchain")?; - anyhow::ensure!( - output_toolchain_add.status.success(), - "could not install required toolchain" + user_output!("Installing {message}\n"); + + // component list may be out of sync + // CMD: `rustup toolchain install nightly-2024-04-24 -c clippy,rust-src,rustc-dev,llvm-tools` + run_cmd( + Command::new("rustup") + .args([ + "toolchain", + "install", + &toolchain, + "-c", + &intersperse(",", REQUIRED_COMPONENTS.iter().copied()), + ]) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()), + )?; + } + + Ok(()) +} + +/// Returns true if the toolchain and required components are installed. +fn is_toolchain_installed(toolchain: &str, host_tuple: &str) -> anyhow::Result { + // check if toolchain is installed + // CMD: `rustup toolchain list -q` + let (list_toolchains, _) = run_cmd(Command::new("rustup").args(["toolchain", "list", "-q"]))?; + if !list_toolchains + .split_ascii_whitespace() + .any(|s| s == toolchain) + { + log::info!("toolchain {toolchain} is not installed"); + return Ok(false); + } + + // check if required components are installed + // NOTE: checking for components will install the toolchain with the default profile, if not already installed! + // So we must check beforehand whether the toolchain is installed, to not accidentally install it here. + // Passing *just* `-q` will list available components, so add `--installed` for installed components. + // CMD: `rustup component list --toolchain nightly-2024-04-24-aarch64-unknown-linux-gnu -q --installed` + let (components, _) = run_cmd(Command::new("rustup").args([ + "component", + "list", + "--toolchain", + toolchain, + "-q", + "--installed", + ]))?; + + // components are listed as: + // * `llvm-tools-aarch64-unknown-linux-gnu` and we need to snippet off the host tuple from the end + // * `rust-src` since source code isn't target dependent + let component_host_suffix = format!("-{host_tuple}"); + let mut required = REQUIRED_COMPONENTS.iter().copied().collect::>(); + for component in components.split_ascii_whitespace() { + required.remove( + component + .strip_suffix(&component_host_suffix) + .unwrap_or(component), ); } + if !required.is_empty() { + log::info!("components {required:?} missing for toolchain {toolchain}"); + return Ok(false); + } - // Check for the required components - let output_component_list = std::process::Command::new("rustup") - .args(["component", "list", "--toolchain"]) - .arg(channel) - .output() - .context("getting toolchain list")?; - anyhow::ensure!( - output_component_list.status.success(), - "could not list installed components" - ); - let string_component_list = String::from_utf8_lossy(&output_component_list.stdout); - let required_components = ["rust-src", "rustc-dev", "llvm-tools"]; - let installed_components = string_component_list.lines().collect::>(); - let all_components_installed = required_components.iter().all(|component| { - installed_components.iter().any(|installed_component| { - let is_component = installed_component.starts_with(component); - let is_installed = installed_component.ends_with("(installed)"); - is_component && is_installed - }) - }); - if all_components_installed { - log::debug!("all required components are installed"); - } else { - let message = "toolchain components [rust-src, rustc-dev, llvm-tools] with `rustup`"; - get_consent_for_toolchain_install( - format!("Install {message}").as_ref(), - skip_toolchain_install_consent, - )?; - crate::user_output!("Installing {message}\n"); - - let output_component_add = std::process::Command::new("rustup") - .args(["component", "add", "--toolchain"]) - .arg(channel) - .args(["rust-src", "rustc-dev", "llvm-tools"]) - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() - .context("adding rustup component")?; - anyhow::ensure!( - output_component_add.status.success(), - "could not install required components" + log::info!("toolchain and required components are already installed"); + Ok(true) +} + +pub fn run_cmd(cmd: &mut Command) -> anyhow::Result<(String, String)> { + let output = cmd.output(); + let fmt_cmd = || { + intersperse( + " ", + std::iter::once(cmd.get_program()) + .chain(cmd.get_args()) + .map(|s| s.to_str().unwrap()), + ) + }; + let output = output.with_context(|| format!("Failed to launch cmd `{}`", fmt_cmd()))?; + + let utf8_error = |e: FromUtf8Error, kind: &str| { + anyhow::anyhow!( + "Command `{}` {} contains invalid UTF-8: {} \n {:?}", + kind, + fmt_cmd(), + e.utf8_error(), + e.into_bytes() + ) + }; + let stdout = String::from_utf8(output.stdout).map_err(|e| utf8_error(e, "stdout"))?; + let stderr = String::from_utf8(output.stderr).map_err(|e| utf8_error(e, "stderr"))?; + + if !output.status.success() { + anyhow::bail!( + "Command `{}` failed with {}:\n-- stdout\n{stdout}\n-- stderr\n{stderr}", + fmt_cmd(), + &output.status, ); } + Ok((stdout, stderr)) +} - Ok(()) +/// Folds an [`Iterator`] of `&str` into a [`String`] while interspersing some `&str` between each element +#[expect(clippy::string_add, reason = "Deliberately using String::add")] +fn intersperse<'a>(intersperse: &str, iter: impl Iterator) -> String { + let mut s = iter.fold(String::new(), |a, b| a + b + intersperse); + s.truncate(s.len() - intersperse.len()); + s } #[cfg(not(feature = "tty"))] From 8b6d98f85dadb9928c69404013253b22f4ecf4ed Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 14:50:34 +0100 Subject: [PATCH 140/162] toolchain: make user consent default to yes on enter --- crates/cargo-gpu-install/src/install_toolchain.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs index 6eb4f29af4..cc04257eaa 100644 --- a/crates/cargo-gpu-install/src/install_toolchain.rs +++ b/crates/cargo-gpu-install/src/install_toolchain.rs @@ -181,7 +181,7 @@ fn get_consent_for_toolchain_install( log::debug!("asking for consent to install the required toolchain"); crossterm::terminal::enable_raw_mode().context("enabling raw mode")?; - crate::user_output!("{prompt} [y/n]: "); + user_output!("{prompt} [Y/n]: "); let mut input = crossterm::event::read().context("reading crossterm event")?; if let crossterm::event::Event::Key(crossterm::event::KeyEvent { @@ -196,14 +196,19 @@ fn get_consent_for_toolchain_install( } crossterm::terminal::disable_raw_mode().context("disabling raw mode")?; + #[expect(clippy::print_stdout, reason = "need a newline after crossterm input")] + { + println!(); + } + if let crossterm::event::Event::Key(crossterm::event::KeyEvent { - code: crossterm::event::KeyCode::Char('y'), + code: crossterm::event::KeyCode::Char('y') | crossterm::event::KeyCode::Enter, .. }) = input { Ok(()) } else { - crate::user_output!("Exiting...\n"); + user_output!("Exiting...\n"); #[expect(clippy::exit, reason = "user requested abort")] std::process::exit(0); } From 710eb00d1f0149256574a1dfefe650950e3402ab Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 14:53:02 +0100 Subject: [PATCH 141/162] toolchain: rustup install with minimal profile --- crates/cargo-gpu-install/src/install_toolchain.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs index cc04257eaa..ab24fd3032 100644 --- a/crates/cargo-gpu-install/src/install_toolchain.rs +++ b/crates/cargo-gpu-install/src/install_toolchain.rs @@ -51,6 +51,8 @@ pub fn ensure_toolchain_and_components_exist( "toolchain", "install", &toolchain, + "--profile", + "minimal", "-c", &intersperse(",", REQUIRED_COMPONENTS.iter().copied()), ]) From 6131200831cf9dbc53a66de22164fd941277cbf1 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 14:54:45 +0100 Subject: [PATCH 142/162] toolchain: add minimal profile components in case they are manually uninstalled --- crates/cargo-gpu-install/src/install_toolchain.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs index ab24fd3032..12e9255ba3 100644 --- a/crates/cargo-gpu-install/src/install_toolchain.rs +++ b/crates/cargo-gpu-install/src/install_toolchain.rs @@ -9,8 +9,16 @@ use std::process::Command; use std::string::FromUtf8Error; /// list of required rustup components -pub const REQUIRED_COMPONENTS: &[&str] = - ["rust-src", "rustc-dev", "llvm-tools", "clippy"].as_slice(); +pub const REQUIRED_COMPONENTS: &[&str] = [ + "cargo", + "rustc", + "rust-std", + "clippy", + "rust-src", + "rustc-dev", + "llvm-tools", +] +.as_slice(); /// Use `rustup` to install the toolchain and components, if not already installed. /// From e87c3d7021874ac4b95a1dcb14fc267d21c9f224 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 10 Feb 2026 16:06:10 +0100 Subject: [PATCH 143/162] update spirv-builder --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d539d3fec..426e96d5d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1011,7 +1011,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=a30bd43db45f2bfe260051f44141e5eaffcbb4b0#a30bd43db45f2bfe260051f44141e5eaffcbb4b0" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e7e447a9395a77caec5cbddea556af86bc68c573#e7e447a9395a77caec5cbddea556af86bc68c573" dependencies = [ "rspirv", "semver", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=a30bd43db45f2bfe260051f44141e5eaffcbb4b0#a30bd43db45f2bfe260051f44141e5eaffcbb4b0" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e7e447a9395a77caec5cbddea556af86bc68c573#e7e447a9395a77caec5cbddea556af86bc68c573" dependencies = [ "cargo_metadata", "clap", diff --git a/Cargo.toml b/Cargo.toml index 26aeba36f6..7aa6c619be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ keywords = ["gpu", "compiler", "rust-gpu"] license = "MIT OR Apache-2.0" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "a30bd43db45f2bfe260051f44141e5eaffcbb4b0", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e7e447a9395a77caec5cbddea556af86bc68c573", default-features = false } cargo-gpu-install = { path = "./crates/cargo-gpu-install" } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } From f2244a3f7f9f30998918a543075a1ce17b42af64 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Fri, 13 Feb 2026 12:58:29 +0100 Subject: [PATCH 144/162] fix spirv-tools skipping C++ compile on install close https://github.com/Rust-GPU/cargo-gpu/issues/140 --- crates/cargo-gpu-install/src/install.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index 0de94036b1..310c535e59 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -284,6 +284,10 @@ package = "rustc_codegen_spirv" crate::user_output!("Compiling `rustc_codegen_spirv` from source {}\n", source); let mut cargo = spirv_builder::cargo_cmd::CargoCmd::new(); + // Make sure spirv-tools is build normally and does not skip C++ compile due to "being run in clippy" + // We add this only to our install and not generally to `CargoCmd` since we do want to forward clippy args + // to clippy running on the spirv target via e.g. `cargo gpu clippy`. + cargo.env_remove("CLIPPY_ARGS"); cargo .current_dir(&install_dir) .arg(format!("+{toolchain_channel}")) From b75274ab6c3bc5b4cc7bdf91e605c57a80ab9d21 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 26 Feb 2026 20:03:56 +0100 Subject: [PATCH 145/162] update spirv-builder --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 426e96d5d3..2a3f222828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1011,7 +1011,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e7e447a9395a77caec5cbddea556af86bc68c573#e7e447a9395a77caec5cbddea556af86bc68c573" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" dependencies = [ "rspirv", "semver", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=e7e447a9395a77caec5cbddea556af86bc68c573#e7e447a9395a77caec5cbddea556af86bc68c573" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" dependencies = [ "cargo_metadata", "clap", diff --git a/Cargo.toml b/Cargo.toml index 7aa6c619be..d72b6efada 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ keywords = ["gpu", "compiler", "rust-gpu"] license = "MIT OR Apache-2.0" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "e7e447a9395a77caec5cbddea556af86bc68c573", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "6a67e7b5954f37989ad540a555b5d6969073592e", default-features = false } cargo-gpu-install = { path = "./crates/cargo-gpu-install" } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } From 7f1995823a82ee6e6b7a63b57313c4a829856e3d Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 26 Feb 2026 20:07:56 +0100 Subject: [PATCH 146/162] update shader crate template --- crates/cargo-gpu-install/src/spirv_source.rs | 6 +++--- crates/shader-crate-template/Cargo.lock | 6 +++--- crates/shader-crate-template/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index d0ae054ffd..0cd45d2abb 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -276,7 +276,7 @@ mod test { source, SpirvSource::Git { url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "2aa4d4f8a8ba73103501562cfca17b8163e5a887".to_owned() + rev: "6a67e7b5954f37989ad540a555b5d6969073592e".to_owned() } ); } @@ -299,13 +299,13 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - assert_eq!("https___github_com_Rust-GPU_rust-gpu+2aa4d4f8", &name); + assert_eq!("https___github_com_Rust-GPU_rust-gpu+6a67e7b5", &name); } #[test_log::test] fn parse_git_with_rev() { let source = parse_git( - "git+https://github.com/Rust-GPU/rust-gpu?rev=86fc48032c4cd4afb74f1d81ae859711d20386a1#86fc4803", + "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#86fc4803", ); assert_eq!( source, diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index a61d1e83a4..950b229b79 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" dependencies = [ "bitflags", "glam", @@ -81,7 +81,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" dependencies = [ "proc-macro2", "quote", @@ -92,7 +92,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=2aa4d4f8a8ba73103501562cfca17b8163e5a887#2aa4d4f8a8ba73103501562cfca17b8163e5a887" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" [[package]] name = "syn" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index 96f0422851..e2b81916a6 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -12,7 +12,7 @@ unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spir # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released -spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "2aa4d4f8a8ba73103501562cfca17b8163e5a887" } +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "6a67e7b5954f37989ad540a555b5d6969073592e" } glam = { version = "0.30.8", default-features = false } [package.metadata.rust-gpu.build] From 45bf1245d29b1c26e3206f39bdb616cb292b1e33 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 24 Mar 2026 11:47:47 +0100 Subject: [PATCH 147/162] add `expect-test` crate to update rust-gpu rev in tests with `cargo xtask update-expect` --- Cargo.lock | 17 ++++++++++++ Cargo.toml | 1 + crates/cargo-gpu-install/Cargo.toml | 1 + crates/cargo-gpu-install/src/spirv_source.rs | 28 ++++++++++---------- crates/xtask/src/main.rs | 26 +++++++++--------- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a3f222828..d50a4e0fb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,6 +125,7 @@ dependencies = [ "clap", "crossterm", "directories", + "expect-test", "log", "serde", "spirv-builder", @@ -349,6 +350,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dissimilar" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" + [[package]] name = "document-features" version = "0.2.11" @@ -413,6 +420,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "expect-test" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" +dependencies = [ + "dissimilar", + "once_cell", +] + [[package]] name = "fastrand" version = "2.3.0" diff --git a/Cargo.toml b/Cargo.toml index d72b6efada..b3654c6e57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ cargo_metadata = "0.21.0" cargo-util-schemas = "0.8.2" semver = "1.0.26" dunce = "1.0.5" +expect-test = "1.5.1" diff --git a/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml index 8a914c7072..233196acce 100644 --- a/crates/cargo-gpu-install/Cargo.toml +++ b/crates/cargo-gpu-install/Cargo.toml @@ -29,6 +29,7 @@ tempfile = { workspace = true, optional = true } test-log.workspace = true cargo_metadata = { workspace = true, features = ["builder"] } cargo-util-schemas = "0.8.2" +expect-test = "1.5.1" [lints] workspace = true diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index 0cd45d2abb..954d130623 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -267,24 +267,18 @@ mod test { use crate::test::TestEnv; use cargo_metadata::{PackageBuilder, PackageId, Source}; use cargo_util_schemas::manifest::PackageName; + use expect_test::expect; #[test_log::test] fn parsing_spirv_std_dep_for_shader_template() { let shader_template_path = crate::test::shader_crate_template_path(); let source = SpirvSource::get_rust_gpu_deps_from_shader(&shader_template_path).unwrap(); - assert_eq!( - source, - SpirvSource::Git { - url: "https://github.com/Rust-GPU/rust-gpu".to_owned(), - rev: "6a67e7b5954f37989ad540a555b5d6969073592e".to_owned() - } - ); - } - - #[test_log::test] - fn path_sanity() { - let path = std::path::PathBuf::from("./"); - assert!(path.is_relative()); + expect![[r#" + Git { + url: "https://github.com/Rust-GPU/rust-gpu", + rev: "6a67e7b5954f37989ad540a555b5d6969073592e", + }"#]] + .assert_eq(&format!("{source:#?}")); } #[test_log::test] @@ -299,7 +293,13 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - assert_eq!("https___github_com_Rust-GPU_rust-gpu+6a67e7b5", &name); + expect!["https___github_com_Rust-GPU_rust-gpu+6a67e7b5"].assert_eq(&name); + } + + #[test_log::test] + fn path_sanity() { + let path = std::path::PathBuf::from("./"); + assert!(path.is_relative()); } #[test_log::test] diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index c596e93cb7..ca699d1e62 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -6,6 +6,7 @@ reason = "This is just a workflow tool" )] +use std::ffi::OsStr; use anyhow::Context as _; use clap::Parser as _; @@ -34,23 +35,17 @@ enum Cli { #[clap(long)] git: Option, }, + UpdateExpect, } /// run some cmd -fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { +fn cmd(args: impl IntoIterator>) -> anyhow::Result<()> { let mut args = args.into_iter(); - let mut cmd = std::process::Command::new(args.next().context("no args")?.as_ref()); - for arg in args { - cmd.arg(arg.as_ref()); - } - - let output = cmd - .stdout(std::process::Stdio::inherit()) - .stderr(std::process::Stdio::inherit()) - .output() + let status = std::process::Command::new(args.next().context("no args")?.as_ref()) + .args(args) + .status() .context("cmd failed")?; - anyhow::ensure!(output.status.success()); - + anyhow::ensure!(status.success()); Ok(()) } @@ -307,6 +302,13 @@ fn main() -> anyhow::Result<()> { &DependencyVersion::parse(version.clone(), git.clone())?, )?; } + Cli::UpdateExpect => { + let status = std::process::Command::new("cargo") + .args(["nextest", "run"]) + .env("UPDATE_EXPECT", "1") + .status()?; + anyhow::ensure!(status.success()); + } } Ok(()) } From 4bbd1ab144ff5c7e6a55d9320eb5aa02e9d701b7 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 24 Mar 2026 12:07:30 +0100 Subject: [PATCH 148/162] add `cargo xtask rust-gpu-rev ` for easy rust-gpu updating --- Cargo.lock | 7 ++ Cargo.toml | 1 + crates/xtask/Cargo.toml | 1 + crates/xtask/src/main.rs | 149 +++++++++++++++++++++++++-------------- 4 files changed, 106 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d50a4e0fb4..bb33262e57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,6 +988,12 @@ dependencies = [ "regex-syntax 0.8.5", ] +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1758,6 +1764,7 @@ dependencies = [ "clap", "env_logger", "log", + "regex-lite", "tempfile", "toml 0.9.2", ] diff --git a/Cargo.toml b/Cargo.toml index b3654c6e57..26c12dba6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ cargo-util-schemas = "0.8.2" semver = "1.0.26" dunce = "1.0.5" expect-test = "1.5.1" +regex-lite = "0.1.9" diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index afe0178a53..f6d7de2746 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -10,6 +10,7 @@ env_logger.workspace = true log.workspace = true tempfile.workspace = true toml.workspace = true +regex-lite.workspace = true [lints] workspace = true diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index ca699d1e62..a0913cb4bc 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -6,9 +6,11 @@ reason = "This is just a workflow tool" )] -use std::ffi::OsStr; use anyhow::Context as _; use clap::Parser as _; +use std::borrow::Cow; +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; /// Path to the shader crate const SHADER_CRATE_PATH: &str = "crates/shader-crate-template"; @@ -36,6 +38,9 @@ enum Cli { git: Option, }, UpdateExpect, + RustGpuRev { + rev: String, + }, } /// run some cmd @@ -254,61 +259,101 @@ impl DependencyVersion { /// Run the xtask. fn main() -> anyhow::Result<()> { - env_logger::builder().init(); - let cli = Cli::parse(); - match &cli { - Cli::TestBuild { - rust_gpu_version, - glam_version, - } => { - log::info!("installing cargo gpu"); - cmd(["cargo", "install", "--path", "crates/cargo-gpu"])?; + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .init(); + Cli::parse().run() +} - log::info!("setup project"); - let mut overwriter = ShaderCrateTemplateCargoTomlWriter::default(); - let dir = tempfile::TempDir::with_prefix("test-shader-output")?; - overwriter.replace_output_dir(dir.path())?; - if let Some(rust_gpu_version) = rust_gpu_version.as_ref() { - overwriter.set_spirv_std_version(rust_gpu_version)?; - } - if let Some(glam_version) = glam_version.as_ref() { - overwriter.set_dependency_glam(glam_version)?; - } +impl Cli { + fn run(&self) -> anyhow::Result<()> { + match &self { + Cli::TestBuild { + rust_gpu_version, + glam_version, + } => { + log::info!("installing cargo gpu"); + cmd(["cargo", "install", "--path", "crates/cargo-gpu"])?; + + log::info!("setup project"); + let mut overwriter = ShaderCrateTemplateCargoTomlWriter::default(); + let dir = tempfile::TempDir::with_prefix("test-shader-output")?; + overwriter.replace_output_dir(dir.path())?; + if let Some(rust_gpu_version) = rust_gpu_version.as_ref() { + overwriter.set_spirv_std_version(rust_gpu_version)?; + } + if let Some(glam_version) = glam_version.as_ref() { + overwriter.set_dependency_glam(glam_version)?; + } - log::info!("building with auto-install"); - cmd([ - "cargo", - "gpu", - "build", - "--shader-crate", - SHADER_CRATE_PATH, - "--auto-install-rust-toolchain", - "--rebuild-codegen", - "--force-overwrite-lockfiles-v4-to-v3", - ])?; + log::info!("building with auto-install"); + cmd([ + "cargo", + "gpu", + "build", + "--shader-crate", + SHADER_CRATE_PATH, + "--auto-install-rust-toolchain", + "--rebuild-codegen", + "--force-overwrite-lockfiles-v4-to-v3", + ])?; - cmd(["ls", "-lah", dir.path().to_str().unwrap()])?; - //NOTE: manifest.json is the default value here, which should be valid - cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()])?; - } - Cli::SetDependency { - package, - version, - git, - } => { - let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(true); - overwriter.set_dependency( + cmd(["ls", "-lah", dir.path().to_str().unwrap()])?; + //NOTE: manifest.json is the default value here, which should be valid + cmd(["cat", dir.path().join("manifest.json").to_str().unwrap()])?; + } + Cli::SetDependency { package, - &DependencyVersion::parse(version.clone(), git.clone())?, - )?; - } - Cli::UpdateExpect => { - let status = std::process::Command::new("cargo") - .args(["nextest", "run"]) - .env("UPDATE_EXPECT", "1") - .status()?; - anyhow::ensure!(status.success()); + version, + git, + } => { + let mut overwriter = ShaderCrateTemplateCargoTomlWriter::new(true); + overwriter.set_dependency( + package, + &DependencyVersion::parse(version.clone(), git.clone())?, + )?; + } + Cli::UpdateExpect => { + let status = std::process::Command::new("cargo") + .args(["nextest", "run"]) + .env("UPDATE_EXPECT", "1") + .status()?; + anyhow::ensure!(status.success()); + } + Cli::RustGpuRev { rev } => { + let root = PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/../..")); + let rev_regex = regex_lite::Regex::new(r#"rev\s*=\s*"[0-9a-f]*""#)?; + let rev_replace = format!("rev = \"{rev}\""); + let replace_rev = |file: &Path, dep: &str| -> anyhow::Result<()> { + log::info!("patching file `{}` dep `{dep}`", file.display()); + let content = std::fs::read_to_string(file)?; + let content = content + // unlike `.lines()`, includes the `\n` or `\r\n` at the end of the line + .split_inclusive("\n") + .map(|line| { + if line.starts_with(dep) { + let replace = rev_regex.replace(line, &rev_replace); + assert!( + matches!(replace, Cow::Owned(..)), + "rev not found in line:\n{line}" + ); + replace + } else { + Cow::Borrowed(line) + } + }) + .collect::(); + std::fs::write(file, content.as_bytes())?; + Ok(()) + }; + replace_rev(&root.join("Cargo.toml"), "spirv-builder")?; + replace_rev( + &root.join("crates/shader-crate-template/Cargo.toml"), + "spirv-std", + )?; + Cli::UpdateExpect.run()?; + } } + Ok(()) } - Ok(()) } From 157bd76d64ff2e4a01e4eede62d3bb27a494c9f4 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 24 Mar 2026 12:30:26 +0100 Subject: [PATCH 149/162] ci: cancel PR actions on new commits --- .github/workflows/push.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 40e18db5eb..500881f486 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -7,6 +7,11 @@ on: pull_request: workflow_dispatch: +# Cancel PR actions on new commits +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + env: # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From c0842d7d98ce3ce26703f244ed3fcc4f5b766e2a Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 24 Mar 2026 12:22:37 +0100 Subject: [PATCH 150/162] update rust-gpu to latest nightly of PR #545 https://github.com/Rust-GPU/rust-gpu/pull/545 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/cargo-gpu-install/src/spirv_source.rs | 4 ++-- crates/shader-crate-template/Cargo.lock | 6 +++--- crates/shader-crate-template/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb33262e57..69310debcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1034,7 +1034,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" dependencies = [ "rspirv", "semver", @@ -1216,7 +1216,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" dependencies = [ "cargo_metadata", "clap", diff --git a/Cargo.toml b/Cargo.toml index 26c12dba6c..590170f22c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ keywords = ["gpu", "compiler", "rust-gpu"] license = "MIT OR Apache-2.0" [workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "6a67e7b5954f37989ad540a555b5d6969073592e", default-features = false } +spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "877bd8697a15f3e6d09446a5e1807e6237ca1dac", default-features = false } cargo-gpu-install = { path = "./crates/cargo-gpu-install" } anyhow = "1.0.98" clap = { version = "4.5.41", features = ["derive"] } diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index 954d130623..1071872b93 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -276,7 +276,7 @@ mod test { expect![[r#" Git { url: "https://github.com/Rust-GPU/rust-gpu", - rev: "6a67e7b5954f37989ad540a555b5d6969073592e", + rev: "877bd8697a15f3e6d09446a5e1807e6237ca1dac", }"#]] .assert_eq(&format!("{source:#?}")); } @@ -293,7 +293,7 @@ mod test { .to_str() .map(std::string::ToString::to_string) .unwrap(); - expect!["https___github_com_Rust-GPU_rust-gpu+6a67e7b5"].assert_eq(&name); + expect!["https___github_com_Rust-GPU_rust-gpu+877bd869"].assert_eq(&name); } #[test_log::test] diff --git a/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock index 950b229b79..d0c753c314 100644 --- a/crates/shader-crate-template/Cargo.lock +++ b/crates/shader-crate-template/Cargo.lock @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" dependencies = [ "bitflags", "glam", @@ -81,7 +81,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" dependencies = [ "proc-macro2", "quote", @@ -92,7 +92,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=6a67e7b5954f37989ad540a555b5d6969073592e#6a67e7b5954f37989ad540a555b5d6969073592e" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" [[package]] name = "syn" diff --git a/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml index e2b81916a6..26a9b82d75 100644 --- a/crates/shader-crate-template/Cargo.toml +++ b/crates/shader-crate-template/Cargo.toml @@ -12,7 +12,7 @@ unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spir # Dependencies for CPU and GPU code [dependencies] # TODO: use a simple crate version once v0.10.0 is released -spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "6a67e7b5954f37989ad540a555b5d6969073592e" } +spirv-std = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "877bd8697a15f3e6d09446a5e1807e6237ca1dac" } glam = { version = "0.30.8", default-features = false } [package.metadata.rust-gpu.build] From 52c6ae36f196e28fa71a311edf02bca927f25a73 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 24 Mar 2026 14:23:38 +0100 Subject: [PATCH 151/162] ci: add revs testing rustc 1.94.0 `-Ztarget-spec-json` requirement --- .github/workflows/push.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 500881f486..ef0c25b113 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -98,6 +98,14 @@ jobs: glam-version: =0.30.7 # after, glam >0.30.8 - rust-gpu-version: e767f24f2565baf1a71bbaf84d453d181cab2417 + + # rustc 1.94.0 destabilised json target specs, requiring `-Ztarget-spec-json` + # see https://github.com/Rust-GPU/rust-gpu/pull/545 + # see https://github.com/rust-lang/rust/pull/150151 + # before + - rust-gpu-version: 30896871ba00e668029ccb724f1438202b284708 + # after + - rust-gpu-version: 877bd8697a15f3e6d09446a5e1807e6237ca1dac runs-on: ubuntu-latest env: RUST_LOG: debug From d673e3a1b10f02c79cd1dd12fb3d8261fef84bbe Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 25 Mar 2026 14:29:31 +0100 Subject: [PATCH 152/162] cargo update --- Cargo.lock | 892 +++++++++++++++++++++++++++++------------------------ 1 file changed, 491 insertions(+), 401 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69310debcf..6fb0e24f80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.6.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -28,50 +28,50 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", - "once_cell", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bitflags" @@ -81,20 +81,20 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "camino" -version = "1.1.9" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -153,7 +153,7 @@ dependencies = [ "serde-untagged", "serde-value", "thiserror", - "toml 0.8.22", + "toml 0.8.23", "unicode-xid", "url", ] @@ -176,15 +176,15 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clap" -version = "4.5.41" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -192,9 +192,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.41" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", @@ -216,15 +216,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "crossterm" @@ -232,7 +232,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "crossterm_winapi", "document-features", "mio", @@ -336,7 +336,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -358,9 +358,9 @@ checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -373,9 +373,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "env_filter" -version = "0.1.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "anstream", "anstyle", @@ -402,22 +402,23 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -442,11 +443,17 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -462,32 +469,42 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.7+wasi-0.2.4", + "wasip2", + "wasip3", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -497,9 +514,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -510,9 +527,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -523,11 +540,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -538,42 +554,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -581,6 +593,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -589,9 +607,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -610,21 +628,23 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] name = "inotify" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "inotify-sys", "libc", ] @@ -640,34 +660,34 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", @@ -700,90 +720,94 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.172" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" dependencies = [ - "bitflags 2.9.0", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mio" -version = "1.0.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "notify" -version = "8.1.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163f59cd3fa0e9ef8c32f242966a7b9994fd7378366099593e0e73077cd8c97" +checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "fsevent-sys", "inotify", "kqueue", @@ -797,18 +821,20 @@ dependencies = [ [[package]] name = "notify-types" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.11.0", +] [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -822,9 +848,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "option-ext" @@ -841,17 +873,11 @@ dependencies = [ "num-traits", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -859,76 +885,86 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "raw-string" @@ -938,54 +974,45 @@ checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", ] [[package]] name = "redox_users" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] @@ -996,15 +1023,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "relative-path" @@ -1046,23 +1067,17 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -1080,30 +1095,33 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] [[package]] name = "serde-untagged" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299d9c19d7d466db4ab10addd5703e4c615dec2a5a16dbbafe191045e87ee66e" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ "erased-serde", "serde", + "serde_core", "typeid", ] @@ -1117,11 +1135,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1130,32 +1157,33 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1190,18 +1218,19 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "spirv" @@ -1209,7 +1238,7 @@ version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.11.0", "serde", ] @@ -1233,9 +1262,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" @@ -1245,9 +1274,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -1267,22 +1296,22 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.22.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "test-log" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b" +checksum = "37d53ac171c92a39e4769491c4b4dde7022c60042254b5fc044ae409d34a24d4" dependencies = [ "env_logger", "test-log-macros", @@ -1291,9 +1320,9 @@ dependencies = [ [[package]] name = "test-log-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" +checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", @@ -1302,18 +1331,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -1322,19 +1351,18 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -1342,89 +1370,89 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned 0.6.8", - "toml_datetime 0.6.9", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_edit", ] [[package]] name = "toml" -version = "0.9.2" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "serde_core", + "serde_spanned 1.1.0", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", - "serde_spanned 0.6.8", - "toml_datetime 0.6.9", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_parser" -version = "1.0.1" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ - "winnow", + "winnow 1.0.0", ] [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-core", @@ -1432,9 +1460,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -1453,14 +1481,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "thread_local", "tracing", @@ -1476,9 +1504,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-xid" @@ -1488,13 +1516,14 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -1527,28 +1556,62 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.7+wasi-0.2.4" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "wasip2", + "wit-bindgen", ] [[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1567,11 +1630,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1581,22 +1644,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -1604,157 +1655,191 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.2", + "windows-targets", ] [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows-link", ] [[package]] name = "windows-targets" -version = "0.53.2" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] -name = "windows_i686_gnu" -version = "0.53.0" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] -name = "windows_i686_msvc" -version = "0.52.6" +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] -name = "windows_i686_msvc" -version = "0.53.0" +name = "windows_x86_64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" +name = "winnow" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" +name = "winnow" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" +name = "wit-bindgen-core" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" +name = "wit-bindgen-rust" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" +name = "wit-bindgen-rust-macro" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] [[package]] -name = "winnow" -version = "0.7.12" +name = "wit-component" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ - "memchr", + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", ] [[package]] -name = "wit-bindgen" -version = "0.46.0" +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "xtask" @@ -1766,16 +1851,15 @@ dependencies = [ "log", "regex-lite", "tempfile", - "toml 0.9.2", + "toml 0.9.12+spec-1.1.0", ] [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -1783,9 +1867,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", @@ -1816,9 +1900,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -1827,9 +1911,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -1838,11 +1922,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" From cf002d455354d08eed121e78a9bbfc47cf0259d0 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 25 Mar 2026 14:14:14 +0100 Subject: [PATCH 153/162] build_script: add `Install.build_script` to prevent stale shaders with local rust-gpu checkouts --- crates/cargo-gpu-install/src/install.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index 310c535e59..4639db0459 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -102,9 +102,17 @@ pub struct Install { /// Clear target dir of `rustc_codegen_spirv` build after a successful build, saves about /// 200MiB of disk space. - #[cfg_attr(feature = "clap", 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, + /// Enables printing `cargo:rerun-if-changed` to stdout for build scripts, defaults to `false`. + /// + /// Currently only used with `path`-based `spirv-std` sources, so that any change in your local rust-gpu checkout + /// reruns the build script to rebuild the codegen backend and your shaders. + #[cfg_attr(feature = "clap", clap(skip))] + pub build_script: bool, + /// There is a tricky situation where a shader crate that depends on workspace config can have /// a different `Cargo.lock` lockfile version from the the workspace's `Cargo.lock`. This can /// prevent builds when an old Rust toolchain doesn't recognise the newer lockfile version. @@ -143,6 +151,7 @@ impl Install { rebuild_codegen: false, auto_install_rust_toolchain: true, clear_target: true, + build_script: false, force_overwrite_lockfiles_v4_to_v3: false, } } @@ -228,6 +237,16 @@ package = "rustc_codegen_spirv" std::env::consts::DLL_SUFFIX ); + if self.build_script { + #[allow(clippy::print_stdout)] + if let SpirvSource::Path { + rust_gpu_repo_root, .. + } = &source + { + println!("cargo:rerun-if-changed={rust_gpu_repo_root}"); + } + } + let (dest_dylib_path, skip_rebuild) = if source.is_path() { ( install_dir From e837b29efe63c98b08b7b25d0ac35ab28a2b5933 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 25 Mar 2026 14:51:14 +0100 Subject: [PATCH 154/162] build_script: forward to spirv_builder --- crates/cargo-gpu-install/src/install.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index 4639db0459..c75b327a32 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -16,6 +16,8 @@ pub struct InstalledBackend { pub rustc_codegen_spirv_location: PathBuf, /// toolchain channel name pub toolchain_channel: String, + /// Whether this runs in a build script + pub build_script: bool, } impl InstalledBackend { @@ -45,6 +47,7 @@ impl InstalledBackend { pub fn configure_spirv_builder(&self, builder: &mut SpirvBuilder) -> anyhow::Result<()> { builder.rustc_codegen_spirv_location = Some(self.rustc_codegen_spirv_location.clone()); builder.toolchain_overwrite = Some(self.toolchain_channel.clone()); + builder.build_script.defaults = self.build_script; Ok(()) } } @@ -108,8 +111,9 @@ pub struct Install { /// Enables printing `cargo:rerun-if-changed` to stdout for build scripts, defaults to `false`. /// - /// Currently only used with `path`-based `spirv-std` sources, so that any change in your local rust-gpu checkout - /// reruns the build script to rebuild the codegen backend and your shaders. + /// Will be forwarded to `spirv_builder.build_script.defaults`. On the cargo-gpu side, only used with `path`-based + /// `spirv-std` sources, so that any change in your local rust-gpu checkout reruns the build script to rebuild the + /// codegen backend and your shaders. #[cfg_attr(feature = "clap", clap(skip))] pub build_script: bool, @@ -156,6 +160,15 @@ impl Install { } } + /// Set `build_script = true` + #[inline] + pub fn within_build_script(self) -> Self { + Self { + build_script: true, + ..self + } + } + /// Create the `rustc_codegen_spirv_dummy` crate that depends on `rustc_codegen_spirv` fn write_source_files(source: &SpirvSource, checkout: &Path) -> anyhow::Result<()> { // skip writing a dummy project if we use a local rust-gpu checkout @@ -352,6 +365,7 @@ package = "rustc_codegen_spirv" Ok(InstalledBackend { rustc_codegen_spirv_location: dest_dylib_path, toolchain_channel, + build_script: self.build_script, }) } } From 602b6a516a56f02071995193c92c5f1eeb1c6219 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 13:50:42 +0200 Subject: [PATCH 155/162] cargo-gpu merge: move cargo-gpu crates into root crates directory --- .cargo/config.toml | 2 + Cargo.lock | 286 ++- Cargo.toml | 33 + cargo-gpu/.cargo/config.toml | 3 - cargo-gpu/.gitignore | 29 - cargo-gpu/Cargo.lock | 1938 ----------------- cargo-gpu/Cargo.toml | 126 -- cargo-gpu/LICENSE-APACHE | 201 -- cargo-gpu/LICENSE-MIT | 23 - cargo-gpu/clippy.toml | 2 - .../crates/shader-crate-template/.gitignore | 1 - .../cargo-gpu-install/Cargo.toml | 0 .../cargo-gpu-install/README.md | 0 .../cargo-gpu-install/src/install.rs | 0 .../src/install_toolchain.rs | 0 .../cargo-gpu-install/src/lib.rs | 0 .../cargo-gpu-install/src/spirv_source.rs | 0 .../cargo-gpu-install/src/test.rs | 0 .../crates => crates}/cargo-gpu/Cargo.toml | 0 {cargo-gpu => crates/cargo-gpu}/README.md | 0 .../crates => crates}/cargo-gpu/build.rs | 0 .../crates => crates}/cargo-gpu/src/build.rs | 0 .../crates => crates}/cargo-gpu/src/config.rs | 0 .../cargo-gpu/src/dump_usage.rs | 0 .../crates => crates}/cargo-gpu/src/lib.rs | 0 .../cargo-gpu/src/linkage.rs | 0 .../cargo-gpu/src/lockfile.rs | 0 .../crates => crates}/cargo-gpu/src/main.rs | 0 .../cargo-gpu/src/metadata.rs | 0 .../crates => crates}/cargo-gpu/src/show.rs | 0 crates/shader-crate-template/.gitignore | 4 + .../shader-crate-template/Cargo.lock | 0 .../shader-crate-template/Cargo.toml | 0 .../shader-crate-template/README.md | 0 .../shader-crate-template/src/lib.rs | 0 {cargo-gpu/crates => crates}/xtask/Cargo.toml | 0 .../crates => crates}/xtask/src/main.rs | 0 37 files changed, 324 insertions(+), 2324 deletions(-) delete mode 100644 cargo-gpu/.cargo/config.toml delete mode 100644 cargo-gpu/.gitignore delete mode 100644 cargo-gpu/Cargo.lock delete mode 100644 cargo-gpu/Cargo.toml delete mode 100644 cargo-gpu/LICENSE-APACHE delete mode 100644 cargo-gpu/LICENSE-MIT delete mode 100644 cargo-gpu/clippy.toml delete mode 100644 cargo-gpu/crates/shader-crate-template/.gitignore rename {cargo-gpu/crates => crates}/cargo-gpu-install/Cargo.toml (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/README.md (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/src/install.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/src/install_toolchain.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/src/lib.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/src/spirv_source.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu-install/src/test.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/Cargo.toml (100%) rename {cargo-gpu => crates/cargo-gpu}/README.md (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/build.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/build.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/config.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/dump_usage.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/lib.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/linkage.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/lockfile.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/main.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/metadata.rs (100%) rename {cargo-gpu/crates => crates}/cargo-gpu/src/show.rs (100%) create mode 100644 crates/shader-crate-template/.gitignore rename {cargo-gpu/crates => crates}/shader-crate-template/Cargo.lock (100%) rename {cargo-gpu/crates => crates}/shader-crate-template/Cargo.toml (100%) rename {cargo-gpu/crates => crates}/shader-crate-template/README.md (100%) rename {cargo-gpu/crates => crates}/shader-crate-template/src/lib.rs (100%) rename {cargo-gpu/crates => crates}/xtask/Cargo.toml (100%) rename {cargo-gpu/crates => crates}/xtask/src/main.rs (100%) diff --git a/.cargo/config.toml b/.cargo/config.toml index 69ee514ab6..5a1b17391b 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,4 +1,6 @@ [alias] +xtask = "run --package xtask --" +build-test-shader = "xtask test-build" compiletest = "run --release -p compiletests --" difftest = "run --release -p difftests --" run-wasm = ["run", "--release", "-p", "run-wasm", "--"] diff --git a/Cargo.lock b/Cargo.lock index e0b1ed7a7b..64ee62a479 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -347,6 +347,42 @@ dependencies = [ "serde_core", ] +[[package]] +name = "cargo-gpu" +version = "0.9.0" +dependencies = [ + "anyhow", + "cargo-gpu-install", + "cargo_metadata", + "clap", + "dunce", + "env_logger", + "log", + "relative-path", + "semver", + "serde", + "serde_json", + "test-log", +] + +[[package]] +name = "cargo-gpu-install" +version = "0.9.0" +dependencies = [ + "anyhow", + "cargo-util-schemas", + "cargo_metadata", + "clap", + "crossterm", + "directories", + "expect-test", + "log", + "serde", + "spirv-builder", + "tempfile", + "test-log", +] + [[package]] name = "cargo-platform" version = "0.2.0" @@ -393,6 +429,7 @@ dependencies = [ "camino", "cargo-platform", "cargo-util-schemas", + "derive_builder", "semver", "serde", "serde_json", @@ -704,6 +741,32 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags 2.10.0", + "crossterm_winapi", + "document-features", + "mio", + "parking_lot", + "rustix 1.1.3", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + [[package]] name = "crunchy" version = "0.2.4" @@ -716,6 +779,72 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -775,6 +904,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "directories" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -785,6 +923,18 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.2", + "windows-sys 0.61.2", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -792,7 +942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -813,6 +963,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dissimilar" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" + [[package]] name = "dlib" version = "0.5.2" @@ -843,6 +999,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.15.0" @@ -964,6 +1126,16 @@ dependencies = [ "spirv-builder", ] +[[package]] +name = "expect-test" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" +dependencies = [ + "dissimilar", + "once_cell", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -1471,6 +1643,12 @@ dependencies = [ "rayon", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.1.0" @@ -2312,6 +2490,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.50" @@ -2647,6 +2831,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + [[package]] name = "reduce" version = "0.0.0" @@ -2677,12 +2872,27 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-lite" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" + [[package]] name = "regex-syntax" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +[[package]] +name = "relative-path" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0" +dependencies = [ + "serde", +] + [[package]] name = "renderdoc-sys" version = "1.1.0" @@ -3006,6 +3216,37 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -3292,6 +3533,28 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-log" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d53ac171c92a39e4769491c4b4dde7022c60042254b5fc044ae409d34a24d4" +dependencies = [ + "env_logger", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tester" version = "0.9.1" @@ -3428,10 +3691,12 @@ version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ + "indexmap 2.13.0", "serde_core", "serde_spanned 1.0.4", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", + "toml_writer", "winnow", ] @@ -3494,6 +3759,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -4655,6 +4926,19 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "env_logger", + "log", + "regex-lite", + "tempfile", + "toml 0.9.11+spec-1.1.0", +] + [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 1eb4422bb0..88a788506d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,9 @@ members = [ "crates/spirv-std", "crates/spirv-std/shared", "crates/spirv-std/macros", + "crates/cargo-gpu", + "crates/cargo-gpu-install", + "crates/xtask", "tests/compiletests", "tests/compiletests/deps-helper", @@ -31,12 +34,21 @@ members = [ "tests/difftests/lib", ] +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", + # Testing infra may copy the `shader-crate-template` into subdirs of target + "target", +] + [workspace.package] version = "0.9.0" authors = ["rust-gpu developers", "Embark "] edition = "2024" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-gpu/rust-gpu" +keywords = ["gpu", "compiler", "rust-gpu"] [workspace.lints.rust] unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spirv"))'] } @@ -49,6 +61,27 @@ spirv-std-macros = { path = "./crates/spirv-std/macros", version = "=0.9.0" } spirv-tools = { version = "0.13.0", default-features = false } rustc_codegen_spirv = { path = "./crates/rustc_codegen_spirv", version = "=0.9.0", default-features = false } rustc_codegen_spirv-types = { path = "./crates/rustc_codegen_spirv-types", version = "=0.9.0" } +cargo-gpu-install = { path = "./crates/cargo-gpu-install" } + +# normal dependencies +anyhow = "1.0.98" +clap = { version = "4.5.41", features = ["derive"] } +crossterm = { version = "0.29.0", default-features = false, features = ["events", "windows"] } +directories = "6.0.0" +env_logger = "0.11.8" +log = "0.4" +relative-path = "2.0.1" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.141" +toml = "0.9.2" +tempfile = "3.22" +test-log = "0.2.18" +cargo_metadata = "0.21.0" +cargo-util-schemas = "0.8.2" +semver = "1.0.26" +dunce = "1.0.5" +expect-test = "1.5.1" +regex-lite = "0.1.9" # difftest libraries mirrored from difftest workspace difftest = { path = "tests/difftests/lib" } diff --git a/cargo-gpu/.cargo/config.toml b/cargo-gpu/.cargo/config.toml deleted file mode 100644 index 99d9bb9366..0000000000 --- a/cargo-gpu/.cargo/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -[alias] -xtask = "run --package xtask --" -build-test-shader = "xtask test-build" diff --git a/cargo-gpu/.gitignore b/cargo-gpu/.gitignore deleted file mode 100644 index 1b8b34a36d..0000000000 --- a/cargo-gpu/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# macOS -*.DS_Store -# will have compiled files and executables -/target/ -**/target - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -# Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - -*~undo-tree~ - -test_output -cmy_triangle_renderer.svg -.aider* -flamegraph.svg - -# Compiled shader assets from running tests -crates/shader-crate-template/shaders - -# Build artefacts used by CI tests -tmp/* -crates/shader-crate-template/manifest.json -crates/shader-crate-template/rust_gpu_shader_crate_template.spv - -.idea diff --git a/cargo-gpu/Cargo.lock b/cargo-gpu/Cargo.lock deleted file mode 100644 index 6fb0e24f80..0000000000 --- a/cargo-gpu/Cargo.lock +++ /dev/null @@ -1,1938 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anstyle-parse" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] - -[[package]] -name = "anyhow" -version = "1.0.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" -dependencies = [ - "serde_core", -] - -[[package]] -name = "camino" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-gpu" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo-gpu-install", - "cargo_metadata", - "clap", - "dunce", - "env_logger", - "log", - "relative-path", - "semver", - "serde", - "serde_json", - "test-log", -] - -[[package]] -name = "cargo-gpu-install" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo-util-schemas", - "cargo_metadata", - "clap", - "crossterm", - "directories", - "expect-test", - "log", - "serde", - "spirv-builder", - "tempfile", - "test-log", -] - -[[package]] -name = "cargo-platform" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-util-schemas" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc1a6f7b5651af85774ae5a34b4e8be397d9cf4bc063b7e6dbd99a841837830" -dependencies = [ - "semver", - "serde", - "serde-untagged", - "serde-value", - "thiserror", - "toml 0.8.23", - "unicode-xid", - "url", -] - -[[package]] -name = "cargo_metadata" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868" -dependencies = [ - "camino", - "cargo-platform", - "cargo-util-schemas", - "derive_builder", - "semver", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "clap" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" - -[[package]] -name = "colorchoice" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" - -[[package]] -name = "crossterm" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" -dependencies = [ - "bitflags 2.11.0", - "crossterm_winapi", - "document-features", - "mio", - "parking_lot", - "rustix", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn", -] - -[[package]] -name = "directories" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dissimilar" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeda16ab4059c5fd2a83f2b9c9e9c981327b18aa8e3b313f7e6563799d4f093e" - -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "env_filter" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "jiff", - "log", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "erased-serde" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" -dependencies = [ - "serde", - "serde_core", - "typeid", -] - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "expect-test" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" -dependencies = [ - "dissimilar", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", - "wasip3", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", -] - -[[package]] -name = "inotify" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" -dependencies = [ - "bitflags 2.11.0", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jiff" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde_core", -] - -[[package]] -name = "jiff-static" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "kqueue" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libc" -version = "0.2.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" - -[[package]] -name = "libredox" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" -dependencies = [ - "libc", -] - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "mio" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "notify" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" -dependencies = [ - "bitflags 2.11.0", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.60.2", -] - -[[package]] -name = "notify-types" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "raw-string" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0501e134c6905fee1f10fed25b0a7e1261bf676cffac9543a7d0730dec01af2" - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-lite" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "relative-path" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca40a312222d8ba74837cb474edef44b37f561da5f773981007a10bbaa992b0" -dependencies = [ - "serde", -] - -[[package]] -name = "rspirv" -version = "0.12.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d" -dependencies = [ - "rustc-hash", - "spirv", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_codegen_spirv-types" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" -dependencies = [ - "rspirv", - "semver", - "serde", - "serde_json", - "spirv", - "thiserror", -] - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" -dependencies = [ - "serde", - "serde_core", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde-untagged" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" -dependencies = [ - "erased-serde", - "serde", - "serde_core", - "typeid", -] - -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_spanned" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" -dependencies = [ - "serde_core", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.11.0", - "serde", -] - -[[package]] -name = "spirv-builder" -version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=877bd8697a15f3e6d09446a5e1807e6237ca1dac#877bd8697a15f3e6d09446a5e1807e6237ca1dac" -dependencies = [ - "cargo_metadata", - "clap", - "log", - "memchr", - "notify", - "raw-string", - "rustc_codegen_spirv-types", - "semver", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "test-log" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d53ac171c92a39e4769491c4b4dde7022c60042254b5fc044ae409d34a24d4" -dependencies = [ - "env_logger", - "test-log-macros", - "tracing-subscriber", -] - -[[package]] -name = "test-log-macros" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit", -] - -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "indexmap", - "serde_core", - "serde_spanned 1.1.0", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "toml_writer", - "winnow 0.7.15", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_write", - "winnow 0.7.15", -] - -[[package]] -name = "toml_parser" -version = "1.1.0+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" -dependencies = [ - "winnow 1.0.0", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "toml_writer" -version = "1.1.0+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8" - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "xtask" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "env_logger", - "log", - "regex-lite", - "tempfile", - "toml 0.9.12+spec-1.1.0", -] - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/cargo-gpu/Cargo.toml b/cargo-gpu/Cargo.toml deleted file mode 100644 index 590170f22c..0000000000 --- a/cargo-gpu/Cargo.toml +++ /dev/null @@ -1,126 +0,0 @@ -[workspace] -members = [ - "crates/cargo-gpu", - "crates/cargo-gpu-install", - "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", - # Testing infra may copy the `shader-crate-template` into subdirs of target - "target", -] - -resolver = "2" - -[workspace.package] -version = "0.1.0" -edition = "2021" -repository = "https://github.com/Rust-GPU/cargo-gpu" -readme = "./README.md" -keywords = ["gpu", "compiler", "rust-gpu"] -license = "MIT OR Apache-2.0" - -[workspace.dependencies] -spirv-builder = { git = "https://github.com/Rust-GPU/rust-gpu", rev = "877bd8697a15f3e6d09446a5e1807e6237ca1dac", default-features = false } -cargo-gpu-install = { path = "./crates/cargo-gpu-install" } -anyhow = "1.0.98" -clap = { version = "4.5.41", features = ["derive"] } -crossterm = { version = "0.29.0", default-features = false, features = ["events", "windows"] } -directories = "6.0.0" -env_logger = "0.11.8" -log = "0.4" -relative-path = "2.0.1" -serde = { version = "1.0.219", features = ["derive"] } -serde_json = "1.0.141" -toml = "0.9.2" -tempfile = "3.22" -test-log = "0.2.18" -cargo_metadata = "0.21.0" -cargo-util-schemas = "0.8.2" -semver = "1.0.26" -dunce = "1.0.5" -expect-test = "1.5.1" -regex-lite = "0.1.9" - - - -[workspace.lints.rust] -missing_docs = "warn" -# copied from rust-gpu -future_incompatible = "warn" -nonstandard_style = "warn" -rust_2018_idioms = "warn" - -[workspace.lints.clippy] -print_stdout = "deny" -print_stderr = "deny" -exit = "deny" -# copied from rust-gpu -all = { level = "warn", priority = -1 } -await_holding_lock = "warn" -char_lit_as_u8 = "warn" -checked_conversions = "warn" -dbg_macro = "warn" -debug_assert_with_mut_call = "warn" -doc_markdown = "warn" -empty_enums = "warn" -enum_glob_use = "warn" -#exit = "warn" -expl_impl_clone_on_copy = "warn" -explicit_deref_methods = "warn" -explicit_into_iter_loop = "warn" -fallible_impl_from = "warn" -filter_map_next = "warn" -flat_map_option = "warn" -float_cmp_const = "warn" -fn_params_excessive_bools = "warn" -from_iter_instead_of_collect = "warn" -if_let_mutex = "warn" -implicit_clone = "warn" -imprecise_flops = "warn" -inefficient_to_string = "warn" -invalid_upcast_comparisons = "warn" -large_digit_groups = "warn" -large_stack_arrays = "warn" -large_types_passed_by_value = "warn" -let_unit_value = "warn" -linkedlist = "warn" -lossy_float_literal = "warn" -macro_use_imports = "warn" -manual_ok_or = "warn" -map_err_ignore = "warn" -map_flatten = "warn" -map_unwrap_or = "warn" -match_same_arms = "warn" -match_wild_err_arm = "warn" -match_wildcard_for_single_variants = "warn" -mem_forget = "warn" -missing_enforced_import_renames = "warn" -mut_mut = "warn" -mutex_integer = "warn" -needless_borrow = "warn" -needless_continue = "warn" -needless_for_each = "warn" -option_option = "warn" -path_buf_push_overwrite = "warn" -ptr_as_ptr = "warn" -rc_mutex = "warn" -ref_option_ref = "warn" -rest_pat_in_fully_bound_structs = "warn" -same_functions_in_if_condition = "warn" -semicolon_if_nothing_returned = "warn" -single_match_else = "warn" -string_add_assign = "warn" -string_add = "warn" -string_lit_as_bytes = "warn" -todo = "warn" -trait_duplication_in_bounds = "warn" -unimplemented = "warn" -unnested_or_patterns = "warn" -unused_self = "warn" -useless_transmute = "warn" -verbose_file_reads = "warn" -zero_sized_map_values = "warn" diff --git a/cargo-gpu/LICENSE-APACHE b/cargo-gpu/LICENSE-APACHE deleted file mode 100644 index 11069edd79..0000000000 --- a/cargo-gpu/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/cargo-gpu/LICENSE-MIT b/cargo-gpu/LICENSE-MIT deleted file mode 100644 index 31aa79387f..0000000000 --- a/cargo-gpu/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/cargo-gpu/clippy.toml b/cargo-gpu/clippy.toml deleted file mode 100644 index f69b4a67f9..0000000000 --- a/cargo-gpu/clippy.toml +++ /dev/null @@ -1,2 +0,0 @@ -allow-unwrap-in-tests = true -allow-panic-in-tests = true diff --git a/cargo-gpu/crates/shader-crate-template/.gitignore b/cargo-gpu/crates/shader-crate-template/.gitignore deleted file mode 100644 index ea8c4bf7f3..0000000000 --- a/cargo-gpu/crates/shader-crate-template/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/cargo-gpu/crates/cargo-gpu-install/Cargo.toml b/crates/cargo-gpu-install/Cargo.toml similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/Cargo.toml rename to crates/cargo-gpu-install/Cargo.toml diff --git a/cargo-gpu/crates/cargo-gpu-install/README.md b/crates/cargo-gpu-install/README.md similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/README.md rename to crates/cargo-gpu-install/README.md diff --git a/cargo-gpu/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/src/install.rs rename to crates/cargo-gpu-install/src/install.rs diff --git a/cargo-gpu/crates/cargo-gpu-install/src/install_toolchain.rs b/crates/cargo-gpu-install/src/install_toolchain.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/src/install_toolchain.rs rename to crates/cargo-gpu-install/src/install_toolchain.rs diff --git a/cargo-gpu/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/src/lib.rs rename to crates/cargo-gpu-install/src/lib.rs diff --git a/cargo-gpu/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/src/spirv_source.rs rename to crates/cargo-gpu-install/src/spirv_source.rs diff --git a/cargo-gpu/crates/cargo-gpu-install/src/test.rs b/crates/cargo-gpu-install/src/test.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu-install/src/test.rs rename to crates/cargo-gpu-install/src/test.rs diff --git a/cargo-gpu/crates/cargo-gpu/Cargo.toml b/crates/cargo-gpu/Cargo.toml similarity index 100% rename from cargo-gpu/crates/cargo-gpu/Cargo.toml rename to crates/cargo-gpu/Cargo.toml diff --git a/cargo-gpu/README.md b/crates/cargo-gpu/README.md similarity index 100% rename from cargo-gpu/README.md rename to crates/cargo-gpu/README.md diff --git a/cargo-gpu/crates/cargo-gpu/build.rs b/crates/cargo-gpu/build.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/build.rs rename to crates/cargo-gpu/build.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/build.rs b/crates/cargo-gpu/src/build.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/build.rs rename to crates/cargo-gpu/src/build.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/config.rs b/crates/cargo-gpu/src/config.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/config.rs rename to crates/cargo-gpu/src/config.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/dump_usage.rs b/crates/cargo-gpu/src/dump_usage.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/dump_usage.rs rename to crates/cargo-gpu/src/dump_usage.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/lib.rs b/crates/cargo-gpu/src/lib.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/lib.rs rename to crates/cargo-gpu/src/lib.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/linkage.rs b/crates/cargo-gpu/src/linkage.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/linkage.rs rename to crates/cargo-gpu/src/linkage.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/lockfile.rs b/crates/cargo-gpu/src/lockfile.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/lockfile.rs rename to crates/cargo-gpu/src/lockfile.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/main.rs rename to crates/cargo-gpu/src/main.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/metadata.rs b/crates/cargo-gpu/src/metadata.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/metadata.rs rename to crates/cargo-gpu/src/metadata.rs diff --git a/cargo-gpu/crates/cargo-gpu/src/show.rs b/crates/cargo-gpu/src/show.rs similarity index 100% rename from cargo-gpu/crates/cargo-gpu/src/show.rs rename to crates/cargo-gpu/src/show.rs diff --git a/crates/shader-crate-template/.gitignore b/crates/shader-crate-template/.gitignore new file mode 100644 index 0000000000..d2cea26009 --- /dev/null +++ b/crates/shader-crate-template/.gitignore @@ -0,0 +1,4 @@ +/target +/shaders +manifest.json +rust_gpu_shader_crate_template.spv diff --git a/cargo-gpu/crates/shader-crate-template/Cargo.lock b/crates/shader-crate-template/Cargo.lock similarity index 100% rename from cargo-gpu/crates/shader-crate-template/Cargo.lock rename to crates/shader-crate-template/Cargo.lock diff --git a/cargo-gpu/crates/shader-crate-template/Cargo.toml b/crates/shader-crate-template/Cargo.toml similarity index 100% rename from cargo-gpu/crates/shader-crate-template/Cargo.toml rename to crates/shader-crate-template/Cargo.toml diff --git a/cargo-gpu/crates/shader-crate-template/README.md b/crates/shader-crate-template/README.md similarity index 100% rename from cargo-gpu/crates/shader-crate-template/README.md rename to crates/shader-crate-template/README.md diff --git a/cargo-gpu/crates/shader-crate-template/src/lib.rs b/crates/shader-crate-template/src/lib.rs similarity index 100% rename from cargo-gpu/crates/shader-crate-template/src/lib.rs rename to crates/shader-crate-template/src/lib.rs diff --git a/cargo-gpu/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml similarity index 100% rename from cargo-gpu/crates/xtask/Cargo.toml rename to crates/xtask/Cargo.toml diff --git a/cargo-gpu/crates/xtask/src/main.rs b/crates/xtask/src/main.rs similarity index 100% rename from cargo-gpu/crates/xtask/src/main.rs rename to crates/xtask/src/main.rs From 42fa16297d946a88e681be6a9b93cfe769d57312 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 13:54:49 +0200 Subject: [PATCH 156/162] cargo-gpu merge: merge in cargo-gpu ci --- .github/workflows/ci.yaml | 106 +++++++++++++++++- cargo-gpu/.github/workflows/push.yaml | 148 -------------------------- 2 files changed, 104 insertions(+), 150 deletions(-) delete mode 100644 cargo-gpu/.github/workflows/push.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 83b0f02b7c..2e252ddde9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -55,7 +55,7 @@ jobs: run: cargo test -p rustc_codegen_spirv --release --no-default-features --features "use-installed-tools" - name: workspace test (excluding examples) - run: cargo test --release --workspace --exclude "example-runner-*" --no-default-features --features "use-installed-tools,clap" + run: cargo test --release --workspace --exclude "example-runner-*" --exclude "cargo-gpu*" --no-default-features --features "use-installed-tools,clap" # Examples - name: cargo check examples @@ -180,11 +180,111 @@ jobs: - name: difftests run: cargo run -p difftests --release --no-default-features --features "use-installed-tools" + cargo-gpu-os: + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + runs-on: ${{ matrix.os }} + env: + RUST_LOG: debug + steps: + - uses: actions/checkout@v4 + - uses: cargo-bins/cargo-binstall@main + - run: cargo binstall cargo-nextest + - run: cargo fetch --locked + - name: shader-crate-template cargo fetch --locked + run: | + cd ./crates/shader-crate-template + cargo fetch --locked + - run: cargo nextest run -p cargo-gpu -p cargo-gpu-install + - name: Run a full build + run: cargo xtask test-build + + cargo-gpu-backwards-compat: + strategy: + fail-fast: false + matrix: + include: + # As well as testing on each OS, we also want to test to make sure we're still supporting + # older versions of `rust-gpu`. However, we can assume that these tests are already okay + # across platforms, so we only need to test on Linux, the chepeast in terms of minutes. + # + # `0.7.0` currently fails building `spirv-builder-cli` with: + # """ + # package `is_terminal_polyfill v1.70.1` cannot be built because it requires rustc + # 1.70.0 or newer, while the currently active rustc version is 1.69.0-nightly + # """ + # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's + # unlikely many users of it? + + # 0.8.0 started failing as well due to `zmij v1.0.20` requiring rustc 1.71 or newer + # - rust-gpu-version: 0.8.0 + # glam-version: 0.24.2 + - rust-gpu-version: 0.9.0 + glam-version: 0.24.2 + + # target spec introduction + # last version before + # * fails: compiler too old, `serde` using `#[diagnostic]` + # - rust-gpu-version: cc752312c3de6813a41189e46476d5c1be5e0bbe + # glam-version: 0.30.7 + # first version requiring target specs + # * fails: target spec mismatch! + # * resolution: Since this is just a few commits, I'd be fine ignoring it. + # - rust-gpu-version: 02cefd101014f66b79dffb20a2c2b5b7c9038401 + # glam-version: 0.30.7 + # target specs change again just a few commits later + # * fails: compiler too old, `proc-macro2` using `Literal::byte_character`. + # * resolution: want to support, can't be bothered to hack in old proc-macro2 versions + # - rust-gpu-version: bbb61f58b3d24f3f64745050eb214b90bf6dcce9 + # glam-version: 0.30.7 + + # testing rustc 1.5 months later + - rust-gpu-version: eea8998df9dc2fd8e7a65c5b5b7ae20c238a665a + glam-version: 0.29.3 + + # just after target specs v2 refactor, we updated to rustc 1.85 and needed to change them again + # before + - rust-gpu-version: a547c6e45266d613d9fec673e869d7a96181e47b + glam-version: =0.30.7 + # after + - rust-gpu-version: 2326b87fe1542eeb898065e36ac949307b55386d + glam-version: =0.30.7 + + # glam semver breakage due to vector type refactor + # before, glam was fixed to <=0.30.7 in this commit + - rust-gpu-version: f79c4181a5dc2d37303947b113f190930c6c1ce6 + glam-version: =0.30.7 + # after, glam >0.30.8 + - rust-gpu-version: e767f24f2565baf1a71bbaf84d453d181cab2417 + + # rustc 1.94.0 destabilised json target specs, requiring `-Ztarget-spec-json` + # see https://github.com/Rust-GPU/rust-gpu/pull/545 + # see https://github.com/rust-lang/rust/pull/150151 + # before + - rust-gpu-version: 30896871ba00e668029ccb724f1438202b284708 + # after + - rust-gpu-version: 877bd8697a15f3e6d09446a5e1807e6237ca1dac + runs-on: ubuntu-latest + env: + RUST_LOG: debug + steps: + - uses: actions/checkout@v4 + - if: ${{ matrix.glam-version }} + name: set glam version + run: cargo xtask set-dependency glam ${{ matrix.glam-version }} + - name: Run a full build + run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} + # This allows us to have a single job we can branch protect on, rather than needing # to update the branch protection rules when the test matrix changes test_success: runs-on: ubuntu-latest - needs: [test, compiletest, difftest, android, lint, cargo-deny] + needs: [test, compiletest, difftest, android, lint, cargo-deny, cargo-gpu-os, cargo-gpu-backwards-compat] # Hack for buggy GitHub Actions behavior with skipped checks: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks if: ${{ always() }} steps: @@ -197,6 +297,8 @@ jobs: [[ "${{ needs.android.result }}" == "success" ]] || exit 1 [[ "${{ needs.lint.result }}" == "success" ]] || exit 1 [[ "${{ needs.cargo-deny.result }}" == "success" ]] || exit 1 + [[ "${{ needs.cargo-gpu-os.result }}" == "success" ]] || exit 1 + [[ "${{ needs.cargo-gpu-backwards-compat.result }}" == "success" ]] || exit 1 lint: name: Lint diff --git a/cargo-gpu/.github/workflows/push.yaml b/cargo-gpu/.github/workflows/push.yaml deleted file mode 100644 index ef0c25b113..0000000000 --- a/cargo-gpu/.github/workflows/push.yaml +++ /dev/null @@ -1,148 +0,0 @@ -name: push - -on: - push: - branches: - - main - pull_request: - workflow_dispatch: - -# Cancel PR actions on new commits -concurrency: - group: ${{ github.workflow }}-${{ github.ref || github.run_id }} - cancel-in-progress: true - -env: - # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - -jobs: - test-os: - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - - macos-latest - - windows-latest - runs-on: ${{ matrix.os }} - env: - RUST_LOG: debug - steps: - - uses: actions/checkout@v4 - - uses: cargo-bins/cargo-binstall@main - - run: cargo binstall cargo-nextest - - run: cargo fetch --locked - - name: shader-crate-template cargo fetch --locked - run: | - cd ./crates/shader-crate-template - cargo fetch --locked - - run: cargo nextest run - - name: Run a full build - run: cargo xtask test-build - - test-rust-gpu: - strategy: - fail-fast: false - matrix: - include: - # As well as testing on each OS, we also want to test to make sure we're still supporting - # older versions of `rust-gpu`. However, we can assume that these tests are already okay - # across platforms, so we only need to test on Linux, the chepeast in terms of minutes. - # - # `0.7.0` currently fails building `spirv-builder-cli` with: - # """ - # package `is_terminal_polyfill v1.70.1` cannot be built because it requires rustc - # 1.70.0 or newer, while the currently active rustc version is 1.69.0-nightly - # """ - # It's probably easily fixable. But also `0.7.0` was released in April 2023, so there's - # unlikely many users of it? - - # 0.8.0 started failing as well due to `zmij v1.0.20` requiring rustc 1.71 or newer -# - rust-gpu-version: 0.8.0 -# glam-version: 0.24.2 - - rust-gpu-version: 0.9.0 - glam-version: 0.24.2 - - # target spec introduction - # last version before - # * fails: compiler too old, `serde` using `#[diagnostic]` -# - rust-gpu-version: cc752312c3de6813a41189e46476d5c1be5e0bbe -# glam-version: 0.30.7 - # first version requiring target specs - # * fails: target spec mismatch! - # * resolution: Since this is just a few commits, I'd be fine ignoring it. -# - rust-gpu-version: 02cefd101014f66b79dffb20a2c2b5b7c9038401 -# glam-version: 0.30.7 - # target specs change again just a few commits later - # * fails: compiler too old, `proc-macro2` using `Literal::byte_character`. - # * resolution: want to support, can't be bothered to hack in old proc-macro2 versions -# - rust-gpu-version: bbb61f58b3d24f3f64745050eb214b90bf6dcce9 -# glam-version: 0.30.7 - - # testing rustc 1.5 months later - - rust-gpu-version: eea8998df9dc2fd8e7a65c5b5b7ae20c238a665a - glam-version: 0.29.3 - - # just after target specs v2 refactor, we updated to rustc 1.85 and needed to change them again - # before - - rust-gpu-version: a547c6e45266d613d9fec673e869d7a96181e47b - glam-version: =0.30.7 - # after - - rust-gpu-version: 2326b87fe1542eeb898065e36ac949307b55386d - glam-version: =0.30.7 - - # glam semver breakage due to vector type refactor - # before, glam was fixed to <=0.30.7 in this commit - - rust-gpu-version: f79c4181a5dc2d37303947b113f190930c6c1ce6 - glam-version: =0.30.7 - # after, glam >0.30.8 - - rust-gpu-version: e767f24f2565baf1a71bbaf84d453d181cab2417 - - # rustc 1.94.0 destabilised json target specs, requiring `-Ztarget-spec-json` - # see https://github.com/Rust-GPU/rust-gpu/pull/545 - # see https://github.com/rust-lang/rust/pull/150151 - # before - - rust-gpu-version: 30896871ba00e668029ccb724f1438202b284708 - # after - - rust-gpu-version: 877bd8697a15f3e6d09446a5e1807e6237ca1dac - runs-on: ubuntu-latest - env: - RUST_LOG: debug - steps: - - uses: actions/checkout@v4 - - if: ${{ matrix.glam-version }} - name: set glam version - run: cargo xtask set-dependency glam ${{ matrix.glam-version }} - - name: Run a full build - run: cargo xtask test-build --rust-gpu-version ${{ matrix.rust-gpu-version }} - - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: cargo-bins/cargo-binstall@main - - run: cargo binstall cargo-shear - - run: cargo fetch --locked - - run: cargo clippy -- --deny warnings - - run: cargo fmt --check - - run: cargo shear - - # This allows us to have a single job we can branch protect on, rather than needing - # to update the branch protection rules when the test matrix changes - test_success: - runs-on: ubuntu-24.04 - needs: [test-os, test-rust-gpu, lint] - # Hack for buggy GitHub Actions behavior with skipped checks: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks - if: ${{ always() }} - steps: - # Another hack is to actually check the status of the dependencies or else it'll fall through - - run: | - echo "Checking statuses..." - [[ "${{ needs.test-os.result }}" == "success" ]] || exit 1 - [[ "${{ needs.test-rust-gpu.result }}" == "success" ]] || exit 1 - [[ "${{ needs.lint.result }}" == "success" ]] || exit 1 - -defaults: - run: - shell: bash From 651f6dbef922fce6f80be82713ddc63725f96a1e Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 14:51:48 +0200 Subject: [PATCH 157/162] cargo-gpu merge: upgrade cargo-gpu to edition 2024 --- crates/cargo-gpu-install/src/install.rs | 2 +- crates/cargo-gpu/src/dump_usage.rs | 2 +- crates/cargo-gpu/src/main.rs | 5 ++++- crates/xtask/Cargo.toml | 2 +- crates/xtask/src/main.rs | 8 ++++---- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index c75b327a32..dcbc4da589 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -1,7 +1,7 @@ //! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it. use crate::spirv_source::{ - get_channel_from_rustc_codegen_spirv_build_script, query_metadata, FindPackage as _, + FindPackage as _, get_channel_from_rustc_codegen_spirv_build_script, query_metadata, }; use crate::{cache_dir, spirv_source::SpirvSource}; use anyhow::Context as _; diff --git a/crates/cargo-gpu/src/dump_usage.rs b/crates/cargo-gpu/src/dump_usage.rs index d53941419f..4dd002af2a 100644 --- a/crates/cargo-gpu/src/dump_usage.rs +++ b/crates/cargo-gpu/src/dump_usage.rs @@ -1,7 +1,7 @@ //! Convenience function for internal use. Dumps all the CLI usage instructions. Useful for //! updating the README. -use crate::{user_output, Cli}; +use crate::{Cli, user_output}; /// main dump usage function pub fn dump_full_usage_for_readme() -> anyhow::Result<()> { diff --git a/crates/cargo-gpu/src/main.rs b/crates/cargo-gpu/src/main.rs index 82151f2eda..cb094c76a1 100644 --- a/crates/cargo-gpu/src/main.rs +++ b/crates/cargo-gpu/src/main.rs @@ -3,8 +3,11 @@ use cargo_gpu::Cli; use clap::Parser as _; fn main() { + // Safety: always in single-threaded code #[cfg(debug_assertions)] - std::env::set_var("RUST_BACKTRACE", "1"); + unsafe { + std::env::set_var("RUST_BACKTRACE", "1"); + } env_logger::builder().init(); diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index f6d7de2746..a6c68dd5c3 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "xtask" version = "0.1.0" -edition = "2021" +edition = "2024" [dependencies] anyhow.workspace = true diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index a0913cb4bc..5f5c3cd255 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -244,10 +244,10 @@ impl DependencyVersion { pub fn modify_toml(&self, toml: &mut toml::Value) { if let Some(mut table) = self.to_toml() { let mut copy = |key: &str| { - if let Some(src_table) = toml.as_table_mut() { - if let Some(value) = src_table.remove(key) { - table.insert(key.to_owned(), value); - } + if let Some(src_table) = toml.as_table_mut() + && let Some(value) = src_table.remove(key) + { + table.insert(key.to_owned(), value); } }; copy("default-features"); From 508ce146ae3e7cfb71b41fd8e4a64cbff64dec0c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 15:07:27 +0200 Subject: [PATCH 158/162] cargo-gpu merge: fix cargo-deny --- crates/xtask/Cargo.toml | 5 ++++- deny.toml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/xtask/Cargo.toml b/crates/xtask/Cargo.toml index a6c68dd5c3..979a50f06f 100644 --- a/crates/xtask/Cargo.toml +++ b/crates/xtask/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "xtask" version = "0.1.0" -edition = "2024" +edition.workspace = true +repository.workspace = true +license.workspace = true +publish = false [dependencies] anyhow.workspace = true diff --git a/deny.toml b/deny.toml index e4feda2e21..4012eba98a 100644 --- a/deny.toml +++ b/deny.toml @@ -39,6 +39,7 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "ISC", + "MPL-2.0", "Zlib", From 251061bdef6611674abebe2c499676451245d88a Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 15:13:58 +0200 Subject: [PATCH 159/162] cargo-gpu merge: fix docs and clippy --- crates/cargo-gpu-install/src/install.rs | 1 + crates/cargo-gpu-install/src/lib.rs | 6 +----- crates/cargo-gpu-install/src/spirv_source.rs | 1 + crates/cargo-gpu-install/src/test.rs | 15 +++++++++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/cargo-gpu-install/src/install.rs b/crates/cargo-gpu-install/src/install.rs index dcbc4da589..c5061d3e6e 100644 --- a/crates/cargo-gpu-install/src/install.rs +++ b/crates/cargo-gpu-install/src/install.rs @@ -80,6 +80,7 @@ pub struct Install { clippy::doc_markdown, reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" )] + #[expect(rustdoc::bare_urls)] /// Source of `spirv-builder` dependency /// Eg: "https://github.com/Rust-GPU/rust-gpu" #[cfg_attr(feature = "clap", clap(long))] diff --git a/crates/cargo-gpu-install/src/lib.rs b/crates/cargo-gpu-install/src/lib.rs index d7b2210156..19cc48bcf8 100644 --- a/crates/cargo-gpu-install/src/lib.rs +++ b/crates/cargo-gpu-install/src/lib.rs @@ -1,9 +1,5 @@ #![expect(clippy::pub_use, reason = "pub use for build scripts")] -#![expect( - missing_docs, - clippy::missing_docs_in_private_items, - reason = "crate docs are cfg'ed out" -)] +#![expect(missing_docs, reason = "crate docs are cfg'ed out")] #![cfg_attr(doc, doc = include_str!("../README.md"))] pub mod install; diff --git a/crates/cargo-gpu-install/src/spirv_source.rs b/crates/cargo-gpu-install/src/spirv_source.rs index 1071872b93..9fc1e01222 100644 --- a/crates/cargo-gpu-install/src/spirv_source.rs +++ b/crates/cargo-gpu-install/src/spirv_source.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; clippy::doc_markdown, reason = "The URL should appear literally like this. But Clippy wants a markdown clickable link" )] +#[expect(rustdoc::bare_urls)] /// The source and version of `rust-gpu`. /// Eg: /// * From crates.io with version "0.10.0" diff --git a/crates/cargo-gpu-install/src/test.rs b/crates/cargo-gpu-install/src/test.rs index 8cdc5cf841..adbec0a527 100644 --- a/crates/cargo-gpu-install/src/test.rs +++ b/crates/cargo-gpu-install/src/test.rs @@ -39,8 +39,9 @@ impl TestEnv { } /// Copies the `shader_crate_template` to the temp dir and returns the path to the directory. + #[expect(clippy::unused_self)] pub fn setup_shader_crate(&self) -> anyhow::Result { - let shader_crate_path = crate::cache_dir().unwrap().join("shader_crate"); + let shader_crate_path = crate::cache_dir()?.join("shader_crate"); copy_dir_all(shader_crate_template_path(), &shader_crate_path)?; Ok(shader_crate_path) } @@ -65,6 +66,12 @@ impl TestEnv { } } +impl Default for TestEnv { + fn default() -> Self { + Self::new() + } +} + impl Drop for TestEnv { fn drop(&mut self) { TESTDIR.replace(None).unwrap(); @@ -76,14 +83,14 @@ impl Drop for TestEnv { } thread_local! { - static TESTDIR: RefCell> = RefCell::new(None); + static TESTDIR: RefCell> = const { RefCell::new(None) }; } /// [`crate::cache_dir`] for testing, see [`TestEnv`] pub fn test_cache_dir() -> anyhow::Result { - Ok(TESTDIR.with_borrow(|a| a.clone()).context( + TESTDIR.with_borrow(|a| a.clone()).context( "TestEnv is not initialized! Add `let _env = TestEnv::new();` to the beginning of your test", - )?) + ) } fn copy_dir_all( From bc20450801b4a43f45a0f728976736765decc118 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 15:09:25 +0200 Subject: [PATCH 160/162] ci: install nextext as recommended, random ci failures on mac --- .github/workflows/ci.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2e252ddde9..81c33e0c05 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -193,8 +193,9 @@ jobs: RUST_LOG: debug steps: - uses: actions/checkout@v4 - - uses: cargo-bins/cargo-binstall@main - - run: cargo binstall cargo-nextest + - uses: taiki-e/install-action@v2 + with: + tool: nextest - run: cargo fetch --locked - name: shader-crate-template cargo fetch --locked run: | From 3a155de59673876d97e4d8dfc412f6c0b4d476a9 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Wed, 8 Apr 2026 15:11:11 +0200 Subject: [PATCH 161/162] ci: upgrade checkout@v6 --- .github/workflows/ci.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 81c33e0c05..da2941d022 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: os: [ ubuntu-latest, windows-latest, macOS-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1 with: @@ -84,7 +84,7 @@ jobs: target: [ aarch64-linux-android ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1 with: @@ -128,7 +128,7 @@ jobs: os: [ ubuntu-latest, windows-latest, macOS-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1 with: @@ -151,7 +151,7 @@ jobs: os: [ ubuntu-latest, windows-latest, macOS-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1 with: @@ -192,7 +192,7 @@ jobs: env: RUST_LOG: debug steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: taiki-e/install-action@v2 with: tool: nextest @@ -274,7 +274,7 @@ jobs: env: RUST_LOG: debug steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - if: ${{ matrix.glam-version }} name: set glam version run: cargo xtask set-dependency glam ${{ matrix.glam-version }} @@ -308,7 +308,7 @@ jobs: # Note that we are explicitly NOT checking out submodules, to validate # that we haven't accidentally enabled spirv-tools native compilation # and regressed CI times - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: submodules: "false" - name: Install native dependencies @@ -347,7 +347,7 @@ jobs: cargo-deny: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: EmbarkStudios/cargo-deny-action@v2 defaults: From 84f9ab916b55ef22228411cb85133f50e3b46fa1 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 9 Apr 2026 10:26:26 +0200 Subject: [PATCH 162/162] ci: delay `cargo-gpu-backwards-compat` to ensure long-running jobs go first --- .github/workflows/ci.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index da2941d022..28f6a2c991 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -206,6 +206,9 @@ jobs: run: cargo xtask test-build cargo-gpu-backwards-compat: + # The dependency is technically unnecessary, this is just to delay the launch of this job, so that github prefers + # launching long-running jobs first. Currently, these jobs take only about 7min compared to 22min of others. + needs: [cargo-deny] strategy: fail-fast: false matrix: