Merge changes I350fe490,I31e61862,I09b78e38 am: 1ee00b54d9
am: 04f6a9db21
Change-Id: I6ba60b168f05f53d1e368229ab2ce2b1d2b9bf87
This commit is contained in:
commit
d0c11753f6
6 changed files with 212 additions and 87 deletions
165
android/apex.go
165
android/apex.go
|
@ -14,7 +14,11 @@
|
|||
|
||||
package android
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
// ApexModule is the interface that a module type is expected to implement if
|
||||
// the module has to be built differently depending on whether the module
|
||||
|
@ -25,7 +29,7 @@ import "sync"
|
|||
// or C APIs from other APEXs.
|
||||
//
|
||||
// A module implementing this interface will be mutated into multiple
|
||||
// variations by the apex mutator if it is directly or indirectly included
|
||||
// variations by apex.apexMutator if it is directly or indirectly included
|
||||
// in one or more APEXs. Specifically, if a module is included in apex.foo and
|
||||
// apex.bar then three apex variants are created: platform, apex.foo and
|
||||
// apex.bar. The platform variant is for the regular partitions
|
||||
|
@ -35,31 +39,44 @@ type ApexModule interface {
|
|||
Module
|
||||
apexModuleBase() *ApexModuleBase
|
||||
|
||||
// Marks that this module should be built for the APEX of the specified name
|
||||
// Marks that this module should be built for the APEX of the specified name.
|
||||
// Call this before apex.apexMutator is run.
|
||||
BuildForApex(apexName string)
|
||||
|
||||
// Tests whether this module will be built for the platform or not (= APEXs)
|
||||
IsForPlatform() bool
|
||||
|
||||
// Returns the name of APEX that this module will be built for. Empty string
|
||||
// is returned when 'IsForPlatform() == true'. Note that a module can be
|
||||
// included to multiple APEXs, in which case, the module is mutated into
|
||||
// included in multiple APEXes, in which case, the module is mutated into
|
||||
// multiple modules each of which for an APEX. This method returns the
|
||||
// name of the APEX that a variant module is for.
|
||||
// Call this after apex.apexMutator is run.
|
||||
ApexName() string
|
||||
|
||||
// Tests if this module can have APEX variants. APEX variants are
|
||||
// Tests whether this module will be built for the platform or not.
|
||||
// This is a shortcut for ApexName() == ""
|
||||
IsForPlatform() bool
|
||||
|
||||
// Tests if this module could have APEX variants. APEX variants are
|
||||
// created only for the modules that returns true here. This is useful
|
||||
// for not creating APEX variants for shared libraries such as NDK stubs.
|
||||
// for not creating APEX variants for certain types of shared libraries
|
||||
// such as NDK stubs.
|
||||
CanHaveApexVariants() bool
|
||||
|
||||
// Tests if this module can be installed to APEX as a file. For example,
|
||||
// this would return true for shared libs while return false for static
|
||||
// libs.
|
||||
IsInstallableToApex() bool
|
||||
|
||||
// Mutate this module into one or more variants each of which is built
|
||||
// for an APEX marked via BuildForApex().
|
||||
CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module
|
||||
|
||||
// Sets the name of the apex variant of this module. Called inside
|
||||
// CreateApexVariations.
|
||||
setApexName(apexName string)
|
||||
}
|
||||
|
||||
type ApexProperties struct {
|
||||
// Name of the apex variant that this module is mutated into
|
||||
ApexName string `blueprint:"mutated"`
|
||||
}
|
||||
|
||||
|
@ -69,6 +86,7 @@ type ApexModuleBase struct {
|
|||
ApexProperties ApexProperties
|
||||
|
||||
canHaveApexVariants bool
|
||||
apexVariations []string
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
|
||||
|
@ -76,15 +94,21 @@ func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
|
|||
}
|
||||
|
||||
func (m *ApexModuleBase) BuildForApex(apexName string) {
|
||||
m.ApexProperties.ApexName = apexName
|
||||
if !InList(apexName, m.apexVariations) {
|
||||
m.apexVariations = append(m.apexVariations, apexName)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) ApexName() string {
|
||||
return m.ApexProperties.ApexName
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) IsForPlatform() bool {
|
||||
return m.ApexProperties.ApexName == ""
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) ApexName() string {
|
||||
return m.ApexProperties.ApexName
|
||||
func (m *ApexModuleBase) setApexName(apexName string) {
|
||||
m.ApexProperties.ApexName = apexName
|
||||
}
|
||||
|
||||
func (m *ApexModuleBase) CanHaveApexVariants() bool {
|
||||
|
@ -96,61 +120,73 @@ func (m *ApexModuleBase) IsInstallableToApex() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// This structure maps a module name to the set of APEX bundle names that the module
|
||||
// should be built for. Examples:
|
||||
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []blueprint.Module {
|
||||
if len(m.apexVariations) > 0 {
|
||||
// The original module is mutated into "platform" variation.
|
||||
variations := []string{"platform"}
|
||||
for _, a := range m.apexVariations {
|
||||
variations = append(variations, a)
|
||||
}
|
||||
modules := mctx.CreateVariations(variations...)
|
||||
for i, m := range modules {
|
||||
if i == 0 {
|
||||
continue // platform
|
||||
}
|
||||
m.(ApexModule).setApexName(variations[i])
|
||||
}
|
||||
return modules
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var apexData OncePer
|
||||
var apexNamesMapMutex sync.Mutex
|
||||
|
||||
// This structure maintains the global mapping in between modules and APEXes.
|
||||
// Examples:
|
||||
//
|
||||
// ...["foo"]["bar"] == true: module foo is directly depended on by APEX bar
|
||||
// ...["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
|
||||
// ...["foo"]["bar"] doesn't exist: foo is not built for APEX bar
|
||||
// ...["foo"] doesn't exist: foo is not built for any APEX
|
||||
func apexBundleNamesMap(config Config) map[string]map[string]bool {
|
||||
return config.Once("apexBundleNames", func() interface{} {
|
||||
// apexNamesMap()["foo"]["bar"] == true: module foo is directly depended on by APEX bar
|
||||
// apexNamesMap()["foo"]["bar"] == false: module foo is indirectly depended on by APEX bar
|
||||
// apexNamesMap()["foo"]["bar"] doesn't exist: foo is not built for APEX bar
|
||||
func apexNamesMap() map[string]map[string]bool {
|
||||
return apexData.Once("apexNames", func() interface{} {
|
||||
return make(map[string]map[string]bool)
|
||||
}).(map[string]map[string]bool)
|
||||
}
|
||||
|
||||
var bundleNamesMapMutex sync.Mutex
|
||||
|
||||
// Mark that a module named moduleName should be built for an apex named bundleName
|
||||
// directDep should be set to true if the module is a direct dependency of the apex.
|
||||
func BuildModuleForApexBundle(ctx BaseModuleContext, moduleName string, bundleName string, directDep bool) {
|
||||
bundleNamesMapMutex.Lock()
|
||||
defer bundleNamesMapMutex.Unlock()
|
||||
bundleNames, ok := apexBundleNamesMap(ctx.Config())[moduleName]
|
||||
// Update the map to mark that a module named moduleName is directly or indirectly
|
||||
// depended on by an APEX named apexName. Directly depending means that a module
|
||||
// is explicitly listed in the build definition of the APEX via properties like
|
||||
// native_shared_libs, java_libs, etc.
|
||||
func UpdateApexDependency(apexName string, moduleName string, directDep bool) {
|
||||
apexNamesMapMutex.Lock()
|
||||
defer apexNamesMapMutex.Unlock()
|
||||
apexNames, ok := apexNamesMap()[moduleName]
|
||||
if !ok {
|
||||
bundleNames = make(map[string]bool)
|
||||
apexBundleNamesMap(ctx.Config())[moduleName] = bundleNames
|
||||
apexNames = make(map[string]bool)
|
||||
apexNamesMap()[moduleName] = apexNames
|
||||
}
|
||||
bundleNames[bundleName] = bundleNames[bundleName] || directDep
|
||||
apexNames[apexName] = apexNames[apexName] || directDep
|
||||
}
|
||||
|
||||
// Returns the list of apex bundle names that the module named moduleName
|
||||
// should be built for.
|
||||
func GetApexBundlesForModule(ctx BaseModuleContext, moduleName string) map[string]bool {
|
||||
bundleNamesMapMutex.Lock()
|
||||
defer bundleNamesMapMutex.Unlock()
|
||||
return apexBundleNamesMap(ctx.Config())[moduleName]
|
||||
}
|
||||
|
||||
// Tests if moduleName is directly depended on by bundleName (i.e. referenced in
|
||||
// native_shared_libs, etc.)
|
||||
func DirectlyInApex(config Config, bundleName string, moduleName string) bool {
|
||||
bundleNamesMapMutex.Lock()
|
||||
defer bundleNamesMapMutex.Unlock()
|
||||
if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
|
||||
return bundleNames[bundleName]
|
||||
// Tests whether a module named moduleName is directly depended on by an APEX
|
||||
// named apexName.
|
||||
func DirectlyInApex(apexName string, moduleName string) bool {
|
||||
apexNamesMapMutex.Lock()
|
||||
defer apexNamesMapMutex.Unlock()
|
||||
if apexNames, ok := apexNamesMap()[moduleName]; ok {
|
||||
return apexNames[apexName]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Tests if moduleName is directly depended on by any APEX. If this returns true,
|
||||
// that means the module is part of the platform.
|
||||
func DirectlyInAnyApex(config Config, moduleName string) bool {
|
||||
bundleNamesMapMutex.Lock()
|
||||
defer bundleNamesMapMutex.Unlock()
|
||||
if bundleNames, ok := apexBundleNamesMap(config)[moduleName]; ok {
|
||||
for bn := range bundleNames {
|
||||
if bundleNames[bn] {
|
||||
// Tests whether a module named moduleName is directly depended on by any APEX.
|
||||
func DirectlyInAnyApex(moduleName string) bool {
|
||||
apexNamesMapMutex.Lock()
|
||||
defer apexNamesMapMutex.Unlock()
|
||||
if apexNames, ok := apexNamesMap()[moduleName]; ok {
|
||||
for an := range apexNames {
|
||||
if apexNames[an] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -158,6 +194,27 @@ func DirectlyInAnyApex(config Config, moduleName string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Tests whether a module named module is depended on (including both
|
||||
// direct and indirect dependencies) by any APEX.
|
||||
func InAnyApex(moduleName string) bool {
|
||||
apexNamesMapMutex.Lock()
|
||||
defer apexNamesMapMutex.Unlock()
|
||||
apexNames, ok := apexNamesMap()[moduleName]
|
||||
return ok && len(apexNames) > 0
|
||||
}
|
||||
|
||||
func GetApexesForModule(moduleName string) []string {
|
||||
ret := []string{}
|
||||
apexNamesMapMutex.Lock()
|
||||
defer apexNamesMapMutex.Unlock()
|
||||
if apexNames, ok := apexNamesMap()[moduleName]; ok {
|
||||
for an := range apexNames {
|
||||
ret = append(ret, an)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func InitApexModule(m ApexModule) {
|
||||
base := m.apexModuleBase()
|
||||
base.canHaveApexVariants = true
|
||||
|
|
24
apex/apex.go
24
apex/apex.go
|
@ -150,11 +150,13 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
|
|||
if _, ok := mctx.Module().(*apexBundle); ok {
|
||||
apexBundleName := mctx.ModuleName()
|
||||
mctx.WalkDeps(func(child, parent android.Module) bool {
|
||||
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
|
||||
moduleName := mctx.OtherModuleName(am) + "-" + am.Target().String()
|
||||
depName := mctx.OtherModuleName(child)
|
||||
// If the parent is apexBundle, this child is directly depended.
|
||||
_, directDep := parent.(*apexBundle)
|
||||
android.BuildModuleForApexBundle(mctx, moduleName, apexBundleName, directDep)
|
||||
android.UpdateApexDependency(apexBundleName, depName, directDep)
|
||||
|
||||
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
|
||||
am.BuildForApex(apexBundleName)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
@ -166,21 +168,7 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
|
|||
// Create apex variations if a module is included in APEX(s).
|
||||
func apexMutator(mctx android.BottomUpMutatorContext) {
|
||||
if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
|
||||
moduleName := mctx.ModuleName() + "-" + am.Target().String()
|
||||
bundleNames := android.GetApexBundlesForModule(mctx, moduleName)
|
||||
if len(bundleNames) > 0 {
|
||||
variations := []string{"platform"}
|
||||
for bn := range bundleNames {
|
||||
variations = append(variations, bn)
|
||||
}
|
||||
modules := mctx.CreateVariations(variations...)
|
||||
for i, m := range modules {
|
||||
if i == 0 {
|
||||
continue // platform
|
||||
}
|
||||
m.(android.ApexModule).BuildForApex(variations[i])
|
||||
}
|
||||
}
|
||||
am.CreateApexVariations(mctx)
|
||||
} else if _, ok := mctx.Module().(*apexBundle); ok {
|
||||
// apex bundle itself is mutated so that it and its modules have same
|
||||
// apex variant.
|
||||
|
|
|
@ -318,6 +318,73 @@ func TestApexWithStubs(t *testing.T) {
|
|||
ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
|
||||
}
|
||||
|
||||
func TestApexWithExplicitStubsDependency(t *testing.T) {
|
||||
ctx := testApex(t, `
|
||||
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"],
|
||||
shared_libs: ["libfoo#10"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
srcs: ["mylib.cpp"],
|
||||
shared_libs: ["libbar"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
versions: ["10", "20", "30"],
|
||||
},
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["mylib.cpp"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
}
|
||||
|
||||
`)
|
||||
|
||||
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
|
||||
copyCmds := apexRule.Args["copy_commands"]
|
||||
|
||||
// Ensure that direct non-stubs dep is always included
|
||||
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
|
||||
|
||||
// Ensure that indirect stubs dep is not included
|
||||
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
|
||||
|
||||
// Ensure that dependency of stubs is not included
|
||||
ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
|
||||
|
||||
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
|
||||
|
||||
// Ensure that mylib is linking with version 10 of libfoo
|
||||
ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10_myapex/libfoo.so")
|
||||
// ... and not linking to the non-stub (impl) variant of libfoo
|
||||
ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_myapex/libfoo.so")
|
||||
|
||||
libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10_myapex").Rule("ld").Args["libFlags"]
|
||||
|
||||
// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
|
||||
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
|
||||
}
|
||||
|
||||
func TestApexWithSystemLibsStubs(t *testing.T) {
|
||||
ctx := testApex(t, `
|
||||
apex {
|
||||
|
|
|
@ -76,6 +76,9 @@ func (c *Module) AndroidMk() android.AndroidMkData {
|
|||
if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_WHOLE_STATIC_LIBRARIES := "+strings.Join(c.Properties.AndroidMkWholeStaticLibs, " "))
|
||||
}
|
||||
if len(c.Properties.ApexesProvidingSharedLibs) > 0 {
|
||||
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+strings.Join(c.Properties.ApexesProvidingSharedLibs, " "))
|
||||
}
|
||||
fmt.Fprintln(w, "LOCAL_SOONG_LINK_TYPE :=", c.getMakeLinkType())
|
||||
if c.useVndk() {
|
||||
fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
|
||||
|
|
22
cc/cc.go
22
cc/cc.go
|
@ -189,6 +189,7 @@ type BaseProperties struct {
|
|||
AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
|
||||
HideFromMake bool `blueprint:"mutated"`
|
||||
PreventInstall bool `blueprint:"mutated"`
|
||||
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
|
||||
|
||||
UseVndk bool `blueprint:"mutated"`
|
||||
|
||||
|
@ -1106,7 +1107,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
addSharedLibDependencies := func(depTag dependencyTag, name string, version string) {
|
||||
var variations []blueprint.Variation
|
||||
variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"})
|
||||
versionVariantAvail := ctx.Os() == android.Android && !ctx.useVndk() && !c.inRecovery()
|
||||
versionVariantAvail := !ctx.useVndk() && !c.inRecovery()
|
||||
if version != "" && versionVariantAvail {
|
||||
// Version is explicitly specified. i.e. libFoo#30
|
||||
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
|
||||
|
@ -1421,9 +1422,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok {
|
||||
depIsStubs := dependentLibrary.buildStubs()
|
||||
depHasStubs := ccDep.HasStubsVariants()
|
||||
depNameWithTarget := depName + "-" + ccDep.Target().String()
|
||||
depInSameApex := android.DirectlyInApex(ctx.Config(), c.ApexName(), depNameWithTarget)
|
||||
depInPlatform := !android.DirectlyInAnyApex(ctx.Config(), depNameWithTarget)
|
||||
depInSameApex := android.DirectlyInApex(c.ApexName(), depName)
|
||||
depInPlatform := !android.DirectlyInAnyApex(depName)
|
||||
|
||||
var useThisDep bool
|
||||
if depIsStubs && explicitlyVersioned {
|
||||
|
@ -1579,6 +1579,20 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
// Export the shared libs to Make.
|
||||
switch depTag {
|
||||
case sharedDepTag, sharedExportDepTag, lateSharedDepTag:
|
||||
// Dependency to the stubs lib which is already included in an APEX
|
||||
// is not added to the androidmk dependency
|
||||
if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok {
|
||||
if dependentLibrary.buildStubs() && android.InAnyApex(depName) {
|
||||
// Also add the dependency to the APEX(es) providing the library so that
|
||||
// m <module> can trigger building the APEXes as well.
|
||||
for _, an := range android.GetApexesForModule(depName) {
|
||||
c.Properties.ApexesProvidingSharedLibs = append(
|
||||
c.Properties.ApexesProvidingSharedLibs, an)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Note: the order of libs in this list is not important because
|
||||
// they merely serve as Make dependencies and do not affect this lib itself.
|
||||
c.Properties.AndroidMkSharedLibs = append(
|
||||
|
|
|
@ -1016,10 +1016,6 @@ func latestStubsVersionFor(config android.Config, name string) string {
|
|||
// Version mutator splits a module into the mandatory non-stubs variant
|
||||
// (which is unnamed) and zero or more stubs variants.
|
||||
func VersionMutator(mctx android.BottomUpMutatorContext) {
|
||||
if mctx.Os() != android.Android {
|
||||
return
|
||||
}
|
||||
|
||||
if m, ok := mctx.Module().(*Module); ok && !m.inRecovery() && m.linker != nil {
|
||||
if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() &&
|
||||
len(library.Properties.Stubs.Versions) > 0 {
|
||||
|
|
Loading…
Reference in a new issue