@@ -345,7 +345,15 @@ impl SpirvBuilder {
345
345
match & metadata. module {
346
346
ModuleResult :: SingleModule ( spirv_module) => {
347
347
assert ! ( !self . multimodule) ;
348
- let env_var = at. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
348
+ let env_var = format ! (
349
+ "{}.spv" ,
350
+ at. file_name( )
351
+ . unwrap( )
352
+ . to_str( )
353
+ . unwrap( )
354
+ . strip_suffix( ".spv.json" )
355
+ . unwrap( )
356
+ ) ;
349
357
if self . print_metadata == MetadataPrintout :: Full {
350
358
println ! ( "cargo:rustc-env={}={}" , env_var, spirv_module. display( ) ) ;
351
359
}
@@ -511,23 +519,41 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
511
519
512
520
// If we're nested in `cargo` invocation, use a different `--target-dir`,
513
521
// to avoid waiting on the same lock (which effectively dead-locks us).
514
- // This also helps with e.g. RLS, which uses `--target target/rls`,
515
- // so we'll have a separate `target/rls/spirv-builder` for it.
516
- if let ( Ok ( profile) , Some ( mut dir) ) = (
517
- env:: var ( "PROFILE" ) ,
518
- env:: var_os ( "OUT_DIR" ) . map ( PathBuf :: from) ,
519
- ) {
520
- // Strip `$profile/build/*/out`.
521
- if dir. ends_with ( "out" )
522
- && dir. pop ( )
523
- && dir. pop ( )
524
- && dir. ends_with ( "build" )
525
- && dir. pop ( )
526
- && dir. ends_with ( profile)
527
- && dir. pop ( )
528
- {
529
- cargo. arg ( "--target-dir" ) . arg ( dir. join ( "spirv-builder" ) ) ;
522
+ let outer_target_dir = match ( env:: var ( "PROFILE" ) , env:: var_os ( "OUT_DIR" ) ) {
523
+ ( Ok ( profile) , Some ( dir) ) => {
524
+ // Strip `$profile/build/*/out`.
525
+ [ & profile, "build" , "*" , "out" ] . iter ( ) . rev ( ) . try_fold (
526
+ PathBuf :: from ( dir) ,
527
+ |mut dir, & filter| {
528
+ if ( filter == "*" || dir. ends_with ( filter) ) && dir. pop ( ) {
529
+ Some ( dir)
530
+ } else {
531
+ None
532
+ }
533
+ } ,
534
+ )
535
+ }
536
+ _ => None ,
537
+ } ;
538
+ // FIXME(eddyb) use `crate metadata` to always be able to get the "outer"
539
+ // (or "default") `--target-dir`, to append `/spirv-builder` to it.
540
+ let target_dir = outer_target_dir. map ( |outer| outer. join ( "spirv-builder" ) ) ;
541
+ if let Some ( target_dir) = target_dir {
542
+ // HACK(eddyb) Cargo caches some information it got from `rustc` in
543
+ // `.rustc_info.json`, and assumes it only depends on the `rustc`
544
+ // binary, but in our case, `rustc_codegen_spirv` changes are also
545
+ // relevant - so we remove the cache file if it may be out of date.
546
+ let mtime = |path| std:: fs:: metadata ( path) ?. modified ( ) ;
547
+ let rustc_info = target_dir. join ( ".rustc_info.json" ) ;
548
+ if let Ok ( rustc_info_mtime) = mtime ( & rustc_info) {
549
+ if let Ok ( rustc_codegen_spirv_mtime) = mtime ( & rustc_codegen_spirv) {
550
+ if rustc_codegen_spirv_mtime > rustc_info_mtime {
551
+ let _ = std:: fs:: remove_file ( rustc_info) ;
552
+ }
553
+ }
530
554
}
555
+
556
+ cargo. arg ( "--target-dir" ) . arg ( target_dir) ;
531
557
}
532
558
533
559
for ( key, _) in env:: vars_os ( ) {
@@ -552,9 +578,14 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result<PathBuf, SpirvBuilderError> {
552
578
// we do that even in case of an error, to let through any useful messages
553
579
// that ended up on stdout instead of stderr.
554
580
let stdout = String :: from_utf8 ( build. stdout ) . unwrap ( ) ;
555
- let artifact = get_last_artifact ( & stdout) ;
556
581
if build. status . success ( ) {
557
- Ok ( artifact. expect ( "Artifact created when compilation succeeded" ) )
582
+ get_sole_artifact ( & stdout) . ok_or_else ( || {
583
+ eprintln ! ( "--- build output ---\n {stdout}" ) ;
584
+ panic ! (
585
+ "`{}` artifact not found in (supposedly successful) build output (see above)" ,
586
+ ARTIFACT_SUFFIX
587
+ ) ;
588
+ } )
558
589
} else {
559
590
Err ( SpirvBuilderError :: BuildFailed )
560
591
}
@@ -566,7 +597,9 @@ struct RustcOutput {
566
597
filenames : Option < Vec < String > > ,
567
598
}
568
599
569
- fn get_last_artifact ( out : & str ) -> Option < PathBuf > {
600
+ const ARTIFACT_SUFFIX : & str = ".spv.json" ;
601
+
602
+ fn get_sole_artifact ( out : & str ) -> Option < PathBuf > {
570
603
let last = out
571
604
. lines ( )
572
605
. filter_map ( |line| {
@@ -586,9 +619,13 @@ fn get_last_artifact(out: &str) -> Option<PathBuf> {
586
619
. filenames
587
620
. unwrap ( )
588
621
. into_iter ( )
589
- . filter ( |v| v. ends_with ( ".spv" ) ) ;
622
+ . filter ( |v| v. ends_with ( ARTIFACT_SUFFIX ) ) ;
590
623
let filename = filenames. next ( ) ?;
591
- assert_eq ! ( filenames. next( ) , None , "Crate had multiple .spv artifacts" ) ;
624
+ assert_eq ! (
625
+ filenames. next( ) ,
626
+ None ,
627
+ "build had multiple `{ARTIFACT_SUFFIX}` artifacts"
628
+ ) ;
592
629
Some ( filename. into ( ) )
593
630
}
594
631
0 commit comments