diff --git a/bloaty/Android.bp b/bloaty/Android.bp index 96cc1a519..7e722a757 100644 --- a/bloaty/Android.bp +++ b/bloaty/Android.bp @@ -11,6 +11,7 @@ bootstrap_go_package { ], srcs: [ "bloaty.go", + "testing.go", ], pluginFor: ["soong_build"], } diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go index 764cded26..50f241f44 100644 --- a/bloaty/bloaty.go +++ b/bloaty/bloaty.go @@ -52,12 +52,28 @@ func init() { pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty") pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger") android.RegisterSingletonType("file_metrics", fileSizesSingleton) - fileSizeMeasurerKey = blueprint.NewProvider(android.ModuleOutPath{}) + fileSizeMeasurerKey = blueprint.NewProvider(measuredFiles{}) } -// MeasureSizeForPath should be called by binary producers (e.g. in builder.go). -func MeasureSizeForPath(ctx android.ModuleContext, filePath android.WritablePath) { - ctx.SetProvider(fileSizeMeasurerKey, filePath) +// measuredFiles contains the paths of the files measured by a module. +type measuredFiles struct { + paths []android.WritablePath +} + +// MeasureSizeForPaths should be called by binary producers to measure the +// sizes of artifacts. It must only be called once per module; it will panic +// otherwise. +func MeasureSizeForPaths(ctx android.ModuleContext, paths ...android.OptionalPath) { + mf := measuredFiles{} + for _, p := range paths { + if !p.Valid() { + continue + } + if p, ok := p.Path().(android.WritablePath); ok { + mf.paths = append(mf.paths, p) + } + } + ctx.SetProvider(fileSizeMeasurerKey, mf) } type sizesSingleton struct{} @@ -68,21 +84,22 @@ func fileSizesSingleton() android.Singleton { func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) { var deps android.Paths - // Visit all modules. If the size provider give us a binary path to measure, - // create the rule to measure it. ctx.VisitAllModules(func(m android.Module) { if !ctx.ModuleHasProvider(m, fileSizeMeasurerKey) { return } - filePath := ctx.ModuleProvider(m, fileSizeMeasurerKey).(android.ModuleOutPath) - sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt) - ctx.Build(pctx, android.BuildParams{ - Rule: bloaty, - Description: "bloaty " + filePath.Rel(), - Input: filePath, - Output: sizeFile, - }) - deps = append(deps, sizeFile) + filePaths := ctx.ModuleProvider(m, fileSizeMeasurerKey).(measuredFiles) + for _, path := range filePaths.paths { + filePath := path.(android.ModuleOutPath) + sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt) + ctx.Build(pctx, android.BuildParams{ + Rule: bloaty, + Description: "bloaty " + filePath.Rel(), + Input: filePath, + Output: sizeFile, + }) + deps = append(deps, sizeFile) + } }) ctx.Build(pctx, android.BuildParams{ diff --git a/bloaty/testing.go b/bloaty/testing.go new file mode 100644 index 000000000..5f5ec841a --- /dev/null +++ b/bloaty/testing.go @@ -0,0 +1,25 @@ +// Copyright 2021 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bloaty + +import ( + "android/soong/android" +) + +// Preparer that will define the default bloaty singleton. +var PrepareForTestWithBloatyDefaultModules = android.GroupFixturePreparers( + android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { + ctx.RegisterSingletonType("file_metrics", fileSizesSingleton) + })) diff --git a/rust/builder.go b/rust/builder.go index 197c7033b..208b73450 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -21,7 +21,6 @@ import ( "github.com/google/blueprint" "android/soong/android" - "android/soong/bloaty" "android/soong/rust/config" ) @@ -254,8 +253,6 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl implicits = append(implicits, clippyFile) } - bloaty.MeasureSizeForPath(ctx, outputFile) - ctx.Build(pctx, android.BuildParams{ Rule: rustc, Description: "rustc " + main.Rel(), diff --git a/rust/rust.go b/rust/rust.go index ca85d74cc..fb0be2a2a 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -22,6 +22,7 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bloaty" "android/soong/cc" cc_config "android/soong/cc/config" "android/soong/rust/config" @@ -731,8 +732,8 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if mod.compiler != nil && !mod.compiler.Disabled() { mod.compiler.initialize(ctx) unstrippedOutputFile := mod.compiler.compile(ctx, flags, deps) - mod.unstrippedOutputFile = android.OptionalPathForPath(unstrippedOutputFile) + bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), mod.unstrippedOutputFile) apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo) if mod.installable(apexInfo) { diff --git a/rust/rust_test.go b/rust/rust_test.go index 890fb262b..3354d1de4 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -384,3 +384,17 @@ func TestMultilib(t *testing.T) { _ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std") _ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_rlib_dylib-std") } + +// Test that library size measurements are generated. +func TestLibrarySizes(t *testing.T) { + ctx := testRust(t, ` + rust_library_dylib { + name: "libwaldo", + srcs: ["foo.rs"], + crate_name: "waldo", + }`) + + m := ctx.SingletonForTests("file_metrics") + m.Output("libwaldo.dylib.so.bloaty.csv") + m.Output("stripped/libwaldo.dylib.so.bloaty.csv") +} diff --git a/rust/testing.go b/rust/testing.go index 1e01cc0c5..10b768ca9 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -16,6 +16,7 @@ package rust import ( "android/soong/android" + "android/soong/bloaty" "android/soong/cc" ) @@ -34,6 +35,7 @@ const rustDefaultsDir = "defaults/rust/" // Preparer that will define default rust modules, e.g. standard prebuilt modules. var PrepareForTestWithRustDefaultModules = android.GroupFixturePreparers( cc.PrepareForTestWithCcDefaultModules, + bloaty.PrepareForTestWithBloatyDefaultModules, PrepareForTestWithRustBuildComponents, android.FixtureAddTextFile(rustDefaultsDir+"Android.bp", GatherRequiredDepsForTest()), )