Skip to content

Commit 9084997

Browse files
committed
spirv-builder: switch to \x1f-separated CARGO_ENCODED_RUSTFLAGS.
1 parent 7501f18 commit 9084997

File tree

2 files changed

+46
-45
lines changed

2 files changed

+46
-45
lines changed

crates/spirv-builder/src/lib.rs

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ mod watch;
7676

7777
use raw_string::{RawStr, RawString};
7878
use serde::Deserialize;
79+
use std::borrow::Borrow;
7980
use std::collections::HashMap;
8081
use std::env;
8182
use std::error::Error;
8283
use std::fmt;
83-
use std::fmt::Write;
8484
use std::fs::File;
8585
use std::io::BufReader;
8686
use std::path::{Path, PathBuf};
@@ -362,6 +362,21 @@ fn find_rustc_codegen_spirv() -> PathBuf {
362362
panic!("Could not find {} in library path", filename);
363363
}
364364

365+
/// Joins strings together while ensuring none of the strings contain the separator.
366+
// NOTE(eddyb) this intentionally consumes the `Vec` to limit accidental misuse.
367+
fn join_checking_for_separators(strings: Vec<impl Borrow<str>>, sep: &str) -> String {
368+
for s in &strings {
369+
let s = s.borrow();
370+
assert!(
371+
!s.contains(sep),
372+
"{:?} may not contain separator {:?}",
373+
s,
374+
sep
375+
);
376+
}
377+
strings.join(sep)
378+
}
379+
365380
// Returns path to the metadata json.
366381
fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
367382
// Okay, this is a little bonkers: in a normal world, we'd have the user clone
@@ -374,7 +389,13 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
374389
// to copy cargo's understanding of library lookup and find the library and its full path.
375390
let rustc_codegen_spirv = find_rustc_codegen_spirv();
376391

377-
let mut llvm_args = Vec::new();
392+
let mut rustflags = vec![
393+
format!("-Zcodegen-backend={}", rustc_codegen_spirv.display()),
394+
//FIXME: reintroduce v0 mangling, see issue #642
395+
"-Zsymbol-mangling-version=legacy".to_string(),
396+
];
397+
398+
let mut llvm_args = vec![];
378399
if builder.multimodule {
379400
llvm_args.push("--module-output=multiple");
380401
}
@@ -399,47 +420,22 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
399420
if builder.skip_block_layout {
400421
llvm_args.push("--skip-block-layout");
401422
}
423+
let llvm_args = join_checking_for_separators(llvm_args, " ");
424+
if !llvm_args.is_empty() {
425+
rustflags.push(["-Cllvm-args=", &llvm_args].concat());
426+
}
402427

403-
let llvm_args = if llvm_args.is_empty() {
404-
String::new()
405-
} else {
406-
// Cargo's handling of RUSTFLAGS is a little cursed. -Cllvm-args is documented as "The list
407-
// must be separated by spaces", but if we set RUSTFLAGS='-C llvm-args="--foo --bar"', then
408-
// cargo will pass -C 'llvm-args="--foo' '--bar"' to rustc. Like, really? c'mon.
409-
// Thankfully, passing -C llvm-args multiple times appends to a list, instead of
410-
// overwriting.
411-
let mut result = String::new();
412-
for arg in llvm_args {
413-
write!(result, " -C llvm-args={}", arg).unwrap();
414-
}
415-
result
416-
};
417-
418-
let mut target_features = Vec::new();
419-
428+
let mut target_features = vec![];
420429
target_features.extend(builder.capabilities.iter().map(|cap| format!("+{:?}", cap)));
421430
target_features.extend(builder.extensions.iter().map(|ext| format!("+ext:{}", ext)));
431+
let target_features = join_checking_for_separators(target_features, ",");
432+
if !target_features.is_empty() {
433+
rustflags.push(["-Ctarget-feature=", &target_features].concat());
434+
}
422435

423-
let feature_flag = if target_features.is_empty() {
424-
String::new()
425-
} else {
426-
format!(" -C target-feature={}", target_features.join(","))
427-
};
428-
429-
let deny_warnings = if builder.deny_warnings {
430-
" -D warnings"
431-
} else {
432-
""
433-
};
434-
435-
//FIXME: reintroduce v0 mangling, see issue #642
436-
let rustflags = format!(
437-
"-Z codegen-backend={} -Zsymbol-mangling-version=legacy{}{}{}",
438-
rustc_codegen_spirv.display(),
439-
feature_flag,
440-
llvm_args,
441-
deny_warnings,
442-
);
436+
if builder.deny_warnings {
437+
rustflags.push("-Dwarnings".to_string());
438+
}
443439

444440
let mut cargo = Command::new("cargo");
445441
cargo.args(&[
@@ -477,10 +473,12 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
477473
}
478474
}
479475

476+
let cargo_encoded_rustflags = join_checking_for_separators(rustflags, "\x1f");
477+
480478
let build = cargo
481479
.stderr(Stdio::inherit())
482480
.current_dir(&builder.path_to_crate)
483-
.env("RUSTFLAGS", rustflags)
481+
.env("CARGO_ENCODED_RUSTFLAGS", cargo_encoded_rustflags)
484482
.output()
485483
.expect("failed to execute cargo build");
486484

examples/multibuilder/src/main.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use spirv_builder::{MetadataPrintout, SpirvBuilder};
22

33
fn main() {
4-
let result = SpirvBuilder::new("../shaders/sky-shader", "spirv-unknown-spv1.3")
5-
.print_metadata(MetadataPrintout::DependencyOnly)
6-
.multimodule(true)
7-
.build()
8-
.unwrap();
4+
let result = SpirvBuilder::new(
5+
concat!(env!("CARGO_MANIFEST_DIR"), "/../shaders/sky-shader"),
6+
"spirv-unknown-spv1.3",
7+
)
8+
.print_metadata(MetadataPrintout::DependencyOnly)
9+
.multimodule(true)
10+
.build()
11+
.unwrap();
912
println!("{:#?}", result);
1013
}

0 commit comments

Comments
 (0)