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