bloaty: measure stripped Rust binaries
Modify bloaty's MeasureSizeForPath to allow a module to provide multiple paths. This is used to measure both unstripped and stripped libraries/binaries. Add unit test to ensure correct measurements are generated for Rust. Test: m out/soong/binary_sizes.pb.gz Change-Id: I59439b77dbf1cf5ad71e1c02996a6a90938536b4
This commit is contained in:
parent
4fab05a2ad
commit
e4dd14b25f
7 changed files with 76 additions and 19 deletions
|
@ -11,6 +11,7 @@ bootstrap_go_package {
|
||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"bloaty.go",
|
"bloaty.go",
|
||||||
|
"testing.go",
|
||||||
],
|
],
|
||||||
pluginFor: ["soong_build"],
|
pluginFor: ["soong_build"],
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,28 @@ func init() {
|
||||||
pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty")
|
pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty")
|
||||||
pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger")
|
pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger")
|
||||||
android.RegisterSingletonType("file_metrics", fileSizesSingleton)
|
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).
|
// measuredFiles contains the paths of the files measured by a module.
|
||||||
func MeasureSizeForPath(ctx android.ModuleContext, filePath android.WritablePath) {
|
type measuredFiles struct {
|
||||||
ctx.SetProvider(fileSizeMeasurerKey, filePath)
|
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{}
|
type sizesSingleton struct{}
|
||||||
|
@ -68,13 +84,13 @@ func fileSizesSingleton() android.Singleton {
|
||||||
|
|
||||||
func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||||
var deps android.Paths
|
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) {
|
ctx.VisitAllModules(func(m android.Module) {
|
||||||
if !ctx.ModuleHasProvider(m, fileSizeMeasurerKey) {
|
if !ctx.ModuleHasProvider(m, fileSizeMeasurerKey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filePath := ctx.ModuleProvider(m, fileSizeMeasurerKey).(android.ModuleOutPath)
|
filePaths := ctx.ModuleProvider(m, fileSizeMeasurerKey).(measuredFiles)
|
||||||
|
for _, path := range filePaths.paths {
|
||||||
|
filePath := path.(android.ModuleOutPath)
|
||||||
sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt)
|
sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt)
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: bloaty,
|
Rule: bloaty,
|
||||||
|
@ -83,6 +99,7 @@ func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonConte
|
||||||
Output: sizeFile,
|
Output: sizeFile,
|
||||||
})
|
})
|
||||||
deps = append(deps, sizeFile)
|
deps = append(deps, sizeFile)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
|
25
bloaty/testing.go
Normal file
25
bloaty/testing.go
Normal file
|
@ -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)
|
||||||
|
}))
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/bloaty"
|
|
||||||
"android/soong/rust/config"
|
"android/soong/rust/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -254,8 +253,6 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
|
||||||
implicits = append(implicits, clippyFile)
|
implicits = append(implicits, clippyFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
bloaty.MeasureSizeForPath(ctx, outputFile)
|
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: rustc,
|
Rule: rustc,
|
||||||
Description: "rustc " + main.Rel(),
|
Description: "rustc " + main.Rel(),
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/google/blueprint/proptools"
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"android/soong/bloaty"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
cc_config "android/soong/cc/config"
|
cc_config "android/soong/cc/config"
|
||||||
"android/soong/rust/config"
|
"android/soong/rust/config"
|
||||||
|
@ -731,8 +732,8 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||||
if mod.compiler != nil && !mod.compiler.Disabled() {
|
if mod.compiler != nil && !mod.compiler.Disabled() {
|
||||||
mod.compiler.initialize(ctx)
|
mod.compiler.initialize(ctx)
|
||||||
unstrippedOutputFile := mod.compiler.compile(ctx, flags, deps)
|
unstrippedOutputFile := mod.compiler.compile(ctx, flags, deps)
|
||||||
|
|
||||||
mod.unstrippedOutputFile = android.OptionalPathForPath(unstrippedOutputFile)
|
mod.unstrippedOutputFile = android.OptionalPathForPath(unstrippedOutputFile)
|
||||||
|
bloaty.MeasureSizeForPaths(ctx, mod.compiler.strippedOutputFilePath(), mod.unstrippedOutputFile)
|
||||||
|
|
||||||
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||||
if mod.installable(apexInfo) {
|
if mod.installable(apexInfo) {
|
||||||
|
|
|
@ -384,3 +384,17 @@ func TestMultilib(t *testing.T) {
|
||||||
_ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std")
|
_ = ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std")
|
||||||
_ = ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_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")
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package rust
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"android/soong/bloaty"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ const rustDefaultsDir = "defaults/rust/"
|
||||||
// Preparer that will define default rust modules, e.g. standard prebuilt modules.
|
// Preparer that will define default rust modules, e.g. standard prebuilt modules.
|
||||||
var PrepareForTestWithRustDefaultModules = android.GroupFixturePreparers(
|
var PrepareForTestWithRustDefaultModules = android.GroupFixturePreparers(
|
||||||
cc.PrepareForTestWithCcDefaultModules,
|
cc.PrepareForTestWithCcDefaultModules,
|
||||||
|
bloaty.PrepareForTestWithBloatyDefaultModules,
|
||||||
PrepareForTestWithRustBuildComponents,
|
PrepareForTestWithRustBuildComponents,
|
||||||
android.FixtureAddTextFile(rustDefaultsDir+"Android.bp", GatherRequiredDepsForTest()),
|
android.FixtureAddTextFile(rustDefaultsDir+"Android.bp", GatherRequiredDepsForTest()),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue