xref: /aosp_15_r20/build/soong/cc/orderfile.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2023 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker//
15*333d2b36SAndroid Build Coastguard Worker// Note: If you want to know how to use orderfile for your binary or shared
16*333d2b36SAndroid Build Coastguard Worker// library, you can go look at the README in toolchains/pgo-profiles/orderfiles
17*333d2b36SAndroid Build Coastguard Worker
18*333d2b36SAndroid Build Coastguard Workerpackage cc
19*333d2b36SAndroid Build Coastguard Worker
20*333d2b36SAndroid Build Coastguard Workerimport (
21*333d2b36SAndroid Build Coastguard Worker	"fmt"
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker// Order files are text files containing symbols representing functions names.
29*333d2b36SAndroid Build Coastguard Worker// Linkers (lld) uses order files to layout functions in a specific order.
30*333d2b36SAndroid Build Coastguard Worker// These binaries with ordered symbols will reduce page faults and improve a program's launch time
31*333d2b36SAndroid Build Coastguard Worker// due to the efficient loading of symbols during a program’s cold-start.
32*333d2b36SAndroid Build Coastguard Workervar (
33*333d2b36SAndroid Build Coastguard Worker	// Add flags to ignore warnings about symbols not be found
34*333d2b36SAndroid Build Coastguard Worker	// or not allowed to be ordered
35*333d2b36SAndroid Build Coastguard Worker	orderfileOtherFlags = []string{
36*333d2b36SAndroid Build Coastguard Worker		"-Wl,--no-warn-symbol-ordering",
37*333d2b36SAndroid Build Coastguard Worker	}
38*333d2b36SAndroid Build Coastguard Worker
39*333d2b36SAndroid Build Coastguard Worker	// Add folder projects for orderfiles
40*333d2b36SAndroid Build Coastguard Worker	globalOrderfileProjects = []string{
41*333d2b36SAndroid Build Coastguard Worker		"toolchain/pgo-profiles/orderfiles",
42*333d2b36SAndroid Build Coastguard Worker		"vendor/google_data/pgo_profile/orderfiles",
43*333d2b36SAndroid Build Coastguard Worker	}
44*333d2b36SAndroid Build Coastguard Worker)
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Workervar orderfileProjectsConfigKey = android.NewOnceKey("OrderfileProjects")
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Workerconst orderfileProfileFlag = "-forder-file-instrumentation"
49*333d2b36SAndroid Build Coastguard Workerconst orderfileUseFormat = "-Wl,--symbol-ordering-file=%s"
50*333d2b36SAndroid Build Coastguard Worker
51*333d2b36SAndroid Build Coastguard Workerfunc getOrderfileProjects(config android.DeviceConfig) []string {
52*333d2b36SAndroid Build Coastguard Worker	return config.OnceStringSlice(orderfileProjectsConfigKey, func() []string {
53*333d2b36SAndroid Build Coastguard Worker		return globalOrderfileProjects
54*333d2b36SAndroid Build Coastguard Worker	})
55*333d2b36SAndroid Build Coastguard Worker}
56*333d2b36SAndroid Build Coastguard Worker
57*333d2b36SAndroid Build Coastguard Workertype OrderfileProperties struct {
58*333d2b36SAndroid Build Coastguard Worker	Orderfile struct {
59*333d2b36SAndroid Build Coastguard Worker		Instrumentation *bool
60*333d2b36SAndroid Build Coastguard Worker		Order_file_path *string `android:"arch_variant"`
61*333d2b36SAndroid Build Coastguard Worker		Load_order_file *bool   `android:"arch_variant"`
62*333d2b36SAndroid Build Coastguard Worker		// Additional compiler flags to use when building this module
63*333d2b36SAndroid Build Coastguard Worker		// for orderfile profiling.
64*333d2b36SAndroid Build Coastguard Worker		Cflags []string `android:"arch_variant"`
65*333d2b36SAndroid Build Coastguard Worker	} `android:"arch_variant"`
66*333d2b36SAndroid Build Coastguard Worker
67*333d2b36SAndroid Build Coastguard Worker	ShouldProfileModule bool `blueprint:"mutated"`
68*333d2b36SAndroid Build Coastguard Worker	OrderfileLoad       bool `blueprint:"mutated"`
69*333d2b36SAndroid Build Coastguard Worker	OrderfileInstrLink  bool `blueprint:"mutated"`
70*333d2b36SAndroid Build Coastguard Worker}
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Workertype orderfile struct {
73*333d2b36SAndroid Build Coastguard Worker	Properties OrderfileProperties
74*333d2b36SAndroid Build Coastguard Worker}
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) shouldInstrument() bool {
77*333d2b36SAndroid Build Coastguard Worker	return Bool(props.Orderfile.Instrumentation)
78*333d2b36SAndroid Build Coastguard Worker}
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker// ShouldLoadOrderfile returns true if we need to load the order file rather than
81*333d2b36SAndroid Build Coastguard Worker// profile the binary or shared library
82*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) shouldLoadOrderfile() bool {
83*333d2b36SAndroid Build Coastguard Worker	return Bool(props.Orderfile.Load_order_file) && props.Orderfile.Order_file_path != nil
84*333d2b36SAndroid Build Coastguard Worker}
85*333d2b36SAndroid Build Coastguard Worker
86*333d2b36SAndroid Build Coastguard Worker// orderfileEnabled returns true for binaries and shared libraries
87*333d2b36SAndroid Build Coastguard Worker// if instrument flag is set to true
88*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) orderfileEnabled() bool {
89*333d2b36SAndroid Build Coastguard Worker	return orderfile != nil && orderfile.Properties.shouldInstrument()
90*333d2b36SAndroid Build Coastguard Worker}
91*333d2b36SAndroid Build Coastguard Worker
92*333d2b36SAndroid Build Coastguard Worker// orderfileLinkEnabled returns true for binaries and shared libraries
93*333d2b36SAndroid Build Coastguard Worker// if you should instrument dependencies
94*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) orderfileLinkEnabled() bool {
95*333d2b36SAndroid Build Coastguard Worker	return orderfile != nil && orderfile.Properties.OrderfileInstrLink
96*333d2b36SAndroid Build Coastguard Worker}
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) props() []interface{} {
99*333d2b36SAndroid Build Coastguard Worker	return []interface{}{&orderfile.Properties}
100*333d2b36SAndroid Build Coastguard Worker}
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker// Get the path to the order file by checking it is valid and not empty
103*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) getOrderfile(ctx BaseModuleContext) android.OptionalPath {
104*333d2b36SAndroid Build Coastguard Worker	orderFile := *props.Orderfile.Order_file_path
105*333d2b36SAndroid Build Coastguard Worker
106*333d2b36SAndroid Build Coastguard Worker	// Test if the order file is present in any of the Orderfile projects
107*333d2b36SAndroid Build Coastguard Worker	for _, profileProject := range getOrderfileProjects(ctx.DeviceConfig()) {
108*333d2b36SAndroid Build Coastguard Worker		path := android.ExistentPathForSource(ctx, profileProject, orderFile)
109*333d2b36SAndroid Build Coastguard Worker		if path.Valid() {
110*333d2b36SAndroid Build Coastguard Worker			return path
111*333d2b36SAndroid Build Coastguard Worker		}
112*333d2b36SAndroid Build Coastguard Worker	}
113*333d2b36SAndroid Build Coastguard Worker
114*333d2b36SAndroid Build Coastguard Worker	// Record that this module's order file is absent
115*333d2b36SAndroid Build Coastguard Worker	missing := *props.Orderfile.Order_file_path + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
116*333d2b36SAndroid Build Coastguard Worker	ctx.getOrCreateMakeVarsInfo().MissingProfile = missing
117*333d2b36SAndroid Build Coastguard Worker
118*333d2b36SAndroid Build Coastguard Worker	return android.OptionalPath{}
119*333d2b36SAndroid Build Coastguard Worker}
120*333d2b36SAndroid Build Coastguard Worker
121*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
122*333d2b36SAndroid Build Coastguard Worker	flags.Local.CFlags = append(flags.Local.CFlags, orderfileProfileFlag)
123*333d2b36SAndroid Build Coastguard Worker	flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm -enable-order-file-instrumentation")
124*333d2b36SAndroid Build Coastguard Worker	flags.Local.CFlags = append(flags.Local.CFlags, props.Orderfile.Cflags...)
125*333d2b36SAndroid Build Coastguard Worker	flags.Local.LdFlags = append(flags.Local.LdFlags, orderfileProfileFlag)
126*333d2b36SAndroid Build Coastguard Worker	return flags
127*333d2b36SAndroid Build Coastguard Worker}
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string {
130*333d2b36SAndroid Build Coastguard Worker	flags := []string{fmt.Sprintf(orderfileUseFormat, file)}
131*333d2b36SAndroid Build Coastguard Worker	flags = append(flags, orderfileOtherFlags...)
132*333d2b36SAndroid Build Coastguard Worker	return flags
133*333d2b36SAndroid Build Coastguard Worker}
134*333d2b36SAndroid Build Coastguard Worker
135*333d2b36SAndroid Build Coastguard Workerfunc (props *OrderfileProperties) addLoadFlags(ctx ModuleContext, flags Flags) Flags {
136*333d2b36SAndroid Build Coastguard Worker	orderFile := props.getOrderfile(ctx)
137*333d2b36SAndroid Build Coastguard Worker	orderFilePath := orderFile.Path()
138*333d2b36SAndroid Build Coastguard Worker	loadFlags := props.loadOrderfileFlags(ctx, orderFilePath.String())
139*333d2b36SAndroid Build Coastguard Worker
140*333d2b36SAndroid Build Coastguard Worker	flags.Local.LdFlags = append(flags.Local.LdFlags, loadFlags...)
141*333d2b36SAndroid Build Coastguard Worker
142*333d2b36SAndroid Build Coastguard Worker	// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
143*333d2b36SAndroid Build Coastguard Worker	// if orderfile gets updated
144*333d2b36SAndroid Build Coastguard Worker	flags.CFlagsDeps = append(flags.CFlagsDeps, orderFilePath)
145*333d2b36SAndroid Build Coastguard Worker	flags.LdFlagsDeps = append(flags.LdFlagsDeps, orderFilePath)
146*333d2b36SAndroid Build Coastguard Worker	return flags
147*333d2b36SAndroid Build Coastguard Worker}
148*333d2b36SAndroid Build Coastguard Worker
149*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) begin(ctx BaseModuleContext) {
150*333d2b36SAndroid Build Coastguard Worker	// Currently, we are not enabling orderfiles for host
151*333d2b36SAndroid Build Coastguard Worker	if ctx.Host() {
152*333d2b36SAndroid Build Coastguard Worker		return
153*333d2b36SAndroid Build Coastguard Worker	}
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker	// Currently, we are not enabling orderfiles to begin from static libraries
156*333d2b36SAndroid Build Coastguard Worker	if ctx.static() && !ctx.staticBinary() {
157*333d2b36SAndroid Build Coastguard Worker		return
158*333d2b36SAndroid Build Coastguard Worker	}
159*333d2b36SAndroid Build Coastguard Worker
160*333d2b36SAndroid Build Coastguard Worker	if ctx.DeviceConfig().ClangCoverageEnabled() {
161*333d2b36SAndroid Build Coastguard Worker		return
162*333d2b36SAndroid Build Coastguard Worker	}
163*333d2b36SAndroid Build Coastguard Worker
164*333d2b36SAndroid Build Coastguard Worker	// Checking if orderfile is enabled for this module
165*333d2b36SAndroid Build Coastguard Worker	if !orderfile.orderfileEnabled() {
166*333d2b36SAndroid Build Coastguard Worker		return
167*333d2b36SAndroid Build Coastguard Worker	}
168*333d2b36SAndroid Build Coastguard Worker
169*333d2b36SAndroid Build Coastguard Worker	orderfile.Properties.OrderfileLoad = orderfile.Properties.shouldLoadOrderfile()
170*333d2b36SAndroid Build Coastguard Worker	orderfile.Properties.ShouldProfileModule = !orderfile.Properties.shouldLoadOrderfile()
171*333d2b36SAndroid Build Coastguard Worker	orderfile.Properties.OrderfileInstrLink = orderfile.orderfileEnabled() && !orderfile.Properties.shouldLoadOrderfile()
172*333d2b36SAndroid Build Coastguard Worker}
173*333d2b36SAndroid Build Coastguard Worker
174*333d2b36SAndroid Build Coastguard Workerfunc (orderfile *orderfile) flags(ctx ModuleContext, flags Flags) Flags {
175*333d2b36SAndroid Build Coastguard Worker	props := orderfile.Properties
176*333d2b36SAndroid Build Coastguard Worker	// Add flags to load the orderfile using the path in its Android.bp
177*333d2b36SAndroid Build Coastguard Worker	if orderfile.Properties.OrderfileLoad {
178*333d2b36SAndroid Build Coastguard Worker		flags = props.addLoadFlags(ctx, flags)
179*333d2b36SAndroid Build Coastguard Worker		return flags
180*333d2b36SAndroid Build Coastguard Worker	}
181*333d2b36SAndroid Build Coastguard Worker
182*333d2b36SAndroid Build Coastguard Worker	// Add flags to profile this module
183*333d2b36SAndroid Build Coastguard Worker	if props.ShouldProfileModule {
184*333d2b36SAndroid Build Coastguard Worker		flags = props.addInstrumentationProfileGatherFlags(ctx, flags)
185*333d2b36SAndroid Build Coastguard Worker		return flags
186*333d2b36SAndroid Build Coastguard Worker	}
187*333d2b36SAndroid Build Coastguard Worker
188*333d2b36SAndroid Build Coastguard Worker	return flags
189*333d2b36SAndroid Build Coastguard Worker}
190*333d2b36SAndroid Build Coastguard Worker
191*333d2b36SAndroid Build Coastguard Workerfunc orderfilePropagateViaDepTag(tag blueprint.DependencyTag) bool {
192*333d2b36SAndroid Build Coastguard Worker	libTag, isLibTag := tag.(libraryDependencyTag)
193*333d2b36SAndroid Build Coastguard Worker	// Do not recurse down non-static dependencies
194*333d2b36SAndroid Build Coastguard Worker	if isLibTag {
195*333d2b36SAndroid Build Coastguard Worker		return libTag.static()
196*333d2b36SAndroid Build Coastguard Worker	} else {
197*333d2b36SAndroid Build Coastguard Worker		return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
198*333d2b36SAndroid Build Coastguard Worker	}
199*333d2b36SAndroid Build Coastguard Worker}
200*333d2b36SAndroid Build Coastguard Worker
201*333d2b36SAndroid Build Coastguard Worker// orderfileTransitionMutator creates orderfile variants of cc modules.
202*333d2b36SAndroid Build Coastguard Workertype orderfileTransitionMutator struct{}
203*333d2b36SAndroid Build Coastguard Worker
204*333d2b36SAndroid Build Coastguard Workerconst ORDERFILE_VARIATION = "orderfile"
205*333d2b36SAndroid Build Coastguard Worker
206*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) Split(ctx android.BaseModuleContext) []string {
207*333d2b36SAndroid Build Coastguard Worker	return []string{""}
208*333d2b36SAndroid Build Coastguard Worker}
209*333d2b36SAndroid Build Coastguard Worker
210*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
211*333d2b36SAndroid Build Coastguard Worker	if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
212*333d2b36SAndroid Build Coastguard Worker		if !orderfilePropagateViaDepTag(ctx.DepTag()) {
213*333d2b36SAndroid Build Coastguard Worker			return ""
214*333d2b36SAndroid Build Coastguard Worker		}
215*333d2b36SAndroid Build Coastguard Worker
216*333d2b36SAndroid Build Coastguard Worker		if sourceVariation != "" {
217*333d2b36SAndroid Build Coastguard Worker			return sourceVariation
218*333d2b36SAndroid Build Coastguard Worker		}
219*333d2b36SAndroid Build Coastguard Worker
220*333d2b36SAndroid Build Coastguard Worker		// Propagate profile orderfile flags down from binaries and shared libraries
221*333d2b36SAndroid Build Coastguard Worker		if m.orderfile.orderfileLinkEnabled() {
222*333d2b36SAndroid Build Coastguard Worker			return ORDERFILE_VARIATION
223*333d2b36SAndroid Build Coastguard Worker		}
224*333d2b36SAndroid Build Coastguard Worker	}
225*333d2b36SAndroid Build Coastguard Worker	return ""
226*333d2b36SAndroid Build Coastguard Worker}
227*333d2b36SAndroid Build Coastguard Worker
228*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
229*333d2b36SAndroid Build Coastguard Worker	if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
230*333d2b36SAndroid Build Coastguard Worker		return incomingVariation
231*333d2b36SAndroid Build Coastguard Worker	}
232*333d2b36SAndroid Build Coastguard Worker	return ""
233*333d2b36SAndroid Build Coastguard Worker}
234*333d2b36SAndroid Build Coastguard Worker
235*333d2b36SAndroid Build Coastguard Workerfunc (o *orderfileTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
236*333d2b36SAndroid Build Coastguard Worker	if variation == "" {
237*333d2b36SAndroid Build Coastguard Worker		return
238*333d2b36SAndroid Build Coastguard Worker	}
239*333d2b36SAndroid Build Coastguard Worker
240*333d2b36SAndroid Build Coastguard Worker	if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
241*333d2b36SAndroid Build Coastguard Worker		m.Properties.PreventInstall = true
242*333d2b36SAndroid Build Coastguard Worker		m.Properties.HideFromMake = true
243*333d2b36SAndroid Build Coastguard Worker		m.orderfile.Properties.ShouldProfileModule = true
244*333d2b36SAndroid Build Coastguard Worker		// We do not allow propagation for load flags because the orderfile is specific
245*333d2b36SAndroid Build Coastguard Worker		// to the module (binary / shared library)
246*333d2b36SAndroid Build Coastguard Worker		m.orderfile.Properties.OrderfileLoad = false
247*333d2b36SAndroid Build Coastguard Worker	}
248*333d2b36SAndroid Build Coastguard Worker}
249