@@ -76,11 +76,11 @@ mod watch;
76
76
77
77
use raw_string:: { RawStr , RawString } ;
78
78
use serde:: Deserialize ;
79
+ use std:: borrow:: Borrow ;
79
80
use std:: collections:: HashMap ;
80
81
use std:: env;
81
82
use std:: error:: Error ;
82
83
use std:: fmt;
83
- use std:: fmt:: Write ;
84
84
use std:: fs:: File ;
85
85
use std:: io:: BufReader ;
86
86
use std:: path:: { Path , PathBuf } ;
@@ -362,6 +362,21 @@ fn find_rustc_codegen_spirv() -> PathBuf {
362
362
panic ! ( "Could not find {} in library path" , filename) ;
363
363
}
364
364
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
+
365
380
// Returns path to the metadata json.
366
381
fn invoke_rustc ( builder : & SpirvBuilder ) -> Result < PathBuf , SpirvBuilderError > {
367
382
// 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> {
374
389
// to copy cargo's understanding of library lookup and find the library and its full path.
375
390
let rustc_codegen_spirv = find_rustc_codegen_spirv ( ) ;
376
391
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 ! [ ] ;
378
399
if builder. multimodule {
379
400
llvm_args. push ( "--module-output=multiple" ) ;
380
401
}
@@ -399,47 +420,22 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
399
420
if builder. skip_block_layout {
400
421
llvm_args. push ( "--skip-block-layout" ) ;
401
422
}
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
+ }
402
427
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 ! [ ] ;
420
429
target_features. extend ( builder. capabilities . iter ( ) . map ( |cap| format ! ( "+{:?}" , cap) ) ) ;
421
430
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
+ }
422
435
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
+ }
443
439
444
440
let mut cargo = Command :: new ( "cargo" ) ;
445
441
cargo. args ( & [
@@ -477,10 +473,12 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
477
473
}
478
474
}
479
475
476
+ let cargo_encoded_rustflags = join_checking_for_separators ( rustflags, "\x1f " ) ;
477
+
480
478
let build = cargo
481
479
. stderr ( Stdio :: inherit ( ) )
482
480
. current_dir ( & builder. path_to_crate )
483
- . env ( "RUSTFLAGS " , rustflags )
481
+ . env ( "CARGO_ENCODED_RUSTFLAGS " , cargo_encoded_rustflags )
484
482
. output ( )
485
483
. expect ( "failed to execute cargo build" ) ;
486
484
0 commit comments