Merge "Dexpreopt soong modules inside soong"
diff --git a/android/apex.go b/android/apex.go
index 3a191cf..d1fb6f4 100644
--- a/android/apex.go
+++ b/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 @@
// 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 @@
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 @@
ApexProperties ApexProperties
canHaveApexVariants bool
+ apexVariations []string
}
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
@@ -76,15 +94,21 @@
}
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 @@
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 @@
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
diff --git a/apex/apex.go b/apex/apex.go
index f412d86..c14cd9e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -150,11 +150,13 @@
if _, ok := mctx.Module().(*apexBundle); ok {
apexBundleName := mctx.ModuleName()
mctx.WalkDeps(func(child, parent android.Module) bool {
+ depName := mctx.OtherModuleName(child)
+ // If the parent is apexBundle, this child is directly depended.
+ _, directDep := parent.(*apexBundle)
+ android.UpdateApexDependency(apexBundleName, depName, directDep)
+
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() {
- moduleName := mctx.OtherModuleName(am) + "-" + am.Target().String()
- // If the parent is apexBundle, this child is directly depended.
- _, directDep := parent.(*apexBundle)
- android.BuildModuleForApexBundle(mctx, moduleName, apexBundleName, directDep)
+ am.BuildForApex(apexBundleName)
return true
} else {
return false
@@ -166,21 +168,7 @@
// 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.
@@ -223,6 +211,9 @@
// or an android_app_certificate module name in the form ":module".
Certificate *string
+ // Whether this APEX is installable to one of the partitions. Default: true.
+ Installable *bool
+
Multilib struct {
First struct {
// List of native libraries whose compile_multilib is "first"
@@ -461,6 +452,10 @@
return android.Paths{a.outputFiles[imageApex]}
}
+func (a *apexBundle) installable() bool {
+ return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
+}
+
func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
// Decide the APEX-local directory by the multilib of the library
// In the future, we may query this to the module.
@@ -788,18 +783,22 @@
})
// Install to $OUT/soong/{target,host}/.../apex
- ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType])
+ if a.installable() {
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "apex"), ctx.ModuleName()+suffix, a.outputFiles[apexType])
+ }
}
func (a *apexBundle) buildFlattenedApex(ctx android.ModuleContext) {
- // For flattened APEX, do nothing but make sure that apex_manifest.json file is also copied along
- // with other ordinary files.
- manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
- a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc})
+ if a.installable() {
+ // For flattened APEX, do nothing but make sure that apex_manifest.json file is also copied along
+ // with other ordinary files.
+ manifest := android.PathForModuleSrc(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json"))
+ a.filesInfo = append(a.filesInfo, apexFile{manifest, ctx.ModuleName() + ".apex_manifest.json", android.Common, ".", etc})
- for _, fi := range a.filesInfo {
- dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
- ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
+ for _, fi := range a.filesInfo {
+ dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
+ ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
+ }
}
}
@@ -844,6 +843,7 @@
fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", fi.builtFile.Base())
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.NameInMake())
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
archStr := fi.archType.String()
if archStr != "common" {
fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
@@ -872,6 +872,7 @@
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFiles[apexType].String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join("$(OUT_DIR)", a.installDir.RelPathString()))
fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name+apexType.suffix())
+ fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", String(a.properties.Key))
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c01c40a..88c57bc 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -267,6 +267,7 @@
cc_library {
name: "mylib2",
srcs: ["mylib.cpp"],
+ cflags: ["-include mylib.h"],
system_shared_libs: [],
stl: "none",
stubs: {
@@ -316,6 +317,77 @@
ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
// .. and not linking to the stubs variant of mylib3
ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
+
+ // Ensure that stubs libs are built without -include flags
+ mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+ ensureNotContains(t, mylib2Cflags, "-include ")
+}
+
+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) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index f5e04bb..1f5a8ad 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -76,6 +76,9 @@
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")
diff --git a/cc/cc.go b/cc/cc.go
index b8cbf26..02fc239 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -183,12 +183,13 @@
// Minimum sdk version supported when compiling against the ndk
Sdk_version *string
- AndroidMkSharedLibs []string `blueprint:"mutated"`
- AndroidMkStaticLibs []string `blueprint:"mutated"`
- AndroidMkRuntimeLibs []string `blueprint:"mutated"`
- AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
- HideFromMake bool `blueprint:"mutated"`
- PreventInstall bool `blueprint:"mutated"`
+ AndroidMkSharedLibs []string `blueprint:"mutated"`
+ AndroidMkStaticLibs []string `blueprint:"mutated"`
+ AndroidMkRuntimeLibs []string `blueprint:"mutated"`
+ AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
+ HideFromMake bool `blueprint:"mutated"`
+ PreventInstall bool `blueprint:"mutated"`
+ ApexesProvidingSharedLibs []string `blueprint:"mutated"`
UseVndk bool `blueprint:"mutated"`
@@ -1106,7 +1107,7 @@
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 @@
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 @@
// 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(
diff --git a/cc/library.go b/cc/library.go
index bd43043..524b886 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -351,6 +351,24 @@
flags = library.baseCompiler.compilerFlags(ctx, flags, deps)
if library.buildStubs() {
+ // Remove -include <file> when compiling stubs. Otherwise, the force included
+ // headers might cause conflicting types error with the symbols in the
+ // generated stubs source code. e.g.
+ // double acos(double); // in header
+ // void acos() {} // in the generated source code
+ removeInclude := func(flags []string) []string {
+ ret := flags[:0]
+ for _, f := range flags {
+ if strings.HasPrefix(f, "-include ") {
+ continue
+ }
+ ret = append(ret, f)
+ }
+ return ret
+ }
+ flags.GlobalFlags = removeInclude(flags.GlobalFlags)
+ flags.CFlags = removeInclude(flags.CFlags)
+
flags = addStubLibraryCompilerFlags(flags)
}
return flags
@@ -1016,10 +1034,6 @@
// 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 {