bloaty.go 3.6 KB

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