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

Commit d8b80bc6 authored by Peter Collingbourne's avatar Peter Collingbourne Committed by Gerrit Code Review
Browse files

Merge "Statically link the unwinder into binaries packaged into an unbundled...

Merge "Statically link the unwinder into binaries packaged into an unbundled APEX with legacy_android10_support: true."
parents ab392f61 dc4f986b
Loading
Loading
Loading
Loading
+44 −31
Original line number Diff line number Diff line
@@ -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
	}
}

+6 −6
Original line number Diff line number Diff line
@@ -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)
		}
	})
}
+44 −1
Original line number Diff line number Diff line
@@ -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) {
+17 −0
Original line number Diff line number Diff line
@@ -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.
+14 −6
Original line number Diff line number Diff line
@@ -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")
				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx))
			} else {
					deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped")
				}
				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