Support mechanism to select a specific version of module sdk prebuilt

This CL is scoped to cc_* module types. With trunk stable, we will have
multiple prebuilts of the cc modules in
prebuilts/module_sdk/art/<v>/host-exports/, and this CL introduces a
mechanism to use apex_contributions to select a specific versioned
prebuilt when building.

If a soong module is selected using apex_contributions, all rdeps will
get that soong module, which includes
- rdep soong modules which might be depending on it via Android.bp
- Soong's rule builder HostToolPath API

Implementation details: Create a new source_module_name property to
identify the root module. rdeps referring to the root module will get
redirected if necessary. This property also
becomes the stem, if `stem` is not set explicitly.

Bug: 322175508

Test: Added a unit test

Change-Id: Ic8725602c81999621fcb33ce2a57fe4b9751baa8
This commit is contained in:
Spandan Das
2024-01-19 00:22:22 +00:00
parent 1f4475cee1
commit 2b6dfb554d
4 changed files with 135 additions and 4 deletions

View File

@@ -83,8 +83,9 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries {
// causing multiple ART APEXes (com.android.art and com.android.art.debug)
// to be installed. And this is breaking some older devices (like marlin)
// where system.img is small.
Required: c.Properties.AndroidMkRuntimeLibs,
Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
Required: c.Properties.AndroidMkRuntimeLibs,
OverrideName: c.BaseModuleName(),
Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {

View File

@@ -1744,7 +1744,7 @@ func (ctx *moduleContextImpl) useClangLld(actx ModuleContext) bool {
}
func (ctx *moduleContextImpl) baseModuleName() string {
return ctx.mod.ModuleBase.BaseModuleName()
return ctx.mod.BaseModuleName()
}
func (ctx *moduleContextImpl) getVndkExtendsModuleName() string {
@@ -4173,6 +4173,18 @@ func (c *Module) Partition() string {
return ""
}
type sourceModuleName interface {
sourceModuleName() string
}
func (c *Module) BaseModuleName() string {
if smn, ok := c.linker.(sourceModuleName); ok && smn.sourceModuleName() != "" {
// if the prebuilt module sets a source_module_name in Android.bp, use that
return smn.sourceModuleName()
}
return c.ModuleBase.BaseModuleName()
}
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var BoolPtr = proptools.BoolPtr

View File

@@ -17,6 +17,8 @@ package cc
import (
"path/filepath"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
@@ -36,9 +38,15 @@ func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
type prebuiltLinkerInterface interface {
Name(string) string
prebuilt() *android.Prebuilt
sourceModuleName() string
}
type prebuiltLinkerProperties struct {
// Name of the source soong module that gets shadowed by this prebuilt
// If unspecified, follows the naming convention that the source module of
// the prebuilt is Name() without "prebuilt_" prefix
Source_module_name *string
// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
Srcs []string `android:"path,arch_variant"`
@@ -337,7 +345,11 @@ func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libr
}
type prebuiltObjectProperties struct {
Srcs []string `android:"path,arch_variant"`
// Name of the source soong module that gets shadowed by this prebuilt
// If unspecified, follows the naming convention that the source module of
// the prebuilt is Name() without "prebuilt_" prefix
Source_module_name *string
Srcs []string `android:"path,arch_variant"`
}
type prebuiltObjectLinker struct {
@@ -351,6 +363,10 @@ func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
return &p.Prebuilt
}
func (p *prebuiltObjectLinker) sourceModuleName() string {
return proptools.String(p.properties.Source_module_name)
}
var _ prebuiltLinkerInterface = (*prebuiltObjectLinker)(nil)
func (p *prebuiltObjectLinker) link(ctx ModuleContext,
@@ -520,3 +536,7 @@ func srcsForSanitizer(sanitize *sanitize, sanitized Sanitized) []string {
}
return sanitized.None.Srcs
}
func (p *prebuiltLinker) sourceModuleName() string {
return proptools.String(p.properties.Source_module_name)
}

View File

@@ -15,6 +15,7 @@
package cc
import (
"fmt"
"runtime"
"testing"
@@ -509,3 +510,100 @@ cc_prebuilt_binary {
}`
testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
}
func TestMultiplePrebuilts(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"],
}
// prebuilt "v2"
cc_prebuilt_library_shared {
name: "libbar.v2",
stem: "libbar",
source_module_name: "libbar",
srcs: ["libbar.so"],
}
// 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
}{
{
desc: "Source library is selected using apex_contributions",
selectedDependencyName: "libbar",
expectedDependencyName: "libbar",
},
{
desc: "Prebuilt library v1 is selected using apex_contributions",
selectedDependencyName: "prebuilt_libbar",
expectedDependencyName: "prebuilt_libbar",
},
{
desc: "Prebuilt library v2 is selected using apex_contributions",
selectedDependencyName: "prebuilt_libbar.v2",
expectedDependencyName: "prebuilt_libbar.v2",
},
}
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",
}
}),
)
ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
"libbar.so": nil,
"crtx.o": nil,
}, preparer)
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))
// check installation rules
// the selected soong module should be exported to make
libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())
// check LOCAL_MODULE of the selected module name
// the prebuilt should have the same LOCAL_MODULE when exported to make
entries := android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
}
}