bp2build: Remove duplicate system shared libs

If a system shared lib is specified in shared_libs, this results in
duplicate values appearing, causing a failure in Bazel. This change
removes any system shared libraries that appear in shared libraries from
bionic OS axes where system_shared_libraries takes the default value.

Test: go soong tests
Test: temporarily allowlist directory with this issue, no longer hits
      duplicate library failure.
Change-Id: I9dce570b73c24973f695b815bce8d50f7259798d
diff --git a/cc/bp2build.go b/cc/bp2build.go
index e4762a0..cc2e60e 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -531,7 +531,7 @@
 	(&linkerAttrs).convertProductVariables(ctx, productVariableProps)
 
 	(&compilerAttrs).finalize(ctx, implementationHdrs)
-	(&linkerAttrs).finalize()
+	(&linkerAttrs).finalize(ctx)
 
 	protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
 
@@ -550,13 +550,14 @@
 
 // Convenience struct to hold all attributes parsed from linker properties.
 type linkerAttributes struct {
-	deps                           bazel.LabelListAttribute
-	implementationDeps             bazel.LabelListAttribute
-	dynamicDeps                    bazel.LabelListAttribute
-	implementationDynamicDeps      bazel.LabelListAttribute
-	wholeArchiveDeps               bazel.LabelListAttribute
-	implementationWholeArchiveDeps bazel.LabelListAttribute
-	systemDynamicDeps              bazel.LabelListAttribute
+	deps                             bazel.LabelListAttribute
+	implementationDeps               bazel.LabelListAttribute
+	dynamicDeps                      bazel.LabelListAttribute
+	implementationDynamicDeps        bazel.LabelListAttribute
+	wholeArchiveDeps                 bazel.LabelListAttribute
+	implementationWholeArchiveDeps   bazel.LabelListAttribute
+	systemDynamicDeps                bazel.LabelListAttribute
+	usedSystemDynamicDepAsDynamicDep map[string]bool
 
 	linkCrt                       bazel.BoolAttribute
 	useLibcrt                     bazel.BoolAttribute
@@ -571,6 +572,10 @@
 	features                      bazel.StringListAttribute
 }
 
+var (
+	soongSystemSharedLibs = []string{"libc", "libm", "libdl"}
+)
+
 func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
 	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
 	var axisFeatures []string
@@ -602,6 +607,17 @@
 	la.systemDynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
 
 	sharedLibs := android.FirstUniqueStrings(props.Shared_libs)
+	excludeSharedLibs := props.Exclude_shared_libs
+	usedSystem := android.FilterListPred(sharedLibs, func(s string) bool {
+		return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs)
+	})
+	for _, el := range usedSystem {
+		if la.usedSystemDynamicDepAsDynamicDep == nil {
+			la.usedSystemDynamicDepAsDynamicDep = map[string]bool{}
+		}
+		la.usedSystemDynamicDepAsDynamicDep[el] = true
+	}
+
 	sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
 	la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
 	la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
@@ -721,13 +737,25 @@
 	}
 }
 
-func (la *linkerAttributes) finalize() {
+func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
+	// if system dynamic deps have the default value, any use of a system dynamic library used will
+	// result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries
+	// from bionic OSes.
+	if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 {
+		toRemove := bazelLabelForSharedDeps(ctx, android.SortedStringKeys(la.usedSystemDynamicDepAsDynamicDep))
+		la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+		la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
+		la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+	}
+
 	la.deps.ResolveExcludes()
 	la.implementationDeps.ResolveExcludes()
 	la.dynamicDeps.ResolveExcludes()
 	la.implementationDynamicDeps.ResolveExcludes()
 	la.wholeArchiveDeps.ResolveExcludes()
 	la.systemDynamicDeps.ForceSpecifyEmptyList = true
+
 }
 
 // Relativize a list of root-relative paths with respect to the module's