Statically link the unwinder into binaries packaged into an unbundled APEX with legacy_android10_support: true.
Bug: 149075752 Test: tapas com.android.conscrypt com.android.tethering arm64 Test: m out/target/product/generic_arm64/{,symbols/}apex/com.android.{tethering,conscrypt}/lib64/libc++.so Test: Verified that unwinder was dynamically linked to tethering's Test: libc++ and statically linked to conscrypt's. Test: lunch flame-userdebug && m Test: Verified that unwinder was dynamically linked to /system/lib64/libc++.so Change-Id: I98eed7cb4316962b19b5c12e150c224c25d0e91d
This commit is contained in:
parent
edb3174967
commit
dc4f986b2a
5 changed files with 125 additions and 44 deletions
|
@ -19,6 +19,14 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ApexInfo struct {
|
||||||
|
// Name of the apex variant that this module is mutated into
|
||||||
|
ApexName string
|
||||||
|
|
||||||
|
// Whether this apex variant needs to target Android 10
|
||||||
|
LegacyAndroid10Support bool
|
||||||
|
}
|
||||||
|
|
||||||
// ApexModule is the interface that a module type is expected to implement if
|
// 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
|
// the module has to be built differently depending on whether the module
|
||||||
// is destined for an apex or not (installed to one of the regular partitions).
|
// is destined for an apex or not (installed to one of the regular partitions).
|
||||||
|
@ -38,12 +46,12 @@ type ApexModule interface {
|
||||||
Module
|
Module
|
||||||
apexModuleBase() *ApexModuleBase
|
apexModuleBase() *ApexModuleBase
|
||||||
|
|
||||||
// Marks that this module should be built for the APEXes of the specified names.
|
// Marks that this module should be built for the specified APEXes.
|
||||||
// Call this before apex.apexMutator is run.
|
// Call this before apex.apexMutator is run.
|
||||||
BuildForApexes(apexNames []string)
|
BuildForApexes(apexes []ApexInfo)
|
||||||
|
|
||||||
// Returns the name of the APEXes that this modoule will be built for
|
// Returns the APEXes that this module will be built for
|
||||||
ApexVariations() []string
|
ApexVariations() []ApexInfo
|
||||||
|
|
||||||
// Returns the name of APEX that this module will be built for. Empty string
|
// 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
|
// is returned when 'IsForPlatform() == true'. Note that a module can be
|
||||||
|
@ -72,10 +80,6 @@ type ApexModule interface {
|
||||||
// for an APEX marked via BuildForApexes().
|
// for an APEX marked via BuildForApexes().
|
||||||
CreateApexVariations(mctx BottomUpMutatorContext) []Module
|
CreateApexVariations(mctx BottomUpMutatorContext) []Module
|
||||||
|
|
||||||
// Sets the name of the apex variant of this module. Called inside
|
|
||||||
// CreateApexVariations.
|
|
||||||
setApexName(apexName string)
|
|
||||||
|
|
||||||
// Tests if this module is available for the specified APEX or ":platform"
|
// Tests if this module is available for the specified APEX or ":platform"
|
||||||
AvailableFor(what string) bool
|
AvailableFor(what string) bool
|
||||||
|
|
||||||
|
@ -94,8 +98,7 @@ type ApexProperties struct {
|
||||||
// Default is ["//apex_available:platform"].
|
// Default is ["//apex_available:platform"].
|
||||||
Apex_available []string
|
Apex_available []string
|
||||||
|
|
||||||
// Name of the apex variant that this module is mutated into
|
Info ApexInfo `blueprint:"mutated"`
|
||||||
ApexName string `blueprint:"mutated"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides default implementation for the ApexModule interface. APEX-aware
|
// Provides default implementation for the ApexModule interface. APEX-aware
|
||||||
|
@ -106,37 +109,37 @@ type ApexModuleBase struct {
|
||||||
canHaveApexVariants bool
|
canHaveApexVariants bool
|
||||||
|
|
||||||
apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator
|
apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator
|
||||||
apexVariations []string
|
apexVariations []ApexInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
|
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) BuildForApexes(apexNames []string) {
|
func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
|
||||||
m.apexVariationsLock.Lock()
|
m.apexVariationsLock.Lock()
|
||||||
defer m.apexVariationsLock.Unlock()
|
defer m.apexVariationsLock.Unlock()
|
||||||
for _, apexName := range apexNames {
|
nextApex:
|
||||||
if !InList(apexName, m.apexVariations) {
|
for _, apex := range apexes {
|
||||||
m.apexVariations = append(m.apexVariations, apexName)
|
for _, v := range m.apexVariations {
|
||||||
|
if v.ApexName == apex.ApexName {
|
||||||
|
continue nextApex
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m.apexVariations = append(m.apexVariations, apex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) ApexVariations() []string {
|
func (m *ApexModuleBase) ApexVariations() []ApexInfo {
|
||||||
return m.apexVariations
|
return m.apexVariations
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) ApexName() string {
|
func (m *ApexModuleBase) ApexName() string {
|
||||||
return m.ApexProperties.ApexName
|
return m.ApexProperties.Info.ApexName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) IsForPlatform() bool {
|
func (m *ApexModuleBase) IsForPlatform() bool {
|
||||||
return m.ApexProperties.ApexName == ""
|
return m.ApexProperties.Info.ApexName == ""
|
||||||
}
|
|
||||||
|
|
||||||
func (m *ApexModuleBase) setApexName(apexName string) {
|
|
||||||
m.ApexProperties.ApexName = apexName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) CanHaveApexVariants() bool {
|
func (m *ApexModuleBase) CanHaveApexVariants() bool {
|
||||||
|
@ -185,25 +188,35 @@ func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type byApexName []ApexInfo
|
||||||
|
|
||||||
|
func (a byApexName) Len() int { return len(a) }
|
||||||
|
func (a byApexName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a byApexName) Less(i, j int) bool { return a[i].ApexName < a[j].ApexName }
|
||||||
|
|
||||||
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
|
func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
|
||||||
if len(m.apexVariations) > 0 {
|
if len(m.apexVariations) > 0 {
|
||||||
m.checkApexAvailableProperty(mctx)
|
m.checkApexAvailableProperty(mctx)
|
||||||
|
|
||||||
sort.Strings(m.apexVariations)
|
sort.Sort(byApexName(m.apexVariations))
|
||||||
variations := []string{}
|
variations := []string{}
|
||||||
variations = append(variations, "") // Original variation for platform
|
variations = append(variations, "") // Original variation for platform
|
||||||
variations = append(variations, m.apexVariations...)
|
for _, apex := range m.apexVariations {
|
||||||
|
variations = append(variations, apex.ApexName)
|
||||||
|
}
|
||||||
|
|
||||||
defaultVariation := ""
|
defaultVariation := ""
|
||||||
mctx.SetDefaultDependencyVariation(&defaultVariation)
|
mctx.SetDefaultDependencyVariation(&defaultVariation)
|
||||||
|
|
||||||
modules := mctx.CreateVariations(variations...)
|
modules := mctx.CreateVariations(variations...)
|
||||||
for i, m := range modules {
|
for i, mod := range modules {
|
||||||
platformVariation := i == 0
|
platformVariation := i == 0
|
||||||
if platformVariation && !mctx.Host() && !m.(ApexModule).AvailableFor(AvailableToPlatform) {
|
if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
|
||||||
m.SkipInstall()
|
mod.SkipInstall()
|
||||||
|
}
|
||||||
|
if !platformVariation {
|
||||||
|
mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1]
|
||||||
}
|
}
|
||||||
m.(ApexModule).setApexName(variations[i])
|
|
||||||
}
|
}
|
||||||
return modules
|
return modules
|
||||||
}
|
}
|
||||||
|
@ -230,16 +243,16 @@ func apexNamesMap() map[string]map[string]bool {
|
||||||
// depended on by the specified APEXes. Directly depending means that a module
|
// depended on by the specified APEXes. Directly depending means that a module
|
||||||
// is explicitly listed in the build definition of the APEX via properties like
|
// is explicitly listed in the build definition of the APEX via properties like
|
||||||
// native_shared_libs, java_libs, etc.
|
// native_shared_libs, java_libs, etc.
|
||||||
func UpdateApexDependency(apexNames []string, moduleName string, directDep bool) {
|
func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) {
|
||||||
apexNamesMapMutex.Lock()
|
apexNamesMapMutex.Lock()
|
||||||
defer apexNamesMapMutex.Unlock()
|
defer apexNamesMapMutex.Unlock()
|
||||||
for _, apexName := range apexNames {
|
for _, apex := range apexes {
|
||||||
apexesForModule, ok := apexNamesMap()[moduleName]
|
apexesForModule, ok := apexNamesMap()[moduleName]
|
||||||
if !ok {
|
if !ok {
|
||||||
apexesForModule = make(map[string]bool)
|
apexesForModule = make(map[string]bool)
|
||||||
apexNamesMap()[moduleName] = apexesForModule
|
apexNamesMap()[moduleName] = apexesForModule
|
||||||
}
|
}
|
||||||
apexesForModule[apexName] = apexesForModule[apexName] || directDep
|
apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
apex/apex.go
12
apex/apex.go
|
@ -1024,17 +1024,17 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
|
||||||
// Mark the direct and transitive dependencies of apex bundles so that they
|
// Mark the direct and transitive dependencies of apex bundles so that they
|
||||||
// can be built for the apex bundles.
|
// can be built for the apex bundles.
|
||||||
func apexDepsMutator(mctx android.TopDownMutatorContext) {
|
func apexDepsMutator(mctx android.TopDownMutatorContext) {
|
||||||
var apexBundleNames []string
|
var apexBundles []android.ApexInfo
|
||||||
var directDep bool
|
var directDep bool
|
||||||
if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
|
if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
|
||||||
apexBundleNames = []string{mctx.ModuleName()}
|
apexBundles = []android.ApexInfo{{mctx.ModuleName(), proptools.Bool(a.properties.Legacy_android10_support)}}
|
||||||
directDep = true
|
directDep = true
|
||||||
} else if am, ok := mctx.Module().(android.ApexModule); ok {
|
} else if am, ok := mctx.Module().(android.ApexModule); ok {
|
||||||
apexBundleNames = am.ApexVariations()
|
apexBundles = am.ApexVariations()
|
||||||
directDep = false
|
directDep = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(apexBundleNames) == 0 {
|
if len(apexBundles) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,8 +1042,8 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
|
||||||
depName := mctx.OtherModuleName(child)
|
depName := mctx.OtherModuleName(child)
|
||||||
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
|
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
|
||||||
(directDep || am.DepIsInSameApex(mctx, child)) {
|
(directDep || am.DepIsInSameApex(mctx, child)) {
|
||||||
android.UpdateApexDependency(apexBundleNames, depName, directDep)
|
android.UpdateApexDependency(apexBundles, depName, directDep)
|
||||||
am.BuildForApexes(apexBundleNames)
|
am.BuildForApexes(apexBundles)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3437,6 +3437,7 @@ func TestLegacyAndroid10Support(t *testing.T) {
|
||||||
apex {
|
apex {
|
||||||
name: "myapex",
|
name: "myapex",
|
||||||
key: "myapex.key",
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["mylib"],
|
||||||
legacy_android10_support: true,
|
legacy_android10_support: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3445,12 +3446,54 @@ func TestLegacyAndroid10Support(t *testing.T) {
|
||||||
public_key: "testkey.avbpubkey",
|
public_key: "testkey.avbpubkey",
|
||||||
private_key: "testkey.pem",
|
private_key: "testkey.pem",
|
||||||
}
|
}
|
||||||
`)
|
|
||||||
|
cc_library {
|
||||||
|
name: "mylib",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
stl: "libc++",
|
||||||
|
system_shared_libs: [],
|
||||||
|
apex_available: [ "myapex" ],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libc++",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
stl: "none",
|
||||||
|
system_shared_libs: [],
|
||||||
|
apex_available: [ "myapex" ],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library_static {
|
||||||
|
name: "libc++demangle",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
stl: "none",
|
||||||
|
system_shared_libs: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library_static {
|
||||||
|
name: "libunwind_llvm",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
stl: "none",
|
||||||
|
system_shared_libs: [],
|
||||||
|
}
|
||||||
|
`, withUnbundledBuild)
|
||||||
|
|
||||||
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
|
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
|
||||||
args := module.Rule("apexRule").Args
|
args := module.Rule("apexRule").Args
|
||||||
ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
|
ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
|
||||||
ensureNotContains(t, args["opt_flags"], "--no_hashtree")
|
ensureNotContains(t, args["opt_flags"], "--no_hashtree")
|
||||||
|
|
||||||
|
// The copies of the libraries in the apex should have one more dependency than
|
||||||
|
// the ones outside the apex, namely the unwinder. Ideally we should check
|
||||||
|
// the dependency names directly here but for some reason the names are blank in
|
||||||
|
// this test.
|
||||||
|
for _, lib := range []string{"libc++", "mylib"} {
|
||||||
|
apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_myapex").Rule("ld").Implicits
|
||||||
|
nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
|
||||||
|
if len(apexImplicits) != len(nonApexImplicits)+1 {
|
||||||
|
t.Errorf("%q missing unwinder dep", lib)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJavaSDKLibrary(t *testing.T) {
|
func TestJavaSDKLibrary(t *testing.T) {
|
||||||
|
|
17
cc/cc.go
17
cc/cc.go
|
@ -95,6 +95,8 @@ type Deps struct {
|
||||||
HeaderLibs []string
|
HeaderLibs []string
|
||||||
RuntimeLibs []string
|
RuntimeLibs []string
|
||||||
|
|
||||||
|
StaticUnwinderIfLegacy bool
|
||||||
|
|
||||||
ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string
|
ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string
|
||||||
|
|
||||||
ObjFiles []string
|
ObjFiles []string
|
||||||
|
@ -385,6 +387,7 @@ var (
|
||||||
lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true}
|
lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true}
|
||||||
staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true}
|
staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true}
|
||||||
lateStaticDepTag = DependencyTag{Name: "late static", Library: true}
|
lateStaticDepTag = DependencyTag{Name: "late static", Library: true}
|
||||||
|
staticUnwinderDepTag = DependencyTag{Name: "static unwinder", Library: true}
|
||||||
wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true}
|
wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true}
|
||||||
headerDepTag = DependencyTag{Name: "header", Library: true}
|
headerDepTag = DependencyTag{Name: "header", Library: true}
|
||||||
headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true}
|
headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true}
|
||||||
|
@ -1796,6 +1799,12 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||||
}, depTag, lib)
|
}, depTag, lib)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() {
|
||||||
|
actx.AddVariationDependencies([]blueprint.Variation{
|
||||||
|
{Mutator: "link", Variation: "static"},
|
||||||
|
}, staticUnwinderDepTag, staticUnwinder(actx))
|
||||||
|
}
|
||||||
|
|
||||||
for _, lib := range deps.LateStaticLibs {
|
for _, lib := range deps.LateStaticLibs {
|
||||||
actx.AddVariationDependencies([]blueprint.Variation{
|
actx.AddVariationDependencies([]blueprint.Variation{
|
||||||
{Mutator: "link", Variation: "static"},
|
{Mutator: "link", Variation: "static"},
|
||||||
|
@ -2169,6 +2178,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if depTag == staticUnwinderDepTag {
|
||||||
|
if c.ApexProperties.Info.LegacyAndroid10Support {
|
||||||
|
depTag = StaticDepTag
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Extract ExplicitlyVersioned field from the depTag and reset it inside the struct.
|
// Extract ExplicitlyVersioned field from the depTag and reset it inside the struct.
|
||||||
// Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true
|
// Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true
|
||||||
// won't be matched to SharedDepTag and lateSharedDepTag.
|
// won't be matched to SharedDepTag and lateSharedDepTag.
|
||||||
|
|
20
cc/stl.go
20
cc/stl.go
|
@ -151,6 +151,14 @@ func needsLibAndroidSupport(ctx BaseModuleContext) bool {
|
||||||
return version < 21
|
return version < 21
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func staticUnwinder(ctx android.BaseModuleContext) string {
|
||||||
|
if ctx.Arch().ArchType == android.Arm {
|
||||||
|
return "libunwind_llvm"
|
||||||
|
} else {
|
||||||
|
return "libgcc_stripped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
|
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
|
||||||
switch stl.Properties.SelectedStl {
|
switch stl.Properties.SelectedStl {
|
||||||
case "libstdc++":
|
case "libstdc++":
|
||||||
|
@ -172,16 +180,16 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
|
||||||
}
|
}
|
||||||
if ctx.toolchain().Bionic() {
|
if ctx.toolchain().Bionic() {
|
||||||
if ctx.staticBinary() {
|
if ctx.staticBinary() {
|
||||||
deps.StaticLibs = append(deps.StaticLibs, "libm", "libc")
|
deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx))
|
||||||
if ctx.Arch().ArchType == android.Arm {
|
} else {
|
||||||
deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm")
|
deps.StaticUnwinderIfLegacy = true
|
||||||
} else {
|
|
||||||
deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "":
|
case "":
|
||||||
// None or error.
|
// None or error.
|
||||||
|
if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" {
|
||||||
|
deps.StaticUnwinderIfLegacy = true
|
||||||
|
}
|
||||||
case "ndk_system":
|
case "ndk_system":
|
||||||
// TODO: Make a system STL prebuilt for the NDK.
|
// TODO: Make a system STL prebuilt for the NDK.
|
||||||
// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
|
// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
|
||||||
|
|
Loading…
Reference in a new issue