Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ee00b54 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I350fe490,I31e61862,I09b78e38

* changes:
  Stubs libs are available for host
  Don't create unnecessary APEX variations
  Stubs dependency is not installed
parents df76efe5 0fefdeac
Loading
Loading
Loading
Loading
+111 −54
Original line number Diff line number Diff line
@@ -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
+7 −19
Original line number Diff line number Diff line
@@ -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.
+67 −0
Original line number Diff line number Diff line
@@ -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 {
+3 −0
Original line number Diff line number Diff line
@@ -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")
+24 −10
Original line number Diff line number Diff line
@@ -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(
Loading