1- use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
1+ use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
22use std:: fmt;
33use std:: marker:: PhantomData ;
44use std:: path:: { Path , PathBuf } ;
@@ -8,6 +8,7 @@ use std::str::{self, FromStr};
88use anyhow:: { anyhow, bail, Context as _} ;
99use cargo_platform:: Platform ;
1010use cargo_util:: paths;
11+ use itertools:: Itertools ;
1112use lazycell:: LazyCell ;
1213use log:: { debug, trace} ;
1314use semver:: { self , VersionReq } ;
@@ -1737,12 +1738,24 @@ impl TomlManifest {
17371738 debug ! ( "manifest has no build targets" ) ;
17381739 }
17391740
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+ } )
17461759 }
17471760
17481761 if let Some ( links) = & package. links {
@@ -2442,16 +2455,27 @@ fn default_readme_from_package_root(package_root: &Path) -> Option<String> {
24422455
24432456/// Checks a list of build targets, and ensures the target names are unique within a vector.
24442457/// 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 ( ) ;
24472463 for target in targets {
24482464 if let TargetSourcePath :: Path ( path) = target. src_path ( ) {
24492465 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 ( ) ) ;
24532467 }
24542468 }
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+
24552479 Ok ( ( ) )
24562480}
24572481
0 commit comments