Select stub/impl per apex variant

Create a select statement for every api_domain a library could be
included in. The stub/impl
selection heuristics per apex domain are
1. If dep has stubs and the api domain appears in dep's apex_available, use
   impl
2. If dep has stubs and the api domain does not appear in dep's
   apex_available, use stubs

(Category 3: If dep does not have stubs and the apex does not appear in
dep's apex_available, then a separate apex_available validation in Bazel
will emit an error).

Platform variants have been special-cased for now to use equality of
apex_available for stub/impl selection

Test: go test ./bp2build
Bug: 272378496

Change-Id: Ibd29efd763c8863c7e6d2a9af0da30bbde07175d
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 47dff8a..2ee9c99 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -609,7 +609,8 @@
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
 				"implementation_dynamic_deps": `select({
-        "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+        "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"],
+        "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
         "//conditions:default": [":a"],
     })`,
 				"tags": `["apex_available=apex_b"]`,
@@ -618,6 +619,64 @@
 	})
 }
 
+// Tests that library in apexfoo links against stubs of platform_lib and otherapex_lib
+func TestCcLibrarySharedStubs_UseStubsFromMultipleApiDomains(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library_shared stubs",
+		ModuleTypeUnderTest:        "cc_library_shared",
+		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+	name: "libplatform_stable",
+	stubs: { symbol_file: "libplatform_stable.map.txt", versions: ["28", "29", "current"] },
+	apex_available: ["//apex_available:platform"],
+	bazel_module: { bp2build_available: false },
+	include_build_directory: false,
+}
+cc_library_shared {
+	name: "libapexfoo_stable",
+	stubs: { symbol_file: "libapexfoo_stable.map.txt", versions: ["28", "29", "current"] },
+	apex_available: ["apexfoo"],
+	bazel_module: { bp2build_available: false },
+	include_build_directory: false,
+}
+cc_library_shared {
+	name: "libutils",
+	shared_libs: ["libplatform_stable", "libapexfoo_stable",],
+	apex_available: ["//apex_available:platform", "apexfoo", "apexbar"],
+	include_build_directory: false,
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "libutils", AttrNameToString{
+				"implementation_dynamic_deps": `select({
+        "//build/bazel/rules/apex:apexbar": [
+            "@api_surfaces//module-libapi/current:libplatform_stable",
+            "@api_surfaces//module-libapi/current:libapexfoo_stable",
+        ],
+        "//build/bazel/rules/apex:apexfoo": [
+            "@api_surfaces//module-libapi/current:libplatform_stable",
+            ":libapexfoo_stable",
+        ],
+        "//build/bazel/rules/apex:system": [
+            "@api_surfaces//module-libapi/current:libplatform_stable",
+            "@api_surfaces//module-libapi/current:libapexfoo_stable",
+        ],
+        "//conditions:default": [
+            ":libplatform_stable",
+            ":libapexfoo_stable",
+        ],
+    })`,
+				"tags": `[
+        "apex_available=//apex_available:platform",
+        "apex_available=apexfoo",
+        "apex_available=apexbar",
+    ]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibrarySharedStubs_IgnorePlatformAvailable(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
 		Description:                "cc_library_shared stubs",
@@ -641,7 +700,8 @@
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
 				"implementation_dynamic_deps": `select({
-        "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+        "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"],
+        "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
         "//conditions:default": [":a"],
     })`,
 				"tags": `[
@@ -653,6 +713,34 @@
 	})
 }
 
+func TestCcLibraryDoesNotDropStubDepIfNoVariationAcrossAxis(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Description:                "cc_library depeends on impl for all configurations",
+		ModuleTypeUnderTest:        "cc_library_shared",
+		ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+		Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+	name: "a",
+	stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+	bazel_module: { bp2build_available: false },
+	apex_available: ["//apex_available:platform"],
+}
+cc_library_shared {
+	name: "b",
+	shared_libs: [":a"],
+	include_build_directory: false,
+	apex_available: ["//apex_available:platform"],
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+				"implementation_dynamic_deps": `[":a"]`,
+				"tags":                        `["apex_available=//apex_available:platform"]`,
+			}),
+		},
+	})
+}
+
 func TestCcLibrarySharedStubs_MultipleApexAvailable(t *testing.T) {
 	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
 		ModuleTypeUnderTest:        "cc_library_shared",
@@ -682,7 +770,7 @@
 		ExpectedBazelTargets: []string{
 			MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
 				"implementation_dynamic_deps": `select({
-        "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+        "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
         "//conditions:default": [":a"],
     })`,
 				"tags": `[