Implement bp2build converter for rust_proc_macro

Test: WIP
Bug: 297356482
Change-Id: I17d1a0a95d4a67ccbc9b2d74e49bcacd6ff4d26b
diff --git a/rust/library.go b/rust/library.go
index da386b3..da2209a 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -800,49 +800,29 @@
 }
 
 type rustLibraryAttributes struct {
-	Srcs           bazel.LabelListAttribute
-	Compile_data   bazel.LabelListAttribute
-	Crate_name     bazel.StringAttribute
-	Edition        bazel.StringAttribute
-	Crate_features bazel.StringListAttribute
-	Deps           bazel.LabelListAttribute
-	Rustc_flags    bazel.StringListAttribute
+	Srcs            bazel.LabelListAttribute
+	Compile_data    bazel.LabelListAttribute
+	Crate_name      bazel.StringAttribute
+	Edition         bazel.StringAttribute
+	Crate_features  bazel.StringListAttribute
+	Deps            bazel.LabelListAttribute
+	Rustc_flags     bazel.StringListAttribute
+	Proc_macro_deps bazel.LabelListAttribute
 }
 
 func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
 	lib := m.compiler.(*libraryDecorator)
-
-	var srcs bazel.LabelList
-	var compileData bazel.LabelList
-	var rustcFLags []string
-
-	// This is a workaround by assuming the conventions that rust crate repos are structured
-	//  while waiting for the sandboxing work to complete.
-	// TODO: When crate_root prop is set which enforces inputs sandboxing,
-	// always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes
-	// instead of using globs.
-	if lib.baseCompiler.Properties.Srcs[0] == "src/lib.rs" {
-		srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
-		compileData = android.BazelLabelForModuleSrc(
-			ctx,
-			[]string{
-				"src/**/*.proto",
-				"examples/**/*.rs",
-				"**/*.md",
-			},
-		)
-	} else {
-		srcs = android.BazelLabelForModuleSrc(ctx, lib.baseCompiler.Properties.Srcs)
-	}
-
-	for _, cfg := range lib.baseCompiler.Properties.Cfgs {
-		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
-	}
-
+	srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
 	deps := android.BazelLabelForModuleDeps(ctx, append(
 		lib.baseCompiler.Properties.Rustlibs,
 		lib.baseCompiler.Properties.Rlibs...,
 	))
+	procMacroDeps := android.BazelLabelForModuleDeps(ctx, lib.baseCompiler.Properties.Proc_macros)
+
+	var rustcFLags []string
+	for _, cfg := range lib.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
 
 	attrs := &rustLibraryAttributes{
 		Srcs: bazel.MakeLabelListAttribute(
@@ -863,6 +843,9 @@
 		Deps: bazel.MakeLabelListAttribute(
 			deps,
 		),
+		Proc_macro_deps: bazel.MakeLabelListAttribute(
+			procMacroDeps,
+		),
 		Rustc_flags: bazel.StringListAttribute{
 			Value: append(
 				rustcFLags,
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 832b62c..26227d0 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -16,6 +16,8 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel"
+	"fmt"
 )
 
 func init() {
@@ -47,6 +49,8 @@
 func NewProcMacro(hod android.HostOrDeviceSupported) (*Module, *procMacroDecorator) {
 	module := newModule(hod, android.MultilibFirst)
 
+	android.InitBazelModule(module)
+
 	procMacro := &procMacroDecorator{
 		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
 		flagExporter: NewFlagExporter(),
@@ -99,3 +103,65 @@
 	// Proc_macros are never installed
 	return false
 }
+
+type procMacroAttributes struct {
+	Srcs           bazel.LabelListAttribute
+	Compile_data   bazel.LabelListAttribute
+	Crate_name     bazel.StringAttribute
+	Edition        bazel.StringAttribute
+	Crate_features bazel.StringListAttribute
+	Deps           bazel.LabelListAttribute
+	Rustc_flags    bazel.StringListAttribute
+}
+
+func procMacroBp2build(ctx android.TopDownMutatorContext, m *Module) {
+	procMacro := m.compiler.(*procMacroDecorator)
+	srcs, compileData := srcsAndCompileDataAttrs(ctx, *procMacro.baseCompiler)
+	deps := android.BazelLabelForModuleDeps(ctx, append(
+		procMacro.baseCompiler.Properties.Rustlibs,
+		procMacro.baseCompiler.Properties.Rlibs...,
+	))
+
+	var rustcFLags []string
+	for _, cfg := range procMacro.baseCompiler.Properties.Cfgs {
+		rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
+	}
+
+	attrs := &procMacroAttributes{
+		Srcs: bazel.MakeLabelListAttribute(
+			srcs,
+		),
+		Compile_data: bazel.MakeLabelListAttribute(
+			compileData,
+		),
+		Crate_name: bazel.StringAttribute{
+			Value: &procMacro.baseCompiler.Properties.Crate_name,
+		},
+		Edition: bazel.StringAttribute{
+			Value: procMacro.baseCompiler.Properties.Edition,
+		},
+		Crate_features: bazel.StringListAttribute{
+			Value: procMacro.baseCompiler.Properties.Features,
+		},
+		Deps: bazel.MakeLabelListAttribute(
+			deps,
+		),
+		Rustc_flags: bazel.StringListAttribute{
+			Value: append(
+				rustcFLags,
+				procMacro.baseCompiler.Properties.Flags...,
+			),
+		},
+	}
+	// m.IsConvertedByBp2build()
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "rust_proc_macro",
+			Bzl_load_location: "@rules_rust//rust:defs.bzl",
+		},
+		android.CommonAttributes{
+			Name: m.Name(),
+		},
+		attrs,
+	)
+}
diff --git a/rust/rust.go b/rust/rust.go
index edd04ac..545d78f 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -15,6 +15,7 @@
 package rust
 
 import (
+	"android/soong/bazel"
 	"android/soong/bloaty"
 	"android/soong/ui/metrics/bp2build_metrics_proto"
 	"fmt"
@@ -1847,11 +1848,41 @@
 func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
 	if ctx.ModuleType() == "rust_library_host" || ctx.ModuleType() == "rust_library" {
 		libraryBp2build(ctx, m)
+	} else if ctx.ModuleType() == "rust_proc_macro" {
+		procMacroBp2build(ctx, m)
 	} else {
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 	}
 }
 
+// This is a workaround by assuming the conventions that rust crate repos are structured
+//
+//	while waiting for the sandboxing work to complete.
+//
+// TODO(b/297344471): When crate_root prop is set which enforces inputs sandboxing,
+// always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes
+// instead of using globs.
+func srcsAndCompileDataAttrs(ctx android.TopDownMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) {
+	var srcs bazel.LabelList
+	var compileData bazel.LabelList
+
+	if c.Properties.Srcs[0] == "src/lib.rs" {
+		srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
+		compileData = android.BazelLabelForModuleSrc(
+			ctx,
+			[]string{
+				"src/**/*.proto",
+				"examples/**/*.rs",
+				"**/*.md",
+			},
+		)
+	} else {
+		srcs = android.BazelLabelForModuleSrc(ctx, c.Properties.Srcs)
+	}
+
+	return srcs, compileData
+}
+
 var Bool = proptools.Bool
 var BoolDefault = proptools.BoolDefault
 var String = proptools.String