xref: /aosp_15_r20/build/soong/bloaty/bloaty.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2021 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// Package bloaty implements a singleton that measures binary (e.g. ELF
16*333d2b36SAndroid Build Coastguard Worker// executable, shared library or Rust rlib) section sizes at build time.
17*333d2b36SAndroid Build Coastguard Workerpackage bloaty
18*333d2b36SAndroid Build Coastguard Worker
19*333d2b36SAndroid Build Coastguard Workerimport (
20*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
23*333d2b36SAndroid Build Coastguard Worker)
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Workerconst bloatyDescriptorExt = ".bloaty.csv"
26*333d2b36SAndroid Build Coastguard Workerconst protoFilename = "binary_sizes.pb.gz"
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Workervar (
29*333d2b36SAndroid Build Coastguard Worker	fileSizeMeasurerKey blueprint.ProviderKey[measuredFiles]
30*333d2b36SAndroid Build Coastguard Worker	pctx                = android.NewPackageContext("android/soong/bloaty")
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Worker	// bloaty is used to measure a binary section sizes.
33*333d2b36SAndroid Build Coastguard Worker	bloaty = pctx.AndroidStaticRule("bloaty",
34*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
35*333d2b36SAndroid Build Coastguard Worker			Command:     "${bloaty} -n 0 --csv ${in} > ${out}",
36*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"${bloaty}"},
37*333d2b36SAndroid Build Coastguard Worker		})
38*333d2b36SAndroid Build Coastguard Worker
39*333d2b36SAndroid Build Coastguard Worker	// The bloaty merger script is used to combine the outputs from bloaty
40*333d2b36SAndroid Build Coastguard Worker	// into a single protobuf.
41*333d2b36SAndroid Build Coastguard Worker	bloatyMerger = pctx.AndroidStaticRule("bloatyMerger",
42*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
43*333d2b36SAndroid Build Coastguard Worker			Command:        "${bloatyMerger} ${out}.lst ${out}",
44*333d2b36SAndroid Build Coastguard Worker			CommandDeps:    []string{"${bloatyMerger}"},
45*333d2b36SAndroid Build Coastguard Worker			Rspfile:        "${out}.lst",
46*333d2b36SAndroid Build Coastguard Worker			RspfileContent: "${in}",
47*333d2b36SAndroid Build Coastguard Worker		})
48*333d2b36SAndroid Build Coastguard Worker)
49*333d2b36SAndroid Build Coastguard Worker
50*333d2b36SAndroid Build Coastguard Workerfunc init() {
51*333d2b36SAndroid Build Coastguard Worker	pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS)
52*333d2b36SAndroid Build Coastguard Worker	pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty")
53*333d2b36SAndroid Build Coastguard Worker	pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger")
54*333d2b36SAndroid Build Coastguard Worker	android.RegisterParallelSingletonType("file_metrics", fileSizesSingleton)
55*333d2b36SAndroid Build Coastguard Worker	fileSizeMeasurerKey = blueprint.NewProvider[measuredFiles]()
56*333d2b36SAndroid Build Coastguard Worker}
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Worker// measuredFiles contains the paths of the files measured by a module.
59*333d2b36SAndroid Build Coastguard Workertype measuredFiles struct {
60*333d2b36SAndroid Build Coastguard Worker	paths []android.WritablePath
61*333d2b36SAndroid Build Coastguard Worker}
62*333d2b36SAndroid Build Coastguard Worker
63*333d2b36SAndroid Build Coastguard Worker// MeasureSizeForPaths should be called by binary producers to measure the
64*333d2b36SAndroid Build Coastguard Worker// sizes of artifacts. It must only be called once per module; it will panic
65*333d2b36SAndroid Build Coastguard Worker// otherwise.
66*333d2b36SAndroid Build Coastguard Workerfunc MeasureSizeForPaths(ctx android.ModuleContext, paths ...android.OptionalPath) {
67*333d2b36SAndroid Build Coastguard Worker	mf := measuredFiles{}
68*333d2b36SAndroid Build Coastguard Worker	for _, p := range paths {
69*333d2b36SAndroid Build Coastguard Worker		if !p.Valid() {
70*333d2b36SAndroid Build Coastguard Worker			continue
71*333d2b36SAndroid Build Coastguard Worker		}
72*333d2b36SAndroid Build Coastguard Worker		if p, ok := p.Path().(android.WritablePath); ok {
73*333d2b36SAndroid Build Coastguard Worker			mf.paths = append(mf.paths, p)
74*333d2b36SAndroid Build Coastguard Worker		}
75*333d2b36SAndroid Build Coastguard Worker	}
76*333d2b36SAndroid Build Coastguard Worker	android.SetProvider(ctx, fileSizeMeasurerKey, mf)
77*333d2b36SAndroid Build Coastguard Worker}
78*333d2b36SAndroid Build Coastguard Worker
79*333d2b36SAndroid Build Coastguard Workertype sizesSingleton struct{}
80*333d2b36SAndroid Build Coastguard Worker
81*333d2b36SAndroid Build Coastguard Workerfunc fileSizesSingleton() android.Singleton {
82*333d2b36SAndroid Build Coastguard Worker	return &sizesSingleton{}
83*333d2b36SAndroid Build Coastguard Worker}
84*333d2b36SAndroid Build Coastguard Worker
85*333d2b36SAndroid Build Coastguard Workerfunc (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
86*333d2b36SAndroid Build Coastguard Worker	var deps android.Paths
87*333d2b36SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(m android.Module) {
88*333d2b36SAndroid Build Coastguard Worker		if !m.ExportedToMake() {
89*333d2b36SAndroid Build Coastguard Worker			return
90*333d2b36SAndroid Build Coastguard Worker		}
91*333d2b36SAndroid Build Coastguard Worker		filePaths, ok := android.OtherModuleProvider(ctx, m, fileSizeMeasurerKey)
92*333d2b36SAndroid Build Coastguard Worker		if !ok {
93*333d2b36SAndroid Build Coastguard Worker			return
94*333d2b36SAndroid Build Coastguard Worker		}
95*333d2b36SAndroid Build Coastguard Worker		for _, path := range filePaths.paths {
96*333d2b36SAndroid Build Coastguard Worker			filePath := path.(android.ModuleOutPath)
97*333d2b36SAndroid Build Coastguard Worker			sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt)
98*333d2b36SAndroid Build Coastguard Worker			ctx.Build(pctx, android.BuildParams{
99*333d2b36SAndroid Build Coastguard Worker				Rule:        bloaty,
100*333d2b36SAndroid Build Coastguard Worker				Description: "bloaty " + filePath.Rel(),
101*333d2b36SAndroid Build Coastguard Worker				Input:       filePath,
102*333d2b36SAndroid Build Coastguard Worker				Output:      sizeFile,
103*333d2b36SAndroid Build Coastguard Worker			})
104*333d2b36SAndroid Build Coastguard Worker			deps = append(deps, sizeFile)
105*333d2b36SAndroid Build Coastguard Worker		}
106*333d2b36SAndroid Build Coastguard Worker	})
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, android.BuildParams{
109*333d2b36SAndroid Build Coastguard Worker		Rule:   bloatyMerger,
110*333d2b36SAndroid Build Coastguard Worker		Inputs: android.SortedUniquePaths(deps),
111*333d2b36SAndroid Build Coastguard Worker		Output: android.PathForOutput(ctx, protoFilename),
112*333d2b36SAndroid Build Coastguard Worker	})
113*333d2b36SAndroid Build Coastguard Worker}
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Workerfunc (singleton *sizesSingleton) MakeVars(ctx android.MakeVarsContext) {
116*333d2b36SAndroid Build Coastguard Worker	ctx.DistForGoalWithFilename("checkbuild", android.PathForOutput(ctx, protoFilename), protoFilename)
117*333d2b36SAndroid Build Coastguard Worker}
118