Skip to content

Commit 91ade61

Browse files
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 <[email protected]>
1 parent 32d297a commit 91ade61

File tree

5 files changed

+183
-103
lines changed

5 files changed

+183
-103
lines changed

crates/cargo-gpu/src/install.rs

Lines changed: 3 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//! Install a dedicated per-shader crate that has the `rust-gpu` compiler in it.
22
3-
use crate::legacy_target_specs::write_legacy_target_specs;
43
use crate::spirv_source::{
54
get_channel_from_rustc_codegen_spirv_build_script, query_metadata, FindPackage as _,
65
};
6+
use crate::target_specs::update_target_specs_files;
77
use crate::{cache_dir, spirv_source::SpirvSource};
88
use anyhow::Context as _;
9-
use cargo_metadata::Metadata;
109
use spirv_builder::SpirvBuilder;
1110
use std::path::{Path, PathBuf};
1211

@@ -196,83 +195,6 @@ package = "rustc_codegen_spirv"
196195
Ok(())
197196
}
198197

199-
/// Copy spec files from one dir to another, assuming no subdirectories
200-
fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> {
201-
std::fs::create_dir_all(dst)?;
202-
let dir = std::fs::read_dir(src)?;
203-
for dir_entry in dir {
204-
let file = dir_entry?;
205-
let file_path = file.path();
206-
if file_path.is_file() {
207-
std::fs::copy(file_path, dst.join(file.file_name()))?;
208-
}
209-
}
210-
Ok(())
211-
}
212-
213-
/// Add the target spec files to the crate.
214-
fn update_spec_files(
215-
source: &SpirvSource,
216-
install_dir: &Path,
217-
dummy_metadata: &Metadata,
218-
skip_rebuild: bool,
219-
) -> anyhow::Result<PathBuf> {
220-
let mut target_specs_dst = install_dir.join("target-specs");
221-
if !skip_rebuild {
222-
if let Ok(target_specs) =
223-
dummy_metadata.find_package("rustc_codegen_spirv-target-specs")
224-
{
225-
log::info!(
226-
"target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`",
227-
target_specs.manifest_path
228-
);
229-
230-
let target_specs_src = target_specs
231-
.manifest_path
232-
.as_std_path()
233-
.parent()
234-
.and_then(|root| {
235-
let src = root.join("target-specs");
236-
src.is_dir().then_some(src)
237-
})
238-
.context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?;
239-
if source.is_path() {
240-
// skip copy
241-
log::info!(
242-
"target-specs: source is local path, use target-specs from `{}`",
243-
target_specs_src.display()
244-
);
245-
target_specs_dst = target_specs_src;
246-
} else {
247-
// copy over the target-specs
248-
log::info!(
249-
"target-specs: Copy target specs from `{}`",
250-
target_specs_src.display()
251-
);
252-
Self::copy_spec_files(&target_specs_src, &target_specs_dst)
253-
.context("copying target-specs json files")?;
254-
}
255-
} else {
256-
// use legacy target specs bundled with cargo gpu
257-
if source.is_path() {
258-
// This is a stupid situation:
259-
// * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`)
260-
// * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout
261-
// -> do what the old cargo gpu did, one global dir for all target specs
262-
// and hope parallel runs don't shred each other
263-
target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout");
264-
}
265-
log::info!(
266-
"target-specs: Writing legacy target specs to `{}`",
267-
target_specs_dst.display()
268-
);
269-
write_legacy_target_specs(&target_specs_dst)?;
270-
}
271-
}
272-
273-
Ok(target_specs_dst)
274-
}
275-
276198
/// Install the binary pair and return the [`InstalledBackend`], from which you can create [`SpirvBuilder`] instances.
277199
///
278200
/// # Errors
@@ -338,9 +260,8 @@ package = "rustc_codegen_spirv"
338260
log::info!("selected toolchain channel `{toolchain_channel:?}`");
339261

340262
log::debug!("update_spec_files");
341-
let target_spec_dir =
342-
Self::update_spec_files(&source, &install_dir, &dummy_metadata, skip_rebuild)
343-
.context("writing target spec files")?;
263+
let target_spec_dir = update_target_specs_files(&source, &dummy_metadata, !skip_rebuild)
264+
.context("writing target spec files")?;
344265

