Fix non-determinism in prebuilt selection

If multiple versions of the prebuilt module sdk share the same soong
config namespace, then PrebuiltPostDepsMutator rewrites rdeps to one of
those prebuilts in a non-deterministic way.

This CL uses apex_contributions to make this deterministic. Multiple
prebuilts will not be allowed to have their prefer evaluate to true. If
this happens, one of the prebuilts must be explicitly declared in
apex_contributions.

This CL also fixes the special-casing of the top-level
java_sdk_library_import in ReplaceDirectDependencies. For
framework-foo.v2, it will use BaseModuleName framework-foo instead of
SdkLibraryName framework-foo.v2 to determine if the source module has
been selected.

Test: Added a unit test
Test: aninja -t query
    out/soong/.intermediates/packages/modules/Permission/SafetyCenter/Config/safety-center-config/android_common/javac/safety-center-config.jar
    | grep module_sdk is empty (should not cause a regression for
    323454855)

Bug: TODO
Change-Id: I7191200c330c5bcb9d5532006d3c573a60db61cc
This commit is contained in:
Spandan Das
2024-02-27 04:49:52 +00:00
parent 688f824e1a
commit 2d8884a377
3 changed files with 120 additions and 3 deletions

View File

@@ -610,3 +610,95 @@ func TestMultiplePrebuilts(t *testing.T) {
android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
}
}
// Setting prefer on multiple prebuilts is an error, unless one of them is also listed in apex_contributions
func TestMultiplePrebuiltsPreferredUsingLegacyFlags(t *testing.T) {
bp := `
// an rdep
cc_library {
name: "libfoo",
shared_libs: ["libbar"],
}
// multiple variations of dep
// source
cc_library {
name: "libbar",
}
// prebuilt "v1"
cc_prebuilt_library_shared {
name: "libbar",
srcs: ["libbar.so"],
prefer: true,
}
// prebuilt "v2"
cc_prebuilt_library_shared {
name: "libbar.v2",
stem: "libbar",
source_module_name: "libbar",
srcs: ["libbar.so"],
prefer: true,
}
// selectors
apex_contributions {
name: "myapex_contributions",
contents: [%v],
}
all_apex_contributions {name: "all_apex_contributions"}
`
hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
t.Helper()
var found bool
ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
if dep == wantDep {
found = true
}
})
return found
}
testCases := []struct {
desc string
selectedDependencyName string
expectedDependencyName string
expectedErr string
}{
{
desc: "Multiple prebuilts have prefer: true",
expectedErr: "Multiple prebuilt modules prebuilt_libbar and prebuilt_libbar.v2 have been marked as preferred for this source module",
},
{
desc: "Multiple prebuilts have prefer: true. The prebuilt listed in apex_contributions wins.",
selectedDependencyName: `"prebuilt_libbar"`,
expectedDependencyName: "prebuilt_libbar",
},
}
for _, tc := range testCases {
preparer := android.GroupFixturePreparers(
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
android.RegisterApexContributionsBuildComponents(ctx)
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.BuildFlags = map[string]string{
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
}
}),
)
if tc.expectedErr != "" {
preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedErr))
}
ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
"libbar.so": nil,
"crtx.o": nil,
}, preparer)
if tc.expectedErr != "" {
return // the fixture will assert that the excepted err has been raised
}
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
}
}