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
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 13cda9d..7a9e89c 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -534,6 +534,31 @@
for _, moduleInFamily := range allModulesInFamily {
if moduleInFamily.Name() != selectedModuleInFamily.Name() {
moduleInFamily.HideFromMake()
+ // If this is a prebuilt module, unset properties.UsePrebuilt
+ // properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism
+ // Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt
+ if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil {
+ p.properties.UsePrebuilt = false
+ }
+ }
+ }
+ }
+ // Do a validation pass to make sure that multiple prebuilts of a specific module are not selected.
+ // This might happen if the prebuilts share the same soong config var namespace.
+ // This should be an error, unless one of the prebuilts has been explicitly declared in apex_contributions
+ var selectedPrebuilt Module
+ for _, moduleInFamily := range allModulesInFamily {
+ // Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first.
+ // This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case
+ if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
+ continue
+ }
+ if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt {
+ if selectedPrebuilt == nil {
+ selectedPrebuilt = moduleInFamily
+ } else {
+ ctx.ModuleErrorf("Multiple prebuilt modules %v and %v have been marked as preferred for this source module. "+
+ "Please add the appropriate prebuilt module to apex_contributions for this release config.", selectedPrebuilt.Name(), moduleInFamily.Name())
}
}
}
@@ -562,7 +587,7 @@
// If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs
// will get prebuilt stubs
// TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
- if psi.IsSelected(*sdkLibrary.SdkLibraryName()) {
+ if psi.IsSelected(name) {
return false
}
}