345266
if !skip_rebuild {
346267
log::debug!("ensure_toolchain_and_components_exist");

crates/cargo-gpu/src/legacy_target_specs.rs

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

crates/cargo-gpu/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,12 @@ mod config;
6161
mod dump_usage;
6262
mod install;
6363
mod install_toolchain;
64-
mod legacy_target_specs;
6564
mod linkage;
6665
mod lockfile;
6766
mod metadata;
6867
mod show;
6968
mod spirv_source;
69+
mod target_specs;
7070
mod test;
7171

7272
pub use install::*;

crates/cargo-gpu/src/show.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Display various information about `cargo gpu`, eg its cache directory.
22
33
use crate::cache_dir;
4+
use crate::spirv_source::{query_metadata, SpirvSource};
5+
use crate::target_specs::update_target_specs_files;
6+
use anyhow::bail;
7+
use std::fs;
8+
use std::path::Path;
49

510
/// Show the computed source of the spirv-std dependency.
611
#[derive(Clone, Debug, clap::Parser)]
@@ -21,6 +26,9 @@ pub enum Info {
2126
Commitsh,
2227
/// All the available SPIR-V capabilities that can be set with `--capabilities`
2328
Capabilities,
29+
30+
/// All available SPIR-V targets
31+
Targets(SpirvSourceDep),
2432
}
2533

2634
/// `cargo gpu show`
@@ -46,8 +54,7 @@ impl Show {
4654
println!("{}\n", cache_dir()?.display());
4755
}
4856
Info::SpirvSource(SpirvSourceDep { shader_crate }) => {
49-
let rust_gpu_source =
50-
crate::spirv_source::SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?;
57+
let rust_gpu_source = SpirvSource::get_rust_gpu_deps_from_shader(shader_crate)?;
5158
println!("{rust_gpu_source}\n");
5259
}
5360
Info::Commitsh => {
@@ -63,6 +70,13 @@ impl Show {
6370
println!(" {capability:?}");
6471
}
6572
}
73+
Info::Targets(SpirvSourceDep { shader_crate }) => {
74+
let (source, targets) = Self::available_spirv_targets_iter(shader_crate)?;
75+
println!("All available targets for rust-gpu version '{source}':");
76+
for target in targets {
77+
println!("{target}");
78+
}
79+
}
6680
}
6781

6882
Ok(())
@@ -76,4 +90,32 @@ impl Show {
7690
let last_capability = spirv_builder::Capability::CacheControlsINTEL as u32;
7791
(0..=last_capability).filter_map(spirv_builder::Capability::from_u32)
7892
}
93+
94+
/// List all available spirv targets, note: the targets from compile time of cargo-gpu and those
95+
/// in the cache-directory will be picked up.
96+
fn available_spirv_targets_iter(
97+
shader_crate: &Path,
98+
) -> anyhow::Result<(SpirvSource, impl Iterator<Item = String>)> {
99+
let source = SpirvSource::new(shader_crate, None, None)?;
100+
let install_dir = source.install_dir()?;
101+
if !install_dir.is_dir() {
102+
bail!("rust-gpu version {} is not installed", source);
103+
}
104+
let dummy_metadata = query_metadata(&install_dir)?;
105+
let target_specs_dir = update_target_specs_files(&source, &dummy_metadata, false)?;
106+
107+
let mut targets = fs::read_dir(target_specs_dir)?
108+
.filter_map(|entry| {
109+
let file = entry.ok()?;
110+
if file.path().is_file() {
111+
if let Some(target) = file.file_name().to_string_lossy().strip_suffix(".json") {
112+
return Some(target.to_owned());
113+
}
114+
}
115+
None
116+
})
117+
.collect::<Vec<_>>();
118+
targets.sort();
119+
Ok((source, targets.into_iter()))
120+
}
79121
}

