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
This commit is contained in:
Liz Kammer
2021-12-14 12:21:22 -05:00
parent 7febef761a
commit 5430953c82
4 changed files with 110 additions and 13 deletions

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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