Create a bp2build converter for ndk_prebuilt_*_stl

This module type will be converted to a cc_prebuilt_* bazel target. It
will provide
1. a prebuilt (.a/.so) file
2. headers (as -isystem)

Test: added a bp2build unit test
Bug: 298088835
Change-Id: Ib58cc7f6fde8f4ca34516f6f18a4c048a02a049a
diff --git a/cc/cc.go b/cc/cc.go
index 3b92696..8d79df2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -879,16 +879,16 @@
 	installer    installer
 	bazelHandler BazelHandler
 
-	features []feature
-	stl      *stl
-	sanitize *sanitize
-	coverage *coverage
-	fuzzer   *fuzzer
-	sabi     *sabi
-	vndkdep  *vndkdep
-	lto      *lto
-	afdo     *afdo
-	pgo      *pgo
+	features  []feature
+	stl       *stl
+	sanitize  *sanitize
+	coverage  *coverage
+	fuzzer    *fuzzer
+	sabi      *sabi
+	vndkdep   *vndkdep
+	lto       *lto
+	afdo      *afdo
+	pgo       *pgo
 	orderfile *orderfile
 
 	library libraryInterface
@@ -1104,6 +1104,16 @@
 	return false
 }
 
+func (c *Module) IsNdkPrebuiltStl() bool {
+	if c.linker == nil {
+		return false
+	}
+	if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok {
+		return true
+	}
+	return false
+}
+
 func (c *Module) RlibStd() bool {
 	panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
 }
@@ -4158,6 +4168,7 @@
 	headerLibrary
 	testBin // testBinary already declared
 	ndkLibrary
+	ndkPrebuiltStl
 )
 
 func (c *Module) typ() moduleType {
@@ -4196,6 +4207,8 @@
 		return sharedLibrary
 	} else if c.isNDKStubLibrary() {
 		return ndkLibrary
+	} else if c.IsNdkPrebuiltStl() {
+		return ndkPrebuiltStl
 	}
 	return unknownType
 }
@@ -4240,6 +4253,8 @@
 		} else {
 			sharedOrStaticLibraryBp2Build(ctx, c, false)
 		}
+	case ndkPrebuiltStl:
+		ndkPrebuiltStlBp2build(ctx, c)
 	default:
 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
 	}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 842bdf6..c2382b3 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -15,9 +15,11 @@
 package cc
 
 import (
+	"path/filepath"
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
 )
 
 func init() {
@@ -64,6 +66,7 @@
 	module.Properties.Sdk_version = StringPtr("minimum")
 	module.Properties.AlwaysSdk = true
 	module.stl.Properties.Stl = StringPtr("none")
+	module.bazelable = true
 	return module.Init()
 }
 
@@ -84,6 +87,7 @@
 	module.Properties.AlwaysSdk = true
 	module.Properties.Sdk_version = StringPtr("current")
 	module.stl.Properties.Stl = StringPtr("none")
+	module.bazelable = true
 	return module.Init()
 }
 
@@ -131,3 +135,81 @@
 
 	return lib
 }
+
+var (
+	archToAbiDirMap = map[string]string{
+		"android_arm":     "armeabi-v7a",
+		"android_arm64":   "arm64-v8a",
+		"android_riscv64": "riscv64",
+		"android_x86":     "x86",
+		"android_x86_64":  "x86_64",
+	}
+)
+
+// stlSrcBp2build returns a bazel label for the checked-in .so/.a file
+// It contains a select statement for each ABI
+func stlSrcBp2build(ctx android.TopDownMutatorContext, c *Module) bazel.LabelAttribute {
+	libName := strings.TrimPrefix(c.Name(), "ndk_")
+	libExt := ".so" // TODO - b/201079053: Support windows
+	if ctx.ModuleType() == "ndk_prebuilt_static_stl" {
+		libExt = ".a"
+	}
+	src := bazel.LabelAttribute{}
+	for arch, abiDir := range archToAbiDirMap {
+		srcPath := filepath.Join(libDir, abiDir, libName+libExt)
+		src.SetSelectValue(
+			bazel.OsArchConfigurationAxis,
+			arch,
+			android.BazelLabelForModuleSrcSingle(ctx, srcPath),
+		)
+	}
+	return src
+}
+
+// stlIncludesBp2build returns the includes exported by the STL
+func stlIncludesBp2build(c *Module) bazel.StringListAttribute {
+	linker, _ := c.linker.(*ndkPrebuiltStlLinker)
+	includeDirs := append(
+		[]string{},
+		linker.libraryDecorator.flagExporter.Properties.Export_include_dirs...,
+	)
+	includeDirs = append(
+		includeDirs,
+		linker.libraryDecorator.flagExporter.Properties.Export_system_include_dirs...,
+	)
+	return bazel.MakeStringListAttribute(android.FirstUniqueStrings(includeDirs))
+}
+
+func ndkPrebuiltStlBp2build(ctx android.TopDownMutatorContext, c *Module) {
+	if ctx.ModuleType() == "ndk_prebuilt_static_stl" {
+		ndkPrebuiltStaticStlBp2build(ctx, c)
+	} else {
+		ndkPrebuiltSharedStlBp2build(ctx, c)
+	}
+}
+
+func ndkPrebuiltStaticStlBp2build(ctx android.TopDownMutatorContext, c *Module) {
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_prebuilt_library_static",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl",
+	}
+	attrs := &bazelPrebuiltLibraryStaticAttributes{
+		Static_library:         stlSrcBp2build(ctx, c),
+		Export_system_includes: stlIncludesBp2build(c), // The exports are always as system
+	}
+	// TODO: min_sdk_version
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs)
+}
+
+func ndkPrebuiltSharedStlBp2build(ctx android.TopDownMutatorContext, c *Module) {
+	props := bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_prebuilt_library_shared",
+		Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl",
+	}
+	attrs := &bazelPrebuiltLibrarySharedAttributes{
+		Shared_library:         stlSrcBp2build(ctx, c),
+		Export_system_includes: stlIncludesBp2build(c), // The exports are always as system
+	}
+	// TODO: min_sdk_version
+	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs)
+}