blob: d96cccd75683eead0adfb9b168509545ada3cc11 [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"
Jiyong Parkdda8f692020-11-09 18:38:48 +090021
22 "github.com/google/blueprint"
Yu Liu3cadf7d2024-10-24 18:47:06 +000023 "github.com/google/blueprint/gobtools"
Jiyong Park105e11c2024-05-17 14:58:24 +090024 "github.com/google/blueprint/proptools"
Jiyong Parkdda8f692020-11-09 18:38:48 +090025)
26
Jiyong Parkcc1157c2020-11-25 11:31:13 +090027// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
28// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
29// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
30// running on a VM), or a zip archive for some of the host tools.
Jiyong Park073ea552020-11-09 14:08:34 +090031type PackagingSpec struct {
32 // Path relative to the root of the package
33 relPathInPackage string
34
35 // The path to the built artifact
36 srcPath Path
37
38 // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
39 // srcPath is of course ignored.)
40 symlinkTarget string
41
42 // Whether relPathInPackage should be marked as executable or not
43 executable bool
Dan Willemsen9fe14102021-07-13 21:52:04 -070044
45 effectiveLicenseFiles *Paths
Jooyung Han99c5fe62022-03-21 15:13:38 +090046
47 partition string
Jiyong Park4152b192024-04-30 21:24:21 +090048
49 // Whether this packaging spec represents an installation of the srcPath (i.e. this struct
50 // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
51 // PackageFile).
52 skipInstall bool
Justin Yun74f3f302024-05-07 14:32:14 +090053
54 // Paths of aconfig files for the built artifact
55 aconfigPaths *Paths
Jiyong Parkc6a773d2024-05-14 21:49:11 +090056
57 // ArchType of the module which produced this packaging spec
58 archType ArchType
Jiyong Parka574d532024-08-28 18:06:43 +090059
60 // List of module names that this packaging spec overrides
61 overrides *[]string
62
63 // Name of the module where this packaging spec is output of
64 owner string
Jiyong Park073ea552020-11-09 14:08:34 +090065}
Jiyong Parkdda8f692020-11-09 18:38:48 +090066
Yu Liu467d7c52024-09-18 21:54:44 +000067type packagingSpecGob struct {
Yu Liu5246a7e2024-10-09 20:04:52 +000068 RelPathInPackage string
69 SrcPath Path
70 SymlinkTarget string
71 Executable bool
72 EffectiveLicenseFiles *Paths
73 Partition string
74 SkipInstall bool
75 AconfigPaths *Paths
76 ArchType ArchType
77 Overrides *[]string
78 Owner string
Yu Liu467d7c52024-09-18 21:54:44 +000079}
Yu Liu26a716d2024-08-30 23:40:32 +000080
Yu Liu467d7c52024-09-18 21:54:44 +000081func (p *PackagingSpec) ToGob() *packagingSpecGob {
82 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +000083 RelPathInPackage: p.relPathInPackage,
84 SrcPath: p.srcPath,
85 SymlinkTarget: p.symlinkTarget,
86 Executable: p.executable,
87 EffectiveLicenseFiles: p.effectiveLicenseFiles,
88 Partition: p.partition,
89 SkipInstall: p.skipInstall,
90 AconfigPaths: p.aconfigPaths,
91 ArchType: p.archType,
92 Overrides: p.overrides,
93 Owner: p.owner,
Yu Liu467d7c52024-09-18 21:54:44 +000094 }
95}
96
97func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
98 p.relPathInPackage = data.RelPathInPackage
99 p.srcPath = data.SrcPath
100 p.symlinkTarget = data.SymlinkTarget
101 p.executable = data.Executable
Yu Liu5246a7e2024-10-09 20:04:52 +0000102 p.effectiveLicenseFiles = data.EffectiveLicenseFiles
Yu Liu467d7c52024-09-18 21:54:44 +0000103 p.partition = data.Partition
104 p.skipInstall = data.SkipInstall
105 p.aconfigPaths = data.AconfigPaths
106 p.archType = data.ArchType
107 p.overrides = data.Overrides
108 p.owner = data.Owner
109}
110
111func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000112 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000113}
114
115func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000116 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000117}
118
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000119func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
120 if other == nil {
121 return false
122 }
123 if p.relPathInPackage != other.relPathInPackage {
124 return false
125 }
126 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
127 return false
128 }
129 if p.executable != other.executable {
130 return false
131 }
132 if p.partition != other.partition {
133 return false
134 }
135 return true
136}
137
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900138// Get file name of installed package
139func (p *PackagingSpec) FileName() string {
140 if p.relPathInPackage != "" {
141 return filepath.Base(p.relPathInPackage)
142 }
143
144 return ""
145}
146
Jiyong Park6446b622021-02-01 20:08:28 +0900147// Path relative to the root of the package
148func (p *PackagingSpec) RelPathInPackage() string {
149 return p.relPathInPackage
150}
151
Dan Willemsen9fe14102021-07-13 21:52:04 -0700152func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
153 p.relPathInPackage = relPathInPackage
154}
155
156func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
157 if p.effectiveLicenseFiles == nil {
158 return Paths{}
159 }
160 return *p.effectiveLicenseFiles
161}
162
Jooyung Han99c5fe62022-03-21 15:13:38 +0900163func (p *PackagingSpec) Partition() string {
164 return p.partition
165}
166
Inseob Kim3c0a0422024-11-05 17:21:37 +0900167func (p *PackagingSpec) SetPartition(partition string) {
168 p.partition = partition
169}
170
Jiyong Park4152b192024-04-30 21:24:21 +0900171func (p *PackagingSpec) SkipInstall() bool {
172 return p.skipInstall
173}
174
Justin Yun74f3f302024-05-07 14:32:14 +0900175// Paths of aconfig files for the built artifact
176func (p *PackagingSpec) GetAconfigPaths() Paths {
177 return *p.aconfigPaths
178}
179
Jiyong Parkdda8f692020-11-09 18:38:48 +0900180type PackageModule interface {
181 Module
182 packagingBase() *PackagingBase
183
184 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900185 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
186 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900187 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900188
Jooyung Hana8834282022-03-25 11:40:12 +0900189 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
190 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900191 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900192 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900193
Jiyong Parkdda8f692020-11-09 18:38:48 +0900194 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900195 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900196 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
197 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900198 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900199}
200
201// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
202// include this struct and call InitPackageModule.
203type PackagingBase struct {
204 properties PackagingProperties
205
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900206 // Allows this module to skip missing dependencies. In most cases, this is not required, but
207 // for rare cases like when there's a dependency to a module which exists in certain repo
208 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900209 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900210
211 // If this is set to true by a module type inheriting PackagingBase, the deps property
212 // collects the first target only even with compile_multilib: true.
213 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000214
215 // If this is set to try by a module type inheriting PackagingBase, the module type is
216 // allowed to utilize High_priority_deps.
217 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900218}
219
Jihoon Kang79196c52024-10-30 18:49:47 +0000220type DepsProperty struct {
221 // Deps that have higher priority in packaging when there is a packaging conflict.
222 // For example, if multiple files are being installed to same filepath, the install file
223 // of the module listed in this property will have a higher priority over those in other
224 // deps properties.
225 High_priority_deps []string `android:"arch_variant"`
226
Jiyong Parkdda8f692020-11-09 18:38:48 +0900227 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900228 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900229}
230
231type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000232 First DepsProperty `android:"arch_variant"`
233 Common DepsProperty `android:"arch_variant"`
234 Lib32 DepsProperty `android:"arch_variant"`
235 Lib64 DepsProperty `android:"arch_variant"`
236 Both DepsProperty `android:"arch_variant"`
237 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900238}
239
Jiyong Park2136d152021-02-01 23:24:56 +0900240type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000241 Arm64 DepsProperty
242 Arm DepsProperty
243 X86_64 DepsProperty
244 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900245}
246
Jiyong Parkdda8f692020-11-09 18:38:48 +0900247type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000248 DepsProperty
249
250 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900251 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900252}
253
Jiyong Parkdda8f692020-11-09 18:38:48 +0900254func InitPackageModule(p PackageModule) {
255 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000256 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900257}
258
259func (p *PackagingBase) packagingBase() *PackagingBase {
260 return p
261}
262
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900263// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
264// the current archicture when this module is not configured for multi target. When configured for
265// multi target, deps is selected for each of the targets and is NOT selected for the current
266// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700267// It returns two lists, the normal and high priority deps, respectively.
268func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
269 var normalDeps []string
270 var highPriorityDeps []string
271
272 get := func(prop DepsProperty) {
273 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
274 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
275 }
276 has := func(prop DepsProperty) bool {
277 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000278 }
279
Jiyong Parkdda8f692020-11-09 18:38:48 +0900280 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700281 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900282 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700283 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900284 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700285 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900286 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700287 normalDeps = append(normalDeps, dep)
288 }
289 }
290 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
291 if checkIfOtherModuleSupportsLib32(ctx, dep) {
292 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900293 }
294 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900295 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700296 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900297 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700298 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900299 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700300 normalDeps = append(normalDeps, dep)
301 }
302 }
303 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
304 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
305 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900306 }
307 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900308 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700309 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 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700313 if has(p.properties.Multilib.First) {
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 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700318 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900319 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700320 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900321 }
322 }
323 }
324 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700325 if has(p.properties.Multilib.Both) {
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 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700330 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900331 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700332 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:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700341 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900342 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700343 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900344 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700345 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900346 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700347 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900348 }
349 }
350
Cole Faust0c5eaed2024-11-01 11:05:00 -0700351 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
352 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
353 }
354
355 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900356}
357
Jiyong Parke6043782024-05-20 16:17:39 +0900358func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900359 var ret []Target
360 // The current and the common OS targets are always supported
361 ret = append(ret, ctx.Target())
362 if ctx.Arch().ArchType != Common {
363 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
364 }
365 // If this module is configured for multi targets, those should be supported as well
366 ret = append(ret, ctx.MultiTargets()...)
367 return ret
368}
369
Jiyong Parke6043782024-05-20 16:17:39 +0900370// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
371// module doesn't support 32-bit target, nil is returned.
372func getLib32Target(ctx BaseModuleContext) *Target {
373 for _, t := range getSupportedTargets(ctx) {
374 if t.Arch.ArchType.Multilib == "lib32" {
375 return &t
376 }
377 }
378 return nil
379}
380
381// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
382func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
383 t := getLib32Target(ctx)
384 if t == nil {
385 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
386 // or not.
387 return false
388 }
389 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
390}
391
Jooyung Han092ef812021-03-10 15:40:34 +0900392// PackagingItem is a marker interface for dependency tags.
393// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
394type PackagingItem interface {
395 // IsPackagingItem returns true if the dep is to be packaged
396 IsPackagingItem() bool
397}
398
Jihoon Kang79196c52024-10-30 18:49:47 +0000399var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
400
Jooyung Han092ef812021-03-10 15:40:34 +0900401// DepTag provides default implementation of PackagingItem interface.
402// PackagingBase-derived modules can define their own dependency tag by embedding this, which
403// can be passed to AddDeps() or AddDependencies().
404type PackagingItemAlwaysDepTag struct {
405}
406
407// IsPackagingItem returns true if the dep is to be packaged
408func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
409 return true
410}
411
Jihoon Kang79196c52024-10-30 18:49:47 +0000412type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000413 blueprint.BaseDependencyTag
414 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000415}
416
Jiyong Parkdda8f692020-11-09 18:38:48 +0900417// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900418func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700419 addDep := func(t Target, dep string, highPriority bool) {
420 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
421 return
422 }
423 targetVariation := t.Variations()
424 sharedVariation := blueprint.Variation{
425 Mutator: "link",
426 Variation: "shared",
427 }
428 // If a shared variation exists, use that. Static variants do not provide any standalone files
429 // for packaging.
430 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
431 targetVariation = append(targetVariation, sharedVariation)
432 }
433 depTagToUse := depTag
434 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000435 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700436 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000437
Cole Faust0c5eaed2024-11-01 11:05:00 -0700438 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
439 }
440 for _, t := range getSupportedTargets(ctx) {
441 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
442 for _, dep := range normalDeps {
443 addDep(t, dep, false)
444 }
445 for _, dep := range highPriorityDeps {
446 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900447 }
448 }
449}
450
Inseob Kim3c0a0422024-11-05 17:21:37 +0900451// See PackageModule.GatherPackagingSpecs
452func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000453 // packaging specs gathered from the dep that are not high priorities.
454 var regularPriorities []PackagingSpec
455
456 // all packaging specs gathered from the high priority deps.
457 var highPriorities []PackagingSpec
458
Spandan Das6c2b01d2024-10-22 22:16:04 +0000459 // Name of the dependency which requested the packaging spec.
460 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
461 // (the packaging spec might still be installed if there are some other deps which depend on it).
462 var depNames []string
463
Jiyong Parka574d532024-08-28 18:06:43 +0900464 // list of module names overridden
465 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900466
467 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900468 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900469 arches = append(arches, target.Arch.ArchType)
470 }
471
472 // filter out packaging specs for unsupported architecture
473 filterArch := func(ps PackagingSpec) bool {
474 for _, arch := range arches {
475 if arch == ps.archType {
476 return true
477 }
478 }
479 return false
480 }
481
Yu Liuac483e02024-11-11 22:29:30 +0000482 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000483 depTag := ctx.OtherModuleDependencyTag(child)
484 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900485 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900486 }
Yu Liubad1eef2024-08-21 22:37:35 +0000487 for _, ps := range OtherModuleProviderOrDefault(
488 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900489 if !filterArch(ps) {
490 continue
491 }
492
Jeongik Cha54bf8752024-02-08 10:44:37 +0900493 if filter != nil {
494 if !filter(ps) {
495 continue
496 }
497 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000498
Inseob Kim3c0a0422024-11-05 17:21:37 +0900499 if modifier != nil {
500 modifier(&ps)
501 }
502
Jihoon Kang79196c52024-10-30 18:49:47 +0000503 if _, ok := depTag.(highPriorityDepTag); ok {
504 highPriorities = append(highPriorities, ps)
505 } else {
506 regularPriorities = append(regularPriorities, ps)
507 }
508
Spandan Das6c2b01d2024-10-22 22:16:04 +0000509 depNames = append(depNames, child.Name())
Jiyong Parka574d532024-08-28 18:06:43 +0900510 if ps.overrides != nil {
511 overridden = append(overridden, *ps.overrides...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900512 }
513 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900514 })
Jiyong Parka574d532024-08-28 18:06:43 +0900515
Jihoon Kang79196c52024-10-30 18:49:47 +0000516 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
517 // input minus packaging specs that are overridden
518 var filtered []PackagingSpec
519 for index, ps := range input {
520 if ps.owner != "" && InList(ps.owner, overridden) {
521 continue
522 }
523 // The dependency which requested this packaging spec has been overridden.
524 if InList(depNames[index], overridden) {
525 continue
526 }
527 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900528 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000529 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900530 }
531
Jihoon Kang79196c52024-10-30 18:49:47 +0000532 filteredRegularPriority := filterOverridden(regularPriorities)
533
Jiyong Parka574d532024-08-28 18:06:43 +0900534 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000535 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900536 dstPath := ps.relPathInPackage
537 if existingPs, ok := m[dstPath]; ok {
538 if !existingPs.Equals(&ps) {
539 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
540 }
541 continue
542 }
543 m[dstPath] = ps
544 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000545
546 filteredHighPriority := filterOverridden(highPriorities)
547 highPriorityPs := make(map[string]PackagingSpec)
548 for _, ps := range filteredHighPriority {
549 dstPath := ps.relPathInPackage
550 if existingPs, ok := highPriorityPs[dstPath]; ok {
551 if !existingPs.Equals(&ps) {
552 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
553 }
554 continue
555 }
556 highPriorityPs[dstPath] = ps
557 m[dstPath] = ps
558 }
559
Jooyung Handf09d172021-05-11 11:13:30 +0900560 return m
561}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900562
Jeongik Cha54bf8752024-02-08 10:44:37 +0900563// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900564func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
565 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
566}
567
568// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900569func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
570 return p.GatherPackagingSpecsWithFilter(ctx, nil)
571}
572
Dan Willemsen9fe14102021-07-13 21:52:04 -0700573// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
574// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700575func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900576 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
577 dirsToSpecs[dir] = specs
578 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
579}
580
581// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
582// entries into corresponding directories.
583func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
584 empty := true
585 for _, specs := range dirsToSpecs {
586 if len(specs) > 0 {
587 empty = false
588 break
589 }
590 }
591 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800592 return entries
593 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900594
Jiyong Parkdda8f692020-11-09 18:38:48 +0900595 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900596
597 dirs := make([]WritablePath, 0, len(dirsToSpecs))
598 for dir, _ := range dirsToSpecs {
599 dirs = append(dirs, dir)
600 }
601 sort.Slice(dirs, func(i, j int) bool {
602 return dirs[i].String() < dirs[j].String()
603 })
604
605 for _, dir := range dirs {
606 specs := dirsToSpecs[dir]
607 for _, k := range SortedKeys(specs) {
608 ps := specs[k]
609 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
610 destDir := filepath.Dir(destPath)
611 entries = append(entries, ps.relPathInPackage)
612 if _, ok := seenDir[destDir]; !ok {
613 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800614 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900615 }
616 if ps.symlinkTarget == "" {
Cole Faustd7556eb2024-12-02 13:18:58 -0800617 builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900618 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800619 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900620 }
621 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800622 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900623 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900624 }
625 }
626
Dan Willemsen9fe14102021-07-13 21:52:04 -0700627 return entries
628}
629
630// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900631func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700632 builder := NewRuleBuilder(pctx, ctx)
633
634 dir := PathForModuleOut(ctx, ".zip")
635 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
636 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900637 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700638
Jiyong Parkdda8f692020-11-09 18:38:48 +0900639 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800640 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900641 FlagWithOutput("-o ", zipOut).
642 FlagWithArg("-C ", dir.String()).
643 Flag("-L 0"). // no compression because this will be unzipped soon
644 FlagWithArg("-D ", dir.String())
645 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
646
Colin Crossf1a035e2020-11-16 17:32:30 -0800647 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900648 return entries
649}