@@ -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 ( ) ,
@@ -2051,12 +2072,10 @@ mod test {
20512072 assert ! ( found) ;
20522073 }
20532074
2054- /// Tests a situation where we have identical aliases to the crate's name on
2055- /// the package's deps, and the dep is itself a workspace member. Because
2056- /// workspace-member deps have no spoke repo and no override_targets["lib"]
2057- /// is set, no hub alias should be emitted at all.
2075+ /// Tests that when a workspace-member dep is aliased under its own crate name
2076+ /// and has no `override_targets` set, no hub alias is emitted.
20582077 #[ test]
2059- fn crate_with_ambiguous_rename ( ) {
2078+ fn workspace_member_dep_with_alias_same_as_crate_name_and_no_override ( ) {
20602079 let mut context = Context :: default ( ) ;
20612080 let crate_id = CrateId :: new ( "mock_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
20622081 context
@@ -2104,11 +2123,11 @@ mod test {
21042123 let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
21052124
21062125 println ! ( "{build_file_content}" ) ;
2107- // mock_crate is a workspace member dep with no override_targets["lib"] ,
2126+ // mock_crate is a workspace member dep with no override_targets set ,
21082127 // so no hub alias should be emitted to avoid dangling spoke-repo refs.
21092128 assert ! (
21102129 !build_file_content. contains( "alias(" ) ,
2111- "no alias should be emitted for workspace member dep with ambiguous rename and no override:\n {build_file_content}"
2130+ "no alias should be emitted for workspace member dep with no override:\n {build_file_content}"
21122131 ) ;
21132132 }
21142133
@@ -2593,4 +2612,170 @@ mod test {
25932612 "no alias should be emitted for workspace member dep without override:\n {build_file_content}"
25942613 ) ;
25952614 }
2615+
2616+ /// When a workspace-member proc-macro dep has `override_targets["proc-macro"]` set,
2617+ /// the hub alias must use that label rather than a non-existent spoke repo.
2618+ /// This exercises the `Rule::ProcMacro` arm of the `find_map` that replaced
2619+ /// the `"lib"` hardcode.
2620+ #[ test]
2621+ fn hub_alias_for_workspace_member_proc_macro_dep_uses_override_target ( ) {
2622+ let mut context = Context :: default ( ) ;
2623+
2624+ let consumer_id = CrateId :: new ( "consumer" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2625+ context
2626+ . workspace_members
2627+ . insert ( consumer_id. clone ( ) , "consumer" . into ( ) ) ;
2628+
2629+ let dep_id = CrateId :: new ( "dep_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2630+ context
2631+ . workspace_members
2632+ . insert ( dep_id. clone ( ) , "dep_crate" . into ( ) ) ;
2633+ context. crates . insert (
2634+ dep_id. clone ( ) ,
2635+ CrateContext {
2636+ name : dep_id. name . clone ( ) ,
2637+ version : dep_id. version . clone ( ) ,
2638+ package_url : None ,
2639+ targets : BTreeSet :: from ( [ Rule :: ProcMacro ( TargetAttributes {
2640+ crate_name : "dep_crate" . to_owned ( ) ,
2641+ crate_root : Some ( "src/lib.rs" . to_owned ( ) ) ,
2642+ ..TargetAttributes :: default ( )
2643+ } ) ] ) ,
2644+ library_target_name : Some ( "dep_crate" . to_owned ( ) ) ,
2645+ common_attrs : CommonAttributes :: default ( ) ,
2646+ build_script_attrs : None ,
2647+ repository : None ,
2648+ license : None ,
2649+ license_ids : BTreeSet :: default ( ) ,
2650+ license_file : None ,
2651+ additive_build_file_content : None ,
2652+ disable_pipelining : false ,
2653+ extra_aliased_targets : BTreeMap :: default ( ) ,
2654+ alias_rule : None ,
2655+ override_targets : BTreeMap :: from ( [ (
2656+ "proc-macro" . to_owned ( ) ,
2657+ Label :: from_str ( "//tools/dep_crate:dep_crate" ) . unwrap ( ) ,
2658+ ) ] ) ,
2659+ } ,
2660+ ) ;
2661+ context. crates . insert (
2662+ consumer_id. clone ( ) ,
2663+ CrateContext {
2664+ name : consumer_id. name . clone ( ) ,
2665+ version : consumer_id. version . clone ( ) ,
2666+ package_url : None ,
2667+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2668+ library_target_name : Some ( "consumer" . to_owned ( ) ) ,
2669+ common_attrs : CommonAttributes {
2670+ deps : Select :: from_value ( BTreeSet :: from ( [ CrateDependency {
2671+ id : dep_id. clone ( ) ,
2672+ target : "dep_crate" . to_owned ( ) ,
2673+ alias : None ,
2674+ local_path : None ,
2675+ } ] ) ) ,
2676+ ..Default :: default ( )
2677+ } ,
2678+ build_script_attrs : None ,
2679+ repository : None ,
2680+ license : None ,
2681+ license_ids : BTreeSet :: default ( ) ,
2682+ license_file : None ,
2683+ additive_build_file_content : None ,
2684+ disable_pipelining : false ,
2685+ extra_aliased_targets : BTreeMap :: default ( ) ,
2686+ alias_rule : None ,
2687+ override_targets : BTreeMap :: default ( ) ,
2688+ } ,
2689+ ) ;
2690+
2691+ let renderer = Renderer :: new ( mock_render_config ( None ) , mock_supported_platform_triples ( ) ) ;
2692+ let output = renderer. render ( & context, None ) . unwrap ( ) ;
2693+ let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
2694+
2695+ assert ! (
2696+ build_file_content. contains( "//tools/dep_crate:dep_crate" ) ,
2697+ "expected override label in hub alias:\n {build_file_content}"
2698+ ) ;
2699+ assert ! (
2700+ !build_file_content. contains( "@test_rendering__dep_crate" ) ,
2701+ "must not emit spoke-repo alias for workspace member proc-macro:\n {build_file_content}"
2702+ ) ;
2703+ }
2704+
2705+ /// When a workspace-member dep has `extra_aliased_targets` set, those aliases
2706+ /// must be suppressed — spoke repos are not created for workspace members so
2707+ /// the generated labels would be dangling.
2708+ #[ test]
2709+ fn extra_aliased_targets_omitted_for_workspace_member_dep ( ) {
2710+ let mut context = Context :: default ( ) ;
2711+
2712+ let consumer_id = CrateId :: new ( "consumer" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2713+ context
2714+ . workspace_members
2715+ . insert ( consumer_id. clone ( ) , "consumer" . into ( ) ) ;
2716+
2717+ let dep_id = CrateId :: new ( "dep_crate" . to_owned ( ) , VERSION_ZERO_ONE_ZERO ) ;
2718+ context
2719+ . workspace_members
2720+ . insert ( dep_id. clone ( ) , "dep_crate" . into ( ) ) ;
2721+ context. crates . insert (
2722+ dep_id. clone ( ) ,
2723+ CrateContext {
2724+ name : dep_id. name . clone ( ) ,
2725+ version : dep_id. version . clone ( ) ,
2726+ package_url : None ,
2727+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2728+ library_target_name : Some ( "dep_crate" . to_owned ( ) ) ,
2729+ common_attrs : CommonAttributes :: default ( ) ,
2730+ build_script_attrs : None ,
2731+ repository : None ,
2732+ license : None ,
2733+ license_ids : BTreeSet :: default ( ) ,
2734+ license_file : None ,
2735+ additive_build_file_content : None ,
2736+ disable_pipelining : false ,
2737+ extra_aliased_targets : BTreeMap :: from ( [ ( "foo" . to_owned ( ) , "foo_impl" . to_owned ( ) ) ] ) ,
2738+ alias_rule : None ,
2739+ override_targets : BTreeMap :: default ( ) ,
2740+ } ,
2741+ ) ;
2742+ context. crates . insert (
2743+ consumer_id. clone ( ) ,
2744+ CrateContext {
2745+ name : consumer_id. name . clone ( ) ,
2746+ version : consumer_id. version . clone ( ) ,
2747+ package_url : None ,
2748+ targets : BTreeSet :: from ( [ Rule :: Library ( mock_target_attributes ( ) ) ] ) ,
2749+ library_target_name : Some ( "consumer" . to_owned ( ) ) ,
2750+ common_attrs : CommonAttributes {
2751+ deps : Select :: from_value ( BTreeSet :: from ( [ CrateDependency {
2752+ id : dep_id. clone ( ) ,
2753+ target : "dep_crate" . to_owned ( ) ,
2754+ alias : None ,
2755+ local_path : None ,
2756+ } ] ) ) ,
2757+ ..Default :: default ( )
2758+ } ,
2759+ build_script_attrs : None ,
2760+ repository : None ,
2761+ license : None ,
2762+ license_ids : BTreeSet :: default ( ) ,
2763+ license_file : None ,
2764+ additive_build_file_content : None ,
2765+ disable_pipelining : false ,
2766+ extra_aliased_targets : BTreeMap :: default ( ) ,
2767+ alias_rule : None ,
2768+ override_targets : BTreeMap :: default ( ) ,
2769+ } ,
2770+ ) ;
2771+
2772+ let renderer = Renderer :: new ( mock_render_config ( None ) , mock_supported_platform_triples ( ) ) ;
2773+ let output = renderer. render ( & context, None ) . unwrap ( ) ;
2774+ let build_file_content = output. get ( & PathBuf :: from ( "BUILD.bazel" ) ) . unwrap ( ) ;
2775+
2776+ assert ! (
2777+ !build_file_content. contains( "alias(" ) ,
2778+ "extra_aliased_targets must not emit aliases for workspace member dep:\n {build_file_content}"
2779+ ) ;
2780+ }
25962781}
0 commit comments