Merge "release_config: implement disallow_lunch_use" into main
diff --git a/Android.bp b/Android.bp
index 434ee9f..d78379a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -179,6 +179,7 @@
visibility: [
"//build/make/target/product/generic",
"//build/make/target/product/gsi",
+ "//build/soong/fsgen",
"//packages/modules/Virtualization/build/microdroid",
"//frameworks/base/ravenwood",
],
@@ -190,7 +191,10 @@
system_ext_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // system_ext/etc/build.prop
- visibility: ["//build/make/target/product/gsi"],
+ visibility: [
+ "//build/make/target/product/gsi",
+ "//build/soong/fsgen",
+ ],
}
build_prop {
@@ -199,7 +203,10 @@
product_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // product/etc/build.prop
- visibility: ["//build/make/target/product/gsi"],
+ visibility: [
+ "//build/make/target/product/gsi",
+ "//build/soong/fsgen",
+ ],
}
build_prop {
@@ -208,7 +215,7 @@
device_specific: true,
product_config: ":product_config",
relative_install_path: "etc", // odm/etc/build.prop
- visibility: ["//visibility:private"],
+ visibility: ["//build/soong/fsgen"],
}
build_prop {
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..79969a8 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -95,6 +95,7 @@
"proto.go",
"provider.go",
"raw_files.go",
+ "recovery_build_prop.go",
"register.go",
"rule_builder.go",
"sandbox.go",
@@ -109,6 +110,7 @@
"test_asserts.go",
"test_suites.go",
"testing.go",
+ "transition.go",
"util.go",
"variable.go",
"vendor_api_levels.go",
@@ -154,6 +156,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..db955b5 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -77,6 +77,9 @@
// Returns the value of `apex_available_name`
ApexAvailableName string
+
+ // Returns the apex names that this module is available for
+ ApexAvailableFor []string
}
// AllApexInfo holds the ApexInfo of all apexes that include this module.
@@ -146,15 +149,25 @@
// extracted from ApexModule to make it easier to define custom subsets of the ApexModule interface
// and improve code navigation within the IDE.
type DepIsInSameApex interface {
- // DepIsInSameApex tests if the other module 'dep' is considered as part of the same APEX as
- // this module. For example, a static lib dependency usually returns true here, while a
+ // OutgoingDepIsInSameApex tests if the module depended on via 'tag' is considered as part of
+ // the same APEX as this module. For example, a static lib dependency usually returns true here, while a
// shared lib dependency to a stub library returns false.
//
// This method must not be called directly without first ignoring dependencies whose tags
// implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
// are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
// IsDepInSameApex instead.
- DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
+ OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool
+
+ // IncomingDepIsInSameApex tests if this module depended on via 'tag' is considered as part of
+ // the same APEX as the depending module module. For example, a static lib dependency usually
+ // returns true here, while a shared lib dependency to a stub library returns false.
+ //
+ // This method must not be called directly without first ignoring dependencies whose tags
+ // implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
+ // are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
+ // IsDepInSameApex instead.
+ IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool
}
func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool {
@@ -164,7 +177,14 @@
// apex as the parent.
return false
}
- return module.(DepIsInSameApex).DepIsInSameApex(ctx, dep)
+
+ if m, ok := module.(DepIsInSameApex); ok && !m.OutgoingDepIsInSameApex(depTag) {
+ return false
+ }
+ if d, ok := dep.(DepIsInSameApex); ok && !d.IncomingDepIsInSameApex(depTag) {
+ return false
+ }
+ return true
}
// ApexModule is the interface that a module type is expected to implement if the module has to be
@@ -213,6 +233,12 @@
// apex_available property of the module.
AvailableFor(what string) bool
+ // Returns the apexes that are available for this module, valid values include
+ // "//apex_available:platform", "//apex_available:anyapex" and specific apexes.
+ // There are some differences between this one and the ApexAvailable on
+ // ApexModuleBase for cc, java library and sdkLibraryXml.
+ ApexAvailableFor() []string
+
// AlwaysRequiresPlatformApexVariant allows the implementing module to determine whether an
// APEX mutator should always be created for it.
//
@@ -264,9 +290,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 +300,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.
@@ -334,6 +346,10 @@
return CopyOf(availableToPlatformList)
}
+func (m *ApexModuleBase) ApexAvailableFor() []string {
+ return m.ApexAvailable()
+}
+
// Implements ApexModule
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexInfosLock.Lock()
@@ -386,7 +402,15 @@
}
// Implements ApexModule
-func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
+func (m *ApexModuleBase) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ // By default, if there is a dependency from A to B, we try to include both in the same
+ // APEX, unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning
+ // true. This is overridden by some module types like apex.ApexBundle, cc.Module,
+ // java.Module, etc.
+ return true
+}
+
+func (m *ApexModuleBase) IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// By default, if there is a dependency from A to B, we try to include both in the same
// APEX, unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning
// true. This is overridden by some module types like apex.ApexBundle, cc.Module,
@@ -434,7 +458,7 @@
// Implements ApexModule
func (m *ApexModuleBase) AvailableFor(what string) bool {
- return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
+ return CheckAvailableForApex(what, m.ApexAvailableFor())
}
// Implements ApexModule
@@ -628,6 +652,7 @@
} else {
panic(fmt.Errorf("failed to find apexInfo for incoming variation %q", variation))
}
+ thisApexInfo.ApexAvailableFor = module.ApexAvailableFor()
SetProvider(ctx, ApexInfoProvider, thisApexInfo)
}
@@ -661,7 +686,7 @@
// variant.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
// anyInSameApex returns true if the two ApexInfo lists contain any values in an
- // InApexVariants list in common. It is used instead of DepIsInSameApex because it needs to
+ // InApexVariants list in common. It is used instead of OutgoingDepIsInSameApex because it needs to
// determine if the dep is in the same APEX due to being directly included, not only if it
// is included _because_ it is a dependency.
anyInSameApex := func(a, b ApexModule) bool {
@@ -778,7 +803,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,14 +831,14 @@
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
// dependencies.
return false
}
- if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
+ if !IsDepInSameApex(ctx, from, to) {
return false
}
if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 1f89dea..06819d6 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -288,7 +288,7 @@
return b.bp.OtherModuleReverseDependencyVariantExists(name)
}
func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
- return b.bp.OtherModuleType(m)
+ return b.bp.OtherModuleType(getWrappedModule(m))
}
func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
diff --git a/android/config.go b/android/config.go
index b811c55..d78bbf7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1320,6 +1320,10 @@
return c.IsEnvTrue("RUN_ERROR_PRONE")
}
+func (c *config) RunErrorProneInline() bool {
+ return c.IsEnvTrue("RUN_ERROR_PRONE_INLINE")
+}
+
// XrefCorpusName returns the Kythe cross-reference corpus name.
func (c *config) XrefCorpusName() string {
return c.Getenv("XREF_CORPUS")
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..abc37f9 100644
--- a/android/logtags.go
+++ b/android/logtags.go
@@ -14,7 +14,11 @@
package android
-import "github.com/google/blueprint"
+import (
+ "strings"
+
+ "github.com/google/blueprint"
+)
func init() {
RegisterParallelSingletonType("logtags", LogtagsSingleton)
@@ -46,11 +50,20 @@
allLogtags = append(allLogtags, logtagsInfo.Logtags...)
}
})
+ allLogtags = SortedUniquePaths(allLogtags)
+ filteredLogTags := make([]Path, 0, len(allLogtags))
+ for _, p := range allLogtags {
+ // Logic copied from make:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=987;drc=0585bb1bcf4c89065adaf709f48acc8b869fd3ce
+ if !strings.HasPrefix(p.String(), "vendor/") && !strings.HasPrefix(p.String(), "device/") && !strings.HasPrefix(p.String(), "out/") {
+ filteredLogTags = append(filteredLogTags, p)
+ }
+ }
builder := NewRuleBuilder(pctx, ctx)
builder.Command().
BuiltTool("merge-event-log-tags").
FlagWithOutput("-o ", MergedLogtagsPath(ctx)).
- Inputs(SortedUniquePaths(allLogtags))
+ Inputs(filteredLogTags)
builder.Build("all-event-log-tags.txt", "merge logtags")
}
diff --git a/android/module.go b/android/module.go
index d703c19..c2f4342 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1870,6 +1870,9 @@
CompileTarget Target
SkipAndroidMkProcessing bool
BaseModuleName string
+ CanHaveApexVariants bool
+ MinSdkVersion string
+ NotAvailableForPlatform bool
}
var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]()
@@ -2140,11 +2143,26 @@
SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
BaseModuleName: m.BaseModuleName(),
}
+ if mm, ok := m.module.(interface {
+ MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+ }); ok {
+ ver := mm.MinSdkVersion(ctx)
+ if !ver.IsNone() {
+ commonData.MinSdkVersion = ver.String()
+ }
+ } else if mm, ok := m.module.(interface{ MinSdkVersion() string }); ok {
+ commonData.MinSdkVersion = mm.MinSdkVersion()
+ }
+
if m.commonProperties.ForcedDisabled {
commonData.Enabled = false
} else {
commonData.Enabled = m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
}
+ if am, ok := m.module.(ApexModule); ok {
+ commonData.CanHaveApexVariants = am.CanHaveApexVariants()
+ commonData.NotAvailableForPlatform = am.NotAvailableForPlatform()
+ }
SetProvider(ctx, CommonModuleInfoKey, commonData)
if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
SetProvider(ctx, PrebuiltModuleProviderKey, PrebuiltModuleProviderData{})
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 30459b9..8cc8fa1 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -189,7 +189,7 @@
}
func (m ModuleProxy) String() string {
- return m.module.Name()
+ return m.module.String()
}
func (m ModuleProxy) qualifiedModuleId(ctx BaseModuleContext) qualifiedModuleName {
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/recovery_build_prop.go b/android/recovery_build_prop.go
new file mode 100644
index 0000000..91d1904
--- /dev/null
+++ b/android/recovery_build_prop.go
@@ -0,0 +1,111 @@
+// 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/proptools"
+
+func init() {
+ RegisterModuleType("recovery_build_prop", RecoveryBuildPropModuleFactory)
+}
+
+type recoveryBuildPropProperties struct {
+ // Path to the system build.prop file
+ System_build_prop *string `android:"path"`
+
+ // Path to the vendor build.prop file
+ Vendor_build_prop *string `android:"path"`
+
+ // Path to the odm build.prop file
+ Odm_build_prop *string `android:"path"`
+
+ // Path to the product build.prop file
+ Product_build_prop *string `android:"path"`
+
+ // Path to the system_ext build.prop file
+ System_ext_build_prop *string `android:"path"`
+}
+
+type recoveryBuildPropModule struct {
+ ModuleBase
+ properties recoveryBuildPropProperties
+
+ outputFilePath ModuleOutPath
+
+ installPath InstallPath
+}
+
+func RecoveryBuildPropModuleFactory() Module {
+ module := &recoveryBuildPropModule{}
+ module.AddProperties(&module.properties)
+ InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
+ return module
+}
+
+// Overrides ctx.Module().InstallInRoot().
+// recovery_build_prop module always installs in root so that the prop.default
+// file is installed in recovery/root instead of recovery/root/system
+func (r *recoveryBuildPropModule) InstallInRoot() bool {
+ return true
+}
+
+func (r *recoveryBuildPropModule) appendRecoveryUIProperties(ctx ModuleContext, rule *RuleBuilder) {
+ rule.Command().Text("echo '#' >>").Output(r.outputFilePath)
+ rule.Command().Text("echo '# RECOVERY UI BUILD PROPERTIES' >>").Output(r.outputFilePath)
+ rule.Command().Text("echo '#' >>").Output(r.outputFilePath)
+
+ for propName, val := range ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.PrivateRecoveryUiProperties {
+ if len(val) > 0 {
+ rule.Command().
+ Textf("echo ro.recovery.ui.%s=%s >>", propName, val).
+ Output(r.outputFilePath)
+ }
+ }
+}
+
+func (r *recoveryBuildPropModule) getBuildProps(ctx ModuleContext) Paths {
+ var buildProps Paths
+ for _, buildProp := range []*string{
+ r.properties.System_build_prop,
+ r.properties.Vendor_build_prop,
+ r.properties.Odm_build_prop,
+ r.properties.Product_build_prop,
+ r.properties.System_ext_build_prop,
+ } {
+ if buildPropPath := PathForModuleSrc(ctx, proptools.String(buildProp)); buildPropPath != nil {
+ buildProps = append(buildProps, buildPropPath)
+ }
+ }
+ return buildProps
+}
+
+func (r *recoveryBuildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ if !r.InstallInRecovery() {
+ ctx.ModuleErrorf("recovery_build_prop module must set `recovery` property to true")
+ }
+ r.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName(), "prop.default")
+
+ // Replicates the logic in https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2733;drc=0585bb1bcf4c89065adaf709f48acc8b869fd3ce
+ rule := NewRuleBuilder(pctx, ctx)
+ rule.Command().Text("rm").FlagWithOutput("-f ", r.outputFilePath)
+ rule.Command().Text("cat").
+ Inputs(r.getBuildProps(ctx)).
+ Text(">>").
+ Output(r.outputFilePath)
+ r.appendRecoveryUIProperties(ctx, rule)
+
+ rule.Build(ctx.ModuleName(), "generating recovery prop.default")
+ r.installPath = PathForModuleInstall(ctx)
+ ctx.InstallFile(r.installPath, "prop.default", r.outputFilePath)
+}
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/android/variable.go b/android/variable.go
index 19f63e3..69e0337 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -688,6 +688,8 @@
ProductFsverityGenerateMetadata bool `json:",omitempty"`
TargetScreenDensity string `json:",omitempty"`
+
+ PrivateRecoveryUiProperties map[string]string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index f934134..fb0d730 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{})
@@ -1235,7 +1222,13 @@
var _ android.DepIsInSameApex = (*apexBundle)(nil)
// Implements android.DepInInSameApex
-func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
+func (a *apexBundle) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ // direct deps of an APEX bundle are all part of the APEX bundle
+ // TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
+ return true
+}
+
+func (a *apexBundle) IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// direct deps of an APEX bundle are all part of the APEX bundle
// TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
return true
@@ -1683,6 +1676,32 @@
})
}
+func (a *apexBundle) WalkPayloadDepsProxy(ctx android.BaseModuleContext,
+ do func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool) {
+ ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool {
+ if !android.OtherModuleProviderOrDefault(ctx, child, android.CommonModuleInfoKey).CanHaveApexVariants {
+ return false
+ }
+ // Filter-out unwanted depedendencies
+ depTag := ctx.OtherModuleDependencyTag(child)
+ if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+ return false
+ }
+ if dt, ok := depTag.(*dependencyTag); ok && !dt.payload {
+ return false
+ }
+ if depTag == android.RequiredDepTag {
+ return false
+ }
+
+ ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
+ externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
+
+ // Visit actually
+ return do(ctx, parent, child, externalDep)
+ })
+}
+
// filesystem type of the apex_payload.img inside the APEX. Currently, ext4 and f2fs are supported.
type fsType int
@@ -2096,17 +2115,14 @@
// like to record requiredNativeLibs even when
// DepIsInSameAPex is false. We also shouldn't do
// this for host.
- //
- // TODO(jiyong): explain why the same module is passed in twice.
- // Switching the first am to parent breaks lots of tests.
- if !android.IsDepInSameApex(ctx, am, am) {
+ if !android.IsDepInSameApex(ctx, parent, am) {
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
return true // track transitive dependencies
} else if rm, ok := child.(*rust.Module); ok {
- if !android.IsDepInSameApex(ctx, am, am) {
+ if !android.IsDepInSameApex(ctx, parent, am) {
return false
}
@@ -2576,21 +2592,19 @@
librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
})
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
- if ccm, ok := to.(*cc.Module); ok {
- apexName := ctx.ModuleName()
- fromName := ctx.OtherModuleName(from)
- toName := ctx.OtherModuleName(to)
-
+ a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
+ if ccInfo, ok := android.OtherModuleProvider(ctx, to, cc.CcInfoProvider); ok {
// If `to` is not actually in the same APEX as `from` then it does not need
// apex_available and neither do any of its dependencies.
- //
- // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
- if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
+ if externalDep {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
}
+ apexName := ctx.ModuleName()
+ fromName := ctx.OtherModuleName(from)
+ toName := ctx.OtherModuleName(to)
+
// The dynamic linker and crash_dump tool in the runtime APEX is the only
// exception to this rule. It can't make the static dependencies dynamic
// because it can't do the dynamic linking for itself.
@@ -2600,12 +2614,11 @@
return false
}
- isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !librariesDirectlyInApex[toName]
+ isStubLibraryFromOtherApex := ccInfo.HasStubsVariants && !librariesDirectlyInApex[toName]
if isStubLibraryFromOtherApex && !externalDep {
ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
"It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
}
-
}
return true
})
@@ -2684,7 +2697,7 @@
return
}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
if externalDep {
return false
@@ -2701,17 +2714,8 @@
fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to)
- // If `to` is not actually in the same APEX as `from` then it does not need
- // apex_available and neither do any of its dependencies.
- //
- // It is ok to call DepIsInSameApex() directly from within WalkPayloadDeps().
- if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
- // As soon as the dependency graph crosses the APEX boundary, don't go
- // further.
- return false
- }
-
- if to.AvailableFor(apexName) {
+ if android.CheckAvailableForApex(apexName,
+ android.OtherModuleProviderOrDefault(ctx, to, android.ApexInfoProvider).ApexAvailableFor) {
return true
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 282cd1d..ced3c46 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5818,7 +5818,6 @@
relative_install_path: "test",
shared_libs: ["mylib"],
system_shared_libs: [],
- static_executable: true,
stl: "none",
data: [":fg"],
}
@@ -6353,10 +6352,16 @@
testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
.*via tag apex\.dependencyTag\{"sharedLib"\}
.*-> libfoo.*link:shared.*
+.*via tag cc\.dependencyTag.*
+.*-> libfoo.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
.*-> libbar.*link:shared.*
+.*via tag cc\.dependencyTag.*
+.*-> libbar.*link:static.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
-.*-> libbaz.*link:shared.*`, `
+.*-> libbaz.*link:shared.*
+.*via tag cc\.dependencyTag.*
+.*-> libbaz.*link:static.*`, `
apex {
name: "myapex",
key: "myapex.key",
diff --git a/apex/builder.go b/apex/builder.go
index e5ae106..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' {
@@ -1049,7 +1049,7 @@
}
depInfos := android.DepNameToDepInfoMap{}
- a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDepsProxy(ctx, func(ctx android.BaseModuleContext, from, to android.ModuleProxy, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
// As soon as the dependency graph crosses the APEX boundary, don't go further.
@@ -1058,7 +1058,7 @@
// Skip dependencies that are only available to APEXes; they are developed with updatability
// in mind and don't need manual approval.
- if to.(android.ApexModule).NotAvailableForPlatform() {
+ if android.OtherModuleProviderOrDefault(ctx, to, android.CommonModuleInfoKey).NotAvailableForPlatform {
return !externalDep
}
@@ -1076,16 +1076,8 @@
depInfos[to.Name()] = info
} else {
toMinSdkVersion := "(no version)"
- if m, ok := to.(interface {
- MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
- }); ok {
- if v := m.MinSdkVersion(ctx); !v.IsNone() {
- toMinSdkVersion = v.String()
- }
- } else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
- // TODO(b/175678607) eliminate the use of MinSdkVersion returning
- // string
- if v := m.MinSdkVersion(); v != "" {
+ if info, ok := android.OtherModuleProvider(ctx, to, android.CommonModuleInfoKey); ok {
+ if v := info.MinSdkVersion; v != "" {
toMinSdkVersion = v
}
}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index f93eada..aaf2cb7 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -274,12 +274,15 @@
}
// Implements android.DepInInSameApex
-func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- tag := ctx.OtherModuleDependencyTag(dep)
+func (p *prebuiltCommon) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
_, ok := tag.(exportedDependencyTag)
return ok
}
+func (p *prebuiltCommon) IncomingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return true
+}
+
// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
// specific variant and checks that they are supported.
//
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 03f738f..04b66d4 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -53,6 +53,13 @@
var CcObjectInfoProvider = blueprint.NewProvider[CcObjectInfo]()
+// Common info about the cc module.
+type CcInfo struct {
+ HasStubsVariants bool
+}
+
+var CcInfoProvider = blueprint.NewProvider[CcInfo]()
+
type LinkableInfo struct {
// StaticExecutable returns true if this is a binary module with "static_executable: true".
StaticExecutable bool
@@ -512,6 +519,7 @@
type ModuleContextIntf interface {
static() bool
staticBinary() bool
+ staticLibrary() bool
testBinary() bool
testLibrary() bool
header() bool
@@ -723,6 +731,9 @@
Kind libraryDependencyKind
Order libraryDependencyOrder
+ // fromStatic is true when the parent module is a static library or binary
+ fromStatic bool
+
wholeStatic bool
reexportFlags bool
@@ -1516,6 +1527,10 @@
return ctx.mod.staticBinary()
}
+func (ctx *moduleContextImpl) staticLibrary() bool {
+ return ctx.mod.staticLibrary()
+}
+
func (ctx *moduleContextImpl) testBinary() bool {
return ctx.mod.testBinary()
}
@@ -2124,6 +2139,10 @@
StaticExecutable: c.StaticExecutable(),
})
+ android.SetProvider(ctx, CcInfoProvider, CcInfo{
+ HasStubsVariants: c.HasStubsVariants(),
+ })
+
c.setOutputFiles(ctx)
if c.makeVarsInfo != nil {
@@ -2536,7 +2555,7 @@
}
for _, lib := range deps.HeaderLibs {
- depTag := libraryDependencyTag{Kind: headerLibraryDependency}
+ depTag := libraryDependencyTag{Kind: headerLibraryDependency, fromStatic: c.static()}
if inList(lib, deps.ReexportHeaderLibHeaders) {
depTag.reexportFlags = true
}
@@ -2578,7 +2597,7 @@
}
for _, lib := range deps.WholeStaticLibs {
- depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -2587,7 +2606,7 @@
for _, lib := range deps.StaticLibs {
// Some dependencies listed in static_libs might actually be rust_ffi rlib variants.
- depTag := libraryDependencyTag{Kind: staticLibraryDependency}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, fromStatic: c.static()}
if inList(lib, deps.ReexportStaticLibHeaders) {
depTag.reexportFlags = true
@@ -2604,7 +2623,7 @@
// so that native libraries/binaries are linked with static unwinder
// because Q libc doesn't have unwinder APIs
if deps.StaticUnwinderIfLegacy {
- depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, staticUnwinder(actx))
@@ -2614,7 +2633,7 @@
var sharedLibNames []string
for _, lib := range deps.SharedLibs {
- depTag := libraryDependencyTag{Kind: sharedLibraryDependency}
+ depTag := libraryDependencyTag{Kind: sharedLibraryDependency, fromStatic: c.static()}
if inList(lib, deps.ReexportSharedLibHeaders) {
depTag.reexportFlags = true
}
@@ -2635,14 +2654,14 @@
}
for _, lib := range deps.LateStaticLibs {
- depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
}
for _, lib := range deps.UnexportedStaticLibs {
- depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency, unexportedSymbols: true}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency, unexportedSymbols: true, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
@@ -2655,7 +2674,7 @@
// linking against both the stubs lib and the non-stubs lib at the same time.
continue
}
- depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency}
+ depTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, fromStatic: c.static()}
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
@@ -2703,7 +2722,7 @@
version := ctx.sdkVersion()
- ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version}
+ ndkStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, ndk: true, makeSuffix: "." + version, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
@@ -2713,7 +2732,7 @@
{Mutator: "link", Variation: "shared"},
}, ndkStubDepTag, apiNdkLibs...)
- ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
+ ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version, fromStatic: c.static()}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
@@ -3539,6 +3558,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
@@ -3664,13 +3692,18 @@
}
func (c *Module) AvailableFor(what string) bool {
+ return android.CheckAvailableForApex(what, c.ApexAvailableFor())
+}
+
+func (c *Module) ApexAvailableFor() []string {
+ list := c.ApexModuleBase.ApexAvailable()
if linker, ok := c.linker.(interface {
- availableFor(string) bool
+ apexAvailable() []string
}); ok {
- return c.ApexModuleBase.AvailableFor(what) || linker.availableFor(what)
- } else {
- return c.ApexModuleBase.AvailableFor(what)
+ list = append(list, linker.apexAvailable()...)
}
+
+ return android.FirstUniqueStrings(list)
}
func (c *Module) EverInstallable() bool {
@@ -3728,35 +3761,7 @@
var _ android.ApexModule = (*Module)(nil)
// Implements android.ApexModule
-func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- depTag := ctx.OtherModuleDependencyTag(dep)
- libDepTag, isLibDepTag := depTag.(libraryDependencyTag)
-
- if cc, ok := dep.(*Module); ok {
- if cc.HasStubsVariants() {
- if isLibDepTag && libDepTag.shared() {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
- }
- if IsRuntimeDepTag(depTag) {
- // runtime dep to a stubs lib also crosses APEX boundary
- return false
- }
- }
- if cc.IsLlndk() {
- return false
- }
- if isLibDepTag && c.static() && libDepTag.shared() {
- // shared_lib dependency from a static lib is considered as crossing
- // the APEX boundary because the dependency doesn't actually is
- // linked; the dependency is used only during the compilation phase.
- return false
- }
-
- if isLibDepTag && libDepTag.excludeInApex {
- return false
- }
- }
+func (c *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
if depTag == stubImplDepTag {
// We don't track from an implementation library to its stubs.
return false
@@ -3770,6 +3775,39 @@
return true
}
+func (c *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ libDepTag, isLibDepTag := depTag.(libraryDependencyTag)
+
+ if c.HasStubsVariants() {
+ if IsSharedDepTag(depTag) {
+ // dynamic dep to a stubs lib crosses APEX boundary
+ return false
+ }
+ if IsRuntimeDepTag(depTag) {
+ // runtime dep to a stubs lib also crosses APEX boundary
+ return false
+ }
+ if IsHeaderDepTag(depTag) {
+ return false
+ }
+ }
+ if c.IsLlndk() {
+ return false
+ }
+ if isLibDepTag && libDepTag.fromStatic && libDepTag.shared() {
+ // shared_lib dependency from a static lib is considered as crossing
+ // the APEX boundary because the dependency doesn't actually is
+ // linked; the dependency is used only during the compilation phase.
+ return false
+ }
+
+ if isLibDepTag && libDepTag.excludeInApex {
+ return false
+ }
+
+ return true
+}
+
// Implements android.ApexModule
func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index a4d43b9..1f6cf23 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -106,6 +106,8 @@
}
windowsAvailableLibraries = addPrefix([]string{
+ "bcrypt",
+ "dbghelp",
"gdi32",
"imagehlp",
"iphlpapi",
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/fuzz.go b/cc/fuzz.go
index 8a974c0..26ac7d1 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -350,6 +350,8 @@
fuzzPackagedModule.Corpus = append(fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
+ fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_data)...)
+ fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_first_data)...)
if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
diff --git a/cc/library.go b/cc/library.go
index ea87946..a3a2f5c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -34,6 +34,8 @@
// LibraryProperties is a collection of properties shared by cc library rules/cc.
type LibraryProperties struct {
+ // local file name to pass to the linker as -exported_symbols_list
+ Exported_symbols_list *string `android:"path,arch_variant"`
// local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list *string `android:"path,arch_variant"`
// local file name to pass to the linker as -force_symbols_not_weak_list
@@ -723,7 +725,7 @@
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer)
- availableFor(string) bool
+ apexAvailable() []string
getAPIListCoverageXMLPath() android.ModuleOutPath
@@ -1049,10 +1051,14 @@
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
+ exportedSymbols := ctx.ExpandOptionalSource(library.Properties.Exported_symbols_list, "exported_symbols_list")
unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list")
forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list")
forceWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_weak_list, "force_symbols_weak_list")
if !ctx.Darwin() {
+ if exportedSymbols.Valid() {
+ ctx.PropertyErrorf("exported_symbols_list", "Only supported on Darwin")
+ }
if unexportedSymbols.Valid() {
ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
}
@@ -1063,6 +1069,10 @@
ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
}
} else {
+ if exportedSymbols.Valid() {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-exported_symbols_list,"+exportedSymbols.String())
+ linkerDeps = append(linkerDeps, exportedSymbols.Path())
+ }
if unexportedSymbols.Valid() {
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
linkerDeps = append(linkerDeps, unexportedSymbols.Path())
@@ -1800,12 +1810,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
}
@@ -1954,17 +1969,15 @@
return library.MutatedProperties.IsLatestVersion
}
-func (library *libraryDecorator) availableFor(what string) bool {
+func (library *libraryDecorator) apexAvailable() []string {
var list []string
if library.static() {
list = library.StaticProperties.Static.Apex_available
} else if library.shared() {
list = library.SharedProperties.Shared.Apex_available
}
- if len(list) == 0 {
- return false
- }
- return android.CheckAvailableForApex(what, list)
+
+ return list
}
func (library *libraryDecorator) installable() *bool {
diff --git a/cc/linkable.go b/cc/linkable.go
index 1a9a9ab..1fade71 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -294,8 +294,8 @@
}
// SharedDepTag returns the dependency tag for any C++ shared libraries.
-func SharedDepTag() blueprint.DependencyTag {
- return libraryDependencyTag{Kind: sharedLibraryDependency}
+func SharedDepTag(fromStatic bool) blueprint.DependencyTag {
+ return libraryDependencyTag{Kind: sharedLibraryDependency, fromStatic: fromStatic}
}
// StaticDepTag returns the dependency tag for any C++ static libraries.
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/cc/test.go b/cc/test.go
index ae73886..abec19a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -83,14 +83,14 @@
// the test
Data []string `android:"path,arch_variant"`
- // Same as data, but adds depedencies on modules using the device's os variant, and common
+ // Same as data, but adds dependencies on modules using the device's os variant, and common
// architecture's variant. Can be useful to add device-built apps to the data of a host
// test.
Device_common_data []string `android:"path_device_common"`
- // Same as data, but adds depedencies on modules using the device's os variant, and the device's
- // first architecture's variant. Can be useful to add device-built apps to the data of a host
- // test.
+ // Same as data, but adds dependencies on modules using the device's os variant, and the
+ // device's first architecture's variant. Can be useful to add device-built apps to the data
+ // of a host test.
Device_first_data []string `android:"path_device_first"`
// list of shared library modules that should be installed alongside the test
diff --git a/cmd/find_input_delta/find_input_delta/main.go b/cmd/find_input_delta/find_input_delta/main.go
index a864584..65ef881 100644
--- a/cmd/find_input_delta/find_input_delta/main.go
+++ b/cmd/find_input_delta/find_input_delta/main.go
@@ -17,11 +17,13 @@
import (
"flag"
"os"
- "strings"
+ "regexp"
fid_lib "android/soong/cmd/find_input_delta/find_input_delta_lib"
)
+var fileSepRegex = regexp.MustCompile("[^[:space:]]+")
+
func main() {
var top string
var prior_state_file string
@@ -46,6 +48,8 @@
if target == "" {
panic("must specify --target")
}
+ // Drop any extra file names that arrived in `target`.
+ target = fileSepRegex.FindString(target)
if prior_state_file == "" {
prior_state_file = target + ".pc_state"
}
@@ -63,7 +67,7 @@
if err != nil {
panic(err)
}
- inputs = append(inputs, strings.Split(string(data), "\n")...)
+ inputs = append(inputs, fileSepRegex.FindAllString(string(data), -1)...)
}
// Read the prior state
@@ -80,15 +84,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/find_input_delta/find_input_delta_proto_internal/regen.sh b/cmd/find_input_delta/find_input_delta_proto_internal/regen.sh
old mode 100644
new mode 100755
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index c7134d7..c119823 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,15 @@
}
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 {
+ 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/etc/otacerts_zip.go b/etc/otacerts_zip.go
index 8220cea..53ddc50 100644
--- a/etc/otacerts_zip.go
+++ b/etc/otacerts_zip.go
@@ -111,6 +111,10 @@
return proptools.StringDefault(m.properties.Filename, "otacerts.zip")
}
+func (m *otacertsZipModule) onlyInRecovery() bool {
+ return m.ModuleBase.InstallInRecovery()
+}
+
func (m *otacertsZipModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Read .x509.pem file defined in PRODUCT_DEFAULT_DEV_CERTIFICATE or the default test key.
pem, _ := ctx.Config().DefaultAppCertificate(ctx)
@@ -136,7 +140,7 @@
func (m *otacertsZipModule) AndroidMkEntries() []android.AndroidMkEntries {
nameSuffix := ""
- if m.InRecovery() {
+ if m.InRecovery() && !m.onlyInRecovery() {
nameSuffix = ".recovery"
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 84384a5..b30c0f7 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -98,6 +98,14 @@
Name *string
}
+// CopyWithNamePrefix returns a new [SymlinkDefinition] with prefix added to Name.
+func (s *SymlinkDefinition) CopyWithNamePrefix(prefix string) SymlinkDefinition {
+ return SymlinkDefinition{
+ Target: s.Target,
+ Name: proptools.StringPtr(filepath.Join(prefix, proptools.String(s.Name))),
+ }
+}
+
type FilesystemProperties struct {
// When set to true, sign the image with avbtool. Default is false.
Use_avb *bool
@@ -457,7 +465,7 @@
}
func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.Path) {
- partitionBaseDir := android.PathForModuleOut(ctx, "root", f.partitionName()).String() + "/"
+ partitionBaseDir := android.PathForModuleOut(ctx, f.rootDirString(), proptools.String(f.properties.Base_dir)).String() + "/"
relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir)
if inTargetPartition {
@@ -547,8 +555,12 @@
builder.Command().Textf("cp -prf %s/* %s", rebasedDir, installPath)
}
+func (f *filesystem) rootDirString() string {
+ return f.partitionName()
+}
+
func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.Path {
- rootDir := android.PathForModuleOut(ctx, "root").OutputPath
+ rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath
rebasedDir := rootDir
if f.properties.Base_dir != nil {
rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir)
@@ -775,7 +787,7 @@
ctx.PropertyErrorf("include_make_built_files", "include_make_built_files is not supported for compressed cpio image.")
}
- rootDir := android.PathForModuleOut(ctx, "root").OutputPath
+ rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath
rebasedDir := rootDir
if f.properties.Base_dir != nil {
rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir)
@@ -860,30 +872,10 @@
return
}
- logtagsFilePaths := make(map[string]bool)
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if logtagsInfo, ok := android.OtherModuleProvider(ctx, child, android.LogtagsProviderKey); ok {
- for _, path := range logtagsInfo.Logtags {
- logtagsFilePaths[path.String()] = true
- }
- }
- return true
- })
-
- if len(logtagsFilePaths) == 0 {
- return
- }
-
etcPath := rebasedDir.Join(ctx, "etc")
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))
-
- for _, path := range android.SortedKeys(logtagsFilePaths) {
- cmd.Text(path)
- }
+ builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String())
f.appendToEntry(ctx, eventLogtagsPath)
}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 86496eb..2dcb23d 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -181,7 +181,7 @@
`)
module := result.ModuleForTests("myfilesystem", "android_common")
- output := module.Output("out/soong/.intermediates/myfilesystem/android_common/root/system/etc/linker.config.pb")
+ output := module.Output("out/soong/.intermediates/myfilesystem/android_common/myfilesystem/system/etc/linker.config.pb")
fullCommand := output.RuleParams.Command
startIndex := strings.Index(fullCommand, "conv_linker_config")
@@ -244,7 +244,7 @@
`)
module := result.ModuleForTests("myfilesystem", "android_common").Module().(*systemImage)
- android.AssertDeepEquals(t, "entries should have foo only", []string{"components/foo"}, module.entries)
+ android.AssertDeepEquals(t, "entries should have foo and not bar", []string{"components/foo", "etc/linker.config.pb"}, module.entries)
}
func TestAvbGenVbmetaImage(t *testing.T) {
diff --git a/filesystem/fsverity_metadata.go b/filesystem/fsverity_metadata.go
index ef46067..91b8c57 100644
--- a/filesystem/fsverity_metadata.go
+++ b/filesystem/fsverity_metadata.go
@@ -85,6 +85,18 @@
f.appendToEntry(ctx, destPath)
}
+ fsVerityBaseDir := rootDir.String()
+ if f.PartitionType() == "system_ext" {
+ // Use the equivalent of $PRODUCT_OUT as the base dir.
+ // This ensures that the paths in build_manifest.pb contain on-device paths
+ // e.g. system_ext/framework/javalib.jar
+ // and not framework/javalib.jar.
+ //
+ // Although base-dir is outside the rootdir provided for packaging, this action
+ // is hermetic since it uses `manifestGeneratorListPath` to filter the files to be written to build_manifest.pb
+ fsVerityBaseDir = filepath.Dir(rootDir.String())
+ }
+
// STEP 2: generate signed BuildManifest.apk
// STEP 2-1: generate build_manifest.pb
manifestGeneratorListPath := android.PathForModuleOut(ctx, "fsverity_manifest.list")
@@ -96,7 +108,7 @@
builder.Command().
BuiltTool("fsverity_manifest_generator").
FlagWithInput("--fsverity-path ", fsverityPath).
- FlagWithArg("--base-dir ", rootDir.String()).
+ FlagWithArg("--base-dir ", fsVerityBaseDir).
FlagWithArg("--output ", manifestPbPath.String()).
FlagWithInput("@", manifestGeneratorListPath)
@@ -120,6 +132,7 @@
}
unsignedApkCommand := builder.Command().
+ Textf("mkdir -p %s && ", filepath.Dir(apkPath.String())).
BuiltTool("aapt2").
Text("link").
FlagWithOutput("-o ", apkPath).
diff --git a/filesystem/super_image.go b/filesystem/super_image.go
index 1583c0b..0f8f614 100644
--- a/filesystem/super_image.go
+++ b/filesystem/super_image.go
@@ -44,7 +44,7 @@
// the block device where metadata for dynamic partitions is stored
Metadata_device *string
// the super partition block device list
- Block_devices *string
+ Block_devices []string
// whether A/B updater is used
Ab_update *bool
// whether dynamic partitions is enabled on devices that were launched without this support
@@ -153,7 +153,9 @@
addStr("dynamic_partition_retrofit", strconv.FormatBool(proptools.Bool(s.properties.Retrofit)))
addStr("lpmake", "lpmake")
addStr("super_metadata_device", proptools.String(s.properties.Metadata_device))
- addStr("super_block_devices", proptools.String(s.properties.Block_devices))
+ if len(s.properties.Block_devices) > 0 {
+ addStr("super_block_devices", strings.Join(s.properties.Block_devices, " "))
+ }
addStr("super_super_device_size", strconv.Itoa(proptools.Int(s.properties.Size)))
var groups, partitionList []string
for _, groupInfo := range s.properties.Partition_groups {
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
index 365d954..1b828c5 100644
--- a/fsgen/Android.bp
+++ b/fsgen/Android.bp
@@ -14,6 +14,7 @@
],
srcs: [
"boot_imgs.go",
+ "config.go",
"filesystem_creator.go",
"fsgen_mutators.go",
"prebuilt_etc_modules_gen.go",
diff --git a/fsgen/config.go b/fsgen/config.go
new file mode 100644
index 0000000..31f721b
--- /dev/null
+++ b/fsgen/config.go
@@ -0,0 +1,142 @@
+// 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.
+
+package fsgen
+
+import (
+ "android/soong/filesystem"
+
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ // Most of the symlinks and directories listed here originate from create_root_structure.mk,
+ // but the handwritten generic system image also recreates them:
+ // https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
+ // TODO(b/377734331): only generate the symlinks if the relevant partitions exist
+ commonSymlinksFromRoot = []filesystem.SymlinkDefinition{
+ {
+ Target: proptools.StringPtr("/system/bin/init"),
+ Name: proptools.StringPtr("init"),
+ },
+ {
+ Target: proptools.StringPtr("/system/etc"),
+ Name: proptools.StringPtr("etc"),
+ },
+ {
+ Target: proptools.StringPtr("/system/bin"),
+ Name: proptools.StringPtr("bin"),
+ },
+ {
+ Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"),
+ Name: proptools.StringPtr("bugreports"),
+ },
+ {
+ Target: proptools.StringPtr("/sys/kernel/debug"),
+ Name: proptools.StringPtr("d"),
+ },
+ {
+ Target: proptools.StringPtr("/product/etc/security/adb_keys"),
+ Name: proptools.StringPtr("adb_keys"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/app"),
+ Name: proptools.StringPtr("odm/app"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/bin"),
+ Name: proptools.StringPtr("odm/bin"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/etc"),
+ Name: proptools.StringPtr("odm/etc"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/firmware"),
+ Name: proptools.StringPtr("odm/firmware"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/framework"),
+ Name: proptools.StringPtr("odm/framework"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/lib"),
+ Name: proptools.StringPtr("odm/lib"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/lib64"),
+ Name: proptools.StringPtr("odm/lib64"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/overlay"),
+ Name: proptools.StringPtr("odm/overlay"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/priv-app"),
+ Name: proptools.StringPtr("odm/priv-app"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/odm/usr"),
+ Name: proptools.StringPtr("odm/usr"),
+ },
+ // For Treble Generic System Image (GSI), system-as-root GSI needs to work on
+ // both devices with and without /odm_dlkm partition. Those symlinks are for
+ // devices without /odm_dlkm partition. For devices with /odm_dlkm
+ // partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
+ // Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
+ // via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
+ {
+ Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
+ Name: proptools.StringPtr("odm_dlkm/etc"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
+ Name: proptools.StringPtr("vendor_dlkm/etc"),
+ },
+ }
+
+ // Common directories between partitions that may be listed as `Dirs` property in the
+ // filesystem module.
+ commonPartitionDirs = []string{
+ // From generic_rootdirs in build/make/target/product/generic/Android.bp
+ "acct",
+ "apex",
+ "bootstrap-apex",
+ "config",
+ "data",
+ "data_mirror",
+ "debug_ramdisk",
+ "dev",
+ "linkerconfig",
+ "metadata",
+ "mnt",
+ "odm",
+ "odm_dlkm",
+ "oem",
+ "postinstall",
+ "proc",
+ "second_stage_resources",
+ "storage",
+ "sys",
+ "system",
+ "system_dlkm",
+ "tmp",
+ "vendor",
+ "vendor_dlkm",
+
+ // from android_rootdirs in build/make/target/product/generic/Android.bp
+ "system_ext",
+ "product",
+ }
+)
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index ec704d5..2dc5077 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -235,145 +235,37 @@
}
fsProps.Fsverity.Libs = []string{":framework-res{.export-package.apk}"}
}
- // Most of the symlinks and directories listed here originate from create_root_structure.mk,
- // but the handwritten generic system image also recreates them:
- // https://cs.android.com/android/platform/superproject/main/+/main:build/make/target/product/generic/Android.bp;l=33;drc=db08311f1b6ef6cb0a4fbcc6263b89849360ce04
- // TODO(b/377734331): only generate the symlinks if the relevant partitions exist
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/bin/init"),
- Name: proptools.StringPtr("init"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/etc"),
- Name: proptools.StringPtr("etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system/bin"),
- Name: proptools.StringPtr("bin"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/data/user_de/0/com.android.shell/files/bugreports"),
- Name: proptools.StringPtr("bugreports"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/sys/kernel/debug"),
- Name: proptools.StringPtr("d"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/storage/self/primary"),
- Name: proptools.StringPtr("sdcard"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/product/etc/security/adb_keys"),
- Name: proptools.StringPtr("adb_keys"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/app"),
- Name: proptools.StringPtr("odm/app"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/bin"),
- Name: proptools.StringPtr("odm/bin"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/etc"),
- Name: proptools.StringPtr("odm/etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/firmware"),
- Name: proptools.StringPtr("odm/firmware"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/framework"),
- Name: proptools.StringPtr("odm/framework"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/lib"),
- Name: proptools.StringPtr("odm/lib"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/lib64"),
- Name: proptools.StringPtr("odm/lib64"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/overlay"),
- Name: proptools.StringPtr("odm/overlay"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/priv-app"),
- Name: proptools.StringPtr("odm/priv-app"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/odm/usr"),
- Name: proptools.StringPtr("odm/usr"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/product"),
- Name: proptools.StringPtr("system/product"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system_ext"),
- Name: proptools.StringPtr("system/system_ext"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor"),
- Name: proptools.StringPtr("system/vendor"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/system_dlkm/lib/modules"),
- Name: proptools.StringPtr("system/lib/modules"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/data/cache"),
- Name: proptools.StringPtr("cache"),
- },
- // For Treble Generic System Image (GSI), system-as-root GSI needs to work on
- // both devices with and without /odm_dlkm partition. Those symlinks are for
- // devices without /odm_dlkm partition. For devices with /odm_dlkm
- // partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
- // Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
- // via /odm/lib/modules directly. All of this also applies to the vendor_dlkm symlink
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/odm/odm_dlkm/etc"),
- Name: proptools.StringPtr("odm_dlkm/etc"),
- },
- filesystem.SymlinkDefinition{
- Target: proptools.StringPtr("/vendor/vendor_dlkm/etc"),
- Name: proptools.StringPtr("vendor_dlkm/etc"),
- },
- }
- fsProps.Dirs = proptools.NewSimpleConfigurable([]string{
- // From generic_rootdirs in build/make/target/product/generic/Android.bp
- "acct",
- "apex",
- "bootstrap-apex",
- "config",
- "data",
- "data_mirror",
- "debug_ramdisk",
- "dev",
- "linkerconfig",
- "metadata",
- "mnt",
- "odm",
- "odm_dlkm",
- "oem",
- "postinstall",
- "proc",
- "second_stage_resources",
- "storage",
- "sys",
- "system",
- "system_dlkm",
- "tmp",
- "vendor",
- "vendor_dlkm",
-
- // from android_rootdirs in build/make/target/product/generic/Android.bp
- "system_ext",
- "product",
- })
+ fsProps.Symlinks = commonSymlinksFromRoot
+ fsProps.Symlinks = append(fsProps.Symlinks,
+ []filesystem.SymlinkDefinition{
+ {
+ Target: proptools.StringPtr("/data/cache"),
+ Name: proptools.StringPtr("cache"),
+ },
+ {
+ Target: proptools.StringPtr("/storage/self/primary"),
+ Name: proptools.StringPtr("sdcard"),
+ },
+ {
+ Target: proptools.StringPtr("/system_dlkm/lib/modules"),
+ Name: proptools.StringPtr("system/lib/modules"),
+ },
+ {
+ Target: proptools.StringPtr("/product"),
+ Name: proptools.StringPtr("system/product"),
+ },
+ {
+ Target: proptools.StringPtr("/system_ext"),
+ Name: proptools.StringPtr("system/system_ext"),
+ },
+ {
+ Target: proptools.StringPtr("/vendor"),
+ Name: proptools.StringPtr("system/vendor"),
+ },
+ }...,
+ )
+ fsProps.Base_dir = proptools.StringPtr("system")
+ fsProps.Dirs = proptools.NewSimpleConfigurable(commonPartitionDirs)
case "system_ext":
if partitionVars.ProductFsverityGenerateMetadata {
fsProps.Fsverity.Inputs = []string{
@@ -394,11 +286,11 @@
fsProps.Symlinks = []filesystem.SymlinkDefinition{
filesystem.SymlinkDefinition{
Target: proptools.StringPtr("/odm"),
- Name: proptools.StringPtr("vendor/odm"),
+ Name: proptools.StringPtr("odm"),
},
filesystem.SymlinkDefinition{
Target: proptools.StringPtr("/vendor_dlkm/lib/modules"),
- Name: proptools.StringPtr("vendor/lib/modules"),
+ Name: proptools.StringPtr("lib/modules"),
},
}
fsProps.Android_filesystem_deps.System = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
@@ -409,7 +301,7 @@
fsProps.Symlinks = []filesystem.SymlinkDefinition{
filesystem.SymlinkDefinition{
Target: proptools.StringPtr("/odm_dlkm/lib/modules"),
- Name: proptools.StringPtr("odm/lib/modules"),
+ Name: proptools.StringPtr("lib/modules"),
},
}
case "userdata":
@@ -437,21 +329,35 @@
})
}
case "recovery":
- // Following https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2826;drc=ad7cfb56010cb22c3aa0e70cf71c804352553526
- fsProps.Dirs = android.NewSimpleConfigurable([]string{
+ dirs := append(commonPartitionDirs, []string{
+ "odm_file_contexts",
+ "odm_property_contexts",
+ "plat_file_contexts",
+ "plat_property_contexts",
+ "plat_service_contexts",
+ "product_file_contexts",
+ "product_property_contexts",
+ "product_service_contexts",
"sdcard",
- "tmp",
- })
- fsProps.Symlinks = []filesystem.SymlinkDefinition{
- {
- Target: proptools.StringPtr("/system/bin/init"),
- Name: proptools.StringPtr("init"),
- },
- {
- Target: proptools.StringPtr("prop.default"),
- Name: proptools.StringPtr("default.prop"),
- },
+ "sepolicy",
+ "system_ext_file_contexts",
+ "system_ext_property_contexts",
+ "system_ext_service_contexts",
+ "vendor_file_contexts",
+ "vendor_property_contexts",
+ "vendor_service_contexts",
+ }...)
+
+ dirsWithRoot := make([]string, len(dirs))
+ for i, dir := range dirs {
+ dirsWithRoot[i] = filepath.Join("root", dir)
}
+
+ fsProps.Dirs = proptools.NewSimpleConfigurable(dirsWithRoot)
+ fsProps.Symlinks = symlinksWithNamePrefix(append(commonSymlinksFromRoot, filesystem.SymlinkDefinition{
+ Target: proptools.StringPtr("prop.default"),
+ Name: proptools.StringPtr("default.prop"),
+ }), "root")
}
}
@@ -584,6 +490,7 @@
Load_by_default *bool
Blocklist_file *string
Options_file *string
+ Strip_debug_symbols *bool
}{
Name: proptools.StringPtr(name),
}
@@ -599,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 {
@@ -608,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)
@@ -686,6 +596,43 @@
vendorBuildProp.HideFromMake()
}
+func createRecoveryBuildProp(ctx android.LoadHookContext) string {
+ moduleName := generatedModuleName(ctx.Config(), "recovery-prop.default")
+
+ var vendorBuildProp *string
+ if android.InList("vendor", generatedPartitions(ctx)) {
+ vendorBuildProp = proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "vendor-build.prop"))
+ }
+
+ recoveryBuildProps := &struct {
+ Name *string
+ System_build_prop *string
+ Vendor_build_prop *string
+ Odm_build_prop *string
+ Product_build_prop *string
+ System_ext_build_prop *string
+
+ Recovery *bool
+ No_full_install *bool
+ Visibility []string
+ }{
+ Name: proptools.StringPtr(moduleName),
+ System_build_prop: proptools.StringPtr(":system-build.prop"),
+ Vendor_build_prop: vendorBuildProp,
+ Odm_build_prop: proptools.StringPtr(":odm-build.prop"),
+ Product_build_prop: proptools.StringPtr(":product-build.prop"),
+ System_ext_build_prop: proptools.StringPtr(":system_ext-build.prop"),
+
+ Recovery: proptools.BoolPtr(true),
+ No_full_install: proptools.BoolPtr(true),
+ Visibility: []string{"//visibility:public"},
+ }
+
+ ctx.CreateModule(android.RecoveryBuildPropModuleFactory, recoveryBuildProps)
+
+ return moduleName
+}
+
// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for the following partitions
// 1. vendor: Using PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS (space separated file list)
// 1. product: Using PRODUCT_PRODUCT_LINKER_CONFIG_FRAGMENTS (space separated file list)
@@ -798,10 +745,6 @@
fsProps.Precompiled_file_contexts = proptools.StringPtr(":file_contexts_bin_gen")
}
- if !strings.Contains(partitionType, "ramdisk") {
- fsProps.Base_dir = proptools.StringPtr(partitionType)
- }
-
fsProps.Is_auto_generated = proptools.BoolPtr(true)
partitionSpecificFsProps(ctx, fsProps, partitionVars, partitionType)
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index f0a54db..de0a1cb 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -164,6 +164,8 @@
// Add common resources `prebuilt_res` module as dep of recovery partition
(*fsGenState.fsDeps["recovery"])[fmt.Sprintf("recovery-resources-common-%s", getDpi(ctx))] = defaultDepCandidateProps(ctx.Config())
+ (*fsGenState.fsDeps["recovery"])[getRecoveryFontModuleName(ctx)] = defaultDepCandidateProps(ctx.Config())
+ (*fsGenState.fsDeps["recovery"])[createRecoveryBuildProp(ctx)] = defaultDepCandidateProps(ctx.Config())
return &fsGenState
}).(*FsGenState)
diff --git a/fsgen/super_img.go b/fsgen/super_img.go
index 4569896..8ee3bf2 100644
--- a/fsgen/super_img.go
+++ b/fsgen/super_img.go
@@ -35,7 +35,7 @@
superImageProps := &filesystem.SuperImageProperties{
Metadata_device: proptools.StringPtr(partitionVars.BoardSuperPartitionMetadataDevice),
- Block_devices: proptools.StringPtr(partitionVars.BoardSuperPartitionBlockDevices[0]),
+ Block_devices: partitionVars.BoardSuperPartitionBlockDevices,
Ab_update: proptools.BoolPtr(partitionVars.AbOtaUpdater),
Retrofit: proptools.BoolPtr(partitionVars.ProductRetrofitDynamicPartitions),
Virtual_ab: proptools.BoolPtr(partitionVars.ProductVirtualAbOta),
diff --git a/fsgen/util.go b/fsgen/util.go
index 9ab3ad8..008f9fe 100644
--- a/fsgen/util.go
+++ b/fsgen/util.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/filesystem"
"fmt"
"strconv"
"strings"
@@ -58,3 +59,21 @@
return recoveryDensity
}
+
+// Returns the name of the appropriate prebuilt module for installing font.png file.
+// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2536;drc=a6af369e71ded123734523ea640b97b70a557cb9
+func getRecoveryFontModuleName(ctx android.LoadHookContext) string {
+ if android.InList(getDpi(ctx), []string{"xxxhdpi", "xxhdpi", "xhdpi"}) {
+ return "recovery-fonts-18"
+ }
+ return "recovery-fonts-12"
+}
+
+// Returns a new list of symlinks with prefix added to the dest directory for all symlinks
+func symlinksWithNamePrefix(symlinks []filesystem.SymlinkDefinition, prefix string) []filesystem.SymlinkDefinition {
+ ret := make([]filesystem.SymlinkDefinition, len(symlinks))
+ for i, symlink := range symlinks {
+ ret[i] = symlink.CopyWithNamePrefix(prefix)
+ }
+ return ret
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index aa393a2..3fd79a7 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -419,6 +419,14 @@
// Optional list of data files to be installed to the fuzz target's output
// directory. Directory structure relative to the module is preserved.
Data []string `android:"path"`
+ // Same as data, but adds dependencies on modules using the device's os variant, and common
+ // architecture's variant. Can be useful to add device-built apps to the data of a host
+ // test.
+ Device_common_data []string `android:"path_device_common"`
+ // Same as data, but adds dependencies on modules using the device's os variant, and the
+ // device's first architecture's variant. Can be useful to add device-built apps to the data
+ // of a host test.
+ Device_first_data []string `android:"path_device_first"`
// Optional dictionary to be installed to the fuzz target's output directory.
Dictionary *string `android:"path"`
// Define the fuzzing frameworks this fuzz target can be built for. If
diff --git a/java/aar.go b/java/aar.go
index 1e5c95a..d9a8c0e 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -257,7 +257,7 @@
}
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext,
- manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
+ manifestPath android.Path, doNotIncludeAssetDirImplicitly bool) (compileFlags, linkFlags []string, linkDeps android.Paths,
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
hasVersionCode := android.PrefixInList(a.aaptProperties.Aaptflags, "--version-code")
@@ -274,7 +274,12 @@
Paths: a.aaptProperties.Assets,
IncludeDirs: false,
})
- assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
+ var assetDirs android.Paths
+ if doNotIncludeAssetDirImplicitly {
+ assetDirs = android.PathsForModuleSrc(ctx, a.aaptProperties.Asset_dirs)
+ } else {
+ assetDirs = android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
+ }
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs.GetOrDefault(ctx, nil), "res")
resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
@@ -494,7 +499,8 @@
a.mergedManifestFile = manifestPath
}
- compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath)
+ // do not include assets in autogenerated RRO.
+ compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath, opts.rroDirs != nil)
a.rroDirsDepSet = depset.NewBuilder[rroDir](depset.TOPOLOGICAL).
Direct(rroDirs...).
@@ -1597,8 +1603,8 @@
var _ android.ApexModule = (*AARImport)(nil)
// Implements android.ApexModule
-func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return a.depIsInSameApex(ctx, dep)
+func (a *AARImport) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return a.depIsInSameApex(tag)
}
// Implements android.ApexModule
diff --git a/java/androidmk.go b/java/androidmk.go
index b6bab53..039e847 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -408,7 +408,7 @@
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_CERTIFICATE", "PRESIGNED") // The apk will be signed by soong
+ entries.SetString("LOCAL_CERTIFICATE", a.certificate.AndroidMkString())
},
},
}}
diff --git a/java/app.go b/java/app.go
index bedb45c..b8c85fb 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1209,7 +1209,10 @@
func (a *AndroidApp) WalkPayloadDeps(ctx android.BaseModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child, parent android.Module) bool {
- isExternal := !a.DepIsInSameApex(ctx, child)
+ // TODO(ccross): Should this use android.DepIsInSameApex? Right now it is applying the android app
+ // heuristics to every transitive dependency, when it should probably be using the heuristics of the
+ // immediate parent.
+ isExternal := !a.OutgoingDepIsInSameApex(ctx.OtherModuleDependencyTag(child))
if am, ok := child.(android.ApexModule); ok {
if !do(ctx, parent, am, isExternal) {
return false
@@ -1225,7 +1228,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
@@ -1286,11 +1289,11 @@
return a.overridableAppProperties.Certificate.GetOrDefault(ctx, "")
}
-func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) {
+func (a *AndroidApp) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ if IsJniDepTag(tag) {
return true
}
- return a.Library.DepIsInSameApex(ctx, dep)
+ return a.Library.OutgoingDepIsInSameApex(tag)
}
func (a *AndroidApp) Privileged() bool {
diff --git a/java/app_import.go b/java/app_import.go
index 8951c7d..f593c02 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -538,7 +538,7 @@
return Bool(a.properties.Privileged)
}
-func (a *AndroidAppImport) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
+func (a *AndroidAppImport) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// android_app_import might have extra dependencies via uses_libs property.
// Don't track the dependency as we don't automatically add those libraries
// to the classpath. It should be explicitly added to java_libs property of APEX
diff --git a/java/base.go b/java/base.go
index c0ac4ab..cd5550a 100644
--- a/java/base.go
+++ b/java/base.go
@@ -60,6 +60,9 @@
// This is most useful in the arch/multilib variants to remove non-common files
Exclude_srcs []string `android:"path,arch_variant"`
+ // list of Kotlin source files that should excluded from the list of common_srcs.
+ Exclude_common_srcs []string `android:"path,arch_variant"`
+
// list of directories containing Java resources
Java_resource_dirs []string `android:"arch_variant"`
@@ -362,13 +365,13 @@
e.initSdkLibraryComponent(module)
}
-// Module/Import's DepIsInSameApex(...) delegates to this method.
+// Module/Import's OutgoingDepIsInSameApex(...) delegates to this method.
//
-// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
+// This cannot implement OutgoingDepIsInSameApex(...) directly as that leads to ambiguity with
// the one provided by ApexModuleBase.
-func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+func (e *embeddableInModuleAndImport) depIsInSameApex(tag blueprint.DependencyTag) bool {
// dependencies other than the static linkage are all considered crossing APEX boundary
- if staticLibTag == ctx.OtherModuleDependencyTag(dep) {
+ if tag == staticLibTag {
return true
}
return false
@@ -835,13 +838,18 @@
}
func (j *Module) AvailableFor(what string) bool {
- if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) {
+ return android.CheckAvailableForApex(what, j.ApexAvailableFor())
+}
+
+func (j *Module) ApexAvailableFor() []string {
+ list := j.ApexModuleBase.ApexAvailable()
+ if Bool(j.deviceProperties.Hostdex) {
// Exception: for hostdex: true libraries, the platform variant is created
// even if it's not marked as available to platform. In that case, the platform
// variant is used only for the hostdex and not installed to the device.
- return true
+ list = append(list, android.AvailableToPlatform)
}
- return j.ApexModuleBase.AvailableFor(what)
+ return android.FirstUniqueStrings(list)
}
func (j *Module) staticLibs(ctx android.BaseModuleContext) []string {
@@ -922,7 +930,7 @@
if j.useCompose(ctx) {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
- "androidx.compose.compiler_compiler-hosted-plugin")
+ "kotlin-compose-compiler-plugin")
}
}
@@ -1182,7 +1190,7 @@
flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
}
- kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
+ kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, j.properties.Exclude_common_srcs)
if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
}
@@ -1434,20 +1442,27 @@
// build.
flags = enableErrorproneFlags(flags)
} else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil {
- // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
- // a new jar file just for compiling with the errorprone compiler to.
- // This is because we don't want to cause the java files to get completely
- // rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
- // We also don't want to run this if errorprone is enabled by default for
- // this module, or else we could have duplicated errorprone messages.
- errorproneFlags := enableErrorproneFlags(flags)
- errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
+ if ctx.Config().RunErrorProneInline() {
+ // On CI, we're not going to toggle back/forth between errorprone and non-errorprone
+ // builds, so it's faster if we don't compile the module twice and instead always
+ // compile the module with errorprone.
+ flags = enableErrorproneFlags(flags)
+ } else {
+ // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
+ // a new jar file just for compiling with the errorprone compiler to.
+ // This is because we don't want to cause the java files to get completely
+ // rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
+ // We also don't want to run this if errorprone is enabled by default for
+ // this module, or else we could have duplicated errorprone messages.
+ errorproneFlags := enableErrorproneFlags(flags)
+ errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+ errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
- transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
- "errorprone", "errorprone")
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
+ "errorprone", "errorprone")
- extraJarDeps = append(extraJarDeps, errorprone)
+ extraJarDeps = append(extraJarDeps, errorprone)
+ }
}
if enableSharding {
@@ -2206,8 +2221,8 @@
}
// Implements android.ApexModule
-func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return j.depIsInSameApex(ctx, dep)
+func (j *Module) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return j.depIsInSameApex(tag)
}
// Implements android.ApexModule
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 375a1aa..d6777e5 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -393,11 +393,9 @@
return i.profileInstallPathInApex
}
-func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- tag := ctx.OtherModuleDependencyTag(dep)
-
+func (b *BootclasspathFragmentModule) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
// If the module is a default module, do not check the tag
- if _, ok := dep.(*Defaults); ok {
+ if tag == android.DefaultsDepTag {
return true
}
if IsBootclasspathFragmentContentDepTag(tag) {
@@ -414,7 +412,7 @@
return false
}
- panic(fmt.Errorf("boot_image module %q should not have a dependency on %q via tag %s", b, dep, android.PrettyPrintTag(tag)))
+ panic(fmt.Errorf("boot_image module %q should not have a dependency tag %s", b, android.PrettyPrintTag(tag)))
}
func (b *BootclasspathFragmentModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
diff --git a/java/builder.go b/java/builder.go
index 895ddb6..01fbbdd 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -46,6 +46,7 @@
`mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
+ `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` +
`${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
`${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
@@ -55,8 +56,10 @@
`$zipTemplate${config.SoongZipCmd} -jar -o $out.tmp -C $outDir -D $outDir && ` +
`if ! cmp -s "$out.tmp" "$out"; then mv "$out.tmp" "$out"; fi && ` +
`if ! cmp -s "$annoSrcJar.tmp" "$annoSrcJar"; then mv "$annoSrcJar.tmp" "$annoSrcJar"; fi && ` +
+ `if [[ -f "$out.pc_state.new" ]]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
`rm -rf "$srcJarDir" "$outDir"`,
CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
"${config.JavacCmd}",
"${config.SoongZipCmd}",
"${config.ZipSyncCmd}",
diff --git a/java/config/config.go b/java/config/config.go
index 87703d8..7c29722 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -159,6 +159,7 @@
pctx.SourcePathVariable("ResourceProcessorBusyBox", "prebuilts/bazel/common/android_tools/android_tools/all_android_tools_deploy.jar")
pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
+ pctx.HostBinToolVariable("FindInputDeltaCmd", "find_input_delta")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh")
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index 302d021..bf4c886 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -49,7 +49,7 @@
"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
}, " "))
- pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
+ pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{"-language-version 1.9"}, " "))
// Use KotlincKytheGlobalFlags to prevent kotlinc version skew issues between android and
// g3 kythe indexers.
// This is necessary because there might be instances of kotlin code in android
diff --git a/java/core-libraries/jarjar-strip-annotations-rules.txt b/java/core-libraries/jarjar-strip-annotations-rules.txt
index a1c261b..c74eaca 100644
--- a/java/core-libraries/jarjar-strip-annotations-rules.txt
+++ b/java/core-libraries/jarjar-strip-annotations-rules.txt
@@ -2,3 +2,4 @@
strip-annotation android.annotation.Nullable
strip-annotation androidx.annotation.RecentlyNonNull
strip-annotation androidx.annotation.RecentlyNullable
+strip-annotation android.annotation.FlaggedApi
diff --git a/java/fuzz.go b/java/fuzz.go
index 90f09a8..dba8815 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -107,23 +107,7 @@
}
func (j *JavaFuzzTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if j.fuzzPackagedModule.FuzzProperties.Corpus != nil {
- j.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Corpus)
- }
- if j.fuzzPackagedModule.FuzzProperties.Device_common_corpus != nil {
- j.fuzzPackagedModule.Corpus = append(j.fuzzPackagedModule.Corpus, android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Device_common_corpus)...)
- }
- if j.fuzzPackagedModule.FuzzProperties.Data != nil {
- j.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, j.fuzzPackagedModule.FuzzProperties.Data)
- }
- if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
- j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
- }
- if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
- configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
- android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
- j.fuzzPackagedModule.Config = configPath
- }
+ j.fuzzPackagedModule = cc.PackageFuzzModule(ctx, j.fuzzPackagedModule, pctx)
_, sharedDeps := cc.CollectAllSharedDependencies(ctx)
for _, dep := range sharedDeps {
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/java/java.go b/java/java.go
index ee112c1..64bc959 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2959,8 +2959,8 @@
var _ android.ApexModule = (*Import)(nil)
// Implements android.ApexModule
-func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- return j.depIsInSameApex(ctx, dep)
+func (j *Import) OutgoingDepIsInSameApex(tag blueprint.DependencyTag) bool {
+ return j.depIsInSameApex(tag)
}
// Implements android.ApexModule
diff --git a/java/kotlin.go b/java/kotlin.go
index f42d163..e1a3f71 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -181,6 +181,7 @@
Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
+ `${config.FindInputDeltaCmd} --template '' --target "$out" --inputs_file "$out.rsp" && ` +
`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
` --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
@@ -197,8 +198,10 @@
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
`${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+ `if [[ -f "$out.pc_state.new" ]]; then mv "$out.pc_state.new" "$out.pc_state"; fi && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
+ "${config.FindInputDeltaCmd}",
"${config.KotlincCmd}",
"${config.KotlinCompilerJar}",
"${config.KotlinKaptJar}",
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 45eac01..ad8734d 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -501,7 +501,7 @@
}
kotlin_plugin {
- name: "androidx.compose.compiler_compiler-hosted-plugin",
+ name: "kotlin-compose-compiler-plugin",
}
java_library {
@@ -523,7 +523,7 @@
buildOS := result.Config.BuildOS.String()
- composeCompiler := result.ModuleForTests("androidx.compose.compiler_compiler-hosted-plugin", buildOS+"_common").Rule("combineJar").Output
+ composeCompiler := result.ModuleForTests("kotlin-compose-compiler-plugin", buildOS+"_common").Rule("combineJar").Output
withCompose := result.ModuleForTests("withcompose", "android_common")
noCompose := result.ModuleForTests("nocompose", "android_common")
diff --git a/java/rro.go b/java/rro.go
index d277e4a..ab4fafa 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -290,7 +290,8 @@
properties AutogenRuntimeResourceOverlayProperties
- outputFile android.Path
+ certificate Certificate
+ outputFile android.Path
}
type AutogenRuntimeResourceOverlayProperties struct {
@@ -380,7 +381,8 @@
return
}
// Sign the built package
- _, certificates := processMainCert(a.ModuleBase, "", nil, ctx)
+ var certificates []Certificate
+ a.certificate, certificates = processMainCert(a.ModuleBase, "", nil, ctx)
signed := android.PathForModuleOut(ctx, "signed", a.Name()+".apk")
SignAppPackage(ctx, signed, a.exportPackage, certificates, nil, nil, "")
a.outputFile = signed
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 7891776..991f847 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1282,7 +1282,7 @@
func CheckMinSdkVersion(ctx android.ModuleContext, module *Library) {
android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), func(c android.BaseModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
- isExternal := !module.depIsInSameApex(ctx, child)
+ isExternal := !android.IsDepInSameApex(ctx, module, child)
if am, ok := child.(android.ApexModule); ok {
if !do(ctx, parent, am, isExternal) {
return false
@@ -1636,15 +1636,14 @@
}
// Implements android.ApexModule
-func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
- depTag := mctx.OtherModuleDependencyTag(dep)
+func (module *SdkLibrary) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
if depTag == xmlPermissionsFileTag {
return true
}
- if dep.Name() == module.implLibraryModuleName() {
+ if depTag == implLibraryTag {
return true
}
- return module.Library.DepIsInSameApex(mctx, dep)
+ return module.Library.OutgoingDepIsInSameApex(depTag)
}
// Implements android.ApexModule
@@ -2059,8 +2058,7 @@
var _ android.ApexModule = (*SdkLibraryImport)(nil)
// Implements android.ApexModule
-func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
- depTag := mctx.OtherModuleDependencyTag(dep)
+func (module *SdkLibraryImport) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
if depTag == xmlPermissionsFileTag {
return true
}
diff --git a/java/sdk_library_internal.go b/java/sdk_library_internal.go
index 768e57a..ec9c160 100644
--- a/java/sdk_library_internal.go
+++ b/java/sdk_library_internal.go
@@ -15,12 +15,13 @@
package java
import (
- "android/soong/android"
- "android/soong/etc"
"fmt"
"path"
"strings"
+ "android/soong/android"
+ "android/soong/etc"
+
"github.com/google/blueprint/proptools"
)
@@ -778,7 +779,11 @@
// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
- return true
+ return android.CheckAvailableForApex(what, module.ApexAvailableFor())
+}
+
+func (module *sdkLibraryXml) ApexAvailableFor() []string {
+ return []string{android.AvailableToPlatform, android.AvailableToAnyApex}
}
func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) {
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/root.bp b/root.bp
index 8e621c4..7e0c1ed 100644
--- a/root.bp
+++ b/root.bp
@@ -2,10 +2,3 @@
// subdirs= and optional_subdirs= are obsolete and this file no longer
// needs a list of the top level directories that may contain Android.bp
// files.
-
-// TODO(b/253827323) Remove this. A module in internal builds needs to disable a new check,
-// IdentifierName, when errorprone is updated. In order to avoid having the update errorprone
-// in internal first, and then aosp, create this variable that we can fill out in internal in the
-// same topic as the errorprone update, then move the flag out of the variable after the update,
-// then remove the variable.
-disable_identifiername_for_errorprone_update = []
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 1ff6637..28ed68b 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -67,6 +67,7 @@
func (procMacro *procMacroDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = procMacro.baseCompiler.compilerFlags(ctx, flags)
flags.RustFlags = append(flags.RustFlags, "--extern proc_macro")
+ flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.ModuleName())
return flags
}
diff --git a/rust/rust.go b/rust/rust.go
index eeb228c..64cfa40 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1683,7 +1683,7 @@
}
for _, lib := range deps.SharedLibs {
- depTag := cc.SharedDepTag()
+ depTag := cc.SharedDepTag(mod.Static())
name, version := cc.StubsLibNameAndVersion(lib)
variations := []blueprint.Variation{
@@ -1824,43 +1824,18 @@
}
// Implements android.ApexModule
-func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
- depTag := ctx.OtherModuleDependencyTag(dep)
-
- if ccm, ok := dep.(*cc.Module); ok {
- if ccm.HasStubsVariants() {
- if cc.IsSharedDepTag(depTag) {
- // dynamic dep to a stubs lib crosses APEX boundary
- return false
- }
- if cc.IsRuntimeDepTag(depTag) {
- // runtime dep to a stubs lib also crosses APEX boundary
- return false
- }
-
- if cc.IsHeaderDepTag(depTag) {
- return false
- }
- }
- if mod.Static() && cc.IsSharedDepTag(depTag) {
- // shared_lib dependency from a static lib is considered as crossing
- // the APEX boundary because the dependency doesn't actually is
- // linked; the dependency is used only during the compilation phase.
- return false
- }
- }
-
+func (mod *Module) OutgoingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
if depTag == procMacroDepTag || depTag == customBindgenDepTag {
return false
}
- if rustDep, ok := dep.(*Module); ok && rustDep.ApexExclude() {
- return false
- }
-
return true
}
+func (mod *Module) IncomingDepIsInSameApex(depTag blueprint.DependencyTag) bool {
+ return !mod.ApexExclude()
+}
+
// Overrides ApexModule.IsInstallabeToApex()
func (mod *Module) IsInstallableToApex() bool {
if mod.compiler != nil {
diff --git a/rust/sanitize.go b/rust/sanitize.go
index b8f922f..4c82de5 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -281,7 +281,7 @@
} else {
variations = append(variations,
blueprint.Variation{Mutator: "link", Variation: "shared"})
- depTag = cc.SharedDepTag()
+ depTag = cc.SharedDepTag(mod.Static())
deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
}
} else if mod.IsSanitizerEnabled(cc.Hwasan) {
@@ -296,7 +296,7 @@
// library during final link if necessary
variations = append(variations,
blueprint.Variation{Mutator: "link", Variation: "shared"})
- depTag = cc.SharedDepTag()
+ depTag = cc.SharedDepTag(mod.Static())
deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "hwasan")}
}
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
index 5f52d6f..47bbf59 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -450,7 +450,7 @@
props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}")
props.append(f"ro.product.board={config['BootloaderBoardName']}")
props.append(f"ro.board.platform={config['BoardPlatform']}")
- props.append(f"ro.hwui.use_vulkan={'true' if config['UsesVulkan'] else 'false'}")
+ props.append(f"ro.hwui.use_vulkan={config['UsesVulkan']}")
if config["ScreenDensity"]:
props.append(f"ro.sf.lcd_density={config['ScreenDensity']}")
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