@@ -218,45 +218,64 @@ fn merge_profraw(cx: &Context) -> Result<()> {
218218fn object_files ( cx : & Context ) -> Result < Vec < OsString > > {
219219 fn walk_target_dir < ' a > (
220220 cx : & ' a Context ,
221- build_script_re : & ' a RegexVec ,
221+ build_script_v1_layout_re : & ' a RegexVec ,
222+ build_script_v2_layout_re : & ' a RegexVec ,
222223 target_dir : & Utf8Path ,
223224 ) -> impl Iterator < Item = walkdir:: DirEntry > + ' a {
225+ let build_dir = target_dir. join ( "build" ) ; // <target>/{debug,release}/build
224226 WalkDir :: new ( target_dir)
225227 . into_iter ( )
226228 . filter_entry ( move |e| {
227229 let p = e. path ( ) ;
228- // Refs: https://github.com/rust-lang/cargo/blob/0.85.0/src/cargo/core/compiler/layout.rs.
229- if p. is_dir ( ) {
230- if p. file_name ( ) . is_some_and ( |f| {
231- f == "incremental"
232- || f == ".fingerprint"
233- || if cx. args . report . include_build_script {
234- f == "out"
230+ // Note that Cargo has 2 file layouts. At the time of writing v2 is still unstable
231+ // but planned to replace the v1 layout.
232+ // v1: https://github.com/rust-lang/cargo/blob/0.85.0/src/cargo/core/compiler/layout.rs.
233+ // v2: https://github.com/rust-lang/cargo/blob/592bc40115849f2f16855f4adb6cc795c208765b/src/cargo/core/compiler/layout.rs
234+ if p. is_dir ( )
235+ && p. file_name ( ) . is_some_and ( |f| {
236+ f == "incremental" || f == ".fingerprint" || f == "fingerprint"
237+ } )
238+ {
239+ // Ignore incremental compilation related files and Cargo fingerprints
240+ return false ;
241+ }
242+ if let ( Some ( stem) , Some ( parent) ) = ( p. file_stem ( ) , p. parent ( ) ) {
243+ if parent. starts_with ( & build_dir) {
244+ if p. is_dir ( ) && p. file_name ( ) . is_some_and ( |f| f == "out" ) {
245+ let is_v2_layout = parent. join ( "fingerprint" ) . exists ( ) ;
246+ if is_v2_layout {
247+ // In the v2 layout, the `<target>/debug/$build-unit/out` dir is a
248+ // generic directory that may be the $OUT_DIR for build script
249+ // execution units or the compilation output.
250+ // We check this by seeing if a `run` directory is present which
251+ // indicates this is a build script run
252+ if parent. join ( "run" ) . exists ( ) {
253+ return false ;
254+ }
235255 } else {
236- f == "build"
256+ // In the v1 layout, `out` is always the build script $OUT_DIR
257+ // which we don't care about.
258+ return false ;
237259 }
238- } ) {
239- // Ignore incremental compilation related files and output from build scripts.
240- return false ;
241- }
242- } else if cx. args . report . include_build_script {
243- if let ( Some ( stem) , Some ( p) ) = ( p. file_stem ( ) , p. parent ( ) ) {
244- fn in_build_dir ( p : & Path ) -> bool {
245- let Some ( p) = p. parent ( ) else { return false } ;
246- let Some ( f) = p. file_name ( ) else { return false } ;
247- f == "build"
248260 }
249- if in_build_dir ( p) {
250- if stem == "build-script-build"
251- || stem
252- . to_str ( )
253- . unwrap_or_default ( )
254- . starts_with ( "build_script_build-" )
255- {
256- // TODO: use os_str_to_str?
257- let dir = p. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
258- if !build_script_re. is_match ( & dir) {
259- return false ;
261+
262+ if stem == "build-script-build"
263+ || stem. to_str ( ) . unwrap_or_default ( ) . starts_with ( "build_script_build-" )
264+ {
265+ if cx. args . report . include_build_script {
266+ let is_v2_layout =
267+ parent. parent ( ) . unwrap ( ) . join ( "fingerprint" ) . exists ( ) ;
268+ if is_v2_layout {
269+ let dir = parent. to_string_lossy ( ) ;
270+ if !build_script_v2_layout_re. is_match ( & dir) {
271+ return false ;
272+ }
273+ } else {
274+ // TODO: use os_str_to_str?
275+ let dir = parent. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
276+ if !build_script_v1_layout_re. is_match ( & dir) {
277+ return false ;
278+ }
260279 }
261280 } else {
262281 return false ;
@@ -273,7 +292,12 @@ fn object_files(cx: &Context) -> Result<Vec<OsString>> {
273292 // We check extension instead of using is_executable crate because it always return true on WSL:
274293 // - https://github.com/taiki-e/cargo-llvm-cov/issues/316
275294 // - https://github.com/taiki-e/cargo-llvm-cov/issues/342
276- if ext == "d" || ext == "rlib" || ext == "rmeta" || f. ends_with ( ".cargo-lock" ) {
295+ if ext == "d"
296+ || ext == "rlib"
297+ || ext == "rmeta"
298+ || f. ends_with ( ".cargo-lock" )
299+ || f. ends_with ( ".cargo-build-lock" )
300+ {
277301 return false ;
278302 }
279303 if cx. ws . target_is_windows
@@ -309,7 +333,8 @@ fn object_files(cx: &Context) -> Result<Vec<OsString>> {
309333 }
310334
311335 let re = pkg_hash_re ( cx) ?;
312- let build_script_re = build_script_hash_re ( cx) ;
336+ let build_script_v1_layout_re = build_script_hash_v1_layout_re ( cx) ;
337+ let build_script_v2_layout_re = build_script_hash_v2_layout_re ( cx) ;
313338 let mut files = vec ! [ ] ;
314339 let mut searched_dir = String :: new ( ) ;
315340 // To support testing binary crate like tests that use the CARGO_BIN_EXE
@@ -364,50 +389,58 @@ fn object_files(cx: &Context) -> Result<Vec<OsString>> {
364389 }
365390 }
366391
367- let mut collect_target_dir =
368- | mut target_dir : Utf8PathBuf , mut build_dir : Option < Utf8PathBuf > | -> Result < ( ) > {
369- if !auto_detect_profile {
370- // https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#custom-profiles
371- let profile = match cx . args . cargo_profile . as_deref ( ) {
372- None if cx. args . release => "release" ,
373- Some ( " release" | "bench" ) => "release" ,
374- None | Some ( "dev " | "test " ) => "debug " ,
375- Some ( p ) => p ,
376- } ;
377- target_dir . push ( profile ) ;
378- if let Some ( build_dir ) = & mut build_dir {
379- build_dir. push ( profile ) ;
380- }
392+ let mut collect_target_dir = | mut target_dir : Utf8PathBuf ,
393+ mut build_dir : Option < Utf8PathBuf > |
394+ -> Result < ( ) > {
395+ if !auto_detect_profile {
396+ // https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#custom-profiles
397+ let profile = match cx. args . cargo_profile . as_deref ( ) {
398+ None if cx . args . release => "release" ,
399+ Some ( "release " | "bench " ) => "release " ,
400+ None | Some ( "dev" | "test" ) => "debug" ,
401+ Some ( p ) => p ,
402+ } ;
403+ target_dir . push ( profile ) ;
404+ if let Some ( build_dir ) = & mut build_dir {
405+ build_dir . push ( profile ) ;
381406 }
382- for f in walk_target_dir ( cx, & build_script_re, & target_dir) {
383- let f = f. path ( ) ;
384- if is_object ( cx, f) {
385- if let Some ( file_stem) = fs:: file_stem_recursive ( f) . unwrap ( ) . to_str ( ) {
386- if re. is_match ( file_stem) {
387- files. push ( make_relative ( cx, f) . to_owned ( ) . into_os_string ( ) ) ;
388- }
407+ }
408+ for f in
409+ walk_target_dir ( cx, & build_script_v1_layout_re, & build_script_v2_layout_re, & target_dir)
410+ {
411+ let f = f. path ( ) ;
412+ if is_object ( cx, f) {
413+ if let Some ( file_stem) = fs:: file_stem_recursive ( f) . unwrap ( ) . to_str ( ) {
414+ if re. is_match ( file_stem) {
415+ files. push ( make_relative ( cx, f) . to_owned ( ) . into_os_string ( ) ) ;
389416 }
390417 }
391418 }
392- searched_dir. push_str ( target_dir. as_str ( ) ) ;
393- if let Some ( build_dir) = & build_dir {
394- if target_dir != * build_dir {
395- for f in walk_target_dir ( cx, & build_script_re, build_dir) {
396- let f = f. path ( ) ;
397- if is_object ( cx, f) {
398- if let Some ( file_stem) = fs:: file_stem_recursive ( f) . unwrap ( ) . to_str ( ) {
399- if re. is_match ( file_stem) {
400- files. push ( make_relative ( cx, f) . to_owned ( ) . into_os_string ( ) ) ;
401- }
419+ }
420+ searched_dir. push_str ( target_dir. as_str ( ) ) ;
421+ if let Some ( build_dir) = & build_dir {
422+ if target_dir != * build_dir {
423+ for f in walk_target_dir (
424+ cx,
425+ & build_script_v1_layout_re,
426+ & build_script_v2_layout_re,
427+ build_dir,
428+ ) {
429+ let f = f. path ( ) ;
430+ if is_object ( cx, f) {
431+ if let Some ( file_stem) = fs:: file_stem_recursive ( f) . unwrap ( ) . to_str ( ) {
432+ if re. is_match ( file_stem) {
433+ files. push ( make_relative ( cx, f) . to_owned ( ) . into_os_string ( ) ) ;
402434 }
403435 }
404436 }
405- searched_dir. push ( ',' ) ;
406- searched_dir. push_str ( build_dir. as_str ( ) ) ;
407437 }
438+ searched_dir. push ( ',' ) ;
439+ searched_dir. push_str ( build_dir. as_str ( ) ) ;
408440 }
409- Ok ( ( ) )
410- } ;
441+ }
442+ Ok ( ( ) )
443+ } ;
411444 // Check both host and target because proc-macro and build script are built for host.
412445 // https://doc.rust-lang.org/nightly/cargo/reference/build-cache.html
413446 if let Some ( target) = & cx. args . target {
@@ -454,7 +487,12 @@ fn object_files(cx: &Context) -> Result<Vec<OsString>> {
454487 if !trybuild_targets. is_empty ( ) {
455488 let re = Regex :: new ( & format ! ( "^({})(-[0-9a-f]+)?$" , trybuild_targets. join( "|" ) ) )
456489 . unwrap ( ) ;
457- for entry in walk_target_dir ( cx, & build_script_re, & trybuild_target_dir) {
490+ for entry in walk_target_dir (
491+ cx,
492+ & build_script_v1_layout_re,
493+ & build_script_v2_layout_re,
494+ & trybuild_target_dir,
495+ ) {
458496 let path = make_relative ( cx, entry. path ( ) ) ;
459497 if let Some ( file_stem) = fs:: file_stem_recursive ( path) . unwrap ( ) . to_str ( ) {
460498 if re. is_match ( file_stem) {
@@ -483,7 +521,12 @@ fn object_files(cx: &Context) -> Result<Vec<OsString>> {
483521 let ui_test_target_dir = cx. ws . ui_test_target_dir ( ) ;
484522 let mut collect_ui_test_target_dir = |ui_test_target_dir : Utf8PathBuf | -> Result < ( ) > {
485523 if ui_test_target_dir. is_dir ( ) {
486- for entry in walk_target_dir ( cx, & build_script_re, & ui_test_target_dir) {
524+ for entry in walk_target_dir (
525+ cx,
526+ & build_script_v1_layout_re,
527+ & build_script_v2_layout_re,
528+ & ui_test_target_dir,
529+ ) {
487530 let path = make_relative ( cx, entry. path ( ) ) ;
488531 if is_object ( cx, path) {
489532 files. push ( path. to_owned ( ) . into_os_string ( ) ) ;
@@ -526,14 +569,22 @@ fn pkg_hash_re(cx: &Context) -> Result<RegexVec> {
526569 re. build ( )
527570}
528571
529- fn build_script_hash_re ( cx : & Context ) -> RegexVec {
572+ fn build_script_hash_v1_layout_re ( cx : & Context ) -> RegexVec {
530573 let mut re = RegexVecBuilder :: new ( "^(" , ")-[0-9a-f]+$" ) ;
531574 for & id in & cx. workspace_members . included {
532575 re. or ( & cx. ws . metadata [ id] . name ) ;
533576 }
534577 re. build ( ) . unwrap ( )
535578}
536579
580+ fn build_script_hash_v2_layout_re ( cx : & Context ) -> RegexVec {
581+ let mut re = RegexVecBuilder :: new ( "build/(" , ")/[0-9a-f]+/out$" ) ;
582+ for & id in & cx. workspace_members . included {
583+ re. or ( & cx. ws . metadata [ id] . name ) ;
584+ }
585+ re. build ( ) . unwrap ( )
586+ }
587+
537588/// Collects metadata for packages generated by trybuild. If the trybuild test
538589/// directory is not found, it returns an empty vector.
539590fn trybuild_metadata ( ws : & Workspace , target_dir : & Utf8Path ) -> Result < Vec < Metadata > > {
0 commit comments