Add Global ThinLTO option (2nd try)

Instead of making everything into ThinLTO variant by default (it works
but many Soong tests don't like this, and got bit rot due to lack of
active builder for this configuration), let the default option be
ThinLTO and no LTO be a special variant.

Test: m GLOBAL_THINLTO=true
Test: m
Bug: 195134194
Change-Id: I2fd98061ba55eba1fdfdd056fb2f8c2051fd2553
This commit is contained in:
Yi Kong
2021-10-14 01:07:42 +08:00
parent ddf4ebae19
commit 8ea56f9da9

View File

@@ -51,6 +51,7 @@ type LTOProperties struct {
// since it is an object dependency of an LTO module. // since it is an object dependency of an LTO module.
FullDep bool `blueprint:"mutated"` FullDep bool `blueprint:"mutated"`
ThinDep bool `blueprint:"mutated"` ThinDep bool `blueprint:"mutated"`
NoLtoDep bool `blueprint:"mutated"`
// Use clang lld instead of gnu ld. // Use clang lld instead of gnu ld.
Use_clang_lld *bool Use_clang_lld *bool
@@ -70,15 +71,6 @@ func (lto *lto) props() []interface{} {
func (lto *lto) begin(ctx BaseModuleContext) { func (lto *lto) begin(ctx BaseModuleContext) {
if ctx.Config().IsEnvTrue("DISABLE_LTO") { if ctx.Config().IsEnvTrue("DISABLE_LTO") {
lto.Properties.Lto.Never = proptools.BoolPtr(true) lto.Properties.Lto.Never = proptools.BoolPtr(true)
} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
staticLib := ctx.static() && !ctx.staticBinary()
hostBin := ctx.Host()
vndk := ctx.isVndk() // b/169217596
if !staticLib && !hostBin && !vndk {
if !lto.Never() && !lto.FullLTO() {
lto.Properties.Lto.Thin = proptools.BoolPtr(true)
}
}
} }
} }
@@ -96,22 +88,27 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
return flags return flags
} }
if lto.LTO() { if lto.LTO(ctx) {
var ltoFlag string var ltoCFlag string
var ltoLdFlag string
if lto.ThinLTO() { if lto.ThinLTO() {
ltoFlag = "-flto=thin -fsplit-lto-unit" ltoCFlag = "-flto=thin -fsplit-lto-unit"
} else if lto.FullLTO() {
ltoCFlag = "-flto"
} else { } else {
ltoFlag = "-flto" ltoCFlag = "-flto=thin -fsplit-lto-unit"
ltoLdFlag = "-Wl,--lto-O0"
} }
flags.Local.CFlags = append(flags.Local.CFlags, ltoFlag) flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlag)
flags.Local.LdFlags = append(flags.Local.LdFlags, ltoFlag) flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlag)
flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlag)
if Bool(lto.Properties.Whole_program_vtables) { if Bool(lto.Properties.Whole_program_vtables) {
flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables") flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
} }
if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) { if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
// Set appropriate ThinLTO cache policy // Set appropriate ThinLTO cache policy
cacheDirFormat := "-Wl,--thinlto-cache-dir=" cacheDirFormat := "-Wl,--thinlto-cache-dir="
cacheDir := android.PathForOutput(ctx, "thinlto-cache").String() cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
@@ -134,33 +131,40 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
return flags return flags
} }
// Can be called with a null receiver func (lto *lto) LTO(ctx BaseModuleContext) bool {
func (lto *lto) LTO() bool { return lto.ThinLTO() || lto.FullLTO() || lto.DefaultThinLTO(ctx)
if lto == nil || lto.Never() { }
return false
}
return lto.FullLTO() || lto.ThinLTO() func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
host := ctx.Host()
vndk := ctx.isVndk() // b/169217596
return GlobalThinLTO(ctx) && !lto.Never() && !host && !vndk
} }
func (lto *lto) FullLTO() bool { func (lto *lto) FullLTO() bool {
return Bool(lto.Properties.Lto.Full) return lto != nil && Bool(lto.Properties.Lto.Full)
} }
func (lto *lto) ThinLTO() bool { func (lto *lto) ThinLTO() bool {
return Bool(lto.Properties.Lto.Thin) return lto != nil && Bool(lto.Properties.Lto.Thin)
} }
// Is lto.never explicitly set to true?
func (lto *lto) Never() bool { func (lto *lto) Never() bool {
return Bool(lto.Properties.Lto.Never) return lto != nil && Bool(lto.Properties.Lto.Never)
}
func GlobalThinLTO(ctx android.BaseModuleContext) bool {
return ctx.Config().IsEnvTrue("GLOBAL_THINLTO")
} }
// Propagate lto requirements down from binaries // Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) { func ltoDepsMutator(mctx android.TopDownMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() { globalThinLTO := GlobalThinLTO(mctx)
if m, ok := mctx.Module().(*Module); ok {
full := m.lto.FullLTO() full := m.lto.FullLTO()
thin := m.lto.ThinLTO() thin := m.lto.ThinLTO()
never := m.lto.Never()
if full && thin { if full && thin {
mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive") mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
} }
@@ -180,14 +184,16 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) {
} }
} }
if dep, ok := dep.(*Module); ok && dep.lto != nil && if dep, ok := dep.(*Module); ok {
!dep.lto.Never() {
if full && !dep.lto.FullLTO() { if full && !dep.lto.FullLTO() {
dep.lto.Properties.FullDep = true dep.lto.Properties.FullDep = true
} }
if thin && !dep.lto.ThinLTO() { if !globalThinLTO && thin && !dep.lto.ThinLTO() {
dep.lto.Properties.ThinDep = true dep.lto.Properties.ThinDep = true
} }
if globalThinLTO && never && !dep.lto.Never() {
dep.lto.Properties.NoLtoDep = true
}
} }
// Recursively walk static dependencies // Recursively walk static dependencies
@@ -198,6 +204,8 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) {
// Create lto variants for modules that need them // Create lto variants for modules that need them
func ltoMutator(mctx android.BottomUpMutatorContext) { func ltoMutator(mctx android.BottomUpMutatorContext) {
globalThinLTO := GlobalThinLTO(mctx)
if m, ok := mctx.Module().(*Module); ok && m.lto != nil { if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
// Create variations for LTO types required as static // Create variations for LTO types required as static
// dependencies // dependencies
@@ -205,18 +213,25 @@ func ltoMutator(mctx android.BottomUpMutatorContext) {
if m.lto.Properties.FullDep && !m.lto.FullLTO() { if m.lto.Properties.FullDep && !m.lto.FullLTO() {
variationNames = append(variationNames, "lto-full") variationNames = append(variationNames, "lto-full")
} }
if m.lto.Properties.ThinDep && !m.lto.ThinLTO() { if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
variationNames = append(variationNames, "lto-thin") variationNames = append(variationNames, "lto-thin")
} }
if globalThinLTO && m.lto.Properties.NoLtoDep && !m.lto.Never() {
variationNames = append(variationNames, "lto-none")
}
// Use correct dependencies if LTO property is explicitly set // Use correct dependencies if LTO property is explicitly set
// (mutually exclusive) // (mutually exclusive)
if m.lto.FullLTO() { if m.lto.FullLTO() {
mctx.SetDependencyVariation("lto-full") mctx.SetDependencyVariation("lto-full")
} }
if m.lto.ThinLTO() { if !globalThinLTO && m.lto.ThinLTO() {
mctx.SetDependencyVariation("lto-thin") mctx.SetDependencyVariation("lto-thin")
} }
// Never must be the last, it overrides Thin or Full.
if globalThinLTO && m.lto.Never() {
mctx.SetDependencyVariation("lto-none")
}
if len(variationNames) > 1 { if len(variationNames) > 1 {
modules := mctx.CreateVariations(variationNames...) modules := mctx.CreateVariations(variationNames...)
@@ -232,16 +247,18 @@ func ltoMutator(mctx android.BottomUpMutatorContext) {
// LTO properties for dependencies // LTO properties for dependencies
if name == "lto-full" { if name == "lto-full" {
variation.lto.Properties.Lto.Full = proptools.BoolPtr(true) variation.lto.Properties.Lto.Full = proptools.BoolPtr(true)
variation.lto.Properties.Lto.Thin = proptools.BoolPtr(false)
} }
if name == "lto-thin" { if name == "lto-thin" {
variation.lto.Properties.Lto.Full = proptools.BoolPtr(false)
variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true) variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true)
} }
if name == "lto-none" {
variation.lto.Properties.Lto.Never = proptools.BoolPtr(true)
}
variation.Properties.PreventInstall = true variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true variation.Properties.HideFromMake = true
variation.lto.Properties.FullDep = false variation.lto.Properties.FullDep = false
variation.lto.Properties.ThinDep = false variation.lto.Properties.ThinDep = false
variation.lto.Properties.NoLtoDep = false
} }
} }
} }