diff options
| author | 2024-01-23 11:23:10 -0800 | |
|---|---|---|
| committer | 2024-01-26 11:06:45 -0800 | |
| commit | 6ac83a8f85529a8261b2988221c60ce388f6b5bc (patch) | |
| tree | cfbcbf1643563cd22ab92f7d4429e8df861bafb2 | |
| parent | f5f4ad3db6b3c0a58381ed808467c174491adbb3 (diff) | |
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
| -rw-r--r-- | cc/cc.go | 3 | ||||
| -rw-r--r-- | cc/lto.go | 145 | ||||
| -rw-r--r-- | cc/lto_test.go | 5 |
3 files changed, 74 insertions, 79 deletions
@@ -76,8 +76,7 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.TopDown("orderfile_deps", orderfileDepsMutator) ctx.BottomUp("orderfile", orderfileMutator).Parallel() - ctx.TopDown("lto_deps", ltoDepsMutator) - ctx.BottomUp("lto", ltoMutator).Parallel() + ctx.Transition("lto", <oTransitionMutator{}) ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel() ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel() @@ -15,9 +15,12 @@ package cc import ( - "android/soong/android" + "fmt" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" + + "android/soong/android" ) // LTO (link-time optimization) allows the compiler to optimize and generate @@ -49,11 +52,6 @@ type LTOProperties struct { LtoEnabled 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. Whole_program_vtables *bool } @@ -176,86 +174,83 @@ func (lto *lto) Never() bool { return lto != nil && proptools.Bool(lto.Properties.Lto.Never) } -// Propagate lto requirements down from binaries -func ltoDepsMutator(mctx android.TopDownMutatorContext) { - if m, ok := mctx.Module().(*Module); ok { - if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault { - return - } - - mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { - tag := mctx.OtherModuleDependencyTag(dep) - libTag, isLibTag := tag.(libraryDependencyTag) +func ltoPropagateViaDepTag(tag blueprint.DependencyTag) bool { + libTag, isLibTag := tag.(libraryDependencyTag) + // Do not recurse down non-static dependencies + if isLibTag { + return libTag.static() + } else { + return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag + } +} - // Do not recurse down non-static dependencies - if isLibTag { - if !libTag.static() { - return false - } - } else { - if tag != objDepTag && tag != reuseObjTag { - return false - } - } +// ltoTransitionMutator creates LTO variants of cc modules. Variant "" is the default variant, which may +// or may not have LTO enabled depending on the config and the module's type and properties. "lto-thin" or +// "lto-none" variants are created when a module needs to compile in the non-default state for that module. +type ltoTransitionMutator struct{} - if dep, ok := dep.(*Module); ok { - if m.lto.Properties.LtoEnabled { - dep.lto.Properties.LtoDep = true - } else { - dep.lto.Properties.NoLtoDep = true - } - } +const LTO_NONE_VARIATION = "lto-none" +const LTO_THIN_VARIATION = "lto-thin" - // Recursively walk static dependencies - return true - }) - } +func (l *ltoTransitionMutator) Split(ctx android.BaseModuleContext) []string { + return []string{""} } -// Create lto variants for modules that need them -func ltoMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && m.lto != nil { - // Create variations for LTO types required as static - // dependencies - variationNames := []string{""} - if m.lto.Properties.LtoDep { - variationNames = append(variationNames, "lto-thin") - } - if m.lto.Properties.NoLtoDep { - 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 { - mctx.SetDependencyVariation("lto-none") + if sourceVariation != "" { + return sourceVariation } + + // Always request an explicit variation, IncomingTransition will rewrite it back to the default variation + // if necessary. if m.lto.Properties.LtoEnabled { - mctx.SetDependencyVariation("lto-thin") + return LTO_THIN_VARIATION + } else { + return LTO_NONE_VARIATION } + } + return "" +} - 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 - } +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 } } diff --git a/cc/lto_test.go b/cc/lto_test.go index 7b7fe8c8a..e4b5a3a01 100644 --- a/cc/lto_test.go +++ b/cc/lto_test.go @@ -146,8 +146,9 @@ func TestThinLtoOnlyOnStaticDep(t *testing.T) { t.Errorf("'root' missing dependency on the default variant of 'foo'") } - if !hasDep(result, libRootLtoNever, libFoo.Module()) { - t.Errorf("'root_no_lto' missing dependency on the default variant of 'foo'") + libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none") + 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"] |