diff --git a/android/apex.go b/android/apex.go index 17ec9b195..43a42df9b 100644 --- a/android/apex.go +++ b/android/apex.go @@ -19,6 +19,14 @@ import ( "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 // 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). @@ -38,12 +46,12 @@ type ApexModule interface { Module 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. - BuildForApexes(apexNames []string) + BuildForApexes(apexes []ApexInfo) - // Returns the name of the APEXes that this modoule will be built for - ApexVariations() []string + // Returns the APEXes that this module will be built for + ApexVariations() []ApexInfo // 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 @@ -72,10 +80,6 @@ type ApexModule interface { // for an APEX marked via BuildForApexes(). 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" AvailableFor(what string) bool @@ -94,8 +98,7 @@ type ApexProperties struct { // Default is ["//apex_available:platform"]. Apex_available []string - // Name of the apex variant that this module is mutated into - ApexName string `blueprint:"mutated"` + Info ApexInfo `blueprint:"mutated"` } // Provides default implementation for the ApexModule interface. APEX-aware @@ -106,37 +109,37 @@ type ApexModuleBase struct { canHaveApexVariants bool apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator - apexVariations []string + apexVariations []ApexInfo } func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase { return m } -func (m *ApexModuleBase) BuildForApexes(apexNames []string) { +func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) { m.apexVariationsLock.Lock() defer m.apexVariationsLock.Unlock() - for _, apexName := range apexNames { - if !InList(apexName, m.apexVariations) { - m.apexVariations = append(m.apexVariations, apexName) +nextApex: + for _, apex := range apexes { + 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 } func (m *ApexModuleBase) ApexName() string { - return m.ApexProperties.ApexName + return m.ApexProperties.Info.ApexName } func (m *ApexModuleBase) IsForPlatform() bool { - return m.ApexProperties.ApexName == "" -} - -func (m *ApexModuleBase) setApexName(apexName string) { - m.ApexProperties.ApexName = apexName + return m.ApexProperties.Info.ApexName == "" } 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 { if len(m.apexVariations) > 0 { m.checkApexAvailableProperty(mctx) - sort.Strings(m.apexVariations) + sort.Sort(byApexName(m.apexVariations)) variations := []string{} variations = append(variations, "") // Original variation for platform - variations = append(variations, m.apexVariations...) + for _, apex := range m.apexVariations { + variations = append(variations, apex.ApexName) + } defaultVariation := "" mctx.SetDefaultDependencyVariation(&defaultVariation) modules := mctx.CreateVariations(variations...) - for i, m := range modules { + for i, mod := range modules { platformVariation := i == 0 - if platformVariation && !mctx.Host() && !m.(ApexModule).AvailableFor(AvailableToPlatform) { - m.SkipInstall() + if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) { + mod.SkipInstall() + } + if !platformVariation { + mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1] } - m.(ApexModule).setApexName(variations[i]) } 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 // is explicitly listed in the build definition of the APEX via properties like // native_shared_libs, java_libs, etc. -func UpdateApexDependency(apexNames []string, moduleName string, directDep bool) { +func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) { apexNamesMapMutex.Lock() defer apexNamesMapMutex.Unlock() - for _, apexName := range apexNames { + for _, apex := range apexes { apexesForModule, ok := apexNamesMap()[moduleName] if !ok { apexesForModule = make(map[string]bool) apexNamesMap()[moduleName] = apexesForModule } - apexesForModule[apexName] = apexesForModule[apexName] || directDep + apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep } } diff --git a/apex/apex.go b/apex/apex.go index 54a335a5f..002bf5be7 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1024,17 +1024,17 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { // Mark the direct and transitive dependencies of apex bundles so that they // can be built for the apex bundles. func apexDepsMutator(mctx android.TopDownMutatorContext) { - var apexBundleNames []string + var apexBundles []android.ApexInfo var directDep bool 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 } else if am, ok := mctx.Module().(android.ApexModule); ok { - apexBundleNames = am.ApexVariations() + apexBundles = am.ApexVariations() directDep = false } - if len(apexBundleNames) == 0 { + if len(apexBundles) == 0 { return } @@ -1042,8 +1042,8 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { depName := mctx.OtherModuleName(child) if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && (directDep || am.DepIsInSameApex(mctx, child)) { - android.UpdateApexDependency(apexBundleNames, depName, directDep) - am.BuildForApexes(apexBundleNames) + android.UpdateApexDependency(apexBundles, depName, directDep) + am.BuildForApexes(apexBundles) } }) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 0420586de..5000c8803 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3437,6 +3437,7 @@ func TestLegacyAndroid10Support(t *testing.T) { apex { name: "myapex", key: "myapex.key", + native_shared_libs: ["mylib"], legacy_android10_support: true, } @@ -3445,12 +3446,54 @@ func TestLegacyAndroid10Support(t *testing.T) { public_key: "testkey.avbpubkey", 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") args := module.Rule("apexRule").Args ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String()) 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) { diff --git a/cc/cc.go b/cc/cc.go index b70e55c88..5af8459a2 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -95,6 +95,8 @@ type Deps struct { HeaderLibs []string RuntimeLibs []string + StaticUnwinderIfLegacy bool + ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string ObjFiles []string @@ -385,6 +387,7 @@ var ( lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true} staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true} lateStaticDepTag = DependencyTag{Name: "late static", Library: true} + staticUnwinderDepTag = DependencyTag{Name: "static unwinder", Library: true} wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true} headerDepTag = DependencyTag{Name: "header", Library: true} headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true} @@ -1788,6 +1791,12 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { }, depTag, lib) } + if deps.StaticUnwinderIfLegacy && ctx.Config().UnbundledBuild() { + actx.AddVariationDependencies([]blueprint.Variation{ + {Mutator: "link", Variation: "static"}, + }, staticUnwinderDepTag, staticUnwinder(actx)) + } + for _, lib := range deps.LateStaticLibs { actx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, @@ -2161,6 +2170,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. // Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true // won't be matched to SharedDepTag and lateSharedDepTag. diff --git a/cc/stl.go b/cc/stl.go index af015f91d..eda8a4ffc 100644 --- a/cc/stl.go +++ b/cc/stl.go @@ -151,6 +151,14 @@ func needsLibAndroidSupport(ctx BaseModuleContext) bool { 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 { switch stl.Properties.SelectedStl { case "libstdc++": @@ -172,16 +180,16 @@ func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { } if ctx.toolchain().Bionic() { if ctx.staticBinary() { - deps.StaticLibs = append(deps.StaticLibs, "libm", "libc") - if ctx.Arch().ArchType == android.Arm { - deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm") - } else { - deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped") - } + deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx)) + } else { + deps.StaticUnwinderIfLegacy = true } } case "": // None or error. + if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" { + deps.StaticUnwinderIfLegacy = true + } case "ndk_system": // 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