blob: be4f50adb83eb5418aa5e3de5a1bb30e6561728c [file] [log] [blame]
Yi Kongeb8efc92021-12-09 18:06:29 +08001// Copyright 2021 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 "fmt"
19 "strings"
20
Yi Kongeb8efc92021-12-09 18:06:29 +080021 "android/soong/android"
Vinh Tran44cb78c2023-03-09 22:07:19 -050022
23 "github.com/google/blueprint"
24 "github.com/google/blueprint/proptools"
Yi Kongeb8efc92021-12-09 18:06:29 +080025)
26
Vinh Trancde10162023-03-09 22:07:19 -050027// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
Yi Kongeb8efc92021-12-09 18:06:29 +080028var (
29 globalAfdoProfileProjects = []string{
30 "vendor/google_data/pgo_profile/sampling/",
31 "toolchain/pgo-profiles/sampling/",
32 }
33)
34
35var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
36
Yi Kong71198ac2022-02-10 15:08:36 +080037const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
Yi Kongeb8efc92021-12-09 18:06:29 +080038
Yi Kong46c6e592022-01-20 22:55:00 +080039func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
Yi Kongeb8efc92021-12-09 18:06:29 +080040 getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
41}
42
Vinh Tran44cb78c2023-03-09 22:07:19 -050043type afdoRdep struct {
44 VariationName *string
45 ProfilePath *string
46}
47
Yi Kongeb8efc92021-12-09 18:06:29 +080048type AfdoProperties struct {
Alix40216ae2022-04-07 20:47:01 +000049 // Afdo allows developers self-service enroll for
50 // automatic feedback-directed optimization using profile data.
Yi Kongeb8efc92021-12-09 18:06:29 +080051 Afdo bool
52
Vinh Tran44cb78c2023-03-09 22:07:19 -050053 FdoProfilePath *string `blueprint:"mutated"`
54
55 AfdoRDeps []afdoRdep `blueprint:"mutated"`
Yi Kongeb8efc92021-12-09 18:06:29 +080056}
57
58type afdo struct {
59 Properties AfdoProperties
60}
61
62func (afdo *afdo) props() []interface{} {
63 return []interface{}{&afdo.Properties}
64}
65
Vinh Tran44cb78c2023-03-09 22:07:19 -050066// afdoEnabled returns true for binaries and shared libraries
67// that set afdo prop to True and there is a profile available
68func (afdo *afdo) afdoEnabled() bool {
69 return afdo != nil && afdo.Properties.Afdo && afdo.Properties.FdoProfilePath != nil
Yi Kongeb8efc92021-12-09 18:06:29 +080070}
71
Yi Kongeb8efc92021-12-09 18:06:29 +080072func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
Vinh Tran44cb78c2023-03-09 22:07:19 -050073 if path := afdo.Properties.FdoProfilePath; path != nil {
Yi Konga1961e72023-04-05 11:33:11 +090074 // The flags are prepended to allow overriding.
Vinh Tran44cb78c2023-03-09 22:07:19 -050075 profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
Yi Konga1961e72023-04-05 11:33:11 +090076 flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
77 flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
Yi Kongeb8efc92021-12-09 18:06:29 +080078
Vinh Tran44cb78c2023-03-09 22:07:19 -050079 // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
80 // if profileFile gets updated
81 pathForSrc := android.PathForSource(ctx, *path)
82 flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
83 flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
Yi Kongeb8efc92021-12-09 18:06:29 +080084 }
85
86 return flags
87}
88
Vinh Tran44cb78c2023-03-09 22:07:19 -050089func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
90 if ctx.Host() {
91 return
92 }
93
94 if ctx.static() && !ctx.staticBinary() {
95 return
96 }
97
98 if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
99 if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
100 actx.AddFarVariationDependencies(
101 []blueprint.Variation{
102 {Mutator: "arch", Variation: actx.Target().ArchVariation()},
103 {Mutator: "os", Variation: "android"},
104 },
105 FdoProfileTag,
106 []string{*fdoProfileName}...,
107 )
108 }
109 }
110}
111
112// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
113// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
Vinh Trancde10162023-03-09 22:07:19 -0500114func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500115 if !c.Enabled() {
116 return
117 }
118
119 ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
120 if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
121 info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
122 c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
123 }
124 })
125}
126
127var _ FdoProfileMutatorInterface = (*Module)(nil)
128
129// Propagate afdo requirements down from binaries and shared libraries
Yi Kongeb8efc92021-12-09 18:06:29 +0800130func afdoDepsMutator(mctx android.TopDownMutatorContext) {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500131 if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
132 if path := m.afdo.Properties.FdoProfilePath; path != nil {
133 mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
134 tag := mctx.OtherModuleDependencyTag(dep)
135 libTag, isLibTag := tag.(libraryDependencyTag)
Yi Kongeb8efc92021-12-09 18:06:29 +0800136
Vinh Tran44cb78c2023-03-09 22:07:19 -0500137 // Do not recurse down non-static dependencies
138 if isLibTag {
139 if !libTag.static() {
140 return false
141 }
142 } else {
143 if tag != objDepTag && tag != reuseObjTag {
144 return false
145 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800146 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500147
148 if dep, ok := dep.(*Module); ok {
149 dep.afdo.Properties.AfdoRDeps = append(
150 dep.afdo.Properties.AfdoRDeps,
151 afdoRdep{
152 VariationName: proptools.StringPtr(encodeTarget(m.Name())),
153 ProfilePath: path,
154 },
155 )
Yi Kongeb8efc92021-12-09 18:06:29 +0800156 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800157
Vinh Tran44cb78c2023-03-09 22:07:19 -0500158 return true
159 })
160 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800161 }
162}
163
164// Create afdo variants for modules that need them
165func afdoMutator(mctx android.BottomUpMutatorContext) {
166 if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
Vinh Tran44cb78c2023-03-09 22:07:19 -0500167 if !m.static() && m.afdo.Properties.Afdo && m.afdo.Properties.FdoProfilePath != nil {
168 mctx.SetDependencyVariation(encodeTarget(m.Name()))
169 return
Yi Kongeb8efc92021-12-09 18:06:29 +0800170 }
171
172 variationNames := []string{""}
Vinh Tran44cb78c2023-03-09 22:07:19 -0500173
174 variantNameToProfilePath := make(map[string]*string)
175
176 for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
177 variantName := *afdoRDep.VariationName
178 // An rdep can be set twice in AfdoRDeps because there can be
179 // more than one path from an afdo-enabled module to
180 // a static dep such as
181 // afdo_enabled_foo -> static_bar ----> static_baz
182 // \ ^
183 // ----------------------|
184 // We only need to create one variant per unique rdep
185 if variantNameToProfilePath[variantName] == nil {
186 variationNames = append(variationNames, variantName)
187 variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
188 }
Yi Kongeb8efc92021-12-09 18:06:29 +0800189 }
Vinh Tran44cb78c2023-03-09 22:07:19 -0500190
Yi Kongeb8efc92021-12-09 18:06:29 +0800191 if len(variationNames) > 1 {
192 modules := mctx.CreateVariations(variationNames...)
193 for i, name := range variationNames {
194 if name == "" {
195 continue
196 }
197 variation := modules[i].(*Module)
198 variation.Properties.PreventInstall = true
199 variation.Properties.HideFromMake = true
Vinh Tran44cb78c2023-03-09 22:07:19 -0500200 variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
Yi Kongeb8efc92021-12-09 18:06:29 +0800201 }
202 }
203 }
204}
205
206// Encode target name to variation name.
207func encodeTarget(target string) string {
208 if target == "" {
209 return ""
210 }
211 return "afdo-" + target
212}
213
214// Decode target name from variation name.
215func decodeTarget(variation string) string {
216 if variation == "" {
217 return ""
218 }
219 return strings.TrimPrefix(variation, "afdo-")
220}