Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes. For example, `apex_available: ["myapex", "otherapex"]` makes the module available only to the two APEXes: myapex and otherapex, and nothing else, even to the platform. If the module is intended to be available to any APEX, then a pseudo name "//apex_available:anyapex" can be used. If the module is intended to be available to the platform, then another pseudo name "//apex_available:platform" is used. For now, if unspecified, this property defaults to ["//apex_available:platform", "//apex_available:anyapex"], which means the module is available to everybody. This will be reduced to ["//apex_available:platform"], when marking for apex_available for existing modules are finished. Bug: 139870423 Bug: 128708192 Test: m Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
This commit is contained in:
parent
fdc9afa15b
commit
127b40b316
|
@ -78,12 +78,23 @@ type ApexModule interface {
|
|||
|
||||
// Return the no_apex property
|
||||
NoApex() bool
|
||||
|
||||
// Tests if this module is available for the specified APEX or ":platform"
|
||||
AvailableFor(what string) bool
|
||||
}
|
||||
|
||||
type ApexProperties struct {
|
||||
// Whether this module should not be part of any APEX. Default is false.
|
||||
// TODO(b/128708192): remove this as this is equal to apex_available: [":platform"]
|
||||
No_apex *bool
|
||||
|
||||
// Availability of this module in APEXes. Only the listed APEXes can include this module.
|
||||
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
|
||||
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
|
||||
// Default is ["//apex_available:platform", "//apex_available:anyapex"].
|
||||
// TODO(b/128708192) change the default to ["//apex_available:platform"]
|
||||
Apex_available []string
|
||||
|
||||
// Name of the apex variant that this module is mutated into
|
||||
ApexName string `blueprint:"mutated"`
|
||||
}
|
||||
|
@ -136,15 +147,46 @@ func (m *ApexModuleBase) NoApex() bool {
|
|||
return proptools.Bool(m.ApexProperties.No_apex)
|
||||
}
|
||||
|
||||
const (
|
||||
availableToPlatform = "//apex_available:platform"
|
||||
availableToAnyApex = "//apex_available:anyapex"
|
||||
)
|
||||
|
||||
func (m *ApexModuleBase) AvailableFor(what string) bool {
|
||||
if len(m.ApexProperties.Apex_available) == 0 {
|
||||
// apex_available defaults to ["//apex_available:platform", "//apex_available:anyapex"],
|
||||
// which means 'available to everybody'.
|
||||
return true
|
||||
}
|
||||
return InList(what, m.ApexProperties.Apex_available) ||
|
||||
(what != availableToPlatform && InList(availableToAnyApex, m.ApexProperties.Apex_available))
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
|
||||
for _, n := range m.ApexProperties.Apex_available {
|
||||
if n == availableToPlatform || n == availableToAnyApex {
|
||||
continue
|
||||
}
|
||||
if !mctx.OtherModuleExists(n) {
|
||||
mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
|
||||
if len(m.apexVariations) > 0 {
|
||||
m.checkApexAvailableProperty(mctx)
|
||||
sort.Strings(m.apexVariations)
|
||||
variations := []string{""} // Original variation for platform
|
||||
variations := []string{}
|
||||
availableForPlatform := m.AvailableFor(availableToPlatform)
|
||||
if availableForPlatform {
|
||||
variations = append(variations, "") // Original variation for platform
|
||||
}
|
||||
variations = append(variations, m.apexVariations...)
|
||||
|
||||
modules := mctx.CreateVariations(variations...)
|
||||
for i, m := range modules {
|
||||
if i == 0 {
|
||||
if availableForPlatform && i == 0 {
|
||||
continue
|
||||
}
|
||||
m.(ApexModule).setApexName(variations[i])
|
||||
|
|
10
apex/apex.go
10
apex/apex.go
|
@ -1215,6 +1215,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
}
|
||||
}
|
||||
|
||||
// check apex_available requirements
|
||||
for _, fi := range filesInfo {
|
||||
if am, ok := fi.module.(android.ApexModule); ok {
|
||||
if !am.AvailableFor(ctx.ModuleName()) {
|
||||
ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prepend the name of this APEX to the module names. These names will be the names of
|
||||
// modules that will be defined if the APEX is flattened.
|
||||
for i := range filesInfo {
|
||||
|
|
|
@ -2422,6 +2422,158 @@ func TestApexWithApps(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func TestApexAvailable(t *testing.T) {
|
||||
// libfoo is not available to myapex, but only to otherapex
|
||||
testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "otherapex",
|
||||
key: "otherapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "otherapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["otherapex"],
|
||||
}`)
|
||||
|
||||
// libbar is an indirect dep
|
||||
testApexError(t, "requires \"libbar\" that is not available for the APEX", `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "otherapex",
|
||||
key: "otherapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "otherapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stl: "none",
|
||||
shared_libs: ["libbar"],
|
||||
system_shared_libs: [],
|
||||
apex_available: ["myapex", "otherapex"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["otherapex"],
|
||||
}`)
|
||||
|
||||
testApexError(t, "\"otherapex\" is not a valid module name", `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["otherapex"],
|
||||
}`)
|
||||
|
||||
ctx, _ := testApex(t, `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo", "libbar"],
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["//apex_available:anyapex"],
|
||||
}`)
|
||||
|
||||
// check that libfoo and libbar are created only for myapex, but not for the platform
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
|
||||
ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared_myapex")
|
||||
ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_core_shared")
|
||||
|
||||
ctx, _ = testApex(t, `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
}
|
||||
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
public_key: "testkey.avbpubkey",
|
||||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
stl: "none",
|
||||
system_shared_libs: [],
|
||||
apex_available: ["//apex_available:platform"],
|
||||
}`)
|
||||
|
||||
// check that libfoo is created only for the platform
|
||||
ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared_myapex")
|
||||
ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_core_shared")
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
run := func() int {
|
||||
setUp()
|
||||
|
|
Loading…
Reference in New Issue