@@ -4,7 +4,6 @@ use std::ffi::OsStr;
4
4
use std:: fmt:: Write ;
5
5
use std:: path:: PathBuf ;
6
6
use std:: sync:: Arc ;
7
- use std:: cmp:: Ordering ;
8
7
9
8
use jobserver:: Client ;
10
9
@@ -42,7 +41,7 @@ use self::compilation_files::CompilationFiles;
42
41
/// example, it needs to know the target architecture (OS, chip arch etc.) and it needs to know
43
42
/// whether you want a debug or release build. There is enough information in this struct to figure
44
43
/// all that out.
45
- #[ derive( Clone , Copy , Eq , PartialEq , Hash , Debug ) ]
44
+ #[ derive( Clone , Copy , Eq , PartialEq , Hash , Debug , PartialOrd , Ord ) ]
46
45
pub struct Unit < ' a > {
47
46
/// Information about available targets, which files to include/exclude, etc. Basically stuff in
48
47
/// `Cargo.toml`.
@@ -72,18 +71,6 @@ impl<'a> Unit<'a> {
72
71
}
73
72
}
74
73
75
- impl < ' a > Ord for Unit < ' a > {
76
- fn cmp ( & self , other : & Unit ) -> Ordering {
77
- self . buildkey ( ) . cmp ( & other. buildkey ( ) )
78
- }
79
- }
80
-
81
- impl < ' a > PartialOrd for Unit < ' a > {
82
- fn partial_cmp ( & self , other : & Unit ) -> Option < Ordering > {
83
- Some ( self . cmp ( other) )
84
- }
85
- }
86
-
87
74
pub struct Context < ' a , ' cfg : ' a > {
88
75
pub bcx : & ' a BuildContext < ' a , ' cfg > ,
89
76
pub compilation : Compilation < ' cfg > ,
@@ -150,6 +137,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
150
137
self . prepare_units ( export_dir, units) ?;
151
138
self . prepare ( ) ?;
152
139
custom_build:: build_map ( & mut self , units) ?;
140
+ self . check_collistions ( ) ?;
153
141
154
142
for unit in units. iter ( ) {
155
143
// Build up a list of pending jobs, each of which represent
@@ -353,13 +341,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
353
341
self . files . as_mut ( ) . unwrap ( )
354
342
}
355
343
356
- /// Return the filenames that the given target for the given profile will
357
- /// generate as a list of 3-tuples (filename, link_dst, linkable)
358
- ///
359
- /// - filename: filename rustc compiles to. (Often has metadata suffix).
360
- /// - link_dst: Optional file to link/copy the result to (without metadata suffix)
361
- /// - linkable: Whether possible to link against file (eg it's a library)
362
- pub fn outputs ( & mut self , unit : & Unit < ' a > ) -> CargoResult < Arc < Vec < OutputFile > > > {
344
+ /// Return the filenames that the given unit will generate.
345
+ pub fn outputs ( & self , unit : & Unit < ' a > ) -> CargoResult < Arc < Vec < OutputFile > > > {
363
346
self . files . as_ref ( ) . unwrap ( ) . outputs ( unit, self . bcx )
364
347
}
365
348
@@ -468,6 +451,90 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
468
451
inputs. sort ( ) ;
469
452
Ok ( inputs)
470
453
}
454
+
455
+ fn check_collistions ( & self ) -> CargoResult < ( ) > {
456
+ let mut output_collisions = HashMap :: new ( ) ;
457
+ let describe_collision = |unit : & Unit , other_unit : & Unit , path : & PathBuf | -> String {
458
+ format ! (
459
+ "The {} target `{}` in package `{}` has the same output \
460
+ filename as the {} target `{}` in package `{}`.\n \
461
+ Colliding filename is: {}\n ",
462
+ unit. target. kind( ) . description( ) ,
463
+ unit. target. name( ) ,
464
+ unit. pkg. package_id( ) ,
465
+ other_unit. target. kind( ) . description( ) ,
466
+ other_unit. target. name( ) ,
467
+ other_unit. pkg. package_id( ) ,
468
+ path. display( )
469
+ )
470
+ } ;
471
+ let suggestion = "Consider changing their names to be unique or compiling them separately.\n \
472
+ This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313";
473
+ let report_collision = |unit : & Unit , other_unit : & Unit , path : & PathBuf | -> CargoResult < ( ) > {
474
+ if unit. target . name ( ) == other_unit. target . name ( ) {
475
+ self . bcx . config . shell ( ) . warn ( format ! (
476
+ "output filename collision.\n \
477
+ {}\
478
+ The targets should have unique names.\n \
479
+ {}",
480
+ describe_collision( unit, other_unit, path) ,
481
+ suggestion
482
+ ) )
483
+ } else {
484
+ self . bcx . config . shell ( ) . warn ( format ! (
485
+ "output filename collision.\n \
486
+ {}\
487
+ The output filenames should be unique.\n \
488
+ {}\n \
489
+ If this looks unexpected, it may be a bug in Cargo. Please file a bug report at\n \
490
+ https://github.com/rust-lang/cargo/issues/ with as much information as you\n \
491
+ can provide.\n \
492
+ {} running on `{}` target `{}`\n \
493
+ First unit: {:?}\n \
494
+ Second unit: {:?}",
495
+ describe_collision( unit, other_unit, path) ,
496
+ suggestion,
497
+ :: version( ) , self . bcx. host_triple( ) , self . bcx. target_triple( ) ,
498
+ unit, other_unit) )
499
+ }
500
+ } ;
501
+ let mut keys = self
502
+ . unit_dependencies
503
+ . keys ( )
504
+ . filter ( |unit| !unit. mode . is_run_custom_build ( ) )
505
+ . collect :: < Vec < _ > > ( ) ;
506
+ // Sort for consistent error messages.
507
+ keys. sort_unstable ( ) ;
508
+ for unit in keys {
509
+ for output in self . outputs ( unit) ?. iter ( ) {
510
+ if let Some ( other_unit) =
511
+ output_collisions. insert ( output. path . clone ( ) , unit)
512
+ {
513
+ report_collision ( unit, & other_unit, & output. path ) ?;
514
+ }
515
+ if let Some ( hardlink) = output. hardlink . as_ref ( ) {
516
+ if let Some ( other_unit) = output_collisions. insert ( hardlink. clone ( ) , unit)
517
+ {
518
+ report_collision ( unit, & other_unit, hardlink) ?;
519
+ }
520
+ }
521
+ if let Some ( ref export_path) = output. export_path {
522
+ if let Some ( other_unit) =
523
+ output_collisions. insert ( export_path. clone ( ) , unit)
524
+ {
525
+ self . bcx . config . shell ( ) . warn ( format ! ( "`--out-dir` filename collision.\n \
526
+ {}\
527
+ The exported filenames should be unique.\n \
528
+ {}",
529
+ describe_collision( unit, & other_unit, & export_path) ,
530
+ suggestion
531
+ ) ) ?;
532
+ }
533
+ }
534
+ }
535
+ }
536
+ Ok ( ( ) )
537
+ }
471
538
}
472
539
473
540
#[ derive( Default ) ]
0 commit comments