@@ -233,6 +233,17 @@ impl Renderer {
233233 ) )
234234 } ;
235235
236+ if context. workspace_members . contains_key ( & dep. id ) && maybe_actual. is_none ( ) {
237+ tracing:: warn!(
238+ "Skipping hub alias for workspace-member dep `{}-{}`: \
239+ no override_targets entry found. Add \
240+ `crate.annotation(override_target_lib = \" ...\" )` in MODULE.bazel \
241+ to emit a hub alias.",
242+ krate. name,
243+ krate. version,
244+ ) ;
245+ }
246+
236247 if let Some ( actual) = maybe_actual {
237248 // Avoid adding the <crate_name>-<version> alias if there are
238249 // more than 1 dependency referencing the same crate at the
@@ -286,6 +297,16 @@ impl Renderer {
286297 }
287298
288299 for ( alias, target) in & krate. extra_aliased_targets {
300+ if context. workspace_members . contains_key ( & dep. id ) {
301+ tracing:: warn!(
302+ "Skipping extra_aliased_targets alias `{alias}` for \
303+ workspace-member dep `{}-{}`: spoke repos are not \
304+ created for workspace members.",
305+ krate. name,
306+ krate. version,
307+ ) ;
308+ continue ;
309+ }
289310 dependencies. push ( Alias {
290311 rule : alias_rule. rule ( ) ,
291312 name : alias. clone ( ) ,
@@ -2044,12 +2065,10 @@ mod test {
20442065 assert ! ( found) ;
20452066 }
20462067
2047- /// Tests a situation where we have identical aliases to the crate's name on
2048- /// the package's deps, and the dep is itself a workspace member. Because
2049- /// workspace-member deps have no spoke repo and no override_targets["lib"]
2050- /// is set, no hub alias should be emitted at all.
2068+ /// Tests that when a workspace-member dep is aliased under its own crate name
2069+ /// and has no `override_targets` set, no hub alias is emitted.
20512070 #[ test]
2052- fn crate_with_ambiguous_rename ( ) {
2071+ fn workspace_member_dep_with_alias_same_as_crate_name_and_no_override ( ) {
20532072 let mut context = Context :: default ( ) ;
20542073 let crate_id = CrateId :: new ( "mock_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
20552074 context
@@ -2097,11 +2116,11 @@ mod test {
20972116 let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
20982117
20992118 println ! ( "{build_file_content}" ) ;
2100- // mock_crate is a workspace member dep with no override_targets["lib"] ,
2119+ // mock_crate is a workspace member dep with no override_targets set ,
21012120 // so no hub alias should be emitted to avoid dangling spoke-repo refs.
21022121 assert ! (
21032122 !build_file_content. contains( "alias(" ) ,
2104- "no alias should be emitted for workspace member dep with ambiguous rename and no override:\n {build_file_content}"
2123+ "no alias should be emitted for workspace member dep with no override:\n {build_file_content}"
21052124 ) ;
21062125 }
21072126
@@ -2519,4 +2538,170 @@ mod test {
25192538 "no alias should be emitted for workspace member dep without override:\n {build_file_content}"
25202539 ) ;
25212540 }
2541+
2542+ /// When a workspace-member proc-macro dep has `override_targets["proc-macro"]` set,
2543+ /// the hub alias must use that label rather than a non-existent spoke repo.
2544+ /// This exercises the `Rule::ProcMacro` arm of the `find_map` that replaced
2545+ /// the `"lib"` hardcode.
2546+ #[ test]
2547+ fn hub_alias_for_workspace_member_proc_macro_dep_uses_override_target ( ) {
2548+ let mut context = Context :: default ( ) ;
2549+
2550+ let consumer_id = CrateId :: new ( "consumer" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2551+ context
2552+ . workspace_members
2553+ . insert ( consumer_id. clone ( ) , "consumer" . into ( ) ) ;
2554+
2555+ let dep_id = CrateId :: new ( "dep_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2556+ context
2557+ . workspace_members
2558+ . insert ( dep_id. clone ( ) , "dep_crate" . into ( ) ) ;
2559+ context. crates . insert (
2560+ dep_id. clone ( ) ,
2561+ CrateContext {
2562+ name : dep_id. name . clone ( ) ,
2563+ version : dep_id. version . clone ( ) ,
2564+ package_url : None ,
2565+ targets : BTreeSet :: from ( [ Rule :: ProcMacro ( TargetAttributes {
2566+ crate_name : "dep_crate" . to_owned ( ) ,
2567+ crate_root : Some ( "src/lib.rs" . to_owned ( ) ) ,
2568+ ..TargetAttributes :: default ( )
2569+ } ) ] ) ,
2570+ library_target_name : Some ( "dep_crate" . to_owned ( ) ) ,
2571+ common_attrs : CommonAttributes :: default ( ) ,
2572+ build_script_attrs : None ,
2573+ repository : None ,
2574+ license : None ,
2575+ license_ids : BTreeSet :: default ( ) ,
2576+ license_file : None ,
2577+ additive_build_file_content : None ,
2578+ disable_pipelining : false ,
2579+ extra_aliased_targets : BTreeMap :: default ( ) ,
2580+ alias_rule : None ,
2581+ override_targets : BTreeMap :: from ( [ (
2582+ "proc-macro" . to_owned ( ) ,
2583+ Label :: from_str ( "//tools/dep_crate:dep_crate" ) . unwrap ( ) ,
2584+ ) ] ) ,
2585+ } ,
2586+ ) ;
2587+ context. crates . insert (
2588+ consumer_id. clone ( ) ,
2589+ CrateContext {
2590+ name : consumer_id. name . clone ( ) ,
2591+ version : consumer_id. version . clone ( ) ,
2592+ package_url : None ,
2593+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2594+ library_target_name : Some ( "consumer" . to_owned ( ) ) ,
2595+ common_attrs : CommonAttributes {
2596+ deps : Select :: from_value ( BTreeSet :: from ( [ CrateDependency {
2597+ id : dep_id. clone ( ) ,
2598+ target : "dep_crate" . to_owned ( ) ,
2599+ alias : None ,
2600+ local_path : None ,
2601+ } ] ) ) ,
2602+ ..Default :: default ( )
2603+ } ,
2604+ build_script_attrs : None ,
2605+ repository : None ,
2606+ license : None ,
2607+ license_ids : BTreeSet :: default ( ) ,
2608+ license_file : None ,
2609+ additive_build_file_content : None ,
2610+ disable_pipelining : false ,
2611+ extra_aliased_targets : BTreeMap :: default ( ) ,
2612+ alias_rule : None ,
2613+ override_targets : BTreeMap :: default ( ) ,
2614+ } ,
2615+ ) ;
2616+
2617+ let renderer = Renderer :: new ( mock_render_config ( None ) , mock_supported_platform_triples ( ) ) ;
2618+ let output = renderer. render ( & context, None ) . unwrap ( ) ;
2619+ let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
2620+
2621+ assert ! (
2622+ build_file_content. contains( "//tools/dep_crate:dep_crate" ) ,
2623+ "expected override label in hub alias:\n {build_file_content}"
2624+ ) ;
2625+ assert ! (
2626+ !build_file_content. contains( "@test_rendering__dep_crate" ) ,
2627+ "must not emit spoke-repo alias for workspace member proc-macro:\n {build_file_content}"
2628+ ) ;
2629+ }
2630+
2631+ /// When a workspace-member dep has `extra_aliased_targets` set, those aliases
2632+ /// must be suppressed — spoke repos are not created for workspace members so
2633+ /// the generated labels would be dangling.
2634+ #[ test]
2635+ fn extra_aliased_targets_omitted_for_workspace_member_dep ( ) {
2636+ let mut context = Context :: default ( ) ;
2637+
2638+ let consumer_id = CrateId :: new ( "consumer" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2639+ context
2640+ . workspace_members
2641+ . insert ( consumer_id. clone ( ) , "consumer" . into ( ) ) ;
2642+
2643+ let dep_id = CrateId :: new ( "dep_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2644+ context
2645+ . workspace_members
2646+ . insert ( dep_id. clone ( ) , "dep_crate" . into ( ) ) ;
2647+ context. crates . insert (
2648+ dep_id. clone ( ) ,
2649+ CrateContext {
2650+ name : dep_id. name . clone ( ) ,
2651+ version : dep_id. version . clone ( ) ,
2652+ package_url : None ,
2653+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2654+ library_target_name : Some ( "dep_crate" . to_owned ( ) ) ,
2655+ common_attrs : CommonAttributes :: default ( ) ,
2656+ build_script_attrs : None ,
2657+ repository : None ,
2658+ license : None ,
2659+ license_ids : BTreeSet :: default ( ) ,
2660+ license_file : None ,
2661+ additive_build_file_content : None ,
2662+ disable_pipelining : false ,
2663+ extra_aliased_targets : BTreeMap :: from ( [ ( "foo" . to_owned ( ) , "foo_impl" . to_owned ( ) ) ] ) ,
2664+ alias_rule : None ,
2665+ override_targets : BTreeMap :: default ( ) ,
2666+ } ,
2667+ ) ;
2668+ context. crates . insert (
2669+ consumer_id. clone ( ) ,
2670+ CrateContext {
2671+ name : consumer_id. name . clone ( ) ,
2672+ version : consumer_id. version . clone ( ) ,
2673+ package_url : None ,
2674+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2675+ library_target_name : Some ( "consumer" . to_owned ( ) ) ,
2676+ common_attrs : CommonAttributes {
2677+ deps : Select :: from_value ( BTreeSet :: from ( [ CrateDependency {
2678+ id : dep_id. clone ( ) ,
2679+ target : "dep_crate" . to_owned ( ) ,
2680+ alias : None ,
2681+ local_path : None ,
2682+ } ] ) ) ,
2683+ ..Default :: default ( )
2684+ } ,
2685+ build_script_attrs : None ,
2686+ repository : None ,
2687+ license : None ,
2688+ license_ids : BTreeSet :: default ( ) ,
2689+ license_file : None ,
2690+ additive_build_file_content : None ,
2691+ disable_pipelining : false ,
2692+ extra_aliased_targets : BTreeMap :: default ( ) ,
2693+ alias_rule : None ,
2694+ override_targets : BTreeMap :: default ( ) ,
2695+ } ,
2696+ ) ;
2697+
2698+ let renderer = Renderer :: new ( mock_render_config ( None ) , mock_supported_platform_triples ( ) ) ;
2699+ let output = renderer. render ( & context, None ) . unwrap ( ) ;
2700+ let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
2701+
2702+ assert ! (
2703+ !build_file_content. contains( "alias(" ) ,
2704+ "extra_aliased_targets must not emit aliases for workspace member dep:\n {build_file_content}"
2705+ ) ;
2706+ }
25222707}
0 commit comments