crates/cargo-gpu/src/target_specs.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
//! This module deals with target specs, which are json metadata files that need to be passed to
2+
//! rustc to add foreign targets such as `spirv_unknown_vulkan1.2`.
3+
//!
4+
//! There are 4 version ranges of `rustc_codegen_spirv` and they all need different handling of
5+
//! their target specs:
6+
//! * "ancient" versions such as 0.9.0 or earlier do not need target specs, just passing the target
7+
//! string (`spirv-unknown-vulkan1.2`) directly is sufficient. We still prep target-specs for them
8+
//! like the "legacy" variant below, spirv-builder
9+
//! [will just ignore it](https://github.com/Rust-GPU/rust-gpu/blob/369122e1703c0c32d3d46f46fa11ccf12667af03/crates/spirv-builder/src/lib.rs#L987)
10+
//! * "legacy" versions require target specs to compile, which is a requirement introduced by some
11+
//! rustc version. Back then it was decided that cargo gpu would ship them, as they'd probably
12+
//! never change, right? So now we're stuck with having to ship these "legacy" target specs with
13+
//! cargo gpu *forever*. These are the symbol `legacy_target_specs::TARGET_SPECS`, with
14+
//! `legacy_target_specs` being a **fixed** version of `rustc_codegen_spirv-target-specs`,
15+
//! which must **never** update.
16+
//! * As of [PR 256](https://github.com/Rust-GPU/rust-gpu/pull/256), `rustc_codegen_spirv` now has
17+
//! a direct dependency on `rustc_codegen_spirv-target-specs`, allowing cargo gpu to pull the
18+
//! required target specs directly from that dependency. At this point, the target specs are
19+
//! still the same as the legacy target specs.
20+
//! * The [edition 2024 PR](https://github.com/Rust-GPU/rust-gpu/pull/249) must update the
21+
//! target specs to comply with newly added validation within rustc. This is why the new system
22+
//! was implemented, so we can support both old and new target specs without having to worry
23+
//! which version of cargo gpu you are using. It'll "just work".
24+
25+
use crate::cache_dir;
26+
use crate::spirv_source::{FindPackage as _, SpirvSource};
27+
use anyhow::Context as _;
28+
use cargo_metadata::Metadata;
29+
use std::path::{Path, PathBuf};
30+
31+
/// Extract legacy target specs from our executable into some directory
32+
pub fn write_legacy_target_specs(target_spec_dir: &Path) -> anyhow::Result<()> {
33+
std::fs::create_dir_all(target_spec_dir)?;
34+
for (filename, contents) in legacy_target_specs::TARGET_SPECS {
35+
let path = target_spec_dir.join(filename);
36+
std::fs::write(&path, contents.as_bytes())
37+
.with_context(|| format!("writing legacy target spec file at [{}]", path.display()))?;
38+
}
39+
Ok(())
40+
}
41+
42+
/// Copy spec files from one dir to another, assuming no subdirectories
43+
fn copy_spec_files(src: &Path, dst: &Path) -> anyhow::Result<()> {
44+
std::fs::create_dir_all(dst)?;
45+
let dir = std::fs::read_dir(src)?;
46+
for dir_entry in dir {
47+
let file = dir_entry?;
48+
let file_path = file.path();
49+
if file_path.is_file() {
50+
std::fs::copy(file_path, dst.join(file.file_name()))?;
51+
}
52+
}
53+
Ok(())
54+
}
55+
56+
/// Computes the `target-specs` directory to use and updates the target spec files, if enabled.
57+
pub fn update_target_specs_files(
58+
source: &SpirvSource,
59+
dummy_metadata: &Metadata,
60+
update_files: bool,
61+
) -> anyhow::Result<PathBuf> {
62+
log::info!(
63+
"target-specs: Resolving target specs `{}`",
64+
if update_files {
65+
"and update them"
66+
} else {
67+
"without updating"
68+
}
69+
);
70+
71+
let mut target_specs_dst = source.install_dir()?.join("target-specs");
72+
if let Ok(target_specs) = dummy_metadata.find_package("rustc_codegen_spirv-target-specs") {
73+
log::info!(
74+
"target-specs: found crate `rustc_codegen_spirv-target-specs` with manifest at `{}`",
75+
target_specs.manifest_path
76+
);
77+
78+
let target_specs_src = target_specs
79+
.manifest_path
80+
.as_std_path()
81+
.parent()
82+
.and_then(|root| {
83+
let src = root.join("target-specs");
84+
src.is_dir().then_some(src)
85+
})
86+
.context("Could not find `target-specs` directory within `rustc_codegen_spirv-target-specs` dependency")?;
87+
log::info!(
88+
"target-specs: found `rustc_codegen_spirv-target-specs` with `target-specs` directory `{}`",
89+
target_specs_dst.display()
90+
);
91+
92+
if source.is_path() {
93+
// skip copy
94+
log::info!(
95+
"target-specs resolution: source is local path, use target-specs directly from `{}`",
96+
target_specs_dst.display()
97+
);
98+
target_specs_dst = target_specs_src;
99+
} else {
100+
// copy over the target-specs
101+
log::info!(
102+
"target-specs resolution: coping target-specs from `{}`{}",
103+
target_specs_dst.display(),
104+
if update_files { "" } else { " was skipped" }
105+
);
106+
if update_files {
107+
copy_spec_files(&target_specs_src, &target_specs_dst)
108+
.context("copying target-specs json files")?;
109+
}
110+
}
111+
} else {
112+
// use legacy target specs bundled with cargo gpu
113+
if source.is_path() {
114+
// This is a stupid situation:
115+
// * We can't be certain that there are `target-specs` in the local checkout (there may be some in `spirv-builder`)
116+
// * We can't dump our legacy ones into the `install_dir`, as that would modify the local rust-gpu checkout
117+
// -> do what the old cargo gpu did, one global dir for all target specs
118+
// and hope parallel runs don't shred each other
119+
target_specs_dst = cache_dir()?.join("legacy-target-specs-for-local-checkout");
120+
}
121+
log::info!(
122+
"target-specs resolution: legacy target specs in directory `{}`",
123+
target_specs_dst.display()
124+
);
125+
if update_files {
126+
log::info!(
127+
"target-specs: Writing legacy target specs into `{}`",
128+
target_specs_dst.display()
129+
);
130+
write_legacy_target_specs(&target_specs_dst)?;
131+
}
132+
}
133+
134+
Ok(target_specs_dst)
135+
}

0 commit comments

Comments
 (0)