Loading android/apex.go +14 −10 Original line number Diff line number Diff line Loading @@ -153,13 +153,12 @@ type ApexModule interface { // run. DirectlyInAnyApex() bool // Returns true in the primary variant of a module if _any_ variant of the module is // directly in any apex. This includes host, arch, asan, etc. variants. It is unused in any // variant that is not the primary variant. Ideally this wouldn't be used, as it incorrectly // mixes arch variants if only one arch is in an apex, but a few places depend on it, for // example when an ASAN variant is created before the apexMutator. Call this after // apex.apexMutator is run. AnyVariantDirectlyInAnyApex() bool // NotInPlatform tells whether or not this module is included in an APEX and therefore // shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is // considered to be included in an APEX either when there actually is an APEX that // explicitly has the module as its dependency or the module is not available to the // platform, which indicates that the module belongs to at least one or more other APEXes. NotInPlatform() bool // Tests if this module could have APEX variants. Even when a module type implements // ApexModule interface, APEX variants are created only for the module instances that return Loading Loading @@ -221,7 +220,12 @@ type ApexProperties struct { // See ApexModule.DirectlyInAnyApex() DirectlyInAnyApex bool `blueprint:"mutated"` // See ApexModule.AnyVariantDirectlyInAnyApex() // AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant // of the module is directly in any apex. This includes host, arch, asan, etc. variants. It // is unused in any variant that is not the primary variant. Ideally this wouldn't be used, // as it incorrectly mixes arch variants if only one arch is in an apex, but a few places // depend on it, for example when an ASAN variant is created before the apexMutator. Call // this after apex.apexMutator is run. AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"` // See ApexModule.NotAvailableForPlatform() Loading Loading @@ -302,8 +306,8 @@ func (m *ApexModuleBase) DirectlyInAnyApex() bool { } // Implements ApexModule func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool { return m.ApexProperties.AnyVariantDirectlyInAnyApex func (m *ApexModuleBase) NotInPlatform() bool { return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform) } // Implements ApexModule Loading apex/apex_test.go +155 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package apex import ( "fmt" "io/ioutil" "os" "path" Loading Loading @@ -6411,6 +6412,160 @@ func TestExcludeDependency(t *testing.T) { ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") } func TestPrebuiltStubLibDep(t *testing.T) { bpBase := ` apex { name: "myapex", key: "myapex.key", native_shared_libs: ["mylib"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } cc_library { name: "mylib", srcs: ["mylib.cpp"], apex_available: ["myapex"], shared_libs: ["stublib"], system_shared_libs: [], } apex { name: "otherapex", enabled: %s, key: "myapex.key", native_shared_libs: ["stublib"], } ` stublibSourceBp := ` cc_library { name: "stublib", srcs: ["mylib.cpp"], apex_available: ["otherapex"], system_shared_libs: [], stl: "none", stubs: { versions: ["1"], }, } ` stublibPrebuiltBp := ` cc_prebuilt_library_shared { name: "stublib", srcs: ["prebuilt.so"], apex_available: ["otherapex"], stubs: { versions: ["1"], }, %s } ` tests := []struct { name string stublibBp string usePrebuilt bool modNames []string // Modules to collect AndroidMkEntries for otherApexEnabled []string }{ { name: "only_source", stublibBp: stublibSourceBp, usePrebuilt: false, modNames: []string{"stublib"}, otherApexEnabled: []string{"true", "false"}, }, { name: "source_preferred", stublibBp: stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, ""), usePrebuilt: false, modNames: []string{"stublib", "prebuilt_stublib"}, otherApexEnabled: []string{"true", "false"}, }, { name: "prebuilt_preferred", stublibBp: stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, "prefer: true,"), usePrebuilt: true, modNames: []string{"stublib", "prebuilt_stublib"}, otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt. }, { name: "only_prebuilt", stublibBp: fmt.Sprintf(stublibPrebuiltBp, ""), usePrebuilt: true, modNames: []string{"stublib"}, otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt. }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { for _, otherApexEnabled := range test.otherApexEnabled { t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) { ctx, config := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp) type modAndMkEntries struct { mod *cc.Module mkEntries android.AndroidMkEntries } entries := []*modAndMkEntries{} // Gather shared lib modules that are installable for _, modName := range test.modNames { for _, variant := range ctx.ModuleVariantsForTests(modName) { if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") { continue } mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module) if !mod.Enabled() || mod.IsSkipInstall() { continue } for _, ent := range android.AndroidMkEntriesForTest(t, config, "", mod) { if ent.Disabled { continue } entries = append(entries, &modAndMkEntries{ mod: mod, mkEntries: ent, }) } } } var entry *modAndMkEntries = nil for _, ent := range entries { if strings.Join(ent.mkEntries.EntryMap["LOCAL_MODULE"], ",") == "stublib" { if entry != nil { t.Errorf("More than one AndroidMk entry for \"stublib\": %s and %s", entry.mod, ent.mod) } else { entry = ent } } } if entry == nil { t.Errorf("AndroidMk entry for \"stublib\" missing") } else { isPrebuilt := entry.mod.Prebuilt() != nil if isPrebuilt != test.usePrebuilt { t.Errorf("Wrong module for \"stublib\" AndroidMk entry: got prebuilt %t, want prebuilt %t", isPrebuilt, test.usePrebuilt) } if !entry.mod.IsStubs() { t.Errorf("Module for \"stublib\" AndroidMk entry isn't a stub: %s", entry.mod) } if entry.mkEntries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"] != nil { t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries) } } }) } }) } } func TestMain(m *testing.M) { run := func() int { setUp() Loading cc/androidmk.go +8 −3 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ type AndroidMkContext interface { InRamdisk() bool InVendorRamdisk() bool InRecovery() bool AnyVariantDirectlyInAnyApex() bool NotInPlatform() bool } type subAndroidMkProvider interface { Loading Loading @@ -281,10 +281,15 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries } }) } if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.AnyVariantDirectlyInAnyApex() && // If a library providing a stub is included in an APEX, the private APIs of the library // is accessible only inside the APEX. From outside of the APEX, clients can only use the // public APIs via the stub. To enforce this, the (latest version of the) stub gets the // name of the library. The impl library instead gets the `.bootstrap` suffix to so that // they can be exceptionally used directly when APEXes are not available (e.g. during the // very early stage in the boot process). if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.NotInPlatform() && !ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() { if library.buildStubs() && library.isLatestStubVersion() { // reference the latest version via its name without suffix when it is provided by apex entries.SubName = "" } if !library.buildStubs() { Loading cc/cc.go +9 −8 Original line number Diff line number Diff line Loading @@ -1586,13 +1586,14 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } c.outputFile = android.OptionalPathForPath(outputFile) // If a lib is directly included in any of the APEXes, unhide the stubs // variant having the latest version gets visible to make. In addition, // the non-stubs variant is renamed to <libname>.bootstrap. This is to // force anything in the make world to link against the stubs library. // (unless it is explicitly referenced via .bootstrap suffix or the // module is marked with 'bootstrap: true'). if c.HasStubsVariants() && c.AnyVariantDirectlyInAnyApex() && !c.InRamdisk() && // If a lib is directly included in any of the APEXes or is not available to the // platform (which is often the case when the stub is provided as a prebuilt), // unhide the stubs variant having the latest version gets visible to make. In // addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to // force anything in the make world to link against the stubs library. (unless it // is explicitly referenced via .bootstrap suffix or the module is marked with // 'bootstrap: true'). if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() && !c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() && c.IsStubs() && !c.InVendorRamdisk() { c.Properties.HideFromMake = false // unhide Loading Loading @@ -2472,7 +2473,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // an APEX (and not from platform) // However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules, // always link to non-stub variant useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !c.bootstrap() useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap() // Another exception: if this module is bundled with an APEX, then // it is linked with the non-stub variant of a module in the APEX // as if this is part of the APEX. Loading Loading
android/apex.go +14 −10 Original line number Diff line number Diff line Loading @@ -153,13 +153,12 @@ type ApexModule interface { // run. DirectlyInAnyApex() bool // Returns true in the primary variant of a module if _any_ variant of the module is // directly in any apex. This includes host, arch, asan, etc. variants. It is unused in any // variant that is not the primary variant. Ideally this wouldn't be used, as it incorrectly // mixes arch variants if only one arch is in an apex, but a few places depend on it, for // example when an ASAN variant is created before the apexMutator. Call this after // apex.apexMutator is run. AnyVariantDirectlyInAnyApex() bool // NotInPlatform tells whether or not this module is included in an APEX and therefore // shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is // considered to be included in an APEX either when there actually is an APEX that // explicitly has the module as its dependency or the module is not available to the // platform, which indicates that the module belongs to at least one or more other APEXes. NotInPlatform() bool // Tests if this module could have APEX variants. Even when a module type implements // ApexModule interface, APEX variants are created only for the module instances that return Loading Loading @@ -221,7 +220,12 @@ type ApexProperties struct { // See ApexModule.DirectlyInAnyApex() DirectlyInAnyApex bool `blueprint:"mutated"` // See ApexModule.AnyVariantDirectlyInAnyApex() // AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant // of the module is directly in any apex. This includes host, arch, asan, etc. variants. It // is unused in any variant that is not the primary variant. Ideally this wouldn't be used, // as it incorrectly mixes arch variants if only one arch is in an apex, but a few places // depend on it, for example when an ASAN variant is created before the apexMutator. Call // this after apex.apexMutator is run. AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"` // See ApexModule.NotAvailableForPlatform() Loading Loading @@ -302,8 +306,8 @@ func (m *ApexModuleBase) DirectlyInAnyApex() bool { } // Implements ApexModule func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool { return m.ApexProperties.AnyVariantDirectlyInAnyApex func (m *ApexModuleBase) NotInPlatform() bool { return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform) } // Implements ApexModule Loading
apex/apex_test.go +155 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package apex import ( "fmt" "io/ioutil" "os" "path" Loading Loading @@ -6411,6 +6412,160 @@ func TestExcludeDependency(t *testing.T) { ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") } func TestPrebuiltStubLibDep(t *testing.T) { bpBase := ` apex { name: "myapex", key: "myapex.key", native_shared_libs: ["mylib"], } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } cc_library { name: "mylib", srcs: ["mylib.cpp"], apex_available: ["myapex"], shared_libs: ["stublib"], system_shared_libs: [], } apex { name: "otherapex", enabled: %s, key: "myapex.key", native_shared_libs: ["stublib"], } ` stublibSourceBp := ` cc_library { name: "stublib", srcs: ["mylib.cpp"], apex_available: ["otherapex"], system_shared_libs: [], stl: "none", stubs: { versions: ["1"], }, } ` stublibPrebuiltBp := ` cc_prebuilt_library_shared { name: "stublib", srcs: ["prebuilt.so"], apex_available: ["otherapex"], stubs: { versions: ["1"], }, %s } ` tests := []struct { name string stublibBp string usePrebuilt bool modNames []string // Modules to collect AndroidMkEntries for otherApexEnabled []string }{ { name: "only_source", stublibBp: stublibSourceBp, usePrebuilt: false, modNames: []string{"stublib"}, otherApexEnabled: []string{"true", "false"}, }, { name: "source_preferred", stublibBp: stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, ""), usePrebuilt: false, modNames: []string{"stublib", "prebuilt_stublib"}, otherApexEnabled: []string{"true", "false"}, }, { name: "prebuilt_preferred", stublibBp: stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, "prefer: true,"), usePrebuilt: true, modNames: []string{"stublib", "prebuilt_stublib"}, otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt. }, { name: "only_prebuilt", stublibBp: fmt.Sprintf(stublibPrebuiltBp, ""), usePrebuilt: true, modNames: []string{"stublib"}, otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt. }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { for _, otherApexEnabled := range test.otherApexEnabled { t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) { ctx, config := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp) type modAndMkEntries struct { mod *cc.Module mkEntries android.AndroidMkEntries } entries := []*modAndMkEntries{} // Gather shared lib modules that are installable for _, modName := range test.modNames { for _, variant := range ctx.ModuleVariantsForTests(modName) { if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") { continue } mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module) if !mod.Enabled() || mod.IsSkipInstall() { continue } for _, ent := range android.AndroidMkEntriesForTest(t, config, "", mod) { if ent.Disabled { continue } entries = append(entries, &modAndMkEntries{ mod: mod, mkEntries: ent, }) } } } var entry *modAndMkEntries = nil for _, ent := range entries { if strings.Join(ent.mkEntries.EntryMap["LOCAL_MODULE"], ",") == "stublib" { if entry != nil { t.Errorf("More than one AndroidMk entry for \"stublib\": %s and %s", entry.mod, ent.mod) } else { entry = ent } } } if entry == nil { t.Errorf("AndroidMk entry for \"stublib\" missing") } else { isPrebuilt := entry.mod.Prebuilt() != nil if isPrebuilt != test.usePrebuilt { t.Errorf("Wrong module for \"stublib\" AndroidMk entry: got prebuilt %t, want prebuilt %t", isPrebuilt, test.usePrebuilt) } if !entry.mod.IsStubs() { t.Errorf("Module for \"stublib\" AndroidMk entry isn't a stub: %s", entry.mod) } if entry.mkEntries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"] != nil { t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries) } } }) } }) } } func TestMain(m *testing.M) { run := func() int { setUp() Loading
cc/androidmk.go +8 −3 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ type AndroidMkContext interface { InRamdisk() bool InVendorRamdisk() bool InRecovery() bool AnyVariantDirectlyInAnyApex() bool NotInPlatform() bool } type subAndroidMkProvider interface { Loading Loading @@ -281,10 +281,15 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries } }) } if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.AnyVariantDirectlyInAnyApex() && // If a library providing a stub is included in an APEX, the private APIs of the library // is accessible only inside the APEX. From outside of the APEX, clients can only use the // public APIs via the stub. To enforce this, the (latest version of the) stub gets the // name of the library. The impl library instead gets the `.bootstrap` suffix to so that // they can be exceptionally used directly when APEXes are not available (e.g. during the // very early stage in the boot process). if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.NotInPlatform() && !ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() { if library.buildStubs() && library.isLatestStubVersion() { // reference the latest version via its name without suffix when it is provided by apex entries.SubName = "" } if !library.buildStubs() { Loading
cc/cc.go +9 −8 Original line number Diff line number Diff line Loading @@ -1586,13 +1586,14 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } c.outputFile = android.OptionalPathForPath(outputFile) // If a lib is directly included in any of the APEXes, unhide the stubs // variant having the latest version gets visible to make. In addition, // the non-stubs variant is renamed to <libname>.bootstrap. This is to // force anything in the make world to link against the stubs library. // (unless it is explicitly referenced via .bootstrap suffix or the // module is marked with 'bootstrap: true'). if c.HasStubsVariants() && c.AnyVariantDirectlyInAnyApex() && !c.InRamdisk() && // If a lib is directly included in any of the APEXes or is not available to the // platform (which is often the case when the stub is provided as a prebuilt), // unhide the stubs variant having the latest version gets visible to make. In // addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to // force anything in the make world to link against the stubs library. (unless it // is explicitly referenced via .bootstrap suffix or the module is marked with // 'bootstrap: true'). if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() && !c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() && c.IsStubs() && !c.InVendorRamdisk() { c.Properties.HideFromMake = false // unhide Loading Loading @@ -2472,7 +2473,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // an APEX (and not from platform) // However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules, // always link to non-stub variant useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !c.bootstrap() useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap() // Another exception: if this module is bundled with an APEX, then // it is linked with the non-stub variant of a module in the APEX // as if this is part of the APEX. Loading