Convert LTO mutators to TransitionMutator
Convert ltoDepsMutator and ltoMutator to a TransitionMutator as a step towards variants-on-demand. Bug: 319288033 Test: lto_test.go Change-Id: I2c9af73fd526adf58ff626831ababea466338205
This commit is contained in:
parent
f5f4ad3db6
commit
6ac83a8f85
3 changed files with 78 additions and 83 deletions
3
cc/cc.go
3
cc/cc.go
|
@ -76,8 +76,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) {
|
||||||
ctx.TopDown("orderfile_deps", orderfileDepsMutator)
|
ctx.TopDown("orderfile_deps", orderfileDepsMutator)
|
||||||
ctx.BottomUp("orderfile", orderfileMutator).Parallel()
|
ctx.BottomUp("orderfile", orderfileMutator).Parallel()
|
||||||
|
|
||||||
ctx.TopDown("lto_deps", ltoDepsMutator)
|
ctx.Transition("lto", <oTransitionMutator{})
|
||||||
ctx.BottomUp("lto", ltoMutator).Parallel()
|
|
||||||
|
|
||||||
ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
|
ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
|
||||||
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
|
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
|
||||||
|
|
153
cc/lto.go
153
cc/lto.go
|
@ -15,9 +15,12 @@
|
||||||
package cc
|
package cc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
"github.com/google/blueprint/proptools"
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LTO (link-time optimization) allows the compiler to optimize and generate
|
// LTO (link-time optimization) allows the compiler to optimize and generate
|
||||||
|
@ -49,11 +52,6 @@ type LTOProperties struct {
|
||||||
LtoEnabled bool `blueprint:"mutated"`
|
LtoEnabled bool `blueprint:"mutated"`
|
||||||
LtoDefault bool `blueprint:"mutated"`
|
LtoDefault bool `blueprint:"mutated"`
|
||||||
|
|
||||||
// Dep properties indicate that this module needs to be built with LTO
|
|
||||||
// since it is an object dependency of an LTO module.
|
|
||||||
LtoDep bool `blueprint:"mutated"`
|
|
||||||
NoLtoDep bool `blueprint:"mutated"`
|
|
||||||
|
|
||||||
// Use -fwhole-program-vtables cflag.
|
// Use -fwhole-program-vtables cflag.
|
||||||
Whole_program_vtables *bool
|
Whole_program_vtables *bool
|
||||||
}
|
}
|
||||||
|
@ -176,86 +174,83 @@ func (lto *lto) Never() bool {
|
||||||
return lto != nil && proptools.Bool(lto.Properties.Lto.Never)
|
return lto != nil && proptools.Bool(lto.Properties.Lto.Never)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate lto requirements down from binaries
|
func ltoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
|
||||||
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
|
libTag, isLibTag := tag.(libraryDependencyTag)
|
||||||
if m, ok := mctx.Module().(*Module); ok {
|
// Do not recurse down non-static dependencies
|
||||||
if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault {
|
if isLibTag {
|
||||||
return
|
return libTag.static()
|
||||||
}
|
} else {
|
||||||
|
return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
|
||||||
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
|
|
||||||
tag := mctx.OtherModuleDependencyTag(dep)
|
|
||||||
libTag, isLibTag := tag.(libraryDependencyTag)
|
|
||||||
|
|
||||||
// Do not recurse down non-static dependencies
|
|
||||||
if isLibTag {
|
|
||||||
if !libTag.static() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if tag != objDepTag && tag != reuseObjTag {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if dep, ok := dep.(*Module); ok {
|
|
||||||
if m.lto.Properties.LtoEnabled {
|
|
||||||
dep.lto.Properties.LtoDep = true
|
|
||||||
} else {
|
|
||||||
dep.lto.Properties.NoLtoDep = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively walk static dependencies
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create lto variants for modules that need them
|
// ltoTransitionMutator creates LTO variants of cc modules. Variant "" is the default variant, which may
|
||||||
func ltoMutator(mctx android.BottomUpMutatorContext) {
|
// or may not have LTO enabled depending on the config and the module's type and properties. "lto-thin" or
|
||||||
if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
|
// "lto-none" variants are created when a module needs to compile in the non-default state for that module.
|
||||||
// Create variations for LTO types required as static
|
type ltoTransitionMutator struct{}
|
||||||
// dependencies
|
|
||||||
variationNames := []string{""}
|
const LTO_NONE_VARIATION = "lto-none"
|
||||||
if m.lto.Properties.LtoDep {
|
const LTO_THIN_VARIATION = "lto-thin"
|
||||||
variationNames = append(variationNames, "lto-thin")
|
|
||||||
}
|
func (l *ltoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
|
||||||
if m.lto.Properties.NoLtoDep {
|
return []string{""}
|
||||||
variationNames = append(variationNames, "lto-none")
|
}
|
||||||
|
|
||||||
|
func (l *ltoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
|
||||||
|
if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
|
||||||
|
if !ltoPropagateViaDepTag(ctx.DepTag()) {
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if !m.lto.Properties.LtoEnabled {
|
if sourceVariation != "" {
|
||||||
mctx.SetDependencyVariation("lto-none")
|
return sourceVariation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always request an explicit variation, IncomingTransition will rewrite it back to the default variation
|
||||||
|
// if necessary.
|
||||||
if m.lto.Properties.LtoEnabled {
|
if m.lto.Properties.LtoEnabled {
|
||||||
mctx.SetDependencyVariation("lto-thin")
|
return LTO_THIN_VARIATION
|
||||||
}
|
} else {
|
||||||
|
return LTO_NONE_VARIATION
|
||||||
if len(variationNames) > 1 {
|
|
||||||
modules := mctx.CreateVariations(variationNames...)
|
|
||||||
for i, name := range variationNames {
|
|
||||||
variation := modules[i].(*Module)
|
|
||||||
// Default module which will be
|
|
||||||
// installed. Variation set above according to
|
|
||||||
// explicit LTO properties
|
|
||||||
if name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// LTO properties for dependencies
|
|
||||||
if name == "lto-thin" {
|
|
||||||
variation.lto.Properties.LtoEnabled = true
|
|
||||||
}
|
|
||||||
if name == "lto-none" {
|
|
||||||
variation.lto.Properties.LtoEnabled = false
|
|
||||||
}
|
|
||||||
variation.Properties.PreventInstall = true
|
|
||||||
variation.Properties.HideFromMake = true
|
|
||||||
variation.lto.Properties.LtoDefault = m.lto.Properties.LtoDefault
|
|
||||||
variation.lto.Properties.LtoDep = false
|
|
||||||
variation.lto.Properties.NoLtoDep = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ltoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
|
||||||
|
if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
|
||||||
|
if m.lto.Never() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// Rewrite explicit variations back to the default variation if the default variation matches.
|
||||||
|
if incomingVariation == LTO_THIN_VARIATION && m.lto.Properties.LtoDefault {
|
||||||
|
return ""
|
||||||
|
} else if incomingVariation == LTO_NONE_VARIATION && !m.lto.Properties.LtoDefault {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return incomingVariation
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ltoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
|
||||||
|
// Default module which will be installed. Variation set above according to explicit LTO properties.
|
||||||
|
if variation == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
|
||||||
|
// Non-default variation, set the LTO properties to match the variation.
|
||||||
|
switch variation {
|
||||||
|
case LTO_THIN_VARIATION:
|
||||||
|
m.lto.Properties.LtoEnabled = true
|
||||||
|
case LTO_NONE_VARIATION:
|
||||||
|
m.lto.Properties.LtoEnabled = false
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown variation %s", variation))
|
||||||
|
}
|
||||||
|
// Non-default variations are never installed.
|
||||||
|
m.Properties.PreventInstall = true
|
||||||
|
m.Properties.HideFromMake = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,8 +146,9 @@ func TestThinLtoOnlyOnStaticDep(t *testing.T) {
|
||||||
t.Errorf("'root' missing dependency on the default variant of 'foo'")
|
t.Errorf("'root' missing dependency on the default variant of 'foo'")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasDep(result, libRootLtoNever, libFoo.Module()) {
|
libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none")
|
||||||
t.Errorf("'root_no_lto' missing dependency on the default variant of 'foo'")
|
if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) {
|
||||||
|
t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'")
|
||||||
}
|
}
|
||||||
|
|
||||||
libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
|
libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
|
||||||
|
|
Loading…
Reference in a new issue