blob: dcd8844f0554fb6d336edf5582029a5f3ff94266 [file] [log] [blame]
Jiyong Park073ea552020-11-09 14:08:34 +09001// Copyright 2020 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License")
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
Jiyong Parkdda8f692020-11-09 18:38:48 +090017import (
18 "fmt"
19 "path/filepath"
Inseob Kim33f95a92024-07-11 15:44:49 +090020 "sort"
Jeongik Cha76e677f2023-12-21 16:39:15 +090021 "strings"
Jiyong Parkdda8f692020-11-09 18:38:48 +090022
23 "github.com/google/blueprint"
Yu Liu3cadf7d2024-10-24 18:47:06 +000024 "github.com/google/blueprint/gobtools"
Jiyong Park105e11c2024-05-17 14:58:24 +090025 "github.com/google/blueprint/proptools"
Jiyong Parkdda8f692020-11-09 18:38:48 +090026)
27
Jiyong Parkcc1157c2020-11-25 11:31:13 +090028// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
29// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
30// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
31// running on a VM), or a zip archive for some of the host tools.
Jiyong Park073ea552020-11-09 14:08:34 +090032type PackagingSpec struct {
33 // Path relative to the root of the package
34 relPathInPackage string
35
36 // The path to the built artifact
37 srcPath Path
38
39 // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
40 // srcPath is of course ignored.)
41 symlinkTarget string
42
43 // Whether relPathInPackage should be marked as executable or not
44 executable bool
Dan Willemsen9fe14102021-07-13 21:52:04 -070045
46 effectiveLicenseFiles *Paths
Jooyung Han99c5fe62022-03-21 15:13:38 +090047
48 partition string
Jiyong Park4152b192024-04-30 21:24:21 +090049
50 // Whether this packaging spec represents an installation of the srcPath (i.e. this struct
51 // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
52 // PackageFile).
53 skipInstall bool
Justin Yun74f3f302024-05-07 14:32:14 +090054
55 // Paths of aconfig files for the built artifact
56 aconfigPaths *Paths
Jiyong Parkc6a773d2024-05-14 21:49:11 +090057
58 // ArchType of the module which produced this packaging spec
59 archType ArchType
Jiyong Parka574d532024-08-28 18:06:43 +090060
61 // List of module names that this packaging spec overrides
62 overrides *[]string
63
64 // Name of the module where this packaging spec is output of
65 owner string
Jiyong Park073ea552020-11-09 14:08:34 +090066}
Jiyong Parkdda8f692020-11-09 18:38:48 +090067
Yu Liu467d7c52024-09-18 21:54:44 +000068type packagingSpecGob struct {
Yu Liu5246a7e2024-10-09 20:04:52 +000069 RelPathInPackage string
70 SrcPath Path
71 SymlinkTarget string
72 Executable bool
73 EffectiveLicenseFiles *Paths
74 Partition string
75 SkipInstall bool
76 AconfigPaths *Paths
77 ArchType ArchType
78 Overrides *[]string
79 Owner string
Yu Liu467d7c52024-09-18 21:54:44 +000080}
Yu Liu26a716d2024-08-30 23:40:32 +000081
Yu Liu467d7c52024-09-18 21:54:44 +000082func (p *PackagingSpec) ToGob() *packagingSpecGob {
83 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +000084 RelPathInPackage: p.relPathInPackage,
85 SrcPath: p.srcPath,
86 SymlinkTarget: p.symlinkTarget,
87 Executable: p.executable,
88 EffectiveLicenseFiles: p.effectiveLicenseFiles,
89 Partition: p.partition,
90 SkipInstall: p.skipInstall,
91 AconfigPaths: p.aconfigPaths,
92 ArchType: p.archType,
93 Overrides: p.overrides,
94 Owner: p.owner,
Yu Liu467d7c52024-09-18 21:54:44 +000095 }
96}
97
98func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
99 p.relPathInPackage = data.RelPathInPackage
100 p.srcPath = data.SrcPath
101 p.symlinkTarget = data.SymlinkTarget
102 p.executable = data.Executable
Yu Liu5246a7e2024-10-09 20:04:52 +0000103 p.effectiveLicenseFiles = data.EffectiveLicenseFiles
Yu Liu467d7c52024-09-18 21:54:44 +0000104 p.partition = data.Partition
105 p.skipInstall = data.SkipInstall
106 p.aconfigPaths = data.AconfigPaths
107 p.archType = data.ArchType
108 p.overrides = data.Overrides
109 p.owner = data.Owner
110}
111
112func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000113 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000114}
115
116func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000117 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000118}
119
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000120func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
121 if other == nil {
122 return false
123 }
124 if p.relPathInPackage != other.relPathInPackage {
125 return false
126 }
127 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
128 return false
129 }
130 if p.executable != other.executable {
131 return false
132 }
133 if p.partition != other.partition {
134 return false
135 }
136 return true
137}
138
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900139// Get file name of installed package
140func (p *PackagingSpec) FileName() string {
141 if p.relPathInPackage != "" {
142 return filepath.Base(p.relPathInPackage)
143 }
144
145 return ""
146}
147
Jiyong Park6446b622021-02-01 20:08:28 +0900148// Path relative to the root of the package
149func (p *PackagingSpec) RelPathInPackage() string {
150 return p.relPathInPackage
151}
152
Dan Willemsen9fe14102021-07-13 21:52:04 -0700153func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
154 p.relPathInPackage = relPathInPackage
155}
156
157func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
158 if p.effectiveLicenseFiles == nil {
159 return Paths{}
160 }
161 return *p.effectiveLicenseFiles
162}
163
Jooyung Han99c5fe62022-03-21 15:13:38 +0900164func (p *PackagingSpec) Partition() string {
165 return p.partition
166}
167
Inseob Kim3c0a0422024-11-05 17:21:37 +0900168func (p *PackagingSpec) SetPartition(partition string) {
169 p.partition = partition
170}
171
Jiyong Park4152b192024-04-30 21:24:21 +0900172func (p *PackagingSpec) SkipInstall() bool {
173 return p.skipInstall
174}
175
Justin Yun74f3f302024-05-07 14:32:14 +0900176// Paths of aconfig files for the built artifact
177func (p *PackagingSpec) GetAconfigPaths() Paths {
178 return *p.aconfigPaths
179}
180
Jiyong Parkdda8f692020-11-09 18:38:48 +0900181type PackageModule interface {
182 Module
183 packagingBase() *PackagingBase
184
185 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900186 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
187 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900188 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900189
Jooyung Hana8834282022-03-25 11:40:12 +0900190 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
191 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900192 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900193 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900194
Jiyong Parkdda8f692020-11-09 18:38:48 +0900195 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900196 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900197 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
198 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900199 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900200}
201
202// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
203// include this struct and call InitPackageModule.
204type PackagingBase struct {
205 properties PackagingProperties
206
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900207 // Allows this module to skip missing dependencies. In most cases, this is not required, but
208 // for rare cases like when there's a dependency to a module which exists in certain repo
209 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900210 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900211
212 // If this is set to true by a module type inheriting PackagingBase, the deps property
213 // collects the first target only even with compile_multilib: true.
214 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000215
216 // If this is set to try by a module type inheriting PackagingBase, the module type is
217 // allowed to utilize High_priority_deps.
218 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900219}
220
Jihoon Kang79196c52024-10-30 18:49:47 +0000221type DepsProperty struct {
222 // Deps that have higher priority in packaging when there is a packaging conflict.
223 // For example, if multiple files are being installed to same filepath, the install file
224 // of the module listed in this property will have a higher priority over those in other
225 // deps properties.
226 High_priority_deps []string `android:"arch_variant"`
227
Jiyong Parkdda8f692020-11-09 18:38:48 +0900228 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900229 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900230}
231
232type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000233 First DepsProperty `android:"arch_variant"`
234 Common DepsProperty `android:"arch_variant"`
235 Lib32 DepsProperty `android:"arch_variant"`
236 Lib64 DepsProperty `android:"arch_variant"`
237 Both DepsProperty `android:"arch_variant"`
238 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900239}
240
Jiyong Park2136d152021-02-01 23:24:56 +0900241type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000242 Arm64 DepsProperty
243 Arm DepsProperty
244 X86_64 DepsProperty
245 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900246}
247
Jiyong Parkdda8f692020-11-09 18:38:48 +0900248type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000249 DepsProperty
250
251 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900252 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900253}
254
Jiyong Parkdda8f692020-11-09 18:38:48 +0900255func InitPackageModule(p PackageModule) {
256 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000257 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900258}
259
260func (p *PackagingBase) packagingBase() *PackagingBase {
261 return p
262}
263
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900264// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
265// the current archicture when this module is not configured for multi target. When configured for
266// multi target, deps is selected for each of the targets and is NOT selected for the current
267// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700268// It returns two lists, the normal and high priority deps, respectively.
269func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
270 var normalDeps []string
271 var highPriorityDeps []string
272
273 get := func(prop DepsProperty) {
274 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
275 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
276 }
277 has := func(prop DepsProperty) bool {
278 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000279 }
280
Jiyong Parkdda8f692020-11-09 18:38:48 +0900281 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700282 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900283 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700284 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900285 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700286 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900287 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700288 normalDeps = append(normalDeps, dep)
289 }
290 }
291 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
292 if checkIfOtherModuleSupportsLib32(ctx, dep) {
293 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900294 }
295 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900296 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700297 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900298 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700299 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900300 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700301 normalDeps = append(normalDeps, dep)
302 }
303 }
304 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
305 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
306 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900307 }
308 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900309 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700310 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900311 }
Jiyong Park2136d152021-02-01 23:24:56 +0900312
Jiyong Park3ea9b652024-05-15 23:01:54 +0900313 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700314 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900315 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
316 }
317 for i, t := range ctx.MultiTargets() {
318 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700319 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900320 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700321 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900322 }
323 }
324 }
325 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700326 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900327 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
328 }
329 for i, t := range ctx.MultiTargets() {
330 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700331 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900332 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700333 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900334 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900335 }
336 }
337 }
Jiyong Park2136d152021-02-01 23:24:56 +0900338
339 if ctx.Arch().ArchType == Common {
340 switch arch {
341 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700342 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900343 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700344 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900345 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700346 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900347 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700348 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900349 }
350 }
351
Cole Faust0c5eaed2024-11-01 11:05:00 -0700352 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
353 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
354 }
355
356 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900357}
358
Jiyong Parke6043782024-05-20 16:17:39 +0900359func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900360 var ret []Target
361 // The current and the common OS targets are always supported
362 ret = append(ret, ctx.Target())
363 if ctx.Arch().ArchType != Common {
364 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
365 }
366 // If this module is configured for multi targets, those should be supported as well
367 ret = append(ret, ctx.MultiTargets()...)
368 return ret
369}
370
Jiyong Parke6043782024-05-20 16:17:39 +0900371// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
372// module doesn't support 32-bit target, nil is returned.
373func getLib32Target(ctx BaseModuleContext) *Target {
374 for _, t := range getSupportedTargets(ctx) {
375 if t.Arch.ArchType.Multilib == "lib32" {
376 return &t
377 }
378 }
379 return nil
380}
381
382// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
383func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
384 t := getLib32Target(ctx)
385 if t == nil {
386 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
387 // or not.
388 return false
389 }
390 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
391}
392
Jooyung Han092ef812021-03-10 15:40:34 +0900393// PackagingItem is a marker interface for dependency tags.
394// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
395type PackagingItem interface {
396 // IsPackagingItem returns true if the dep is to be packaged
397 IsPackagingItem() bool
398}
399
Jihoon Kang79196c52024-10-30 18:49:47 +0000400var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
401
Jooyung Han092ef812021-03-10 15:40:34 +0900402// DepTag provides default implementation of PackagingItem interface.
403// PackagingBase-derived modules can define their own dependency tag by embedding this, which
404// can be passed to AddDeps() or AddDependencies().
405type PackagingItemAlwaysDepTag struct {
406}
407
408// IsPackagingItem returns true if the dep is to be packaged
409func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
410 return true
411}
412
Jihoon Kang79196c52024-10-30 18:49:47 +0000413type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000414 blueprint.BaseDependencyTag
415 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000416}
417
Jiyong Parkdda8f692020-11-09 18:38:48 +0900418// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900419func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700420 addDep := func(t Target, dep string, highPriority bool) {
421 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
422 return
423 }
424 targetVariation := t.Variations()
425 sharedVariation := blueprint.Variation{
426 Mutator: "link",
427 Variation: "shared",
428 }
429 // If a shared variation exists, use that. Static variants do not provide any standalone files
430 // for packaging.
431 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
432 targetVariation = append(targetVariation, sharedVariation)
433 }
434 depTagToUse := depTag
435 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000436 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700437 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000438
Cole Faust0c5eaed2024-11-01 11:05:00 -0700439 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
440 }
441 for _, t := range getSupportedTargets(ctx) {
442 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
443 for _, dep := range normalDeps {
444 addDep(t, dep, false)
445 }
446 for _, dep := range highPriorityDeps {
447 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900448 }
449 }
450}
451
Inseob Kim3c0a0422024-11-05 17:21:37 +0900452// See PackageModule.GatherPackagingSpecs
453func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000454 // packaging specs gathered from the dep that are not high priorities.
455 var regularPriorities []PackagingSpec
456
457 // all packaging specs gathered from the high priority deps.
458 var highPriorities []PackagingSpec
459
Spandan Das6c2b01d2024-10-22 22:16:04 +0000460 // Name of the dependency which requested the packaging spec.
461 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
462 // (the packaging spec might still be installed if there are some other deps which depend on it).
463 var depNames []string
464
Jiyong Parka574d532024-08-28 18:06:43 +0900465 // list of module names overridden
466 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900467
468 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900469 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900470 arches = append(arches, target.Arch.ArchType)
471 }
472
473 // filter out packaging specs for unsupported architecture
474 filterArch := func(ps PackagingSpec) bool {
475 for _, arch := range arches {
476 if arch == ps.archType {
477 return true
478 }
479 }
480 return false
481 }
482
Yu Liuac483e02024-11-11 22:29:30 +0000483 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000484 depTag := ctx.OtherModuleDependencyTag(child)
485 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900486 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900487 }
Yu Liubad1eef2024-08-21 22:37:35 +0000488 for _, ps := range OtherModuleProviderOrDefault(
489 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900490 if !filterArch(ps) {
491 continue
492 }
493
Jeongik Cha54bf8752024-02-08 10:44:37 +0900494 if filter != nil {
495 if !filter(ps) {
496 continue
497 }
498 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000499
Inseob Kim3c0a0422024-11-05 17:21:37 +0900500 if modifier != nil {
501 modifier(&ps)
502 }
503
Jihoon Kang79196c52024-10-30 18:49:47 +0000504 if _, ok := depTag.(highPriorityDepTag); ok {
505 highPriorities = append(highPriorities, ps)
506 } else {
507 regularPriorities = append(regularPriorities, ps)
508 }
509
Spandan Das6c2b01d2024-10-22 22:16:04 +0000510 depNames = append(depNames, child.Name())
Jiyong Parka574d532024-08-28 18:06:43 +0900511 if ps.overrides != nil {
512 overridden = append(overridden, *ps.overrides...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900513 }
514 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900515 })
Jiyong Parka574d532024-08-28 18:06:43 +0900516
Jihoon Kang79196c52024-10-30 18:49:47 +0000517 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
518 // input minus packaging specs that are overridden
519 var filtered []PackagingSpec
520 for index, ps := range input {
521 if ps.owner != "" && InList(ps.owner, overridden) {
522 continue
523 }
524 // The dependency which requested this packaging spec has been overridden.
525 if InList(depNames[index], overridden) {
526 continue
527 }
528 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900529 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000530 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900531 }
532
Jihoon Kang79196c52024-10-30 18:49:47 +0000533 filteredRegularPriority := filterOverridden(regularPriorities)
534
Jiyong Parka574d532024-08-28 18:06:43 +0900535 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000536 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900537 dstPath := ps.relPathInPackage
538 if existingPs, ok := m[dstPath]; ok {
539 if !existingPs.Equals(&ps) {
540 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
541 }
542 continue
543 }
544 m[dstPath] = ps
545 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000546
547 filteredHighPriority := filterOverridden(highPriorities)
548 highPriorityPs := make(map[string]PackagingSpec)
549 for _, ps := range filteredHighPriority {
550 dstPath := ps.relPathInPackage
551 if existingPs, ok := highPriorityPs[dstPath]; ok {
552 if !existingPs.Equals(&ps) {
553 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
554 }
555 continue
556 }
557 highPriorityPs[dstPath] = ps
558 m[dstPath] = ps
559 }
560
Jooyung Handf09d172021-05-11 11:13:30 +0900561 return m
562}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900563
Jeongik Cha54bf8752024-02-08 10:44:37 +0900564// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900565func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
566 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
567}
568
569// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900570func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
571 return p.GatherPackagingSpecsWithFilter(ctx, nil)
572}
573
Dan Willemsen9fe14102021-07-13 21:52:04 -0700574// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
575// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700576func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900577 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
578 dirsToSpecs[dir] = specs
579 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
580}
581
582// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
583// entries into corresponding directories.
584func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
585 empty := true
586 for _, specs := range dirsToSpecs {
587 if len(specs) > 0 {
588 empty = false
589 break
590 }
591 }
592 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800593 return entries
594 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900595
Jiyong Parkdda8f692020-11-09 18:38:48 +0900596 seenDir := make(map[string]bool)
Jeongik Cha76e677f2023-12-21 16:39:15 +0900597 preparerPath := PathForModuleOut(ctx, "preparer.sh")
598 cmd := builder.Command().Tool(preparerPath)
599 var sb strings.Builder
Cole Faust3b3a0112024-01-03 15:16:55 -0800600 sb.WriteString("set -e\n")
Inseob Kim33f95a92024-07-11 15:44:49 +0900601
602 dirs := make([]WritablePath, 0, len(dirsToSpecs))
603 for dir, _ := range dirsToSpecs {
604 dirs = append(dirs, dir)
605 }
606 sort.Slice(dirs, func(i, j int) bool {
607 return dirs[i].String() < dirs[j].String()
608 })
609
610 for _, dir := range dirs {
611 specs := dirsToSpecs[dir]
612 for _, k := range SortedKeys(specs) {
613 ps := specs[k]
614 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
615 destDir := filepath.Dir(destPath)
616 entries = append(entries, ps.relPathInPackage)
617 if _, ok := seenDir[destDir]; !ok {
618 seenDir[destDir] = true
619 sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
620 }
621 if ps.symlinkTarget == "" {
622 cmd.Implicit(ps.srcPath)
623 sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
624 } else {
625 sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
626 }
627 if ps.executable {
628 sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
629 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900630 }
631 }
632
Jeongik Cha76e677f2023-12-21 16:39:15 +0900633 WriteExecutableFileRuleVerbatim(ctx, preparerPath, sb.String())
634
Dan Willemsen9fe14102021-07-13 21:52:04 -0700635 return entries
636}
637
638// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900639func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700640 builder := NewRuleBuilder(pctx, ctx)
641
642 dir := PathForModuleOut(ctx, ".zip")
643 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
644 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900645 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700646
Jiyong Parkdda8f692020-11-09 18:38:48 +0900647 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800648 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900649 FlagWithOutput("-o ", zipOut).
650 FlagWithArg("-C ", dir.String()).
651 Flag("-L 0"). // no compression because this will be unzipped soon
652 FlagWithArg("-D ", dir.String())
653 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
654
Colin Crossf1a035e2020-11-16 17:32:30 -0800655 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900656 return entries
657}