Loading android/apex.go +44 −2 Original line number Diff line number Diff line Loading @@ -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"` } Loading Loading @@ -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]) Loading apex/apex.go +10 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading apex/apex_test.go +152 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
android/apex.go +44 −2 Original line number Diff line number Diff line Loading @@ -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"` } Loading Loading @@ -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]) Loading
apex/apex.go +10 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
apex/apex_test.go +152 −0 Original line number Diff line number Diff line Loading @@ -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