Merge changes from topic "recovery_font" into main
* changes:
Install font module in recovery partition
Define additional symlinks and dirs for recovery partition
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
index ed0b3ed..34fdca3 100644
--- a/aconfig/codegen/init.go
+++ b/aconfig/codegen/init.go
@@ -33,6 +33,7 @@
` --cache ${in}` +
` --out ${out}.tmp` +
` --allow-instrumentation ${debug}` +
+ ` --new-exported ${new_exported}` +
` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
` && rm -rf ${out}.tmp`,
CommandDeps: []string{
@@ -40,7 +41,7 @@
"$soong_zip",
},
Restat: true,
- }, "mode", "debug")
+ }, "mode", "debug", "new_exported")
// For cc_aconfig_library: Generate C++ library
cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
index 9f399bf..cd1767b 100644
--- a/aconfig/codegen/java_aconfig_library.go
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -98,14 +98,23 @@
ctx.PropertyErrorf("mode", "exported mode requires its aconfig_declaration has exportable prop true")
}
+ var newExported bool
+ if useNewExported, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_NEW_EXPORTED"); ok {
+ // The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag
+ // (allow-read-write) for historical reasons.
+ // Bool build flags are always "" for false, and generally "true" for true.
+ newExported = useNewExported == "true"
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: javaRule,
Input: declarations.IntermediateCacheOutputPath,
Output: srcJarPath,
Description: "aconfig.srcjar",
Args: map[string]string{
- "mode": mode,
- "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
+ "mode": mode,
+ "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorage()),
+ "new_exported": strconv.FormatBool(newExported),
},
})
diff --git a/android/Android.bp b/android/Android.bp
index dfea8f9..20cd28b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -109,6 +109,7 @@
"test_asserts.go",
"test_suites.go",
"testing.go",
+ "transition.go",
"util.go",
"variable.go",
"vendor_api_levels.go",
@@ -154,6 +155,7 @@
"singleton_module_test.go",
"soong_config_modules_test.go",
"test_suites_test.go",
+ "transition_test.go",
"util_test.go",
"variable_test.go",
"vintf_fragment_test.go",
diff --git a/android/apex.go b/android/apex.go
index db93912..f625baf 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -264,9 +264,6 @@
// Marker interface that identifies dependencies that are excluded from APEX contents.
//
-// Unless the tag also implements the AlwaysRequireApexVariantTag this will prevent an apex variant
-// from being created for the module.
-//
// At the moment the sdk.sdkRequirementsMutator relies on the fact that the existing tags which
// implement this interface do not define dependencies onto members of an sdk_snapshot. If that
// changes then sdk.sdkRequirementsMutator will need fixing.
@@ -277,17 +274,6 @@
ExcludeFromApexContents()
}
-// Marker interface that identifies dependencies that always requires an APEX variant to be created.
-//
-// It is possible for a dependency to require an apex variant but exclude the module from the APEX
-// contents. See sdk.sdkMemberDependencyTag.
-type AlwaysRequireApexVariantTag interface {
- blueprint.DependencyTag
-
- // Return true if this tag requires that the target dependency has an apex variant.
- AlwaysRequireApexVariant() bool
-}
-
// Interface that identifies dependencies to skip Apex dependency check
type SkipApexAllowedDependenciesCheck interface {
// Returns true to skip the Apex dependency check, which limits the allowed dependency in build.
@@ -778,7 +764,7 @@
// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
-type PayloadDepsCallback func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+type PayloadDepsCallback func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool
type WalkPayloadDepsFunc func(ctx BaseModuleContext, do PayloadDepsCallback)
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
@@ -806,7 +792,7 @@
return
}
- walk(ctx, func(ctx BaseModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ walk(ctx, func(ctx BaseModuleContext, from Module, to ApexModule, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable"
// interface. We don't have to check min_sdk_version for external
diff --git a/android/container_violations.go b/android/container_violations.go
index 4251484..cfee562 100644
--- a/android/container_violations.go
+++ b/android/container_violations.go
@@ -827,6 +827,13 @@
"framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
},
+ // TODO(b/382743602): Remove "app-compat-annotations" and depend on the stub version jar
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "framework-connectivity-b.impl": {
+ "app-compat-annotations", // apex [com.android.tethering] -> system
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
"framework-connectivity.impl": {
"app-compat-annotations", // apex [com.android.tethering] -> system
},
@@ -1029,6 +1036,13 @@
"framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
},
+ // TODO(b/382301972): Remove the violations and use jarjar_rename or jarjar_prefix
+ "service-connectivity-b-pre-jarjar": {
+ "framework-connectivity-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-b-pre-jarjar", // apex [com.android.tethering] -> system
+ "framework-connectivity-t-pre-jarjar", // apex [com.android.tethering] -> system
+ },
+
"service-entitlement": {
"auto_value_annotations", // apex [com.android.wifi, test_com.android.wifi] -> apex [com.android.adservices, com.android.extservices, com.android.extservices_tplus]
},
diff --git a/android/logtags.go b/android/logtags.go
index 7929057..1e92dad 100644
--- a/android/logtags.go
+++ b/android/logtags.go
@@ -16,41 +16,8 @@
import "github.com/google/blueprint"
-func init() {
- RegisterParallelSingletonType("logtags", LogtagsSingleton)
-}
-
type LogtagsInfo struct {
Logtags Paths
}
var LogtagsProviderKey = blueprint.NewProvider[*LogtagsInfo]()
-
-func LogtagsSingleton() Singleton {
- return &logtagsSingleton{}
-}
-
-type logtagsSingleton struct{}
-
-func MergedLogtagsPath(ctx PathContext) OutputPath {
- return PathForIntermediates(ctx, "all-event-log-tags.txt")
-}
-
-func (l *logtagsSingleton) GenerateBuildActions(ctx SingletonContext) {
- var allLogtags Paths
- ctx.VisitAllModules(func(module Module) {
- if !module.ExportedToMake() {
- return
- }
- if logtagsInfo, ok := OtherModuleProvider(ctx, module, LogtagsProviderKey); ok {
- allLogtags = append(allLogtags, logtagsInfo.Logtags...)
- }
- })
-
- builder := NewRuleBuilder(pctx, ctx)
- builder.Command().
- BuiltTool("merge-event-log-tags").
- FlagWithOutput("-o ", MergedLogtagsPath(ctx)).
- Inputs(SortedUniquePaths(allLogtags))
- builder.Build("all-event-log-tags.txt", "merge logtags")
-}
diff --git a/android/mutator.go b/android/mutator.go
index fdd16a8..1523794 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -337,248 +337,6 @@
return mutator
}
-type IncomingTransitionContext interface {
- ArchModuleContext
- ModuleProviderContext
- ModuleErrorContext
-
- // Module returns the target of the dependency edge for which the transition
- // is being computed
- Module() Module
-
- // Config returns the configuration for the build.
- Config() Config
-
- DeviceConfig() DeviceConfig
-
- // IsAddingDependency returns true if the transition is being called while adding a dependency
- // after the transition mutator has already run, or false if it is being called when the transition
- // mutator is running. This should be used sparingly, all uses will have to be removed in order
- // to support creating variants on demand.
- IsAddingDependency() bool
-}
-
-type OutgoingTransitionContext interface {
- ArchModuleContext
- ModuleProviderContext
-
- // Module returns the target of the dependency edge for which the transition
- // is being computed
- Module() Module
-
- // DepTag() Returns the dependency tag through which this dependency is
- // reached
- DepTag() blueprint.DependencyTag
-
- // Config returns the configuration for the build.
- Config() Config
-
- DeviceConfig() DeviceConfig
-}
-
-// TransitionMutator implements a top-down mechanism where a module tells its
-// direct dependencies what variation they should be built in but the dependency
-// has the final say.
-//
-// When implementing a transition mutator, one needs to implement four methods:
-// - Split() that tells what variations a module has by itself
-// - OutgoingTransition() where a module tells what it wants from its
-// dependency
-// - IncomingTransition() where a module has the final say about its own
-// variation
-// - Mutate() that changes the state of a module depending on its variation
-//
-// That the effective variation of module B when depended on by module A is the
-// composition the outgoing transition of module A and the incoming transition
-// of module B.
-//
-// the outgoing transition should not take the properties of the dependency into
-// account, only those of the module that depends on it. For this reason, the
-// dependency is not even passed into it as an argument. Likewise, the incoming
-// transition should not take the properties of the depending module into
-// account and is thus not informed about it. This makes for a nice
-// decomposition of the decision logic.
-//
-// A given transition mutator only affects its own variation; other variations
-// stay unchanged along the dependency edges.
-//
-// Soong makes sure that all modules are created in the desired variations and
-// that dependency edges are set up correctly. This ensures that "missing
-// variation" errors do not happen and allows for more flexible changes in the
-// value of the variation among dependency edges (as oppposed to bottom-up
-// mutators where if module A in variation X depends on module B and module B
-// has that variation X, A must depend on variation X of B)
-//
-// The limited power of the context objects passed to individual mutators
-// methods also makes it more difficult to shoot oneself in the foot. Complete
-// safety is not guaranteed because no one prevents individual transition
-// mutators from mutating modules in illegal ways and for e.g. Split() or
-// Mutate() to run their own visitations of the transitive dependency of the
-// module and both of these are bad ideas, but it's better than no guardrails at
-// all.
-//
-// This model is pretty close to Bazel's configuration transitions. The mapping
-// between concepts in Soong and Bazel is as follows:
-// - Module == configured target
-// - Variant == configuration
-// - Variation name == configuration flag
-// - Variation == configuration flag value
-// - Outgoing transition == attribute transition
-// - Incoming transition == rule transition
-//
-// The Split() method does not have a Bazel equivalent and Bazel split
-// transitions do not have a Soong equivalent.
-//
-// Mutate() does not make sense in Bazel due to the different models of the
-// two systems: when creating new variations, Soong clones the old module and
-// thus some way is needed to change it state whereas Bazel creates each
-// configuration of a given configured target anew.
-type TransitionMutator interface {
- // Split returns the set of variations that should be created for a module no
- // matter who depends on it. Used when Make depends on a particular variation
- // or when the module knows its variations just based on information given to
- // it in the Blueprint file. This method should not mutate the module it is
- // called on.
- Split(ctx BaseModuleContext) []string
-
- // OutgoingTransition is called on a module to determine which variation it wants
- // from its direct dependencies. The dependency itself can override this decision.
- // This method should not mutate the module itself.
- OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
-
- // IncomingTransition is called on a module to determine which variation it should
- // be in based on the variation modules that depend on it want. This gives the module
- // a final say about its own variations. This method should not mutate the module
- // itself.
- IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
-
- // Mutate is called after a module was split into multiple variations on each variation.
- // It should not split the module any further but adding new dependencies is
- // fine. Unlike all the other methods on TransitionMutator, this method is
- // allowed to mutate the module.
- Mutate(ctx BottomUpMutatorContext, variation string)
-}
-
-type androidTransitionMutator struct {
- finalPhase bool
- mutator TransitionMutator
- name string
-}
-
-func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
- if a.finalPhase {
- panic("TransitionMutator not allowed in FinalDepsMutators")
- }
- if m, ok := ctx.Module().(Module); ok {
- moduleContext := m.base().baseModuleContextFactory(ctx)
- return a.mutator.Split(&moduleContext)
- } else {
- return []string{""}
- }
-}
-
-type outgoingTransitionContextImpl struct {
- archModuleContext
- bp blueprint.OutgoingTransitionContext
-}
-
-func (c *outgoingTransitionContextImpl) Module() Module {
- return c.bp.Module().(Module)
-}
-
-func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag {
- return c.bp.DepTag()
-}
-
-func (c *outgoingTransitionContextImpl) Config() Config {
- return c.bp.Config().(Config)
-}
-
-func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
- return DeviceConfig{c.bp.Config().(Config).deviceConfig}
-}
-
-func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
- return c.bp.Provider(provider)
-}
-
-func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
- if m, ok := bpctx.Module().(Module); ok {
- ctx := outgoingTransitionContextPool.Get().(*outgoingTransitionContextImpl)
- defer outgoingTransitionContextPool.Put(ctx)
- *ctx = outgoingTransitionContextImpl{
- archModuleContext: m.base().archModuleContextFactory(bpctx),
- bp: bpctx,
- }
- return a.mutator.OutgoingTransition(ctx, sourceVariation)
- } else {
- return ""
- }
-}
-
-type incomingTransitionContextImpl struct {
- archModuleContext
- bp blueprint.IncomingTransitionContext
-}
-
-func (c *incomingTransitionContextImpl) Module() Module {
- return c.bp.Module().(Module)
-}
-
-func (c *incomingTransitionContextImpl) Config() Config {
- return c.bp.Config().(Config)
-}
-
-func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig {
- return DeviceConfig{c.bp.Config().(Config).deviceConfig}
-}
-
-func (c *incomingTransitionContextImpl) IsAddingDependency() bool {
- return c.bp.IsAddingDependency()
-}
-
-func (c *incomingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
- return c.bp.Provider(provider)
-}
-
-func (c *incomingTransitionContextImpl) ModuleErrorf(fmt string, args ...interface{}) {
- c.bp.ModuleErrorf(fmt, args)
-}
-
-func (c *incomingTransitionContextImpl) PropertyErrorf(property, fmt string, args ...interface{}) {
- c.bp.PropertyErrorf(property, fmt, args)
-}
-
-func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string {
- if m, ok := bpctx.Module().(Module); ok {
- ctx := incomingTransitionContextPool.Get().(*incomingTransitionContextImpl)
- defer incomingTransitionContextPool.Put(ctx)
- *ctx = incomingTransitionContextImpl{
- archModuleContext: m.base().archModuleContextFactory(bpctx),
- bp: bpctx,
- }
- return a.mutator.IncomingTransition(ctx, incomingVariation)
- } else {
- return ""
- }
-}
-
-func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
- if am, ok := ctx.Module().(Module); ok {
- if variation != "" {
- // TODO: this should really be checking whether the TransitionMutator affected this module, not
- // the empty variant, but TransitionMutator has no concept of skipping a module.
- base := am.base()
- base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
- base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
- }
-
- mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
- defer bottomUpMutatorContextPool.Put(mctx)
- a.mutator.Mutate(mctx, variation)
- }
-}
-
func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) TransitionMutatorHandle {
atm := &androidTransitionMutator{
finalPhase: x.finalPhase,
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 1d5f890..60a6119 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -83,132 +83,6 @@
AssertDeepEquals(t, "foo missing deps", []string{"added_missing_dep", "regular_missing_dep"}, foo.missingDeps)
}
-type testTransitionMutator struct {
- split func(ctx BaseModuleContext) []string
- outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
- incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
- mutate func(ctx BottomUpMutatorContext, variation string)
-}
-
-func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
- if t.split != nil {
- return t.split(ctx)
- }
- return []string{""}
-}
-
-func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
- if t.outgoingTransition != nil {
- return t.outgoingTransition(ctx, sourceVariation)
- }
- return sourceVariation
-}
-
-func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
- if t.incomingTransition != nil {
- return t.incomingTransition(ctx, incomingVariation)
- }
- return incomingVariation
-}
-
-func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
- if t.mutate != nil {
- t.mutate(ctx, variation)
- }
-}
-
-func TestModuleString(t *testing.T) {
- bp := `
- test {
- name: "foo",
- }
- `
-
- var moduleStrings []string
-
- GroupFixturePreparers(
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
-
- ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("pre_arch", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"a", "b"}
- },
- })
- })
-
- ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("pre_deps", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"c", "d"}
- },
- })
- })
-
- ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("post_deps", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- return []string{"e", "f"}
- },
- outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
- return ""
- },
- })
- ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- ctx.Rename(ctx.Module().base().Name() + "_renamed1")
- }).UsesRename()
- ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
- moduleStrings = append(moduleStrings, ctx.Module().String())
- })
- })
-
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- }),
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- want := []string{
- // Initial name.
- "foo{}",
-
- // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
- "foo{pre_arch:b}",
- "foo{pre_arch:a}",
-
- // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
- "foo{pre_arch:b,pre_deps:d}",
- "foo{pre_arch:b,pre_deps:c}",
- "foo{pre_arch:a,pre_deps:d}",
- "foo{pre_arch:a,pre_deps:c}",
-
- // After post_deps.
- "foo{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo{pre_arch:b,pre_deps:d,post_deps:f}",
-
- // After rename_bottom_up.
- "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
- "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
- "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
- "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
- "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
- "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
- "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
- "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
- }
-
- AssertDeepEquals(t, "module String() values", want, moduleStrings)
-}
-
func TestFinalDepsPhase(t *testing.T) {
bp := `
test {
@@ -288,22 +162,3 @@
AssertDeepEquals(t, "final", finalWant, finalGotMap)
}
-
-func TestTransitionMutatorInFinalDeps(t *testing.T) {
- GroupFixturePreparers(
- FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
- ctx.Transition("vars", &testTransitionMutator{
- split: func(ctx BaseModuleContext) []string {
- return []string{"a", "b"}
- },
- })
- })
-
- ctx.RegisterModuleType("test", mutatorTestModuleFactory)
- }),
- FixtureWithRootAndroidBp(`test {name: "foo"}`),
- ).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
- RunTest(t)
-}
diff --git a/android/paths.go b/android/paths.go
index 7ab1f22..94f00ad 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1437,33 +1437,6 @@
return p.withRel(path)
}
-// OverlayPath returns the overlay for `path' if it exists. This assumes that the
-// SourcePath is the path to a resource overlay directory.
-func (p SourcePath) OverlayPath(ctx ModuleMissingDepsPathContext, path Path) OptionalPath {
- var relDir string
- if srcPath, ok := path.(SourcePath); ok {
- relDir = srcPath.path
- } else {
- ReportPathErrorf(ctx, "Cannot find relative path for %s(%s)", reflect.TypeOf(path).Name(), path)
- // No need to put the error message into the returned path since it has been reported already.
- return OptionalPath{}
- }
- dir := filepath.Join(p.path, relDir)
- // Use Glob so that we are run again if the directory is added.
- if pathtools.IsGlob(dir) {
- ReportPathErrorf(ctx, "Path may not contain a glob: %s", dir)
- }
- paths, err := ctx.GlobWithDeps(dir, nil)
- if err != nil {
- ReportPathErrorf(ctx, "glob: %s", err.Error())
- return OptionalPath{}
- }
- if len(paths) == 0 {
- return InvalidOptionalPath(dir + " does not exist")
- }
- return OptionalPathForPath(PathForSource(ctx, paths[0]))
-}
-
// OutputPath is a Path representing an intermediates file path rooted from the build directory
type OutputPath struct {
basePath
diff --git a/android/transition.go b/android/transition.go
new file mode 100644
index 0000000..7c04eff
--- /dev/null
+++ b/android/transition.go
@@ -0,0 +1,259 @@
+// Copyright 2024 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 android
+
+import "github.com/google/blueprint"
+
+// TransitionMutator implements a top-down mechanism where a module tells its
+// direct dependencies what variation they should be built in but the dependency
+// has the final say.
+//
+// When implementing a transition mutator, one needs to implement four methods:
+// - Split() that tells what variations a module has by itself
+// - OutgoingTransition() where a module tells what it wants from its
+// dependency
+// - IncomingTransition() where a module has the final say about its own
+// variation
+// - Mutate() that changes the state of a module depending on its variation
+//
+// That the effective variation of module B when depended on by module A is the
+// composition the outgoing transition of module A and the incoming transition
+// of module B.
+//
+// the outgoing transition should not take the properties of the dependency into
+// account, only those of the module that depends on it. For this reason, the
+// dependency is not even passed into it as an argument. Likewise, the incoming
+// transition should not take the properties of the depending module into
+// account and is thus not informed about it. This makes for a nice
+// decomposition of the decision logic.
+//
+// A given transition mutator only affects its own variation; other variations
+// stay unchanged along the dependency edges.
+//
+// Soong makes sure that all modules are created in the desired variations and
+// that dependency edges are set up correctly. This ensures that "missing
+// variation" errors do not happen and allows for more flexible changes in the
+// value of the variation among dependency edges (as oppposed to bottom-up
+// mutators where if module A in variation X depends on module B and module B
+// has that variation X, A must depend on variation X of B)
+//
+// The limited power of the context objects passed to individual mutators
+// methods also makes it more difficult to shoot oneself in the foot. Complete
+// safety is not guaranteed because no one prevents individual transition
+// mutators from mutating modules in illegal ways and for e.g. Split() or
+// Mutate() to run their own visitations of the transitive dependency of the
+// module and both of these are bad ideas, but it's better than no guardrails at
+// all.
+//
+// This model is pretty close to Bazel's configuration transitions. The mapping
+// between concepts in Soong and Bazel is as follows:
+// - Module == configured target
+// - Variant == configuration
+// - Variation name == configuration flag
+// - Variation == configuration flag value
+// - Outgoing transition == attribute transition
+// - Incoming transition == rule transition
+//
+// The Split() method does not have a Bazel equivalent and Bazel split
+// transitions do not have a Soong equivalent.
+//
+// Mutate() does not make sense in Bazel due to the different models of the
+// two systems: when creating new variations, Soong clones the old module and
+// thus some way is needed to change it state whereas Bazel creates each
+// configuration of a given configured target anew.
+type TransitionMutator interface {
+ // Split returns the set of variations that should be created for a module no
+ // matter who depends on it. Used when Make depends on a particular variation
+ // or when the module knows its variations just based on information given to
+ // it in the Blueprint file. This method should not mutate the module it is
+ // called on.
+ Split(ctx BaseModuleContext) []string
+
+ // OutgoingTransition is called on a module to determine which variation it wants
+ // from its direct dependencies. The dependency itself can override this decision.
+ // This method should not mutate the module itself.
+ OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
+
+ // IncomingTransition is called on a module to determine which variation it should
+ // be in based on the variation modules that depend on it want. This gives the module
+ // a final say about its own variations. This method should not mutate the module
+ // itself.
+ IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
+
+ // Mutate is called after a module was split into multiple variations on each variation.
+ // It should not split the module any further but adding new dependencies is
+ // fine. Unlike all the other methods on TransitionMutator, this method is
+ // allowed to mutate the module.
+ Mutate(ctx BottomUpMutatorContext, variation string)
+}
+
+type IncomingTransitionContext interface {
+ ArchModuleContext
+ ModuleProviderContext
+ ModuleErrorContext
+
+ // Module returns the target of the dependency edge for which the transition
+ // is being computed
+ Module() Module
+
+ // Config returns the configuration for the build.
+ Config() Config
+
+ DeviceConfig() DeviceConfig
+
+ // IsAddingDependency returns true if the transition is being called while adding a dependency
+ // after the transition mutator has already run, or false if it is being called when the transition
+ // mutator is running. This should be used sparingly, all uses will have to be removed in order
+ // to support creating variants on demand.
+ IsAddingDependency() bool
+}
+
+type OutgoingTransitionContext interface {
+ ArchModuleContext
+ ModuleProviderContext
+
+ // Module returns the target of the dependency edge for which the transition
+ // is being computed
+ Module() Module
+
+ // DepTag() Returns the dependency tag through which this dependency is
+ // reached
+ DepTag() blueprint.DependencyTag
+
+ // Config returns the configuration for the build.
+ Config() Config
+
+ DeviceConfig() DeviceConfig
+}
+
+type androidTransitionMutator struct {
+ finalPhase bool
+ mutator TransitionMutator
+ name string
+}
+
+func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
+ if a.finalPhase {
+ panic("TransitionMutator not allowed in FinalDepsMutators")
+ }
+ if m, ok := ctx.Module().(Module); ok {
+ moduleContext := m.base().baseModuleContextFactory(ctx)
+ return a.mutator.Split(&moduleContext)
+ } else {
+ return []string{""}
+ }
+}
+
+func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
+ if m, ok := bpctx.Module().(Module); ok {
+ ctx := outgoingTransitionContextPool.Get().(*outgoingTransitionContextImpl)
+ defer outgoingTransitionContextPool.Put(ctx)
+ *ctx = outgoingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.OutgoingTransition(ctx, sourceVariation)
+ } else {
+ return ""
+ }
+}
+
+func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string {
+ if m, ok := bpctx.Module().(Module); ok {
+ ctx := incomingTransitionContextPool.Get().(*incomingTransitionContextImpl)
+ defer incomingTransitionContextPool.Put(ctx)
+ *ctx = incomingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.IncomingTransition(ctx, incomingVariation)
+ } else {
+ return ""
+ }
+}
+
+func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
+ if am, ok := ctx.Module().(Module); ok {
+ if variation != "" {
+ // TODO: this should really be checking whether the TransitionMutator affected this module, not
+ // the empty variant, but TransitionMutator has no concept of skipping a module.
+ base := am.base()
+ base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name)
+ base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation)
+ }
+
+ mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase)
+ defer bottomUpMutatorContextPool.Put(mctx)
+ a.mutator.Mutate(mctx, variation)
+ }
+}
+
+type incomingTransitionContextImpl struct {
+ archModuleContext
+ bp blueprint.IncomingTransitionContext
+}
+
+func (c *incomingTransitionContextImpl) Module() Module {
+ return c.bp.Module().(Module)
+}
+
+func (c *incomingTransitionContextImpl) Config() Config {
+ return c.bp.Config().(Config)
+}
+
+func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (c *incomingTransitionContextImpl) IsAddingDependency() bool {
+ return c.bp.IsAddingDependency()
+}
+
+func (c *incomingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return c.bp.Provider(provider)
+}
+
+func (c *incomingTransitionContextImpl) ModuleErrorf(fmt string, args ...interface{}) {
+ c.bp.ModuleErrorf(fmt, args)
+}
+
+func (c *incomingTransitionContextImpl) PropertyErrorf(property, fmt string, args ...interface{}) {
+ c.bp.PropertyErrorf(property, fmt, args)
+}
+
+type outgoingTransitionContextImpl struct {
+ archModuleContext
+ bp blueprint.OutgoingTransitionContext
+}
+
+func (c *outgoingTransitionContextImpl) Module() Module {
+ return c.bp.Module().(Module)
+}
+
+func (c *outgoingTransitionContextImpl) DepTag() blueprint.DependencyTag {
+ return c.bp.DepTag()
+}
+
+func (c *outgoingTransitionContextImpl) Config() Config {
+ return c.bp.Config().(Config)
+}
+
+func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (c *outgoingTransitionContextImpl) provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return c.bp.Provider(provider)
+}
diff --git a/android/transition_test.go b/android/transition_test.go
new file mode 100644
index 0000000..f7618f3
--- /dev/null
+++ b/android/transition_test.go
@@ -0,0 +1,162 @@
+// Copyright 2024 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 android
+
+import "testing"
+
+type testTransitionMutator struct {
+ split func(ctx BaseModuleContext) []string
+ outgoingTransition func(ctx OutgoingTransitionContext, sourceVariation string) string
+ incomingTransition func(ctx IncomingTransitionContext, incomingVariation string) string
+ mutate func(ctx BottomUpMutatorContext, variation string)
+}
+
+func (t *testTransitionMutator) Split(ctx BaseModuleContext) []string {
+ if t.split != nil {
+ return t.split(ctx)
+ }
+ return []string{""}
+}
+
+func (t *testTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
+ if t.outgoingTransition != nil {
+ return t.outgoingTransition(ctx, sourceVariation)
+ }
+ return sourceVariation
+}
+
+func (t *testTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
+ if t.incomingTransition != nil {
+ return t.incomingTransition(ctx, incomingVariation)
+ }
+ return incomingVariation
+}
+
+func (t *testTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
+ if t.mutate != nil {
+ t.mutate(ctx, variation)
+ }
+}
+
+func TestModuleString(t *testing.T) {
+ bp := `
+ test {
+ name: "foo",
+ }
+ `
+
+ var moduleStrings []string
+
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+
+ ctx.PreArchMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("pre_arch", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"a", "b"}
+ },
+ })
+ })
+
+ ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("pre_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"c", "d"}
+ },
+ })
+ })
+
+ ctx.PostDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("post_deps", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ return []string{"e", "f"}
+ },
+ outgoingTransition: func(ctx OutgoingTransitionContext, sourceVariation string) string {
+ return ""
+ },
+ })
+ ctx.BottomUp("rename_bottom_up", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ ctx.Rename(ctx.Module().base().Name() + "_renamed1")
+ }).UsesRename()
+ ctx.BottomUp("final", func(ctx BottomUpMutatorContext) {
+ moduleStrings = append(moduleStrings, ctx.Module().String())
+ })
+ })
+
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ want := []string{
+ // Initial name.
+ "foo{}",
+
+ // After pre_arch (reversed because rename_top_down is TopDown so it visits in reverse order).
+ "foo{pre_arch:b}",
+ "foo{pre_arch:a}",
+
+ // After pre_deps (reversed because post_deps TransitionMutator.Split is TopDown).
+ "foo{pre_arch:b,pre_deps:d}",
+ "foo{pre_arch:b,pre_deps:c}",
+ "foo{pre_arch:a,pre_deps:d}",
+ "foo{pre_arch:a,pre_deps:c}",
+
+ // After post_deps.
+ "foo{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo{pre_arch:b,pre_deps:d,post_deps:f}",
+
+ // After rename_bottom_up.
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:a,pre_deps:d,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:c,post_deps:f}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:e}",
+ "foo_renamed1{pre_arch:b,pre_deps:d,post_deps:f}",
+ }
+
+ AssertDeepEquals(t, "module String() values", want, moduleStrings)
+}
+
+func TestTransitionMutatorInFinalDeps(t *testing.T) {
+ GroupFixturePreparers(
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.FinalDepsMutators(func(ctx RegisterMutatorsContext) {
+ ctx.Transition("vars", &testTransitionMutator{
+ split: func(ctx BaseModuleContext) []string {
+ return []string{"a", "b"}
+ },
+ })
+ })
+
+ ctx.RegisterModuleType("test", mutatorTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(`test {name: "foo"}`),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern("not allowed in FinalDepsMutators")).
+ RunTest(t)
+}
diff --git a/apex/apex.go b/apex/apex.go
index 5f700ee..e22cf9e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -973,21 +973,8 @@
if !ok || !am.CanHaveApexVariants() {
return false
}
- depTag := mctx.OtherModuleDependencyTag(child)
- // Check to see if the tag always requires that the child module has an apex variant for every
- // apex variant of the parent module. If it does not then it is still possible for something
- // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required.
- if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() {
- return true
- }
- if !android.IsDepInSameApex(mctx, parent, child) {
- return false
- }
-
- // By default, all the transitive dependencies are collected, unless filtered out
- // above.
- return true
+ return android.IsDepInSameApex(mctx, parent, child)
}
android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{})
@@ -2707,7 +2694,7 @@
return
}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
if externalDep {
return false
diff --git a/apex/builder.go b/apex/builder.go
index 6204caa..45608c9 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -337,8 +337,8 @@
if err != nil {
ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to be an int, but got %s", defaultVersion)
}
- if defaultVersionInt%10 != 0 {
- ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to end in a zero, but got %s", defaultVersion)
+ if defaultVersionInt%10 != 0 && defaultVersionInt%10 != 9 {
+ ctx.ModuleErrorf("expected RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION to end in a zero or a nine, but got %s", defaultVersion)
}
variantVersion := []rune(*a.properties.Variant_version)
if len(variantVersion) != 1 || variantVersion[0] < '0' || variantVersion[0] > '9' {
diff --git a/bin/get_build_vars b/bin/get_build_vars
new file mode 100755
index 0000000..aa887c7
--- /dev/null
+++ b/bin/get_build_vars
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# Copyright (C) 2024 The Android Open Source Project
+#
+# 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.
+
+# Get the value of build variables. The values are printed in a format suitable
+# for use in the import_build_vars function in build/make/shell_utils.sh
+#
+# For absolute variables, prefix the variable name with a '/'
+
+# Common script utilities
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh
+
+require_top
+
+$TOP/build/soong/soong_ui.bash --dumpvars-mode \
+ --vars="$(printf '%s\n' "$@" | grep -v '^/')" \
+ --abs-vars="$(printf '%s\n' "$@" | grep '^/' | sed 's:^/::')" \
+ --var-prefix= \
+ --abs-var-prefix=
+
+exit $?
diff --git a/cc/afdo.go b/cc/afdo.go
index 14d105e..03dc271 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -163,7 +163,7 @@
}
// TODO(b/324141705): this is designed to prevent propagating AFDO from static libraries that have afdo: true set, but
- // it should be m.static() && !m.staticBinary() so that static binaries use AFDO variants of dependencies.
+ // it should be m.staticLibrary() so that static binaries use AFDO variants of dependencies.
if m.static() {
return ""
}
@@ -188,7 +188,7 @@
if variation == "" {
// The empty variation is either a module that has enabled AFDO for itself, or the non-AFDO
// variant of a dependency.
- if m.afdo.afdoEnabled() && !(m.static() && !m.staticBinary()) && !m.Host() {
+ if m.afdo.afdoEnabled() && !m.staticLibrary() && !m.Host() {
m.afdo.addDep(ctx, ctx.ModuleName())
}
} else {
diff --git a/cc/cc.go b/cc/cc.go
index 4838a5f..8023324 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -519,6 +519,7 @@
type ModuleContextIntf interface {
static() bool
staticBinary() bool
+ staticLibrary() bool
testBinary() bool
testLibrary() bool
header() bool
@@ -1523,6 +1524,10 @@
return ctx.mod.staticBinary()
}
+func (ctx *moduleContextImpl) staticLibrary() bool {
+ return ctx.mod.staticLibrary()
+}
+
func (ctx *moduleContextImpl) testBinary() bool {
return ctx.mod.testBinary()
}
@@ -3550,6 +3555,15 @@
return false
}
+func (c *Module) staticLibrary() bool {
+ if static, ok := c.linker.(interface {
+ staticLibrary() bool
+ }); ok {
+ return static.staticLibrary()
+ }
+ return false
+}
+
func (c *Module) staticBinary() bool {
if static, ok := c.linker.(interface {
staticBinary() bool
diff --git a/cc/coverage.go b/cc/coverage.go
index a7618dd..dbb424f 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -145,7 +145,7 @@
// Even if we don't have coverage enabled, if any of our object files were compiled
// with coverage, then we need to add --coverage to our ldflags.
if !cov.linkCoverage {
- if ctx.static() && !ctx.staticBinary() {
+ if ctx.staticLibrary() {
// For static libraries, the only thing that changes our object files
// are included whole static libraries, so check to see if any of
// those have coverage enabled.
diff --git a/cc/library.go b/cc/library.go
index ea87946..6485ea3 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1800,12 +1800,17 @@
return library.shared() || library.static()
}
-// static returns true if this library is for a "static' variant.
+// static returns true if this library is for a "static" variant.
func (library *libraryDecorator) static() bool {
return library.MutatedProperties.VariantIsStatic
}
-// shared returns true if this library is for a "shared' variant.
+// staticLibrary returns true if this library is for a "static"" variant.
+func (library *libraryDecorator) staticLibrary() bool {
+ return library.static()
+}
+
+// shared returns true if this library is for a "shared" variant.
func (library *libraryDecorator) shared() bool {
return library.MutatedProperties.VariantIsShared
}
diff --git a/cc/orderfile.go b/cc/orderfile.go
index 6e08da7..c07a098 100644
--- a/cc/orderfile.go
+++ b/cc/orderfile.go
@@ -153,7 +153,7 @@
}
// Currently, we are not enabling orderfiles to begin from static libraries
- if ctx.static() && !ctx.staticBinary() {
+ if ctx.staticLibrary() {
return
}
diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go
index a864584..036b239 100644
--- a/cmd/find_input_delta/find_input_delta/main.go
+++ b/cmd/find_input_delta/find_input_delta/main.go
@@ -80,15 +80,16 @@
panic(err)
}
- file_list := *fid_lib.CompareInternalState(prior_state, new_state, target)
+ file_list := fid_lib.CompareInternalState(prior_state, new_state, target)
if err = file_list.Format(os.Stdout, template); err != nil {
panic(err)
}
- metrics_file := os.Getenv("SOONG_METRICS_AGGREGATION_FILE")
- if metrics_file != "" {
- if err = file_list.SendMetrics(metrics_file); err != nil {
+ metrics_dir := os.Getenv("SOONG_METRICS_AGGREGATION_DIR")
+ out_dir := os.Getenv("OUT_DIR")
+ if metrics_dir != "" {
+ if err = file_list.WriteMetrics(metrics_dir, out_dir); err != nil {
panic(err)
}
}
diff --git a/cmd/find_input_delta/find_input_delta_lib/file_list.go b/cmd/find_input_delta/find_input_delta_lib/file_list.go
index 01242a0..f1d588b 100644
--- a/cmd/find_input_delta/find_input_delta_lib/file_list.go
+++ b/cmd/find_input_delta/find_input_delta_lib/file_list.go
@@ -16,10 +16,11 @@
import (
"fmt"
+ "hash/fnv"
"io"
"os"
"path/filepath"
- "slices"
+ "strings"
"text/template"
fid_exp "android/soong/cmd/find_input_delta/find_input_delta_proto"
@@ -106,95 +107,75 @@
fl.ExtCountMap[ext].Changes += 1
}
-func (fl FileList) ToProto() (*fid_exp.FileList, error) {
- var count uint32
- return fl.toProto(&count)
-}
-
-func (fl FileList) toProto(count *uint32) (*fid_exp.FileList, error) {
- ret := &fid_exp.FileList{
- Name: proto.String(fl.Name),
+// Write a SoongExecutionMetrics FileList proto to `dir`.
+//
+// Path
+// Prune any paths that
+// begin with `pruneDir` (usually ${OUT_DIR}). The file is only written if any
+// non-pruned changes are present.
+func (fl *FileList) WriteMetrics(dir, pruneDir string) (err error) {
+ if dir == "" {
+ return fmt.Errorf("No directory given")
}
+ var needed bool
+
+ if !strings.HasSuffix(pruneDir, "/") {
+ pruneDir += "/"
+ }
+
+ // Hash the dir and `fl.Name` to simplify scanning the metrics
+ // aggregation directory.
+ h := fnv.New128()
+ h.Write([]byte(dir + " " + fl.Name + ".FileList"))
+ path := fmt.Sprintf("%x.pb", h.Sum([]byte{}))
+ path = filepath.Join(dir, path[0:2], path[2:])
+
+ var msg = &fid_exp.FileList{Name: proto.String(fl.Name)}
for _, a := range fl.Additions {
- if *count >= MaxFilesRecorded {
- break
+ if strings.HasPrefix(a, pruneDir) {
+ continue
}
- ret.Additions = append(ret.Additions, a)
- *count += 1
+ msg.Additions = append(msg.Additions, a)
+ needed = true
}
for _, ch := range fl.Changes {
- if *count >= MaxFilesRecorded {
- break
- } else {
- // Pre-increment to limit what the call adds.
- *count += 1
- change, err := ch.toProto(count)
- if err != nil {
- return nil, err
- }
- ret.Changes = append(ret.Changes, change)
+ if strings.HasPrefix(ch.Name, pruneDir) {
+ continue
}
+ msg.Changes = append(msg.Changes, ch.Name)
+ needed = true
}
for _, d := range fl.Deletions {
- if *count >= MaxFilesRecorded {
- break
+ if strings.HasPrefix(d, pruneDir) {
+ continue
}
- ret.Deletions = append(ret.Deletions, d)
+ msg.Deletions = append(msg.Deletions, d)
+ needed = true
}
- ret.TotalDelta = proto.Uint32(*count)
- exts := []string{}
- for k := range fl.ExtCountMap {
- exts = append(exts, k)
+ if !needed {
+ return nil
}
- slices.Sort(exts)
- for _, k := range exts {
- v := fl.ExtCountMap[k]
- ret.Counts = append(ret.Counts, &fid_exp.FileCount{
- Extension: proto.String(k),
- Additions: proto.Uint32(v.Additions),
- Deletions: proto.Uint32(v.Deletions),
- Modifications: proto.Uint32(v.Changes),
- })
- }
- return ret, nil
-}
-
-func (fl FileList) SendMetrics(path string) error {
- if path == "" {
- return fmt.Errorf("No path given")
- }
- message, err := fl.ToProto()
- if err != nil {
- return err
- }
-
- // Marshal the message wrapped in SoongCombinedMetrics.
data := protowire.AppendVarint(
[]byte{},
protowire.EncodeTag(
protowire.Number(fid_exp.FieldNumbers_FIELD_NUMBERS_FILE_LIST),
protowire.BytesType))
- size := uint64(proto.Size(message))
+ size := uint64(proto.Size(msg))
data = protowire.AppendVarint(data, size)
- data, err = proto.MarshalOptions{UseCachedSize: true}.MarshalAppend(data, message)
+ data, err = proto.MarshalOptions{UseCachedSize: true}.MarshalAppend(data, msg)
if err != nil {
return err
}
- out, err := os.Create(path)
+ err = os.MkdirAll(filepath.Dir(path), 0777)
if err != nil {
return err
}
- defer func() {
- if err := out.Close(); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to close %s: %v\n", path, err)
- }
- }()
- _, err = out.Write(data)
- return err
+
+ return os.WriteFile(path, data, 0644)
}
-func (fl FileList) Format(wr io.Writer, format string) error {
+func (fl *FileList) Format(wr io.Writer, format string) error {
tmpl, err := template.New("filelist").Parse(format)
if err != nil {
return err
diff --git a/cmd/find_input_delta/find_input_delta_lib/internal_state.go b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
index 2b8c395..bf4f866 100644
--- a/cmd/find_input_delta/find_input_delta_lib/internal_state.go
+++ b/cmd/find_input_delta/find_input_delta_lib/internal_state.go
@@ -51,6 +51,9 @@
for _, input := range inputs {
stat, err := fs.Stat(fsys, input)
if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ continue
+ }
return ret, err
}
pci := &fid_proto.PartialCompileInput{
diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
index 745de2d..b6adc45 100644
--- a/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
+++ b/cmd/find_input_delta/find_input_delta_proto/file_list.pb.go
@@ -96,20 +96,14 @@
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // The name of the file.
- // In the outermost message, this is the name of the Ninja target.
- // When used in `changes`, this is the name of the changed file.
+ // The name of the output file (Ninja target).
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// The added files.
Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"`
// The changed files.
- Changes []*FileList `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
+ Changes []string `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
// The deleted files.
Deletions []string `protobuf:"bytes,4,rep,name=deletions" json:"deletions,omitempty"`
- // Count of files added/changed/deleted.
- TotalDelta *uint32 `protobuf:"varint,5,opt,name=total_delta,json=totalDelta" json:"total_delta,omitempty"`
- // Counts by extension.
- Counts []*FileCount `protobuf:"bytes,6,rep,name=counts" json:"counts,omitempty"`
}
func (x *FileList) Reset() {
@@ -158,7 +152,7 @@
return nil
}
-func (x *FileList) GetChanges() []*FileList {
+func (x *FileList) GetChanges() []string {
if x != nil {
return x.Changes
}
@@ -172,135 +166,28 @@
return nil
}
-func (x *FileList) GetTotalDelta() uint32 {
- if x != nil && x.TotalDelta != nil {
- return *x.TotalDelta
- }
- return 0
-}
-
-func (x *FileList) GetCounts() []*FileCount {
- if x != nil {
- return x.Counts
- }
- return nil
-}
-
-type FileCount struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // The file extension
- Extension *string `protobuf:"bytes,1,opt,name=extension" json:"extension,omitempty"`
- // Number of added files with this extension.
- Additions *uint32 `protobuf:"varint,2,opt,name=additions" json:"additions,omitempty"`
- // Number of modified files with this extension.
- Modifications *uint32 `protobuf:"varint,3,opt,name=modifications" json:"modifications,omitempty"`
- // Number of deleted files with this extension.
- Deletions *uint32 `protobuf:"varint,4,opt,name=deletions" json:"deletions,omitempty"`
-}
-
-func (x *FileCount) Reset() {
- *x = FileCount{}
- if protoimpl.UnsafeEnabled {
- mi := &file_file_list_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *FileCount) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*FileCount) ProtoMessage() {}
-
-func (x *FileCount) ProtoReflect() protoreflect.Message {
- mi := &file_file_list_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use FileCount.ProtoReflect.Descriptor instead.
-func (*FileCount) Descriptor() ([]byte, []int) {
- return file_file_list_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *FileCount) GetExtension() string {
- if x != nil && x.Extension != nil {
- return *x.Extension
- }
- return ""
-}
-
-func (x *FileCount) GetAdditions() uint32 {
- if x != nil && x.Additions != nil {
- return *x.Additions
- }
- return 0
-}
-
-func (x *FileCount) GetModifications() uint32 {
- if x != nil && x.Modifications != nil {
- return *x.Modifications
- }
- return 0
-}
-
-func (x *FileCount) GetDeletions() uint32 {
- if x != nil && x.Deletions != nil {
- return *x.Deletions
- }
- return 0
-}
-
var File_file_list_proto protoreflect.FileDescriptor
var file_file_list_proto_rawDesc = []byte{
0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x12, 0x1e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f,
0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x22, 0x82, 0x02, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x42, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64,
- 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x07, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f,
- 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74,
- 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x65,
- 0x6c, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x66, 0x69,
- 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
- 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
- 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69,
- 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55,
- 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
- 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d,
- 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01,
- 0x42, 0x3b, 0x5a, 0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
- 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75,
- 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x6f, 0x22, 0x74, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+ 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c,
+ 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65,
+ 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64,
+ 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45, 0x4c, 0x44,
+ 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+ 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f,
+ 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c, 0x49, 0x53,
+ 0x54, 0x10, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -316,20 +203,17 @@
}
var file_file_list_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_file_list_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_file_list_proto_goTypes = []interface{}{
(FieldNumbers)(0), // 0: android.find_input_delta_proto.FieldNumbers
(*FileList)(nil), // 1: android.find_input_delta_proto.FileList
- (*FileCount)(nil), // 2: android.find_input_delta_proto.FileCount
}
var file_file_list_proto_depIdxs = []int32{
- 1, // 0: android.find_input_delta_proto.FileList.changes:type_name -> android.find_input_delta_proto.FileList
- 2, // 1: android.find_input_delta_proto.FileList.counts:type_name -> android.find_input_delta_proto.FileCount
- 2, // [2:2] is the sub-list for method output_type
- 2, // [2:2] is the sub-list for method input_type
- 2, // [2:2] is the sub-list for extension type_name
- 2, // [2:2] is the sub-list for extension extendee
- 0, // [0:2] is the sub-list for field type_name
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
}
func init() { file_file_list_proto_init() }
@@ -350,18 +234,6 @@
return nil
}
}
- file_file_list_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FileCount); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -369,7 +241,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_file_list_proto_rawDesc,
NumEnums: 1,
- NumMessages: 2,
+ NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/cmd/find_input_delta/find_input_delta_proto/file_list.proto b/cmd/find_input_delta/find_input_delta_proto/file_list.proto
index 7180358..5309d66 100644
--- a/cmd/find_input_delta/find_input_delta_proto/file_list.proto
+++ b/cmd/find_input_delta/find_input_delta_proto/file_list.proto
@@ -23,37 +23,15 @@
}
message FileList {
- // The name of the file.
- // In the outermost message, this is the name of the Ninja target.
- // When used in `changes`, this is the name of the changed file.
+ // The name of the output file (Ninja target).
optional string name = 1;
// The added files.
repeated string additions = 2;
// The changed files.
- repeated FileList changes = 3;
+ repeated string changes = 3;
// The deleted files.
repeated string deletions = 4;
-
- // Count of files added/changed/deleted.
- optional uint32 total_delta = 5;
-
- // Counts by extension.
- repeated FileCount counts = 6;
-}
-
-message FileCount {
- // The file extension
- optional string extension = 1;
-
- // Number of added files with this extension.
- optional uint32 additions = 2;
-
- // Number of modified files with this extension.
- optional uint32 modifications = 3;
-
- // Number of deleted files with this extension.
- optional uint32 deletions = 4;
}
diff --git a/cmd/find_input_delta/find_input_delta_proto/regen.sh b/cmd/find_input_delta/find_input_delta_proto/regen.sh
old mode 100644
new mode 100755
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index c7134d7..9721794 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -27,6 +27,7 @@
"android/soong/shared"
"android/soong/ui/build"
+ "android/soong/ui/execution_metrics"
"android/soong/ui/logger"
"android/soong/ui/metrics"
"android/soong/ui/signal"
@@ -170,14 +171,16 @@
stat.Finish()
})
criticalPath := status.NewCriticalPath()
+ emet := execution_metrics.NewExecutionMetrics(log)
buildCtx := build.Context{ContextImpl: &build.ContextImpl{
- Context: ctx,
- Logger: log,
- Metrics: met,
- Tracer: trace,
- Writer: output,
- Status: stat,
- CriticalPath: criticalPath,
+ Context: ctx,
+ Logger: log,
+ Metrics: met,
+ ExecutionMetrics: emet,
+ Tracer: trace,
+ Writer: output,
+ Status: stat,
+ CriticalPath: criticalPath,
}}
freshConfig := func() build.Config {
@@ -194,6 +197,7 @@
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb")
buildTraceFile := filepath.Join(logsDir, c.logsPrefix+"build.trace.gz")
+ executionMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_execution_metrics.pb")
metricsFiles := []string{
buildErrorFile, // build error strings
@@ -204,9 +208,16 @@
}
defer func() {
+ emet.Finish(buildCtx)
stat.Finish()
criticalPath.WriteToMetrics(met)
met.Dump(soongMetricsFile)
+ emet.Dump(executionMetricsFile, args)
+ // If there are execution metrics, upload them.
+ if _, err := os.Stat(executionMetricsFile); err == nil {
+ // TODO: Upload the metrics file.
+ // metricsFiles = append(metricsFiles, executionMetricsFile)
+ }
if !config.SkipMetricsUpload() {
build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, metricsFiles...)
}
diff --git a/cmd/source_tree_size/Android.bp b/cmd/source_tree_size/Android.bp
new file mode 100644
index 0000000..97d29c6
--- /dev/null
+++ b/cmd/source_tree_size/Android.bp
@@ -0,0 +1,28 @@
+// Copyright 2024 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "source_tree_size",
+ srcs: [
+ "source_tree.pb.go",
+ "source_tree_size.go",
+ ],
+ deps: [
+ "golang-protobuf-runtime-protoimpl",
+ ],
+}
diff --git a/cmd/source_tree_size/regen.sh b/cmd/source_tree_size/regen.sh
new file mode 100755
index 0000000..b0f1c80
--- /dev/null
+++ b/cmd/source_tree_size/regen.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. source_tree.proto
+
diff --git a/cmd/source_tree_size/source_tree.pb.go b/cmd/source_tree_size/source_tree.pb.go
new file mode 100644
index 0000000..da8cba5
--- /dev/null
+++ b/cmd/source_tree_size/source_tree.pb.go
@@ -0,0 +1,230 @@
+// Copyright 2024 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: source_tree.proto
+
+package main
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type SourceFile struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Path *string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"`
+ SizeBytes *int32 `protobuf:"varint,2,opt,name=size_bytes,json=sizeBytes" json:"size_bytes,omitempty"`
+}
+
+func (x *SourceFile) Reset() {
+ *x = SourceFile{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_source_tree_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SourceFile) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SourceFile) ProtoMessage() {}
+
+func (x *SourceFile) ProtoReflect() protoreflect.Message {
+ mi := &file_source_tree_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SourceFile.ProtoReflect.Descriptor instead.
+func (*SourceFile) Descriptor() ([]byte, []int) {
+ return file_source_tree_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *SourceFile) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *SourceFile) GetSizeBytes() int32 {
+ if x != nil && x.SizeBytes != nil {
+ return *x.SizeBytes
+ }
+ return 0
+}
+
+type SourceTree struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Files []*SourceFile `protobuf:"bytes,1,rep,name=files" json:"files,omitempty"`
+}
+
+func (x *SourceTree) Reset() {
+ *x = SourceTree{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_source_tree_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SourceTree) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SourceTree) ProtoMessage() {}
+
+func (x *SourceTree) ProtoReflect() protoreflect.Message {
+ mi := &file_source_tree_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SourceTree.ProtoReflect.Descriptor instead.
+func (*SourceTree) Descriptor() ([]byte, []int) {
+ return file_source_tree_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *SourceTree) GetFiles() []*SourceFile {
+ if x != nil {
+ return x.Files
+ }
+ return nil
+}
+
+var File_source_tree_proto protoreflect.FileDescriptor
+
+var file_source_tree_proto_rawDesc = []byte{
+ 0x0a, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+ 0x73, 0x22, 0x3f, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12,
+ 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70,
+ 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74,
+ 0x65, 0x73, 0x22, 0x3c, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x72, 0x65, 0x65,
+ 0x12, 0x2e, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x18, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73,
+ 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x6d, 0x61, 0x69, 0x6e,
+}
+
+var (
+ file_source_tree_proto_rawDescOnce sync.Once
+ file_source_tree_proto_rawDescData = file_source_tree_proto_rawDesc
+)
+
+func file_source_tree_proto_rawDescGZIP() []byte {
+ file_source_tree_proto_rawDescOnce.Do(func() {
+ file_source_tree_proto_rawDescData = protoimpl.X.CompressGZIP(file_source_tree_proto_rawDescData)
+ })
+ return file_source_tree_proto_rawDescData
+}
+
+var file_source_tree_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_source_tree_proto_goTypes = []interface{}{
+ (*SourceFile)(nil), // 0: source_files.SourceFile
+ (*SourceTree)(nil), // 1: source_files.SourceTree
+}
+var file_source_tree_proto_depIdxs = []int32{
+ 0, // 0: source_files.SourceTree.files:type_name -> source_files.SourceFile
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_source_tree_proto_init() }
+func file_source_tree_proto_init() {
+ if File_source_tree_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_source_tree_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SourceFile); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_source_tree_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SourceTree); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_source_tree_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_source_tree_proto_goTypes,
+ DependencyIndexes: file_source_tree_proto_depIdxs,
+ MessageInfos: file_source_tree_proto_msgTypes,
+ }.Build()
+ File_source_tree_proto = out.File
+ file_source_tree_proto_rawDesc = nil
+ file_source_tree_proto_goTypes = nil
+ file_source_tree_proto_depIdxs = nil
+}
diff --git a/cmd/source_tree_size/source_tree.proto b/cmd/source_tree_size/source_tree.proto
new file mode 100644
index 0000000..1a5b89f
--- /dev/null
+++ b/cmd/source_tree_size/source_tree.proto
@@ -0,0 +1,27 @@
+// Copyright 2024 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.
+
+syntax = "proto2";
+
+package source_files;
+option go_package = "./main";
+
+message SourceFile {
+ optional string path = 1;
+ optional int32 size_bytes = 2;
+}
+
+message SourceTree {
+ repeated SourceFile files = 1;
+}
diff --git a/cmd/source_tree_size/source_tree_size.go b/cmd/source_tree_size/source_tree_size.go
new file mode 100644
index 0000000..8b2a4cf
--- /dev/null
+++ b/cmd/source_tree_size/source_tree_size.go
@@ -0,0 +1,126 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "path/filepath"
+ "sort"
+ "strings"
+ "sync"
+
+ "google.golang.org/protobuf/proto"
+)
+
+var root string
+var repo string
+var outDir string
+var channel chan SourceFile
+var waiter sync.WaitGroup
+var sourceTree SourceTree
+
+func normalizeOutDir(outDir, root string) string {
+ if len(outDir) == 0 {
+ return ""
+ }
+ if filepath.IsAbs(outDir) {
+ if strings.HasPrefix(outDir, root) {
+ // Absolute path inside root, use it
+ return outDir
+ } else {
+ // Not inside root, we don't care about it
+ return ""
+ }
+ } else {
+ // Relative path inside root, make it absolute
+ return root + outDir
+ }
+}
+
+func walkDir(dir string) {
+ defer waiter.Done()
+
+ visit := func(path string, info os.FileInfo, err error) error {
+ name := info.Name()
+
+ // Repo git projects are symlinks. A real directory called .git counts as checked in
+ // (and is very likely to be wasted space)
+ if info.Mode().Type()&os.ModeSymlink != 0 && name == ".git" {
+ return nil
+ }
+
+ // Skip .repo and out
+ if info.IsDir() && (path == repo || path == outDir) {
+ return filepath.SkipDir
+ }
+
+ if info.IsDir() && path != dir {
+ waiter.Add(1)
+ go walkDir(path)
+ return filepath.SkipDir
+ }
+
+ if !info.IsDir() {
+ sourcePath := strings.TrimPrefix(path, root)
+ file := SourceFile{
+ Path: proto.String(sourcePath),
+ SizeBytes: proto.Int32(42),
+ }
+ channel <- file
+ }
+ return nil
+
+ }
+ filepath.Walk(dir, visit)
+}
+
+func main() {
+ var outputFile string
+ flag.StringVar(&outputFile, "o", "", "The file to write")
+ flag.StringVar(&outDir, "out_dir", "out", "The out directory")
+ flag.Parse()
+
+ if outputFile == "" {
+ fmt.Fprintf(os.Stderr, "source_tree_size: Missing argument: -o\n")
+ os.Exit(1)
+ }
+
+ root, _ = os.Getwd()
+ if root[len(root)-1] != '/' {
+ root += "/"
+ }
+
+ outDir = normalizeOutDir(outDir, root)
+ repo = path.Join(root, ".repo")
+
+ // The parallel scanning reduces the run time by about a minute
+ channel = make(chan SourceFile)
+ waiter.Add(1)
+ go walkDir(root)
+ go func() {
+ waiter.Wait()
+ close(channel)
+ }()
+ for sourceFile := range channel {
+ sourceTree.Files = append(sourceTree.Files, &sourceFile)
+ }
+
+ // Sort the results, for a stable output
+ sort.Slice(sourceTree.Files, func(i, j int) bool {
+ return *sourceTree.Files[i].Path < *sourceTree.Files[j].Path
+ })
+
+ // Flatten and write
+ buf, err := proto.Marshal(&sourceTree)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Couldn't marshal protobuf\n")
+ os.Exit(1)
+ }
+ err = ioutil.WriteFile(outputFile, buf, 0644)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 7cd5b72..1d32b8f 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -886,8 +886,7 @@
eventLogtagsPath := etcPath.Join(ctx, "event-log-tags")
builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String())
cmd := builder.Command().BuiltTool("merge-event-log-tags").
- FlagWithArg("-o ", eventLogtagsPath.String()).
- FlagWithInput("-m ", android.MergedLogtagsPath(ctx))
+ FlagWithArg("-o ", eventLogtagsPath.String())
for _, path := range android.SortedKeys(logtagsFilePaths) {
cmd.Text(path)
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 774320f..b9fddca 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -490,6 +490,7 @@
Load_by_default *bool
Blocklist_file *string
Options_file *string
+ Strip_debug_symbols *bool
}{
Name: proptools.StringPtr(name),
}
@@ -505,6 +506,7 @@
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
case "vendor_dlkm":
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelModules).Strings()
if len(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.SystemKernelModules) > 0 {
@@ -514,12 +516,14 @@
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
case "odm_dlkm":
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelModules).Strings()
props.Odm_dlkm_specific = proptools.BoolPtr(true)
if blocklistFile := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.OdmKernelBlocklistFile; blocklistFile != "" {
props.Blocklist_file = proptools.StringPtr(blocklistFile)
}
+ props.Strip_debug_symbols = proptools.BoolPtr(false)
case "vendor_ramdisk":
props.Srcs = android.ExistentPathsForSources(ctx, ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.VendorRamdiskKernelModules).Strings()
props.Vendor_ramdisk = proptools.BoolPtr(true)
diff --git a/java/app.go b/java/app.go
index bedb45c..276e960 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1225,7 +1225,7 @@
}
depsInfo := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from android.Module, to android.ApexModule, externalDep bool) bool {
depName := to.Name()
// Skip dependencies that are only available to APEXes; they are developed with updatability
diff --git a/java/dex.go b/java/dex.go
index 875d092..2b3c931 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -136,7 +136,6 @@
`rm -f "$outDir"/classes*.dex "$outDir/classes.dex.jar"`,
CommandDeps: []string{
"${config.D8Cmd}",
- "${config.D8Jar}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
diff --git a/java/gen.go b/java/gen.go
index 1b4f4c7..aab8418 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -26,15 +26,14 @@
)
func init() {
- pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
- pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
+ pctx.HostBinToolVariable("logtagsCmd", "java-event-log-tags")
}
var (
logtags = pctx.AndroidStaticRule("logtags",
blueprint.RuleParams{
Command: "$logtagsCmd -o $out $in",
- CommandDeps: []string{"$logtagsCmd", "$logtagsLib"},
+ CommandDeps: []string{"$logtagsCmd"},
})
)
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 001a1e7..ec7a971 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -67,6 +67,10 @@
// Whether this module is directly installable to one of the partitions. Default is true
Installable *bool
+
+ // Whether debug symbols should be stripped from the *.ko files.
+ // Defaults to true.
+ Strip_debug_symbols *bool
}
// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory.
@@ -100,7 +104,9 @@
systemModules := android.PathsForModuleSrc(ctx, pkm.properties.System_deps)
depmodOut := pkm.runDepmod(ctx, modules, systemModules)
- strippedModules := stripDebugSymbols(ctx, modules)
+ if proptools.BoolDefault(pkm.properties.Strip_debug_symbols, true) {
+ modules = stripDebugSymbols(ctx, modules)
+ }
installDir := android.PathForModuleInstall(ctx, "lib", "modules")
// Kernel module is installed to vendor_ramdisk/lib/modules regardless of product
@@ -114,7 +120,7 @@
installDir = installDir.Join(ctx, pkm.KernelVersion())
}
- for _, m := range strippedModules {
+ for _, m := range modules {
ctx.InstallFile(installDir, filepath.Base(m.String()), m)
}
ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad)
@@ -165,9 +171,9 @@
}, "stripCmd")
)
-func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths {
+func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.Paths {
dir := android.PathForModuleOut(ctx, "stripped").OutputPath
- var outputs android.OutputPaths
+ var outputs android.Paths
for _, m := range modules {
stripped := dir.Join(ctx, filepath.Base(m.String()))
@@ -305,7 +311,7 @@
finalModulesDep := modulesDep
// Add a leading slash to paths in modules.dep of android dlkm
if ctx.InstallInSystemDlkm() || ctx.InstallInVendorDlkm() || ctx.InstallInOdmDlkm() {
- finalModulesDep := modulesDep.ReplaceExtension(ctx, "intermediates")
+ finalModulesDep = modulesDep.ReplaceExtension(ctx, "intermediates")
ctx.Build(pctx, android.BuildParams{
Rule: addLeadingSlashToPaths,
Input: modulesDep,
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index dc1abd9..a868d6a 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -41,6 +41,7 @@
"soong-remoteexec",
"soong-shared",
"soong-ui-build-paths",
+ "soong-ui-execution-metrics",
"soong-ui-logger",
"soong-ui-metrics",
"soong-ui-status",
@@ -54,6 +55,7 @@
"config.go",
"context.go",
"staging_snapshot.go",
+ "source_inputs.go",
"dumpvars.go",
"environment.go",
"exec.go",
diff --git a/ui/build/build.go b/ui/build/build.go
index d5a20b4..110ee95 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -502,4 +502,5 @@
// Be careful, anything added here slows down EVERY CI build
func runDistActions(ctx Context, config Config) {
runStagingSnapshot(ctx, config)
+ runSourceInputs(ctx, config)
}
diff --git a/ui/build/context.go b/ui/build/context.go
index fd20e26..69e5f96 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -18,6 +18,7 @@
"context"
"io"
+ "android/soong/ui/execution_metrics"
"android/soong/ui/logger"
"android/soong/ui/metrics"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -33,7 +34,8 @@
context.Context
logger.Logger
- Metrics *metrics.Metrics
+ Metrics *metrics.Metrics
+ ExecutionMetrics *execution_metrics.ExecutionMetrics
Writer io.Writer
Status *status.Status
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 5df3a95..e0b2c08 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -273,6 +273,7 @@
"BUILD_BROKEN_USES_BUILD_SHARED_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_JAVA_LIBRARY",
"BUILD_BROKEN_USES_BUILD_STATIC_LIBRARY",
+ "RELEASE_BUILD_EXECUTION_METRICS",
}, exportEnvVars...), BannerVars...)
makeVars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true, "")
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index f5f637f..b0c9c07 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -17,6 +17,7 @@
import (
"fmt"
"os"
+ "os/exec"
"path/filepath"
"sort"
"strconv"
@@ -244,6 +245,9 @@
// SOONG_USE_PARTIAL_COMPILE only determines which half of the rule we execute.
"SOONG_USE_PARTIAL_COMPILE",
+
+ // Directory for ExecutionMetrics
+ "SOONG_METRICS_AGGREGATION_DIR",
}, config.BuildBrokenNinjaUsesEnvVars()...)...)
}
@@ -256,6 +260,10 @@
// Only set RUST_BACKTRACE for n2.
}
+ // Set up the metrics aggregation directory.
+ ctx.ExecutionMetrics.SetDir(filepath.Join(config.OutDir(), "soong", "metrics_aggregation"))
+ cmd.Environment.Set("SOONG_METRICS_AGGREGATION_DIR", ctx.ExecutionMetrics.MetricsAggregationDir)
+
// Print the environment variables that Ninja is operating in.
ctx.Verboseln("Ninja environment: ")
envVars := cmd.Environment.Environ()
@@ -300,6 +308,8 @@
}
}()
+ ctx.ExecutionMetrics.Start()
+ defer ctx.ExecutionMetrics.Finish(ctx)
ctx.Status.Status("Starting ninja...")
cmd.RunAndStreamOrFatal()
}
@@ -339,3 +349,40 @@
}
c.prevModTime = newModTime
}
+
+// Constructs and runs the Ninja command line to get the inputs of a goal.
+// For now, this will always run ninja, because ninjago, n2 and siso don't have the
+// `-t inputs` command. This command will use the inputs command's -d option,
+// to use the dep file iff ninja was the executor. For other executors, the
+// results will be wrong.
+func runNinjaInputs(ctx Context, config Config, goal string) ([]string, error) {
+ executable := config.PrebuiltBuildTool("ninja")
+
+ args := []string{
+ "-f",
+ config.CombinedNinjaFile(),
+ "-t",
+ "inputs",
+ }
+ // Add deps file arg for ninja
+ // TODO: Update as inputs command is implemented
+ if config.ninjaCommand == NINJA_NINJA && !config.UseABFS() {
+ args = append(args, "-d")
+ }
+ args = append(args, goal)
+
+ // This is just ninja -t inputs, so we won't bother running it in the sandbox,
+ // so use exec.Command, not soong_ui's command.
+ cmd := exec.Command(executable, args...)
+
+ cmd.Stdin = os.Stdin
+ cmd.Stderr = os.Stderr
+
+ out, err := cmd.Output()
+ if err != nil {
+ fmt.Printf("Error getting goal inputs for %s: %s\n", goal, err)
+ return nil, err
+ }
+
+ return strings.Split(strings.TrimSpace(string(out)), "\n"), nil
+}
diff --git a/ui/build/source_inputs.go b/ui/build/source_inputs.go
new file mode 100644
index 0000000..d1cc1a2
--- /dev/null
+++ b/ui/build/source_inputs.go
@@ -0,0 +1,100 @@
+package build
+
+import (
+ "compress/gzip"
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "android/soong/shared"
+ "android/soong/ui/metrics"
+)
+
+func sortedStringSetKeys(m map[string]bool) []string {
+ result := make([]string, 0, len(m))
+ for key := range m {
+ result = append(result, key)
+ }
+ sort.Strings(result)
+ return result
+}
+
+func addSlash(str string) string {
+ if len(str) == 0 {
+ return ""
+ }
+ if str[len(str)-1] == '/' {
+ return str
+ }
+ return str + "/"
+}
+
+func hasPrefixStrings(str string, prefixes []string) bool {
+ for _, prefix := range prefixes {
+ if strings.HasPrefix(str, prefix) {
+ return true
+ }
+ }
+ return false
+}
+
+// Output DIST_DIR/source_inputs.txt.gz, which will contain a listing of the files
+// in the source tree (not including in the out directory) that were declared as ninja
+// inputs to the build that was just done.
+func runSourceInputs(ctx Context, config Config) {
+ ctx.BeginTrace(metrics.RunSoong, "runSourceInputs")
+ defer ctx.EndTrace()
+
+ success := false
+ outputFilename := shared.JoinPath(config.RealDistDir(), "source_inputs.txt.gz")
+
+ outputFile, err := os.Create(outputFilename)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "source_files_used: unable to open file for write: %s\n", outputFilename)
+ return
+ }
+ defer func() {
+ outputFile.Close()
+ if !success {
+ os.Remove(outputFilename)
+ }
+ }()
+
+ output := gzip.NewWriter(outputFile)
+ defer output.Close()
+
+ // Skip out dir, both absolute and relative. There are some files
+ // generated during analysis that ninja thinks are inputs not intermediates.
+ absOut, _ := filepath.Abs(config.OutDir())
+ excludes := []string{
+ addSlash(config.OutDir()),
+ addSlash(absOut),
+ }
+
+ goals := config.NinjaArgs()
+
+ result := make(map[string]bool)
+ for _, goal := range goals {
+ inputs, err := runNinjaInputs(ctx, config, goal)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "source_files_used: %v\n", err)
+ return
+ }
+
+ for _, filename := range inputs {
+ if !hasPrefixStrings(filename, excludes) {
+ result[filename] = true
+ }
+ }
+ }
+
+ for _, filename := range sortedStringSetKeys(result) {
+ output.Write([]byte(filename))
+ output.Write([]byte("\n"))
+ }
+
+ output.Flush()
+ success = true
+}
diff --git a/ui/execution_metrics/Android.bp b/ui/execution_metrics/Android.bp
new file mode 100644
index 0000000..542e550
--- /dev/null
+++ b/ui/execution_metrics/Android.bp
@@ -0,0 +1,35 @@
+// Copyright 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-ui-execution-metrics",
+ pkgPath: "android/soong/ui/execution_metrics",
+ deps: [
+ "golang-protobuf-proto",
+ "soong-shared",
+ "soong-ui-logger",
+ "soong-ui-execution_metrics_proto",
+ "soong-ui-metrics_proto",
+ "soong-cmd-find_input_delta-proto",
+ ],
+ srcs: [
+ "execution_metrics.go",
+ ],
+ testSrcs: [
+ ],
+}
diff --git a/ui/execution_metrics/execution_metrics.go b/ui/execution_metrics/execution_metrics.go
new file mode 100644
index 0000000..4ea251f
--- /dev/null
+++ b/ui/execution_metrics/execution_metrics.go
@@ -0,0 +1,273 @@
+// Copyright 2024 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 execution_metrics represents the metrics system for Android Platform Build Systems.
+package execution_metrics
+
+// This is the main heart of the metrics system for Android Platform Build Systems.
+// The starting of the soong_ui (cmd/soong_ui/main.go), the metrics system is
+// initialized by the invocation of New and is then stored in the context
+// (ui/build/context.go) to be used throughout the system. During the build
+// initialization phase, several functions in this file are invoked to store
+// information such as the environment, build configuration and build metadata.
+// There are several scoped code that has Begin() and defer End() functions
+// that captures the metrics and is them added as a perfInfo into the set
+// of the collected metrics. Finally, when soong_ui has finished the build,
+// the defer Dump function is invoked to store the collected metrics to the
+// raw protobuf file in the $OUT directory and this raw protobuf file will be
+// uploaded to the destination. See ui/build/upload.go for more details. The
+// filename of the raw protobuf file and the list of files to be uploaded is
+// defined in cmd/soong_ui/main.go. See ui/metrics/event.go for the explanation
+// of what an event is and how the metrics system is a stack based system.
+
+import (
+ "context"
+ "io/fs"
+ "maps"
+ "os"
+ "path/filepath"
+ "slices"
+ "sync"
+
+ "android/soong/ui/logger"
+
+ fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+ "android/soong/ui/metrics"
+ soong_execution_proto "android/soong/ui/metrics/execution_metrics_proto"
+ soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
+ "google.golang.org/protobuf/encoding/protowire"
+ "google.golang.org/protobuf/proto"
+)
+
+type ExecutionMetrics struct {
+ MetricsAggregationDir string
+ ctx context.Context
+ logger logger.Logger
+ waitGroup sync.WaitGroup
+ fileList *fileList
+}
+
+type fileList struct {
+ totalChanges uint32
+ changes fileChanges
+ seenFiles map[string]bool
+}
+
+type fileChanges struct {
+ additions changeInfo
+ deletions changeInfo
+ modifications changeInfo
+}
+
+type fileChangeCounts struct {
+ additions uint32
+ deletions uint32
+ modifications uint32
+}
+
+type changeInfo struct {
+ total uint32
+ list []string
+ byExtension map[string]uint32
+}
+
+var MAXIMUM_FILES uint32 = 50
+
+// Setup the handler for SoongExecutionMetrics.
+func NewExecutionMetrics(log logger.Logger) *ExecutionMetrics {
+ return &ExecutionMetrics{
+ logger: log,
+ fileList: &fileList{seenFiles: make(map[string]bool)},
+ }
+}
+
+// Save the path for ExecutionMetrics communications.
+func (c *ExecutionMetrics) SetDir(path string) {
+ c.MetricsAggregationDir = path
+}
+
+// Start collecting SoongExecutionMetrics.
+func (c *ExecutionMetrics) Start() {
+ if c.MetricsAggregationDir == "" {
+ return
+ }
+
+ tmpDir := c.MetricsAggregationDir + ".rm"
+ if _, err := fs.Stat(os.DirFS("."), c.MetricsAggregationDir); err == nil {
+ if err = os.RemoveAll(tmpDir); err != nil {
+ c.logger.Fatalf("Failed to remove %s: %v", tmpDir, err)
+ }
+ if err = os.Rename(c.MetricsAggregationDir, tmpDir); err != nil {
+ c.logger.Fatalf("Failed to rename %s to %s: %v", c.MetricsAggregationDir, tmpDir)
+ }
+ }
+ if err := os.MkdirAll(c.MetricsAggregationDir, 0777); err != nil {
+ c.logger.Fatalf("Failed to create %s: %v", c.MetricsAggregationDir)
+ }
+
+ c.waitGroup.Add(1)
+ go func(d string) {
+ defer c.waitGroup.Done()
+ os.RemoveAll(d)
+ }(tmpDir)
+
+ c.logger.Verbosef("ExecutionMetrics running\n")
+}
+
+type hasTrace interface {
+ BeginTrace(name, desc string)
+ EndTrace()
+}
+
+// Aggregate any execution metrics.
+func (c *ExecutionMetrics) Finish(ctx hasTrace) {
+ ctx.BeginTrace(metrics.RunSoong, "execution_metrics.Finish")
+ defer ctx.EndTrace()
+ if c.MetricsAggregationDir == "" {
+ return
+ }
+ c.waitGroup.Wait()
+
+ // Find and process all of the metrics files.
+ aggFs := os.DirFS(c.MetricsAggregationDir)
+ fs.WalkDir(aggFs, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ c.logger.Fatalf("ExecutionMetrics.Finish: Error walking %s: %v", c.MetricsAggregationDir, err)
+ }
+ if d.IsDir() {
+ return nil
+ }
+ path = filepath.Join(c.MetricsAggregationDir, path)
+ r, err := os.ReadFile(path)
+ if err != nil {
+ c.logger.Fatalf("ExecutionMetrics.Finish: Failed to read %s: %v", path, err)
+ }
+ msg := &soong_execution_proto.SoongExecutionMetrics{}
+ err = proto.Unmarshal(r, msg)
+ if err != nil {
+ c.logger.Verbosef("ExecutionMetrics.Finish: Error unmarshalling SoongExecutionMetrics message: %v\n", err)
+ return nil
+ }
+ switch {
+ case msg.GetFileList() != nil:
+ if err := c.fileList.aggregateFileList(msg.GetFileList()); err != nil {
+ c.logger.Verbosef("ExecutionMetrics.Finish: Error processing SoongExecutionMetrics message: %v\n", err)
+ }
+ // Status update for all others.
+ default:
+ tag, _ := protowire.ConsumeVarint(r)
+ id, _ := protowire.DecodeTag(tag)
+ c.logger.Verbosef("ExecutionMetrics.Finish: Unexpected SoongExecutionMetrics submessage id=%d\n", id)
+ }
+ return nil
+ })
+}
+
+func (fl *fileList) aggregateFileList(msg *fid_proto.FileList) error {
+ fl.updateChangeInfo(msg.GetAdditions(), &fl.changes.additions)
+ fl.updateChangeInfo(msg.GetDeletions(), &fl.changes.deletions)
+ fl.updateChangeInfo(msg.GetChanges(), &fl.changes.modifications)
+ return nil
+}
+
+func (fl *fileList) updateChangeInfo(list []string, info *changeInfo) {
+ for _, filename := range list {
+ if fl.seenFiles[filename] {
+ continue
+ }
+ fl.seenFiles[filename] = true
+ if info.total < MAXIMUM_FILES {
+ info.list = append(info.list, filename)
+ }
+ ext := filepath.Ext(filename)
+ if info.byExtension == nil {
+ info.byExtension = make(map[string]uint32)
+ }
+ info.byExtension[ext] += 1
+ info.total += 1
+ fl.totalChanges += 1
+ }
+}
+
+func (c *ExecutionMetrics) Dump(path string, args []string) error {
+ if c.MetricsAggregationDir == "" {
+ return nil
+ }
+ msg := c.GetMetrics()
+ msg.CommandArgs = args
+
+ if _, err := os.Stat(filepath.Dir(path)); err != nil {
+ if err = os.MkdirAll(filepath.Dir(path), 0775); err != nil {
+ return err
+ }
+ }
+ data, err := proto.Marshal(msg)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(path, data, 0644)
+}
+
+func (c *ExecutionMetrics) GetMetrics() *soong_metrics_proto.AggregatedFileList {
+ fl := c.fileList
+ if fl == nil {
+ return nil
+ }
+ var count uint32
+ fileCounts := make(map[string]*soong_metrics_proto.FileCount)
+ ret := &soong_metrics_proto.AggregatedFileList{TotalDelta: proto.Uint32(c.fileList.totalChanges)}
+
+ // MAXIMUM_FILES is the upper bound on total file names reported.
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.additions.total); limit > 0 {
+ ret.Additions = fl.changes.additions.list[:limit]
+ count += limit
+ }
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.modifications.total); limit > 0 {
+ ret.Changes = fl.changes.modifications.list[:limit]
+ count += limit
+ }
+ if limit := min(MAXIMUM_FILES-min(MAXIMUM_FILES, count), fl.changes.deletions.total); limit > 0 {
+ ret.Deletions = fl.changes.deletions.list[:limit]
+ count += limit
+ }
+
+ addExt := func(key string) *soong_metrics_proto.FileCount {
+ // Create the fileCounts map entry if needed, and return the address to the caller.
+ if _, ok := fileCounts[key]; !ok {
+ fileCounts[key] = &soong_metrics_proto.FileCount{Extension: proto.String(key)}
+ }
+ return fileCounts[key]
+ }
+ addCount := func(loc **uint32, count uint32) {
+ if *loc == nil {
+ *loc = proto.Uint32(0)
+ }
+ **loc += count
+ }
+ for k, v := range fl.changes.additions.byExtension {
+ addCount(&addExt(k).Additions, v)
+ }
+ for k, v := range fl.changes.modifications.byExtension {
+ addCount(&addExt(k).Modifications, v)
+ }
+ for k, v := range fl.changes.deletions.byExtension {
+ addCount(&addExt(k).Deletions, v)
+ }
+
+ keys := slices.Sorted(maps.Keys(fileCounts))
+ for _, k := range keys {
+ ret.Counts = append(ret.Counts, fileCounts[k])
+ }
+ return ret
+}
diff --git a/ui/execution_metrics/execution_metrics_test.go b/ui/execution_metrics/execution_metrics_test.go
new file mode 100644
index 0000000..28fa973
--- /dev/null
+++ b/ui/execution_metrics/execution_metrics_test.go
@@ -0,0 +1,63 @@
+// Copyright 2024 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 execution_metrics represents the metrics system for Android Platform Build Systems.
+package execution_metrics
+
+import (
+ "reflect"
+ "testing"
+
+ fid_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+)
+
+func TestUpdateChangeInfo(t *testing.T) {
+ testCases := []struct {
+ Name string
+ Message *fid_proto.FileList
+ FileList *fileList
+ Expected *fileList
+ }{
+ {
+ Name: "various",
+ Message: &fid_proto.FileList{
+ Additions: []string{"file1", "file2", "file3", "file2"},
+ Deletions: []string{"file5.go", "file6"},
+ },
+ FileList: &fileList{seenFiles: make(map[string]bool)},
+ Expected: &fileList{
+ seenFiles: map[string]bool{"file1": true, "file2": true, "file3": true, "file5.go": true, "file6": true},
+ totalChanges: 5,
+ changes: fileChanges{
+ additions: changeInfo{
+ total: 3,
+ list: []string{"file1", "file2", "file3"},
+ byExtension: map[string]uint32{"": 3},
+ },
+ deletions: changeInfo{
+ total: 2,
+ list: []string{"file5.go", "file6"},
+ byExtension: map[string]uint32{"": 1, ".go": 1},
+ },
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ tc.FileList.aggregateFileList(tc.Message)
+ if !reflect.DeepEqual(tc.FileList, tc.Expected) {
+ t.Errorf("Expected: %v, Actual: %v", tc.Expected, tc.FileList)
+ }
+ }
+}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 591e3cc..2e19f7a 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -26,7 +26,7 @@
"soong-ui-metrics_proto",
"soong-ui-mk_metrics_proto",
"soong-shared",
- "soong-ui-metrics_combined_proto",
+ "soong-ui-execution_metrics_proto",
],
srcs: [
"hostinfo.go",
@@ -64,15 +64,15 @@
}
bootstrap_go_package {
- name: "soong-ui-metrics_combined_proto",
- pkgPath: "android/soong/ui/metrics/combined_metrics_proto",
+ name: "soong-ui-execution_metrics_proto",
+ pkgPath: "android/soong/ui/metrics/execution_metrics_proto",
deps: [
"golang-protobuf-reflect-protoreflect",
"golang-protobuf-runtime-protoimpl",
"soong-cmd-find_input_delta-proto",
],
srcs: [
- "metrics_proto/metrics.pb.go",
+ "execution_metrics_proto/execution_metrics.pb.go",
],
}
diff --git a/ui/metrics/execution_metrics_proto/execution_metrics.pb.go b/ui/metrics/execution_metrics_proto/execution_metrics.pb.go
new file mode 100644
index 0000000..a065dbd
--- /dev/null
+++ b/ui/metrics/execution_metrics_proto/execution_metrics.pb.go
@@ -0,0 +1,240 @@
+// Copyright 2024 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: execution_metrics.proto
+
+package execution_metrics_proto
+
+import (
+ find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// These field numbers are also found in the inner message declarations.
+// We verify that the values are the same, and that every enum value is checked
+// in execution_metrics_test.go.
+// Do not change this enum without also updating:
+// - the submessage's .proto file
+// - execution_metrics_test.go
+type FieldNumbers int32
+
+const (
+ FieldNumbers_FIELD_NUMBERS_UNSPECIFIED FieldNumbers = 0
+ FieldNumbers_FIELD_NUMBERS_FILE_LIST FieldNumbers = 1
+)
+
+// Enum value maps for FieldNumbers.
+var (
+ FieldNumbers_name = map[int32]string{
+ 0: "FIELD_NUMBERS_UNSPECIFIED",
+ 1: "FIELD_NUMBERS_FILE_LIST",
+ }
+ FieldNumbers_value = map[string]int32{
+ "FIELD_NUMBERS_UNSPECIFIED": 0,
+ "FIELD_NUMBERS_FILE_LIST": 1,
+ }
+)
+
+func (x FieldNumbers) Enum() *FieldNumbers {
+ p := new(FieldNumbers)
+ *p = x
+ return p
+}
+
+func (x FieldNumbers) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (FieldNumbers) Descriptor() protoreflect.EnumDescriptor {
+ return file_execution_metrics_proto_enumTypes[0].Descriptor()
+}
+
+func (FieldNumbers) Type() protoreflect.EnumType {
+ return &file_execution_metrics_proto_enumTypes[0]
+}
+
+func (x FieldNumbers) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *FieldNumbers) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = FieldNumbers(num)
+ return nil
+}
+
+// Deprecated: Use FieldNumbers.Descriptor instead.
+func (FieldNumbers) EnumDescriptor() ([]byte, []int) {
+ return file_execution_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+type SoongExecutionMetrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // cmd/find_input_delta/find_input_delta_proto.FileList
+ FileList *find_input_delta_proto.FileList `protobuf:"bytes,1,opt,name=file_list,json=fileList" json:"file_list,omitempty"`
+}
+
+func (x *SoongExecutionMetrics) Reset() {
+ *x = SoongExecutionMetrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_execution_metrics_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SoongExecutionMetrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SoongExecutionMetrics) ProtoMessage() {}
+
+func (x *SoongExecutionMetrics) ProtoReflect() protoreflect.Message {
+ mi := &file_execution_metrics_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use SoongExecutionMetrics.ProtoReflect.Descriptor instead.
+func (*SoongExecutionMetrics) Descriptor() ([]byte, []int) {
+ return file_execution_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *SoongExecutionMetrics) GetFileList() *find_input_delta_proto.FileList {
+ if x != nil {
+ return x.FileList
+ }
+ return nil
+}
+
+var File_execution_metrics_proto protoreflect.FileDescriptor
+
+var file_execution_metrics_proto_rawDesc = []byte{
+ 0x0a, 0x17, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0x3b,
+ 0x63, 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6c, 0x65,
+ 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x15, 0x53,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73,
+ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x2e, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73,
+ 0x74, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2a, 0x4a, 0x0a, 0x0c, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46,
+ 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49,
+ 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+ 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x42, 0x32, 0x5a, 0x30, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_execution_metrics_proto_rawDescOnce sync.Once
+ file_execution_metrics_proto_rawDescData = file_execution_metrics_proto_rawDesc
+)
+
+func file_execution_metrics_proto_rawDescGZIP() []byte {
+ file_execution_metrics_proto_rawDescOnce.Do(func() {
+ file_execution_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_execution_metrics_proto_rawDescData)
+ })
+ return file_execution_metrics_proto_rawDescData
+}
+
+var file_execution_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
+var file_execution_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_execution_metrics_proto_goTypes = []interface{}{
+ (FieldNumbers)(0), // 0: soong_build_metrics.FieldNumbers
+ (*SoongExecutionMetrics)(nil), // 1: soong_build_metrics.SoongExecutionMetrics
+ (*find_input_delta_proto.FileList)(nil), // 2: android.find_input_delta_proto.FileList
+}
+var file_execution_metrics_proto_depIdxs = []int32{
+ 2, // 0: soong_build_metrics.SoongExecutionMetrics.file_list:type_name -> android.find_input_delta_proto.FileList
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_execution_metrics_proto_init() }
+func file_execution_metrics_proto_init() {
+ if File_execution_metrics_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_execution_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SoongExecutionMetrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_execution_metrics_proto_rawDesc,
+ NumEnums: 1,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_execution_metrics_proto_goTypes,
+ DependencyIndexes: file_execution_metrics_proto_depIdxs,
+ EnumInfos: file_execution_metrics_proto_enumTypes,
+ MessageInfos: file_execution_metrics_proto_msgTypes,
+ }.Build()
+ File_execution_metrics_proto = out.File
+ file_execution_metrics_proto_rawDesc = nil
+ file_execution_metrics_proto_goTypes = nil
+ file_execution_metrics_proto_depIdxs = nil
+}
diff --git a/ui/metrics/metrics_proto/combined_metrics.proto b/ui/metrics/execution_metrics_proto/execution_metrics.proto
similarity index 83%
rename from ui/metrics/metrics_proto/combined_metrics.proto
rename to ui/metrics/execution_metrics_proto/execution_metrics.proto
index 3cd9a53..381dcd1 100644
--- a/ui/metrics/metrics_proto/combined_metrics.proto
+++ b/ui/metrics/execution_metrics_proto/execution_metrics.proto
@@ -1,4 +1,4 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
+// Copyright 2024 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.
@@ -15,22 +15,22 @@
syntax = "proto2";
package soong_build_metrics;
-option go_package = "android/soong/ui/metrics/metrics_proto";
+option go_package = "android/soong/ui/metrics/execution_metrics_proto";
import "cmd/find_input_delta/find_input_delta_proto/file_list.proto";
// These field numbers are also found in the inner message declarations.
// We verify that the values are the same, and that every enum value is checked
-// in combined_metrics_test.go.
+// in execution_metrics_test.go.
// Do not change this enum without also updating:
// - the submessage's .proto file
-// - combined_metrics_test.go
+// - execution_metrics_test.go
enum FieldNumbers {
FIELD_NUMBERS_UNSPECIFIED = 0;
FIELD_NUMBERS_FILE_LIST = 1;
}
-message SoongCombinedMetrics {
+message SoongExecutionMetrics {
// cmd/find_input_delta/find_input_delta_proto.FileList
optional android.find_input_delta_proto.FileList file_list = 1;
}
diff --git a/ui/metrics/metrics_proto/combined_metrics_test.go b/ui/metrics/execution_metrics_proto/execution_metrics_test.go
similarity index 89%
rename from ui/metrics/metrics_proto/combined_metrics_test.go
rename to ui/metrics/execution_metrics_proto/execution_metrics_test.go
index eedb12a..2f71c21 100644
--- a/ui/metrics/metrics_proto/combined_metrics_test.go
+++ b/ui/metrics/execution_metrics_proto/execution_metrics_test.go
@@ -1,4 +1,4 @@
-package metrics_proto
+package execution_metrics_proto
import (
"testing"
@@ -6,7 +6,7 @@
find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
)
-func TestCombinedMetricsMessageNums(t *testing.T) {
+func TestExecutionMetricsMessageNums(t *testing.T) {
testCases := []struct {
Name string
FieldNumbers map[string]int32
diff --git a/ui/metrics/execution_metrics_proto/regen.sh b/ui/metrics/execution_metrics_proto/regen.sh
new file mode 100755
index 0000000..5339a9a
--- /dev/null
+++ b/ui/metrics/execution_metrics_proto/regen.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Generates the golang source file of metrics.proto protobuf file.
+
+set -e
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. -I .:../../.. execution_metrics.proto; then
+ die "build failed. ${error_msg}"
+fi
diff --git a/ui/metrics/metrics_proto/combined_metrics.pb.go b/ui/metrics/metrics_proto/combined_metrics.pb.go
deleted file mode 100644
index f49d64d..0000000
--- a/ui/metrics/metrics_proto/combined_metrics.pb.go
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2018 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.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// protoc-gen-go v1.33.0
-// protoc v3.21.12
-// source: combined_metrics.proto
-
-package metrics_proto
-
-import (
- find_input_delta_proto "android/soong/cmd/find_input_delta/find_input_delta_proto"
- protoreflect "google.golang.org/protobuf/reflect/protoreflect"
- protoimpl "google.golang.org/protobuf/runtime/protoimpl"
- reflect "reflect"
- sync "sync"
-)
-
-const (
- // Verify that this generated code is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
- // Verify that runtime/protoimpl is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// These field numbers are also found in the inner message declarations.
-// We verify that the values are the same, and that every enum value is checked
-// in combined_metrics_test.go.
-// Do not change this enum without also updating:
-// - the submessage's .proto file
-// - combined_metrics_test.go
-type FieldNumbers int32
-
-const (
- FieldNumbers_FIELD_NUMBERS_UNSPECIFIED FieldNumbers = 0
- FieldNumbers_FIELD_NUMBERS_FILE_LIST FieldNumbers = 1
-)
-
-// Enum value maps for FieldNumbers.
-var (
- FieldNumbers_name = map[int32]string{
- 0: "FIELD_NUMBERS_UNSPECIFIED",
- 1: "FIELD_NUMBERS_FILE_LIST",
- }
- FieldNumbers_value = map[string]int32{
- "FIELD_NUMBERS_UNSPECIFIED": 0,
- "FIELD_NUMBERS_FILE_LIST": 1,
- }
-)
-
-func (x FieldNumbers) Enum() *FieldNumbers {
- p := new(FieldNumbers)
- *p = x
- return p
-}
-
-func (x FieldNumbers) String() string {
- return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
-}
-
-func (FieldNumbers) Descriptor() protoreflect.EnumDescriptor {
- return file_combined_metrics_proto_enumTypes[0].Descriptor()
-}
-
-func (FieldNumbers) Type() protoreflect.EnumType {
- return &file_combined_metrics_proto_enumTypes[0]
-}
-
-func (x FieldNumbers) Number() protoreflect.EnumNumber {
- return protoreflect.EnumNumber(x)
-}
-
-// Deprecated: Do not use.
-func (x *FieldNumbers) UnmarshalJSON(b []byte) error {
- num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
- if err != nil {
- return err
- }
- *x = FieldNumbers(num)
- return nil
-}
-
-// Deprecated: Use FieldNumbers.Descriptor instead.
-func (FieldNumbers) EnumDescriptor() ([]byte, []int) {
- return file_combined_metrics_proto_rawDescGZIP(), []int{0}
-}
-
-type SoongCombinedMetrics struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // cmd/find_input_delta/find_input_delta_proto.FileList
- FileList *find_input_delta_proto.FileList `protobuf:"bytes,1,opt,name=file_list,json=fileList" json:"file_list,omitempty"`
-}
-
-func (x *SoongCombinedMetrics) Reset() {
- *x = SoongCombinedMetrics{}
- if protoimpl.UnsafeEnabled {
- mi := &file_combined_metrics_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SoongCombinedMetrics) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SoongCombinedMetrics) ProtoMessage() {}
-
-func (x *SoongCombinedMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_combined_metrics_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SoongCombinedMetrics.ProtoReflect.Descriptor instead.
-func (*SoongCombinedMetrics) Descriptor() ([]byte, []int) {
- return file_combined_metrics_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *SoongCombinedMetrics) GetFileList() *find_input_delta_proto.FileList {
- if x != nil {
- return x.FileList
- }
- return nil
-}
-
-var File_combined_metrics_proto protoreflect.FileDescriptor
-
-var file_combined_metrics_proto_rawDesc = []byte{
- 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0x3b, 0x63,
- 0x6d, 0x64, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x2f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64,
- 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x5f,
- 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x14, 0x53, 0x6f,
- 0x6f, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e,
- 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
- 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52,
- 0x08, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2a, 0x4a, 0x0a, 0x0c, 0x46, 0x69, 0x65,
- 0x6c, 0x64, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x49, 0x45,
- 0x4c, 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
- 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x49, 0x45, 0x4c,
- 0x44, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x53, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4c,
- 0x49, 0x53, 0x54, 0x10, 0x01, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-}
-
-var (
- file_combined_metrics_proto_rawDescOnce sync.Once
- file_combined_metrics_proto_rawDescData = file_combined_metrics_proto_rawDesc
-)
-
-func file_combined_metrics_proto_rawDescGZIP() []byte {
- file_combined_metrics_proto_rawDescOnce.Do(func() {
- file_combined_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_combined_metrics_proto_rawDescData)
- })
- return file_combined_metrics_proto_rawDescData
-}
-
-var file_combined_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_combined_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_combined_metrics_proto_goTypes = []interface{}{
- (FieldNumbers)(0), // 0: soong_build_metrics.FieldNumbers
- (*SoongCombinedMetrics)(nil), // 1: soong_build_metrics.SoongCombinedMetrics
- (*find_input_delta_proto.FileList)(nil), // 2: android.find_input_delta_proto.FileList
-}
-var file_combined_metrics_proto_depIdxs = []int32{
- 2, // 0: soong_build_metrics.SoongCombinedMetrics.file_list:type_name -> android.find_input_delta_proto.FileList
- 1, // [1:1] is the sub-list for method output_type
- 1, // [1:1] is the sub-list for method input_type
- 1, // [1:1] is the sub-list for extension type_name
- 1, // [1:1] is the sub-list for extension extendee
- 0, // [0:1] is the sub-list for field type_name
-}
-
-func init() { file_combined_metrics_proto_init() }
-func file_combined_metrics_proto_init() {
- if File_combined_metrics_proto != nil {
- return
- }
- if !protoimpl.UnsafeEnabled {
- file_combined_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SoongCombinedMetrics); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
- type x struct{}
- out := protoimpl.TypeBuilder{
- File: protoimpl.DescBuilder{
- GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_combined_metrics_proto_rawDesc,
- NumEnums: 1,
- NumMessages: 1,
- NumExtensions: 0,
- NumServices: 0,
- },
- GoTypes: file_combined_metrics_proto_goTypes,
- DependencyIndexes: file_combined_metrics_proto_depIdxs,
- EnumInfos: file_combined_metrics_proto_enumTypes,
- MessageInfos: file_combined_metrics_proto_msgTypes,
- }.Build()
- File_combined_metrics_proto = out.File
- file_combined_metrics_proto_rawDesc = nil
- file_combined_metrics_proto_goTypes = nil
- file_combined_metrics_proto_depIdxs = nil
-}
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 72fdbe8..0aa51b1 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.33.0
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: metrics.proto
@@ -2080,6 +2080,177 @@
return nil
}
+// This is created by soong_ui from the various
+// android.find_input_delta_proto.FileList metrics provided to it by
+// find_input_delta.
+type AggregatedFileList struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The arguments provided on the command line.
+ CommandArgs []string `protobuf:"bytes,1,rep,name=command_args,json=commandArgs" json:"command_args,omitempty"`
+ // The (possibly truncated list of) added files.
+ Additions []string `protobuf:"bytes,2,rep,name=additions" json:"additions,omitempty"`
+ // The (possibly truncated list of) changed files.
+ Changes []string `protobuf:"bytes,3,rep,name=changes" json:"changes,omitempty"`
+ // The (possibly truncated list of) deleted files.
+ Deletions []string `protobuf:"bytes,4,rep,name=deletions" json:"deletions,omitempty"`
+ // Count of files added/changed/deleted.
+ TotalDelta *uint32 `protobuf:"varint,5,opt,name=total_delta,json=totalDelta" json:"total_delta,omitempty"`
+ // Counts by extension.
+ Counts []*FileCount `protobuf:"bytes,6,rep,name=counts" json:"counts,omitempty"`
+}
+
+func (x *AggregatedFileList) Reset() {
+ *x = AggregatedFileList{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[19]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AggregatedFileList) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AggregatedFileList) ProtoMessage() {}
+
+func (x *AggregatedFileList) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[19]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AggregatedFileList.ProtoReflect.Descriptor instead.
+func (*AggregatedFileList) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{19}
+}
+
+func (x *AggregatedFileList) GetCommandArgs() []string {
+ if x != nil {
+ return x.CommandArgs
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetAdditions() []string {
+ if x != nil {
+ return x.Additions
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetChanges() []string {
+ if x != nil {
+ return x.Changes
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetDeletions() []string {
+ if x != nil {
+ return x.Deletions
+ }
+ return nil
+}
+
+func (x *AggregatedFileList) GetTotalDelta() uint32 {
+ if x != nil && x.TotalDelta != nil {
+ return *x.TotalDelta
+ }
+ return 0
+}
+
+func (x *AggregatedFileList) GetCounts() []*FileCount {
+ if x != nil {
+ return x.Counts
+ }
+ return nil
+}
+
+type FileCount struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The file extension
+ Extension *string `protobuf:"bytes,1,opt,name=extension" json:"extension,omitempty"`
+ // Number of added files with this extension.
+ Additions *uint32 `protobuf:"varint,2,opt,name=additions" json:"additions,omitempty"`
+ // Number of modified files with this extension.
+ Modifications *uint32 `protobuf:"varint,3,opt,name=modifications" json:"modifications,omitempty"`
+ // Number of deleted files with this extension.
+ Deletions *uint32 `protobuf:"varint,4,opt,name=deletions" json:"deletions,omitempty"`
+}
+
+func (x *FileCount) Reset() {
+ *x = FileCount{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[20]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *FileCount) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*FileCount) ProtoMessage() {}
+
+func (x *FileCount) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[20]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use FileCount.ProtoReflect.Descriptor instead.
+func (*FileCount) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{20}
+}
+
+func (x *FileCount) GetExtension() string {
+ if x != nil && x.Extension != nil {
+ return *x.Extension
+ }
+ return ""
+}
+
+func (x *FileCount) GetAdditions() uint32 {
+ if x != nil && x.Additions != nil {
+ return *x.Additions
+ }
+ return 0
+}
+
+func (x *FileCount) GetModifications() uint32 {
+ if x != nil && x.Modifications != nil {
+ return *x.Modifications
+ }
+ return 0
+}
+
+func (x *FileCount) GetDeletions() uint32 {
+ if x != nil && x.Deletions != nil {
+ return *x.Deletions
+ }
+ return 0
+}
+
type OptimizedBuildMetrics_TargetOptimizationResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -2101,7 +2272,7 @@
func (x *OptimizedBuildMetrics_TargetOptimizationResult) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2114,7 +2285,7 @@
func (*OptimizedBuildMetrics_TargetOptimizationResult) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[19]
+ mi := &file_metrics_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2181,7 +2352,7 @@
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) Reset() {
*x = OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -2194,7 +2365,7 @@
func (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoMessage() {}
func (x *OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[20]
+ mi := &file_metrics_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -2637,10 +2808,33 @@
0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69,
0x7a, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x6d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e,
- 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28, 0x5a,
- 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
- 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0xe6, 0x01,
+ 0x0a, 0x12, 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65,
+ 0x4c, 0x69, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f,
+ 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x41, 0x72, 0x67, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73,
+ 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12,
+ 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x36,
+ 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e,
+ 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x8b, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+ 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x65, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -2656,7 +2850,7 @@
}
var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 21)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
var file_metrics_proto_goTypes = []interface{}{
(MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
(MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
@@ -2682,8 +2876,10 @@
(*CriticalPathInfo)(nil), // 21: soong_build_metrics.CriticalPathInfo
(*JobInfo)(nil), // 22: soong_build_metrics.JobInfo
(*OptimizedBuildMetrics)(nil), // 23: soong_build_metrics.OptimizedBuildMetrics
- (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 24: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 25: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ (*AggregatedFileList)(nil), // 24: soong_build_metrics.AggregatedFileList
+ (*FileCount)(nil), // 25: soong_build_metrics.FileCount
+ (*OptimizedBuildMetrics_TargetOptimizationResult)(nil), // 26: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ (*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact)(nil), // 27: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
@@ -2719,14 +2915,15 @@
22, // 30: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
10, // 31: soong_build_metrics.OptimizedBuildMetrics.analysis_perf:type_name -> soong_build_metrics.PerfInfo
10, // 32: soong_build_metrics.OptimizedBuildMetrics.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 24, // 33: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
- 10, // 34: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
- 25, // 35: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
- 36, // [36:36] is the sub-list for method output_type
- 36, // [36:36] is the sub-list for method input_type
- 36, // [36:36] is the sub-list for extension type_name
- 36, // [36:36] is the sub-list for extension extendee
- 0, // [0:36] is the sub-list for field type_name
+ 26, // 33: soong_build_metrics.OptimizedBuildMetrics.target_result:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult
+ 25, // 34: soong_build_metrics.AggregatedFileList.counts:type_name -> soong_build_metrics.FileCount
+ 10, // 35: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.packaging_perf:type_name -> soong_build_metrics.PerfInfo
+ 27, // 36: soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.output_artifact:type_name -> soong_build_metrics.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact
+ 37, // [37:37] is the sub-list for method output_type
+ 37, // [37:37] is the sub-list for method input_type
+ 37, // [37:37] is the sub-list for extension type_name
+ 37, // [37:37] is the sub-list for extension extendee
+ 0, // [0:37] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -2964,7 +3161,7 @@
}
}
file_metrics_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult); i {
+ switch v := v.(*AggregatedFileList); i {
case 0:
return &v.state
case 1:
@@ -2976,6 +3173,30 @@
}
}
file_metrics_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*FileCount); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OptimizedBuildMetrics_TargetOptimizationResult_OutputArtifact); i {
case 0:
return &v.state
@@ -2994,7 +3215,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
NumEnums: 5,
- NumMessages: 21,
+ NumMessages: 23,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 3fbe97c..8437b65 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -451,3 +451,40 @@
}
}
}
+
+// This is created by soong_ui from the various
+// android.find_input_delta_proto.FileList metrics provided to it by
+// find_input_delta.
+message AggregatedFileList {
+ // The arguments provided on the command line.
+ repeated string command_args = 1;
+
+ // The (possibly truncated list of) added files.
+ repeated string additions = 2;
+
+ // The (possibly truncated list of) changed files.
+ repeated string changes = 3;
+
+ // The (possibly truncated list of) deleted files.
+ repeated string deletions = 4;
+
+ // Count of files added/changed/deleted.
+ optional uint32 total_delta = 5;
+
+ // Counts by extension.
+ repeated FileCount counts = 6;
+}
+
+message FileCount {
+ // The file extension
+ optional string extension = 1;
+
+ // Number of added files with this extension.
+ optional uint32 additions = 2;
+
+ // Number of modified files with this extension.
+ optional uint32 modifications = 3;
+
+ // Number of deleted files with this extension.
+ optional uint32 deletions = 4;
+}
diff --git a/ui/metrics/metrics_proto/regen.sh b/ui/metrics/metrics_proto/regen.sh
index 5e5f9b8..8eb2d74 100755
--- a/ui/metrics/metrics_proto/regen.sh
+++ b/ui/metrics/metrics_proto/regen.sh
@@ -12,6 +12,6 @@
die "could not find aprotoc. ${error_msg}"
fi
-if ! aprotoc --go_out=paths=source_relative:. -I .:../../.. metrics.proto combined_metrics.proto; then
+if ! aprotoc --go_out=paths=source_relative:. metrics.proto; then
die "build failed. ${error_msg}"
fi