mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
outputs: ⋯.spv
→ ⋯.spv.json
, ⋯.spv.dir/⋯
→ ⋯.spvs/⋯.spv
(or ⋯.spv
).
This commit is contained in:
parent
3fca36ecb2
commit
6fb35ffeeb
@ -137,40 +137,34 @@ fn link_exe(
|
||||
|
||||
let cg_args = CodegenArgs::from_session(sess);
|
||||
|
||||
let spv_binary = do_link(sess, &cg_args, &objects, &rlibs);
|
||||
// HACK(eddyb) this removes the `.json` in `.spv.json`, from `out_filename`.
|
||||
let out_path_spv = out_filename.with_extension("");
|
||||
|
||||
let mut root_file_name = out_filename.file_name().unwrap().to_owned();
|
||||
root_file_name.push(".dir");
|
||||
let out_dir = out_filename.with_file_name(root_file_name);
|
||||
if !out_dir.is_dir() {
|
||||
std::fs::create_dir_all(&out_dir).unwrap();
|
||||
}
|
||||
|
||||
let compile_result = match spv_binary {
|
||||
linker::LinkResult::SingleModule(spv_binary) => {
|
||||
let mut module_filename = out_dir;
|
||||
module_filename.push("module");
|
||||
post_link_single_module(sess, &cg_args, spv_binary.assemble(), &module_filename);
|
||||
cg_args.do_disassemble(&spv_binary);
|
||||
let compile_result = match do_link(sess, &cg_args, &objects, &rlibs) {
|
||||
linker::LinkResult::SingleModule(module) => {
|
||||
let module_filename = out_path_spv;
|
||||
post_link_single_module(sess, &cg_args, module.assemble(), &module_filename);
|
||||
cg_args.do_disassemble(&module);
|
||||
let module_result = ModuleResult::SingleModule(module_filename);
|
||||
CompileResult {
|
||||
module: module_result,
|
||||
entry_points: entry_points(&spv_binary),
|
||||
entry_points: entry_points(&module),
|
||||
}
|
||||
}
|
||||
linker::LinkResult::MultipleModules(map) => {
|
||||
let out_dir = out_path_spv.with_extension("spvs");
|
||||
if !out_dir.is_dir() {
|
||||
std::fs::create_dir_all(&out_dir).unwrap();
|
||||
}
|
||||
|
||||
let entry_points = map.keys().cloned().collect();
|
||||
let map = map
|
||||
.into_iter()
|
||||
.map(|(name, spv_binary)| {
|
||||
.map(|(name, module)| {
|
||||
let mut module_filename = out_dir.clone();
|
||||
module_filename.push(sanitize_filename::sanitize(&name));
|
||||
post_link_single_module(
|
||||
sess,
|
||||
&cg_args,
|
||||
spv_binary.assemble(),
|
||||
&module_filename,
|
||||
);
|
||||
module_filename.set_extension("spv");
|
||||
post_link_single_module(sess, &cg_args, module.assemble(), &module_filename);
|
||||
(name, module_filename)
|
||||
})
|
||||
.collect();
|
||||
|
@ -81,7 +81,7 @@ impl SpirvTarget {
|
||||
o.allows_weak_linkage = false;
|
||||
o.crt_static_allows_dylibs = true;
|
||||
o.dll_prefix = "".into();
|
||||
o.dll_suffix = ".spv".into();
|
||||
o.dll_suffix = ".spv.json".into();
|
||||
o.dynamic_linking = true;
|
||||
o.emit_debug_gdb_scripts = false;
|
||||
o.linker_flavor = LinkerFlavor::Unix(Cc::No);
|
||||
|
@ -345,7 +345,15 @@ impl SpirvBuilder {
|
||||
match &metadata.module {
|
||||
ModuleResult::SingleModule(spirv_module) => {
|
||||
assert!(!self.multimodule);
|
||||
let env_var = at.file_name().unwrap().to_str().unwrap();
|
||||
let env_var = format!(
|
||||
"{}.spv",
|
||||
at.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.strip_suffix(".spv.json")
|
||||
.unwrap()
|
||||
);
|
||||
if self.print_metadata == MetadataPrintout::Full {
|
||||
println!("cargo:rustc-env={}={}", env_var, spirv_module.display());
|
||||
}
|
||||
@ -511,23 +519,41 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
|
||||
|
||||
// If we're nested in `cargo` invocation, use a different `--target-dir`,
|
||||
// to avoid waiting on the same lock (which effectively dead-locks us).
|
||||
// This also helps with e.g. RLS, which uses `--target target/rls`,
|
||||
// so we'll have a separate `target/rls/spirv-builder` for it.
|
||||
if let (Ok(profile), Some(mut dir)) = (
|
||||
env::var("PROFILE"),
|
||||
env::var_os("OUT_DIR").map(PathBuf::from),
|
||||
) {
|
||||
// Strip `$profile/build/*/out`.
|
||||
if dir.ends_with("out")
|
||||
&& dir.pop()
|
||||
&& dir.pop()
|
||||
&& dir.ends_with("build")
|
||||
&& dir.pop()
|
||||
&& dir.ends_with(profile)
|
||||
&& dir.pop()
|
||||
{
|
||||
cargo.arg("--target-dir").arg(dir.join("spirv-builder"));
|
||||
let outer_target_dir = match (env::var("PROFILE"), env::var_os("OUT_DIR")) {
|
||||
(Ok(profile), Some(dir)) => {
|
||||
// Strip `$profile/build/*/out`.
|
||||
[&profile, "build", "*", "out"].iter().rev().try_fold(
|
||||
PathBuf::from(dir),
|
||||
|mut dir, &filter| {
|
||||
if (filter == "*" || dir.ends_with(filter)) && dir.pop() {
|
||||
Some(dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
// FIXME(eddyb) use `crate metadata` to always be able to get the "outer"
|
||||
// (or "default") `--target-dir`, to append `/spirv-builder` to it.
|
||||
let target_dir = outer_target_dir.map(|outer| outer.join("spirv-builder"));
|
||||
if let Some(target_dir) = target_dir {
|
||||
// HACK(eddyb) Cargo caches some information it got from `rustc` in
|
||||
// `.rustc_info.json`, and assumes it only depends on the `rustc`
|
||||
// binary, but in our case, `rustc_codegen_spirv` changes are also
|
||||
// relevant - so we remove the cache file if it may be out of date.
|
||||
let mtime = |path| std::fs::metadata(path)?.modified();
|
||||
let rustc_info = target_dir.join(".rustc_info.json");
|
||||
if let Ok(rustc_info_mtime) = mtime(&rustc_info) {
|
||||
if let Ok(rustc_codegen_spirv_mtime) = mtime(&rustc_codegen_spirv) {
|
||||
if rustc_codegen_spirv_mtime > rustc_info_mtime {
|
||||
let _ = std::fs::remove_file(rustc_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cargo.arg("--target-dir").arg(target_dir);
|
||||
}
|
||||
|
||||
for (key, _) in env::vars_os() {
|
||||
@ -552,9 +578,14 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
|
||||
// we do that even in case of an error, to let through any useful messages
|
||||
// that ended up on stdout instead of stderr.
|
||||
let stdout = String::from_utf8(build.stdout).unwrap();
|
||||
let artifact = get_last_artifact(&stdout);
|
||||
if build.status.success() {
|
||||
Ok(artifact.expect("Artifact created when compilation succeeded"))
|
||||
get_sole_artifact(&stdout).ok_or_else(|| {
|
||||
eprintln!("--- build output ---\n{stdout}");
|
||||
panic!(
|
||||
"`{}` artifact not found in (supposedly successful) build output (see above)",
|
||||
ARTIFACT_SUFFIX
|
||||
);
|
||||
})
|
||||
} else {
|
||||
Err(SpirvBuilderError::BuildFailed)
|
||||
}
|
||||
@ -566,7 +597,9 @@ struct RustcOutput {
|
||||
filenames: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
fn get_last_artifact(out: &str) -> Option<PathBuf> {
|
||||
const ARTIFACT_SUFFIX: &str = ".spv.json";
|
||||
|
||||
fn get_sole_artifact(out: &str) -> Option<PathBuf> {
|
||||
let last = out
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
@ -586,9 +619,13 @@ fn get_last_artifact(out: &str) -> Option<PathBuf> {
|
||||
.filenames
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.filter(|v| v.ends_with(".spv"));
|
||||
.filter(|v| v.ends_with(ARTIFACT_SUFFIX));
|
||||
let filename = filenames.next()?;
|
||||
assert_eq!(filenames.next(), None, "Crate had multiple .spv artifacts");
|
||||
assert_eq!(
|
||||
filenames.next(),
|
||||
None,
|
||||
"build had multiple `{ARTIFACT_SUFFIX}` artifacts"
|
||||
);
|
||||
Some(filename.into())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user