Introduce packaging property high_priority_deps
The property is used to specify the modules with higher install property
when there are multiple source files for an install file.
Test: m nothing
Bug: 376345875
Change-Id: I4fc474b7c8d5e07dd59d509064e50d9798ae9e71
diff --git a/android/packaging.go b/android/packaging.go
index acafcd4..b5c4503 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "slices"
"sort"
"strings"
@@ -207,97 +208,128 @@
// If this is set to true by a module type inheriting PackagingBase, the deps property
// collects the first target only even with compile_multilib: true.
DepsCollectFirstTargetOnly bool
+
+ // If this is set to try by a module type inheriting PackagingBase, the module type is
+ // allowed to utilize High_priority_deps.
+ AllowHighPriorityDeps bool
}
-type depsProperty struct {
+type DepsProperty struct {
+ // Deps that have higher priority in packaging when there is a packaging conflict.
+ // For example, if multiple files are being installed to same filepath, the install file
+ // of the module listed in this property will have a higher priority over those in other
+ // deps properties.
+ High_priority_deps []string `android:"arch_variant"`
+
// Modules to include in this package
Deps proptools.Configurable[[]string] `android:"arch_variant"`
}
type packagingMultilibProperties struct {
- First depsProperty `android:"arch_variant"`
- Common depsProperty `android:"arch_variant"`
- Lib32 depsProperty `android:"arch_variant"`
- Lib64 depsProperty `android:"arch_variant"`
- Both depsProperty `android:"arch_variant"`
- Prefer32 depsProperty `android:"arch_variant"`
+ First DepsProperty `android:"arch_variant"`
+ Common DepsProperty `android:"arch_variant"`
+ Lib32 DepsProperty `android:"arch_variant"`
+ Lib64 DepsProperty `android:"arch_variant"`
+ Both DepsProperty `android:"arch_variant"`
+ Prefer32 DepsProperty `android:"arch_variant"`
}
type packagingArchProperties struct {
- Arm64 depsProperty
- Arm depsProperty
- X86_64 depsProperty
- X86 depsProperty
+ Arm64 DepsProperty
+ Arm DepsProperty
+ X86_64 DepsProperty
+ X86 DepsProperty
}
type PackagingProperties struct {
- Deps proptools.Configurable[[]string] `android:"arch_variant"`
- Multilib packagingMultilibProperties `android:"arch_variant"`
+ DepsProperty
+
+ Multilib packagingMultilibProperties `android:"arch_variant"`
Arch packagingArchProperties
}
func InitPackageModule(p PackageModule) {
base := p.packagingBase()
- p.AddProperties(&base.properties)
+ p.AddProperties(&base.properties, &base.properties.DepsProperty)
}
func (p *PackagingBase) packagingBase() *PackagingBase {
return p
}
+func (p *PackagingBase) highPriorityDeps() []string {
+ return slices.Concat(
+ p.properties.High_priority_deps,
+ p.properties.Multilib.Both.High_priority_deps,
+ p.properties.Multilib.Common.High_priority_deps,
+ p.properties.Multilib.First.High_priority_deps,
+ p.properties.Multilib.Lib32.High_priority_deps,
+ p.properties.Multilib.Lib64.High_priority_deps,
+ p.properties.Multilib.Prefer32.High_priority_deps,
+ p.properties.Arch.Arm.High_priority_deps,
+ p.properties.Arch.Arm64.High_priority_deps,
+ p.properties.Arch.X86.High_priority_deps,
+ p.properties.Arch.X86_64.High_priority_deps,
+ )
+}
+
// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
// the current archicture when this module is not configured for multi target. When configured for
// multi target, deps is selected for each of the targets and is NOT selected for the current
// architecture which would be Common.
func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
- get := func(prop proptools.Configurable[[]string]) []string {
- return prop.GetOrDefault(ctx, nil)
+ if len(p.highPriorityDeps()) > 0 && !p.AllowHighPriorityDeps {
+ ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
+ }
+
+ get := func(prop DepsProperty) []string {
+ return Concat(prop.Deps.GetOrDefault(ctx, nil), prop.High_priority_deps)
}
var ret []string
if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
- ret = append(ret, get(p.properties.Deps)...)
+ ret = append(ret, get(p.properties.DepsProperty)...)
} else if arch.Multilib == "lib32" {
- ret = append(ret, get(p.properties.Multilib.Lib32.Deps)...)
+ ret = append(ret, get(p.properties.Multilib.Lib32)...)
// multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
- for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
+ for _, dep := range get(p.properties.Multilib.Prefer32) {
if checkIfOtherModuleSupportsLib32(ctx, dep) {
ret = append(ret, dep)
}
}
} else if arch.Multilib == "lib64" {
- ret = append(ret, get(p.properties.Multilib.Lib64.Deps)...)
+ ret = append(ret, get(p.properties.Multilib.Lib64)...)
// multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
- for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
+ for _, dep := range get(p.properties.Multilib.Prefer32) {
if !checkIfOtherModuleSupportsLib32(ctx, dep) {
ret = append(ret, dep)
}
}
} else if arch == Common {
- ret = append(ret, get(p.properties.Multilib.Common.Deps)...)
+ ret = append(ret, get(p.properties.Multilib.Common)...)
}
if p.DepsCollectFirstTargetOnly {
- if len(get(p.properties.Multilib.First.Deps)) > 0 {
+ if len(get(p.properties.Multilib.First)) > 0 {
ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
}
for i, t := range ctx.MultiTargets() {
if t.Arch.ArchType == arch {
- ret = append(ret, get(p.properties.Multilib.Both.Deps)...)
+ ret = append(ret, get(p.properties.Multilib.Both)...)
if i == 0 {
- ret = append(ret, get(p.properties.Deps)...)
+ ret = append(ret, get(p.properties.DepsProperty)...)
}
}
}
} else {
- if len(get(p.properties.Multilib.Both.Deps)) > 0 {
+ if len(get(p.properties.Multilib.Both)) > 0 {
ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
}
for i, t := range ctx.MultiTargets() {
if t.Arch.ArchType == arch {
- ret = append(ret, get(p.properties.Deps)...)
+ ret = append(ret, get(p.properties.DepsProperty)...)
if i == 0 {
- ret = append(ret, get(p.properties.Multilib.First.Deps)...)
+ ret = append(ret, get(p.properties.Multilib.First)...)
}
}
}
@@ -306,13 +338,13 @@
if ctx.Arch().ArchType == Common {
switch arch {
case Arm64:
- ret = append(ret, get(p.properties.Arch.Arm64.Deps)...)
+ ret = append(ret, get(p.properties.Arch.Arm64)...)
case Arm:
- ret = append(ret, get(p.properties.Arch.Arm.Deps)...)
+ ret = append(ret, get(p.properties.Arch.Arm)...)
case X86_64:
- ret = append(ret, get(p.properties.Arch.X86_64.Deps)...)
+ ret = append(ret, get(p.properties.Arch.X86_64)...)
case X86:
- ret = append(ret, get(p.properties.Arch.X86.Deps)...)
+ ret = append(ret, get(p.properties.Arch.X86)...)
}
}
@@ -360,6 +392,8 @@
IsPackagingItem() bool
}
+var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
+
// DepTag provides default implementation of PackagingItem interface.
// PackagingBase-derived modules can define their own dependency tag by embedding this, which
// can be passed to AddDeps() or AddDependencies().
@@ -371,8 +405,14 @@
return true
}
+// highPriorityDepTag provides default implementation of HighPriorityPackagingItem interface.
+type highPriorityDepTag struct {
+ blueprint.DependencyTag
+}
+
// See PackageModule.AddDeps
func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
+ highPriorityDeps := p.highPriorityDeps()
for _, t := range getSupportedTargets(ctx) {
for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
@@ -388,14 +428,22 @@
if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
targetVariation = append(targetVariation, sharedVariation)
}
+ if InList(dep, highPriorityDeps) {
+ depTag = highPriorityDepTag{depTag}
+ }
+
ctx.AddFarVariationDependencies(targetVariation, depTag, dep)
}
}
}
func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
- // all packaging specs gathered from the dep.
- var all []PackagingSpec
+ // packaging specs gathered from the dep that are not high priorities.
+ var regularPriorities []PackagingSpec
+
+ // all packaging specs gathered from the high priority deps.
+ var highPriorities []PackagingSpec
+
// Name of the dependency which requested the packaging spec.
// If this dep is overridden, the packaging spec will not be installed via this dependency chain.
// (the packaging spec might still be installed if there are some other deps which depend on it).
@@ -420,7 +468,8 @@
}
ctx.VisitDirectDeps(func(child Module) {
- if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
+ depTag := ctx.OtherModuleDependencyTag(child)
+ if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
return
}
for _, ps := range OtherModuleProviderOrDefault(
@@ -434,7 +483,13 @@
continue
}
}
- all = append(all, ps)
+
+ if _, ok := depTag.(highPriorityDepTag); ok {
+ highPriorities = append(highPriorities, ps)
+ } else {
+ regularPriorities = append(regularPriorities, ps)
+ }
+
depNames = append(depNames, child.Name())
if ps.overrides != nil {
overridden = append(overridden, *ps.overrides...)
@@ -442,21 +497,26 @@
}
})
- // all minus packaging specs that are overridden
- var filtered []PackagingSpec
- for index, ps := range all {
- if ps.owner != "" && InList(ps.owner, overridden) {
- continue
+ filterOverridden := func(input []PackagingSpec) []PackagingSpec {
+ // input minus packaging specs that are overridden
+ var filtered []PackagingSpec
+ for index, ps := range input {
+ if ps.owner != "" && InList(ps.owner, overridden) {
+ continue
+ }
+ // The dependency which requested this packaging spec has been overridden.
+ if InList(depNames[index], overridden) {
+ continue
+ }
+ filtered = append(filtered, ps)
}
- // The dependency which requested this packaging spec has been overridden.
- if InList(depNames[index], overridden) {
- continue
- }
- filtered = append(filtered, ps)
+ return filtered
}
+ filteredRegularPriority := filterOverridden(regularPriorities)
+
m := make(map[string]PackagingSpec)
- for _, ps := range filtered {
+ for _, ps := range filteredRegularPriority {
dstPath := ps.relPathInPackage
if existingPs, ok := m[dstPath]; ok {
if !existingPs.Equals(&ps) {
@@ -466,6 +526,21 @@
}
m[dstPath] = ps
}
+
+ filteredHighPriority := filterOverridden(highPriorities)
+ highPriorityPs := make(map[string]PackagingSpec)
+ for _, ps := range filteredHighPriority {
+ dstPath := ps.relPathInPackage
+ if existingPs, ok := highPriorityPs[dstPath]; ok {
+ if !existingPs.Equals(&ps) {
+ ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
+ }
+ continue
+ }
+ highPriorityPs[dstPath] = ps
+ m[dstPath] = ps
+ }
+
return m
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 97421c8..0599ea0 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -179,6 +179,7 @@
module.AddProperties(&filesystemModule.properties)
android.InitPackageModule(filesystemModule)
filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true
+ filesystemModule.PackagingBase.AllowHighPriorityDeps = true
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
}