Merge "Prebuilt stub not available to platform is handled correctly" am: e223512bb4
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1521398 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I758475508d69ab6db867fecd4ea649f81fdf25de
This commit is contained in:
@@ -153,13 +153,12 @@ type ApexModule interface {
|
|||||||
// run.
|
// run.
|
||||||
DirectlyInAnyApex() bool
|
DirectlyInAnyApex() bool
|
||||||
|
|
||||||
// Returns true in the primary variant of a module if _any_ variant of the module is
|
// NotInPlatform tells whether or not this module is included in an APEX and therefore
|
||||||
// directly in any apex. This includes host, arch, asan, etc. variants. It is unused in any
|
// shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is
|
||||||
// variant that is not the primary variant. Ideally this wouldn't be used, as it incorrectly
|
// considered to be included in an APEX either when there actually is an APEX that
|
||||||
// mixes arch variants if only one arch is in an apex, but a few places depend on it, for
|
// explicitly has the module as its dependency or the module is not available to the
|
||||||
// example when an ASAN variant is created before the apexMutator. Call this after
|
// platform, which indicates that the module belongs to at least one or more other APEXes.
|
||||||
// apex.apexMutator is run.
|
NotInPlatform() bool
|
||||||
AnyVariantDirectlyInAnyApex() bool
|
|
||||||
|
|
||||||
// Tests if this module could have APEX variants. Even when a module type implements
|
// 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
|
// ApexModule interface, APEX variants are created only for the module instances that return
|
||||||
@@ -221,7 +220,12 @@ type ApexProperties struct {
|
|||||||
// See ApexModule.DirectlyInAnyApex()
|
// See ApexModule.DirectlyInAnyApex()
|
||||||
DirectlyInAnyApex bool `blueprint:"mutated"`
|
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"`
|
AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"`
|
||||||
|
|
||||||
// See ApexModule.NotAvailableForPlatform()
|
// See ApexModule.NotAvailableForPlatform()
|
||||||
@@ -302,8 +306,8 @@ func (m *ApexModuleBase) DirectlyInAnyApex() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implements ApexModule
|
// Implements ApexModule
|
||||||
func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool {
|
func (m *ApexModuleBase) NotInPlatform() bool {
|
||||||
return m.ApexProperties.AnyVariantDirectlyInAnyApex
|
return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements ApexModule
|
// Implements ApexModule
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package apex
|
package apex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -6411,6 +6412,160 @@ func TestExcludeDependency(t *testing.T) {
|
|||||||
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
|
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) {
|
func TestMain(m *testing.M) {
|
||||||
run := func() int {
|
run := func() int {
|
||||||
setUp()
|
setUp()
|
||||||
|
@@ -46,7 +46,7 @@ type AndroidMkContext interface {
|
|||||||
InRamdisk() bool
|
InRamdisk() bool
|
||||||
InVendorRamdisk() bool
|
InVendorRamdisk() bool
|
||||||
InRecovery() bool
|
InRecovery() bool
|
||||||
AnyVariantDirectlyInAnyApex() bool
|
NotInPlatform() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type subAndroidMkProvider interface {
|
type subAndroidMkProvider interface {
|
||||||
@@ -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() {
|
!ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() {
|
||||||
if library.buildStubs() && library.isLatestStubVersion() {
|
if library.buildStubs() && library.isLatestStubVersion() {
|
||||||
// reference the latest version via its name without suffix when it is provided by apex
|
|
||||||
entries.SubName = ""
|
entries.SubName = ""
|
||||||
}
|
}
|
||||||
if !library.buildStubs() {
|
if !library.buildStubs() {
|
||||||
|
17
cc/cc.go
17
cc/cc.go
@@ -1586,13 +1586,14 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
c.outputFile = android.OptionalPathForPath(outputFile)
|
c.outputFile = android.OptionalPathForPath(outputFile)
|
||||||
|
|
||||||
// If a lib is directly included in any of the APEXes, unhide the stubs
|
// If a lib is directly included in any of the APEXes or is not available to the
|
||||||
// variant having the latest version gets visible to make. In addition,
|
// platform (which is often the case when the stub is provided as a prebuilt),
|
||||||
// the non-stubs variant is renamed to <libname>.bootstrap. This is to
|
// unhide the stubs variant having the latest version gets visible to make. In
|
||||||
// force anything in the make world to link against the stubs library.
|
// addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to
|
||||||
// (unless it is explicitly referenced via .bootstrap suffix or the
|
// force anything in the make world to link against the stubs library. (unless it
|
||||||
// module is marked with 'bootstrap: true').
|
// is explicitly referenced via .bootstrap suffix or the module is marked with
|
||||||
if c.HasStubsVariants() && c.AnyVariantDirectlyInAnyApex() && !c.InRamdisk() &&
|
// 'bootstrap: true').
|
||||||
|
if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() &&
|
||||||
!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
|
!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
|
||||||
c.IsStubs() && !c.InVendorRamdisk() {
|
c.IsStubs() && !c.InVendorRamdisk() {
|
||||||
c.Properties.HideFromMake = false // unhide
|
c.Properties.HideFromMake = false // unhide
|
||||||
@@ -2472,7 +2473,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
// an APEX (and not from platform)
|
// an APEX (and not from platform)
|
||||||
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
|
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
|
||||||
// always link to non-stub variant
|
// 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
|
// 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
|
// it is linked with the non-stub variant of a module in the APEX
|
||||||
// as if this is part of the APEX.
|
// as if this is part of the APEX.
|
||||||
|
Reference in New Issue
Block a user