blob: b5c4503b659e3702da7ba9f30694391098cb704d [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"
Jihoon Kang79196c52024-10-30 18:49:47 +000020 "slices"
Inseob Kim33f95a92024-07-11 15:44:49 +090021 "sort"
Jeongik Cha76e677f2023-12-21 16:39:15 +090022 "strings"
Jiyong Parkdda8f692020-11-09 18:38:48 +090023
24 "github.com/google/blueprint"
Yu Liu3cadf7d2024-10-24 18:47:06 +000025 "github.com/google/blueprint/gobtools"
Jiyong Park105e11c2024-05-17 14:58:24 +090026 "github.com/google/blueprint/proptools"
Jiyong Parkdda8f692020-11-09 18:38:48 +090027)
28
Jiyong Parkcc1157c2020-11-25 11:31:13 +090029// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
30// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
31// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
32// running on a VM), or a zip archive for some of the host tools.
Jiyong Park073ea552020-11-09 14:08:34 +090033type PackagingSpec struct {
34 // Path relative to the root of the package
35 relPathInPackage string
36
37 // The path to the built artifact
38 srcPath Path
39
40 // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
41 // srcPath is of course ignored.)
42 symlinkTarget string
43
44 // Whether relPathInPackage should be marked as executable or not
45 executable bool
Dan Willemsen9fe14102021-07-13 21:52:04 -070046
47 effectiveLicenseFiles *Paths
Jooyung Han99c5fe62022-03-21 15:13:38 +090048
49 partition string
Jiyong Park4152b192024-04-30 21:24:21 +090050
51 // Whether this packaging spec represents an installation of the srcPath (i.e. this struct
52 // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
53 // PackageFile).
54 skipInstall bool
Justin Yun74f3f302024-05-07 14:32:14 +090055
56 // Paths of aconfig files for the built artifact
57 aconfigPaths *Paths
Jiyong Parkc6a773d2024-05-14 21:49:11 +090058
59 // ArchType of the module which produced this packaging spec
60 archType ArchType
Jiyong Parka574d532024-08-28 18:06:43 +090061
62 // List of module names that this packaging spec overrides
63 overrides *[]string
64
65 // Name of the module where this packaging spec is output of
66 owner string
Jiyong Park073ea552020-11-09 14:08:34 +090067}
Jiyong Parkdda8f692020-11-09 18:38:48 +090068
Yu Liu467d7c52024-09-18 21:54:44 +000069type packagingSpecGob struct {
Yu Liu5246a7e2024-10-09 20:04:52 +000070 RelPathInPackage string
71 SrcPath Path
72 SymlinkTarget string
73 Executable bool
74 EffectiveLicenseFiles *Paths
75 Partition string
76 SkipInstall bool
77 AconfigPaths *Paths
78 ArchType ArchType
79 Overrides *[]string
80 Owner string
Yu Liu467d7c52024-09-18 21:54:44 +000081}
Yu Liu26a716d2024-08-30 23:40:32 +000082
Yu Liu467d7c52024-09-18 21:54:44 +000083func (p *PackagingSpec) ToGob() *packagingSpecGob {
84 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +000085 RelPathInPackage: p.relPathInPackage,
86 SrcPath: p.srcPath,
87 SymlinkTarget: p.symlinkTarget,
88 Executable: p.executable,
89 EffectiveLicenseFiles: p.effectiveLicenseFiles,
90 Partition: p.partition,
91 SkipInstall: p.skipInstall,
92 AconfigPaths: p.aconfigPaths,
93 ArchType: p.archType,
94 Overrides: p.overrides,
95 Owner: p.owner,
Yu Liu467d7c52024-09-18 21:54:44 +000096 }
97}
98
99func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
100 p.relPathInPackage = data.RelPathInPackage
101 p.srcPath = data.SrcPath
102 p.symlinkTarget = data.SymlinkTarget
103 p.executable = data.Executable
Yu Liu5246a7e2024-10-09 20:04:52 +0000104 p.effectiveLicenseFiles = data.EffectiveLicenseFiles
Yu Liu467d7c52024-09-18 21:54:44 +0000105 p.partition = data.Partition
106 p.skipInstall = data.SkipInstall
107 p.aconfigPaths = data.AconfigPaths
108 p.archType = data.ArchType
109 p.overrides = data.Overrides
110 p.owner = data.Owner
111}
112
113func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000114 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000115}
116
117func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000118 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000119}
120
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000121func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
122 if other == nil {
123 return false
124 }
125 if p.relPathInPackage != other.relPathInPackage {
126 return false
127 }
128 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
129 return false
130 }
131 if p.executable != other.executable {
132 return false
133 }
134 if p.partition != other.partition {
135 return false
136 }
137 return true
138}
139
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900140// Get file name of installed package
141func (p *PackagingSpec) FileName() string {
142 if p.relPathInPackage != "" {
143 return filepath.Base(p.relPathInPackage)
144 }
145
146 return ""
147}
148
Jiyong Park6446b622021-02-01 20:08:28 +0900149// Path relative to the root of the package
150func (p *PackagingSpec) RelPathInPackage() string {
151 return p.relPathInPackage
152}
153
Dan Willemsen9fe14102021-07-13 21:52:04 -0700154func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
155 p.relPathInPackage = relPathInPackage
156}
157
158func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
159 if p.effectiveLicenseFiles == nil {
160 return Paths{}
161 }
162 return *p.effectiveLicenseFiles
163}
164
Jooyung Han99c5fe62022-03-21 15:13:38 +0900165func (p *PackagingSpec) Partition() string {
166 return p.partition
167}
168
Jiyong Park4152b192024-04-30 21:24:21 +0900169func (p *PackagingSpec) SkipInstall() bool {
170 return p.skipInstall
171}
172
Justin Yun74f3f302024-05-07 14:32:14 +0900173// Paths of aconfig files for the built artifact
174func (p *PackagingSpec) GetAconfigPaths() Paths {
175 return *p.aconfigPaths
176}
177
Jiyong Parkdda8f692020-11-09 18:38:48 +0900178type PackageModule interface {
179 Module
180 packagingBase() *PackagingBase
181
182 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900183 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
184 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900185 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900186
Jooyung Hana8834282022-03-25 11:40:12 +0900187 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
188 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900189 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900190
Jiyong Parkdda8f692020-11-09 18:38:48 +0900191 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900192 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900193 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
194 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900195 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900196}
197
198// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
199// include this struct and call InitPackageModule.
200type PackagingBase struct {
201 properties PackagingProperties
202
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900203 // Allows this module to skip missing dependencies. In most cases, this is not required, but
204 // for rare cases like when there's a dependency to a module which exists in certain repo
205 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900206 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900207
208 // If this is set to true by a module type inheriting PackagingBase, the deps property
209 // collects the first target only even with compile_multilib: true.
210 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000211
212 // If this is set to try by a module type inheriting PackagingBase, the module type is
213 // allowed to utilize High_priority_deps.
214 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900215}
216
Jihoon Kang79196c52024-10-30 18:49:47 +0000217type DepsProperty struct {
218 // Deps that have higher priority in packaging when there is a packaging conflict.
219 // For example, if multiple files are being installed to same filepath, the install file
220 // of the module listed in this property will have a higher priority over those in other
221 // deps properties.
222 High_priority_deps []string `android:"arch_variant"`
223
Jiyong Parkdda8f692020-11-09 18:38:48 +0900224 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900225 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900226}
227
228type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000229 First DepsProperty `android:"arch_variant"`
230 Common DepsProperty `android:"arch_variant"`
231 Lib32 DepsProperty `android:"arch_variant"`
232 Lib64 DepsProperty `android:"arch_variant"`
233 Both DepsProperty `android:"arch_variant"`
234 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900235}
236
Jiyong Park2136d152021-02-01 23:24:56 +0900237type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000238 Arm64 DepsProperty
239 Arm DepsProperty
240 X86_64 DepsProperty
241 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900242}
243
Jiyong Parkdda8f692020-11-09 18:38:48 +0900244type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000245 DepsProperty
246
247 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900248 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900249}
250
Jiyong Parkdda8f692020-11-09 18:38:48 +0900251func InitPackageModule(p PackageModule) {
252 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000253 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900254}
255
256func (p *PackagingBase) packagingBase() *PackagingBase {
257 return p
258}
259
Jihoon Kang79196c52024-10-30 18:49:47 +0000260func (p *PackagingBase) highPriorityDeps() []string {
261 return slices.Concat(
262 p.properties.High_priority_deps,
263 p.properties.Multilib.Both.High_priority_deps,
264 p.properties.Multilib.Common.High_priority_deps,
265 p.properties.Multilib.First.High_priority_deps,
266 p.properties.Multilib.Lib32.High_priority_deps,
267 p.properties.Multilib.Lib64.High_priority_deps,
268 p.properties.Multilib.Prefer32.High_priority_deps,
269 p.properties.Arch.Arm.High_priority_deps,
270 p.properties.Arch.Arm64.High_priority_deps,
271 p.properties.Arch.X86.High_priority_deps,
272 p.properties.Arch.X86_64.High_priority_deps,
273 )
274}
275
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900276// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
277// the current archicture when this module is not configured for multi target. When configured for
278// multi target, deps is selected for each of the targets and is NOT selected for the current
279// architecture which would be Common.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900280func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
Jihoon Kang79196c52024-10-30 18:49:47 +0000281 if len(p.highPriorityDeps()) > 0 && !p.AllowHighPriorityDeps {
282 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
283 }
284
285 get := func(prop DepsProperty) []string {
286 return Concat(prop.Deps.GetOrDefault(ctx, nil), prop.High_priority_deps)
Jiyong Park105e11c2024-05-17 14:58:24 +0900287 }
288
Jiyong Parkdda8f692020-11-09 18:38:48 +0900289 var ret []string
290 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Jihoon Kang79196c52024-10-30 18:49:47 +0000291 ret = append(ret, get(p.properties.DepsProperty)...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900292 } else if arch.Multilib == "lib32" {
Jihoon Kang79196c52024-10-30 18:49:47 +0000293 ret = append(ret, get(p.properties.Multilib.Lib32)...)
Jiyong Parke6043782024-05-20 16:17:39 +0900294 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Jihoon Kang79196c52024-10-30 18:49:47 +0000295 for _, dep := range get(p.properties.Multilib.Prefer32) {
Jiyong Parke6043782024-05-20 16:17:39 +0900296 if checkIfOtherModuleSupportsLib32(ctx, dep) {
297 ret = append(ret, dep)
298 }
299 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900300 } else if arch.Multilib == "lib64" {
Jihoon Kang79196c52024-10-30 18:49:47 +0000301 ret = append(ret, get(p.properties.Multilib.Lib64)...)
Jiyong Parke6043782024-05-20 16:17:39 +0900302 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Jihoon Kang79196c52024-10-30 18:49:47 +0000303 for _, dep := range get(p.properties.Multilib.Prefer32) {
Jiyong Parke6043782024-05-20 16:17:39 +0900304 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
305 ret = append(ret, dep)
306 }
307 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900308 } else if arch == Common {
Jihoon Kang79196c52024-10-30 18:49:47 +0000309 ret = append(ret, get(p.properties.Multilib.Common)...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900310 }
Jiyong Park2136d152021-02-01 23:24:56 +0900311
Jiyong Park3ea9b652024-05-15 23:01:54 +0900312 if p.DepsCollectFirstTargetOnly {
Jihoon Kang79196c52024-10-30 18:49:47 +0000313 if len(get(p.properties.Multilib.First)) > 0 {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900314 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
315 }
316 for i, t := range ctx.MultiTargets() {
317 if t.Arch.ArchType == arch {
Jihoon Kang79196c52024-10-30 18:49:47 +0000318 ret = append(ret, get(p.properties.Multilib.Both)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900319 if i == 0 {
Jihoon Kang79196c52024-10-30 18:49:47 +0000320 ret = append(ret, get(p.properties.DepsProperty)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900321 }
322 }
323 }
324 } else {
Jihoon Kang79196c52024-10-30 18:49:47 +0000325 if len(get(p.properties.Multilib.Both)) > 0 {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900326 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
327 }
328 for i, t := range ctx.MultiTargets() {
329 if t.Arch.ArchType == arch {
Jihoon Kang79196c52024-10-30 18:49:47 +0000330 ret = append(ret, get(p.properties.DepsProperty)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900331 if i == 0 {
Jihoon Kang79196c52024-10-30 18:49:47 +0000332 ret = append(ret, get(p.properties.Multilib.First)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900333 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900334 }
335 }
336 }
Jiyong Park2136d152021-02-01 23:24:56 +0900337
338 if ctx.Arch().ArchType == Common {
339 switch arch {
340 case Arm64:
Jihoon Kang79196c52024-10-30 18:49:47 +0000341 ret = append(ret, get(p.properties.Arch.Arm64)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900342 case Arm:
Jihoon Kang79196c52024-10-30 18:49:47 +0000343 ret = append(ret, get(p.properties.Arch.Arm)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900344 case X86_64:
Jihoon Kang79196c52024-10-30 18:49:47 +0000345 ret = append(ret, get(p.properties.Arch.X86_64)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900346 case X86:
Jihoon Kang79196c52024-10-30 18:49:47 +0000347 ret = append(ret, get(p.properties.Arch.X86)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900348 }
349 }
350
Jiyong Parkdda8f692020-11-09 18:38:48 +0900351 return FirstUniqueStrings(ret)
352}
353
Jiyong Parke6043782024-05-20 16:17:39 +0900354func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900355 var ret []Target
356 // The current and the common OS targets are always supported
357 ret = append(ret, ctx.Target())
358 if ctx.Arch().ArchType != Common {
359 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
360 }
361 // If this module is configured for multi targets, those should be supported as well
362 ret = append(ret, ctx.MultiTargets()...)
363 return ret
364}
365
Jiyong Parke6043782024-05-20 16:17:39 +0900366// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
367// module doesn't support 32-bit target, nil is returned.
368func getLib32Target(ctx BaseModuleContext) *Target {
369 for _, t := range getSupportedTargets(ctx) {
370 if t.Arch.ArchType.Multilib == "lib32" {
371 return &t
372 }
373 }
374 return nil
375}
376
377// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
378func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
379 t := getLib32Target(ctx)
380 if t == nil {
381 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
382 // or not.
383 return false
384 }
385 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
386}
387
Jooyung Han092ef812021-03-10 15:40:34 +0900388// PackagingItem is a marker interface for dependency tags.
389// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
390type PackagingItem interface {
391 // IsPackagingItem returns true if the dep is to be packaged
392 IsPackagingItem() bool
393}
394
Jihoon Kang79196c52024-10-30 18:49:47 +0000395var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
396
Jooyung Han092ef812021-03-10 15:40:34 +0900397// DepTag provides default implementation of PackagingItem interface.
398// PackagingBase-derived modules can define their own dependency tag by embedding this, which
399// can be passed to AddDeps() or AddDependencies().
400type PackagingItemAlwaysDepTag struct {
401}
402
403// IsPackagingItem returns true if the dep is to be packaged
404func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
405 return true
406}
407
Jihoon Kang79196c52024-10-30 18:49:47 +0000408// highPriorityDepTag provides default implementation of HighPriorityPackagingItem interface.
409type highPriorityDepTag struct {
410 blueprint.DependencyTag
411}
412
Jiyong Parkdda8f692020-11-09 18:38:48 +0900413// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900414func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000415 highPriorityDeps := p.highPriorityDeps()
Jiyong Parke6043782024-05-20 16:17:39 +0900416 for _, t := range getSupportedTargets(ctx) {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900417 for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
418 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
419 continue
420 }
Spandan Das405f2d42024-10-22 18:31:25 +0000421 targetVariation := t.Variations()
422 sharedVariation := blueprint.Variation{
423 Mutator: "link",
424 Variation: "shared",
425 }
426 // If a shared variation exists, use that. Static variants do not provide any standalone files
427 // for packaging.
428 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
429 targetVariation = append(targetVariation, sharedVariation)
430 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000431 if InList(dep, highPriorityDeps) {
432 depTag = highPriorityDepTag{depTag}
433 }
434
Spandan Das405f2d42024-10-22 18:31:25 +0000435 ctx.AddFarVariationDependencies(targetVariation, depTag, dep)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900436 }
437 }
438}
439
Jeongik Cha54bf8752024-02-08 10:44:37 +0900440func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000441 // packaging specs gathered from the dep that are not high priorities.
442 var regularPriorities []PackagingSpec
443
444 // all packaging specs gathered from the high priority deps.
445 var highPriorities []PackagingSpec
446
Spandan Das6c2b01d2024-10-22 22:16:04 +0000447 // Name of the dependency which requested the packaging spec.
448 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
449 // (the packaging spec might still be installed if there are some other deps which depend on it).
450 var depNames []string
451
Jiyong Parka574d532024-08-28 18:06:43 +0900452 // list of module names overridden
453 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900454
455 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900456 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900457 arches = append(arches, target.Arch.ArchType)
458 }
459
460 // filter out packaging specs for unsupported architecture
461 filterArch := func(ps PackagingSpec) bool {
462 for _, arch := range arches {
463 if arch == ps.archType {
464 return true
465 }
466 }
467 return false
468 }
469
Jooyung Han092ef812021-03-10 15:40:34 +0900470 ctx.VisitDirectDeps(func(child Module) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000471 depTag := ctx.OtherModuleDependencyTag(child)
472 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900473 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900474 }
Yu Liubad1eef2024-08-21 22:37:35 +0000475 for _, ps := range OtherModuleProviderOrDefault(
476 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900477 if !filterArch(ps) {
478 continue
479 }
480
Jeongik Cha54bf8752024-02-08 10:44:37 +0900481 if filter != nil {
482 if !filter(ps) {
483 continue
484 }
485 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000486
487 if _, ok := depTag.(highPriorityDepTag); ok {
488 highPriorities = append(highPriorities, ps)
489 } else {
490 regularPriorities = append(regularPriorities, ps)
491 }
492
Spandan Das6c2b01d2024-10-22 22:16:04 +0000493 depNames = append(depNames, child.Name())
Jiyong Parka574d532024-08-28 18:06:43 +0900494 if ps.overrides != nil {
495 overridden = append(overridden, *ps.overrides...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900496 }
497 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900498 })
Jiyong Parka574d532024-08-28 18:06:43 +0900499
Jihoon Kang79196c52024-10-30 18:49:47 +0000500 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
501 // input minus packaging specs that are overridden
502 var filtered []PackagingSpec
503 for index, ps := range input {
504 if ps.owner != "" && InList(ps.owner, overridden) {
505 continue
506 }
507 // The dependency which requested this packaging spec has been overridden.
508 if InList(depNames[index], overridden) {
509 continue
510 }
511 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900512 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000513 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900514 }
515
Jihoon Kang79196c52024-10-30 18:49:47 +0000516 filteredRegularPriority := filterOverridden(regularPriorities)
517
Jiyong Parka574d532024-08-28 18:06:43 +0900518 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000519 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900520 dstPath := ps.relPathInPackage
521 if existingPs, ok := m[dstPath]; ok {
522 if !existingPs.Equals(&ps) {
523 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
524 }
525 continue
526 }
527 m[dstPath] = ps
528 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000529
530 filteredHighPriority := filterOverridden(highPriorities)
531 highPriorityPs := make(map[string]PackagingSpec)
532 for _, ps := range filteredHighPriority {
533 dstPath := ps.relPathInPackage
534 if existingPs, ok := highPriorityPs[dstPath]; ok {
535 if !existingPs.Equals(&ps) {
536 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
537 }
538 continue
539 }
540 highPriorityPs[dstPath] = ps
541 m[dstPath] = ps
542 }
543
Jooyung Handf09d172021-05-11 11:13:30 +0900544 return m
545}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900546
Jeongik Cha54bf8752024-02-08 10:44:37 +0900547// See PackageModule.GatherPackagingSpecs
548func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
549 return p.GatherPackagingSpecsWithFilter(ctx, nil)
550}
551
Dan Willemsen9fe14102021-07-13 21:52:04 -0700552// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
553// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700554func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900555 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
556 dirsToSpecs[dir] = specs
557 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
558}
559
560// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
561// entries into corresponding directories.
562func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
563 empty := true
564 for _, specs := range dirsToSpecs {
565 if len(specs) > 0 {
566 empty = false
567 break
568 }
569 }
570 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800571 return entries
572 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900573
Jiyong Parkdda8f692020-11-09 18:38:48 +0900574 seenDir := make(map[string]bool)
Jeongik Cha76e677f2023-12-21 16:39:15 +0900575 preparerPath := PathForModuleOut(ctx, "preparer.sh")
576 cmd := builder.Command().Tool(preparerPath)
577 var sb strings.Builder
Cole Faust3b3a0112024-01-03 15:16:55 -0800578 sb.WriteString("set -e\n")
Inseob Kim33f95a92024-07-11 15:44:49 +0900579
580 dirs := make([]WritablePath, 0, len(dirsToSpecs))
581 for dir, _ := range dirsToSpecs {
582 dirs = append(dirs, dir)
583 }
584 sort.Slice(dirs, func(i, j int) bool {
585 return dirs[i].String() < dirs[j].String()
586 })
587
588 for _, dir := range dirs {
589 specs := dirsToSpecs[dir]
590 for _, k := range SortedKeys(specs) {
591 ps := specs[k]
592 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
593 destDir := filepath.Dir(destPath)
594 entries = append(entries, ps.relPathInPackage)
595 if _, ok := seenDir[destDir]; !ok {
596 seenDir[destDir] = true
597 sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
598 }
599 if ps.symlinkTarget == "" {
600 cmd.Implicit(ps.srcPath)
601 sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
602 } else {
603 sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
604 }
605 if ps.executable {
606 sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
607 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900608 }
609 }
610
Jeongik Cha76e677f2023-12-21 16:39:15 +0900611 WriteExecutableFileRuleVerbatim(ctx, preparerPath, sb.String())
612
Dan Willemsen9fe14102021-07-13 21:52:04 -0700613 return entries
614}
615
616// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900617func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700618 builder := NewRuleBuilder(pctx, ctx)
619
620 dir := PathForModuleOut(ctx, ".zip")
621 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
622 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900623 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700624
Jiyong Parkdda8f692020-11-09 18:38:48 +0900625 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800626 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900627 FlagWithOutput("-o ", zipOut).
628 FlagWithArg("-C ", dir.String()).
629 Flag("-L 0"). // no compression because this will be unzipped soon
630 FlagWithArg("-D ", dir.String())
631 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
632
Colin Crossf1a035e2020-11-16 17:32:30 -0800633 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900634 return entries
635}