blob: b6bc9961db6e8ec91095c47b12a850c3d66c0610 [file] [log] [blame]
Stephen Craneba090d12017-05-09 15:44:35 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18 "github.com/google/blueprint"
19
20 "android/soong/android"
21)
22
23// LTO (link-time optimization) allows the compiler to optimize and generate
24// code for the entire module at link time, rather than per-compilation
25// unit. LTO is required for Clang CFI and other whole-program optimization
26// techniques. LTO also allows cross-compilation unit optimizations that should
27// result in faster and smaller code, at the expense of additional compilation
28// time.
29//
30// To properly build a module with LTO, the module and all recursive static
31// dependencies should be compiled with -flto which directs the compiler to emit
32// bitcode rather than native object files. These bitcode files are then passed
33// by the linker to the LLVM plugin for compilation at link time. Static
34// dependencies not built as bitcode will still function correctly but cannot be
35// optimized at link time and may not be compatible with features that require
36// LTO, such as CFI.
37//
38// This file adds support to soong to automatically propogate LTO options to a
39// new variant of all static dependencies for each module with LTO enabled.
40
41type LTOProperties struct {
42 // Lto must violate capitialization style for acronyms so that it can be
43 // referred to in blueprint files as "lto"
44 Lto *bool `android:"arch_variant"`
45 LTODep bool `blueprint:"mutated"`
46}
47
48type lto struct {
49 Properties LTOProperties
50}
51
52func (lto *lto) props() []interface{} {
53 return []interface{}{&lto.Properties}
54}
55
56func (lto *lto) begin(ctx BaseModuleContext) {
57}
58
59func (lto *lto) deps(ctx BaseModuleContext, deps Deps) Deps {
60 return deps
61}
62
63func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags {
64 if Bool(lto.Properties.Lto) {
65 flags.CFlags = append(flags.CFlags, "-flto")
66 flags.LdFlags = append(flags.LdFlags, "-flto")
67 flags.ArFlags = append(flags.ArFlags, " --plugin ${config.LLVMGoldPlugin}")
68 }
69 return flags
70}
71
72// Can be called with a null receiver
73func (lto *lto) LTO() bool {
74 if lto == nil {
75 return false
76 }
77
78 return Bool(lto.Properties.Lto)
79}
80
81// Propagate lto requirements down from binaries
82func ltoDepsMutator(mctx android.TopDownMutatorContext) {
83 if c, ok := mctx.Module().(*Module); ok && c.lto.LTO() {
84 mctx.VisitDepsDepthFirst(func(m blueprint.Module) {
85 tag := mctx.OtherModuleDependencyTag(m)
86 switch tag {
87 case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
88 if cc, ok := m.(*Module); ok && cc.lto != nil {
89 cc.lto.Properties.LTODep = true
90 }
91 }
92 })
93 }
94}
95
96// Create lto variants for modules that need them
97func ltoMutator(mctx android.BottomUpMutatorContext) {
98 if c, ok := mctx.Module().(*Module); ok && c.lto != nil {
99 if c.lto.LTO() {
100 mctx.SetDependencyVariation("lto")
101 } else if c.lto.Properties.LTODep {
102 modules := mctx.CreateVariations("", "lto")
103 modules[0].(*Module).lto.Properties.Lto = boolPtr(false)
104 modules[1].(*Module).lto.Properties.Lto = boolPtr(true)
105 modules[0].(*Module).lto.Properties.LTODep = false
106 modules[1].(*Module).lto.Properties.LTODep = false
107 modules[1].(*Module).Properties.PreventInstall = true
108 modules[1].(*Module).Properties.HideFromMake = true
109 }
110 c.lto.Properties.LTODep = false
111 }
112}