diff --git a/bazel/properties.go b/bazel/properties.go index d8b3a3a02..870d29366 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -736,6 +736,24 @@ func (lla LabelListAttribute) IsEmpty() bool { return true } +// IsNil returns true if the attribute has not been set for any configuration. +func (lla LabelListAttribute) IsNil() bool { + if lla.Value.Includes != nil { + return false + } + return !lla.HasConfigurableValues() +} + +// Exclude for the given axis, config, removes Includes in labelList from Includes and appends them +// to Excludes. This is to special case any excludes that are not specified in a bp file but need to +// be removed, e.g. if they could cause duplicate element failures. +func (lla *LabelListAttribute) Exclude(axis ConfigurationAxis, config string, labelList LabelList) { + val := lla.SelectValue(axis, config) + newList := SubtractBazelLabelList(val, labelList) + newList.Excludes = append(newList.Excludes, labelList.Includes...) + lla.SetSelectValue(axis, config, newList) +} + // ResolveExcludes handles excludes across the various axes, ensuring that items are removed from // the base value and included in default values as appropriate. func (lla *LabelListAttribute) ResolveExcludes() { diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index e65a1fa0b..fac741cf8 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -65,7 +65,6 @@ func TestCcLibraryStaticLoadStatement(t *testing.T) { t.Fatalf("Expected load statements to be %s, got %s", expected, actual) } } - } func registerCcLibraryStaticModuleTypes(ctx android.RegistrationContext) { @@ -1395,6 +1394,54 @@ cc_library_static { }) } +func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) { + runCcLibraryStaticTestCase(t, bp2buildTestCase{ + description: "cc_library_static system_shared_lib empty for linux_bionic variant", + blueprint: soongCcLibraryStaticPreamble + + simpleModuleDoNotConvertBp2build("cc_library", "libc") + ` +cc_library_static { + name: "used_in_bionic_oses", + target: { + android: { + shared_libs: ["libc"], + }, + linux_bionic: { + shared_libs: ["libc"], + }, + }, + include_build_directory: false, +} + +cc_library_static { + name: "all", + shared_libs: ["libc"], + include_build_directory: false, +} + +cc_library_static { + name: "keep_for_empty_system_shared_libs", + shared_libs: ["libc"], + system_shared_libs: [], + include_build_directory: false, +} +`, + expectedBazelTargets: []string{ + makeBazelTarget("cc_library_static", "all", attrNameToString{ + "implementation_dynamic_deps": `select({ + "//build/bazel/platforms/os:android": [], + "//build/bazel/platforms/os:linux_bionic": [], + "//conditions:default": [":libc"], + })`, + }), + makeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", attrNameToString{ + "implementation_dynamic_deps": `[":libc"]`, + "system_dynamic_deps": `[]`, + }), + makeBazelTarget("cc_library_static", "used_in_bionic_oses", attrNameToString{}), + }, + }) +} + func TestCcLibraryStaticProto(t *testing.T) { runCcLibraryStaticTestCase(t, bp2buildTestCase{ blueprint: soongCcProtoPreamble + `cc_library_static { diff --git a/bp2build/testing.go b/bp2build/testing.go index 8ae1a38ba..53b60fa81 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -43,7 +43,7 @@ func checkError(t *testing.T, errs []error, expectedErr error) bool { if len(errs) != 1 { return false } - if errs[0].Error() == expectedErr.Error() { + if strings.Contains(errs[0].Error(), expectedErr.Error()) { return true } @@ -127,8 +127,12 @@ func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build) codegenCtx.unconvertedDepMode = tc.unconvertedDepsMode bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir) - if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) { - return + if tc.expectedErr != nil { + if checkError(t, errs, tc.expectedErr) { + return + } else { + t.Errorf("Expected error: %q, got: %q", tc.expectedErr, errs) + } } else { android.FailIfErrored(t, errs) } diff --git a/cc/bp2build.go b/cc/bp2build.go index e4762a064..cc2e60e57 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -531,7 +531,7 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) (&linkerAttrs).convertProductVariables(ctx, productVariableProps) (&compilerAttrs).finalize(ctx, implementationHdrs) - (&linkerAttrs).finalize() + (&linkerAttrs).finalize(ctx) protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs) @@ -550,13 +550,14 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) // 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 @@ type linkerAttributes struct { 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 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion 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) convertProductVariables(ctx android.BazelConversionP } } -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