1
- use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
1
+ use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
2
2
use std:: fmt;
3
3
use std:: marker:: PhantomData ;
4
4
use std:: path:: { Path , PathBuf } ;
@@ -8,6 +8,7 @@ use std::str::{self, FromStr};
8
8
use anyhow:: { anyhow, bail, Context as _} ;
9
9
use cargo_platform:: Platform ;
10
10
use cargo_util:: paths;
11
+ use itertools:: Itertools ;
11
12
use lazycell:: LazyCell ;
12
13
use log:: { debug, trace} ;
13
14
use semver:: { self , VersionReq } ;
@@ -1737,12 +1738,24 @@ impl TomlManifest {
1737
1738
debug ! ( "manifest has no build targets" ) ;
1738
1739
}
1739
1740
1740
- if let Err ( e) = unique_build_targets ( & targets, package_root) {
1741
- warnings. push ( format ! (
1742
- "file found to be present in multiple \
1743
- build targets: {}",
1744
- e
1745
- ) ) ;
1741
+ if let Err ( conflict_targets) = unique_build_targets ( & targets, package_root) {
1742
+ conflict_targets
1743
+ . iter ( )
1744
+ . for_each ( |( target_path, conflicts) | {
1745
+ warnings. push ( format ! (
1746
+ "file `{}` found to be present in multiple \
1747
+ build targets:\n {}",
1748
+ target_path. display( ) . to_string( ) ,
1749
+ conflicts
1750
+ . iter( )
1751
+ . map( |t| format!(
1752
+ " * `{}` target `{}`" ,
1753
+ t. kind( ) . description( ) ,
1754
+ t. name( ) ,
1755
+ ) )
1756
+ . join( "\n " )
1757
+ ) ) ;
1758
+ } )
1746
1759
}
1747
1760
1748
1761
if let Some ( links) = & package. links {
@@ -2442,16 +2455,27 @@ fn default_readme_from_package_root(package_root: &Path) -> Option<String> {
2442
2455
2443
2456
/// Checks a list of build targets, and ensures the target names are unique within a vector.
2444
2457
/// If not, the name of the offending build target is returned.
2445
- fn unique_build_targets ( targets : & [ Target ] , package_root : & Path ) -> Result < ( ) , String > {
2446
- let mut seen = HashSet :: new ( ) ;
2458
+ fn unique_build_targets (
2459
+ targets : & [ Target ] ,
2460
+ package_root : & Path ,
2461
+ ) -> Result < ( ) , HashMap < PathBuf , Vec < Target > > > {
2462
+ let mut source_targets = HashMap :: < _ , Vec < _ > > :: new ( ) ;
2447
2463
for target in targets {
2448
2464
if let TargetSourcePath :: Path ( path) = target. src_path ( ) {
2449
2465
let full = package_root. join ( path) ;
2450
- if !seen. insert ( full. clone ( ) ) {
2451
- return Err ( full. display ( ) . to_string ( ) ) ;
2452
- }
2466
+ source_targets. entry ( full) . or_default ( ) . push ( target. clone ( ) ) ;
2453
2467
}
2454
2468
}
2469
+
2470
+ let conflict_targets = source_targets
2471
+ . into_iter ( )
2472
+ . filter ( |( _, targets) | targets. len ( ) > 1 )
2473
+ . collect :: < HashMap < _ , _ > > ( ) ;
2474
+
2475
+ if !conflict_targets. is_empty ( ) {
2476
+ return Err ( conflict_targets) ;
2477
+ }
2478
+
2455
2479
Ok ( ( ) )
2456
2480
}
2457
2481
0 commit comments