blob: 6146f02c99d6a932a7204c60b2d174abe74f430c [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"
Colin Crossf0c1ede2025-01-23 13:30:36 -080025 "github.com/google/blueprint/uniquelist"
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
Colin Crossf0c1ede2025-01-23 13:30:36 -080046 effectiveLicenseFiles uniquelist.UniqueList[Path]
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
Colin Crossf0c1ede2025-01-23 13:30:36 -080056 aconfigPaths uniquelist.UniqueList[Path]
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
Colin Crossf0c1ede2025-01-23 13:30:36 -080062 overrides uniquelist.UniqueList[string]
Jiyong Parka574d532024-08-28 18:06:43 +090063
64 // Name of the module where this packaging spec is output of
65 owner string
Cole Faust19fbb072025-01-30 18:19:29 -080066
67 // If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
68 // for the soong-only migration.
69 requiresFullInstall bool
70
71 // The path to the installed file in out/target/product. This is for legacy purposes, with
72 // tools that want to interact with these files outside of the build. You should not use it
73 // inside of the build. Will be nil if this module doesn't require a "full install".
74 fullInstallPath InstallPath
Jihoon Kangabec3ec2025-02-19 00:55:10 +000075
76 // String representation of the variation of the module where this packaging spec is output of
77 variation string
Jiyong Park073ea552020-11-09 14:08:34 +090078}
Jiyong Parkdda8f692020-11-09 18:38:48 +090079
Yu Liu467d7c52024-09-18 21:54:44 +000080type packagingSpecGob struct {
Yu Liu5246a7e2024-10-09 20:04:52 +000081 RelPathInPackage string
82 SrcPath Path
83 SymlinkTarget string
84 Executable bool
Colin Crossf0c1ede2025-01-23 13:30:36 -080085 EffectiveLicenseFiles Paths
Yu Liu5246a7e2024-10-09 20:04:52 +000086 Partition string
87 SkipInstall bool
Colin Crossf0c1ede2025-01-23 13:30:36 -080088 AconfigPaths Paths
Yu Liu5246a7e2024-10-09 20:04:52 +000089 ArchType ArchType
Colin Crossf0c1ede2025-01-23 13:30:36 -080090 Overrides []string
Yu Liu5246a7e2024-10-09 20:04:52 +000091 Owner string
Jihoon Kangabec3ec2025-02-19 00:55:10 +000092 Variation string
93}
94
95func (p *PackagingSpec) Owner() string {
96 return p.owner
97}
98
99func (p *PackagingSpec) Variation() string {
100 return p.variation
Yu Liu467d7c52024-09-18 21:54:44 +0000101}
Yu Liu26a716d2024-08-30 23:40:32 +0000102
Yu Liu467d7c52024-09-18 21:54:44 +0000103func (p *PackagingSpec) ToGob() *packagingSpecGob {
104 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +0000105 RelPathInPackage: p.relPathInPackage,
106 SrcPath: p.srcPath,
107 SymlinkTarget: p.symlinkTarget,
108 Executable: p.executable,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800109 EffectiveLicenseFiles: p.effectiveLicenseFiles.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000110 Partition: p.partition,
111 SkipInstall: p.skipInstall,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800112 AconfigPaths: p.aconfigPaths.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000113 ArchType: p.archType,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800114 Overrides: p.overrides.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000115 Owner: p.owner,
Jihoon Kangabec3ec2025-02-19 00:55:10 +0000116 Variation: p.variation,
Yu Liu467d7c52024-09-18 21:54:44 +0000117 }
118}
119
120func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
121 p.relPathInPackage = data.RelPathInPackage
122 p.srcPath = data.SrcPath
123 p.symlinkTarget = data.SymlinkTarget
124 p.executable = data.Executable
Colin Crossf0c1ede2025-01-23 13:30:36 -0800125 p.effectiveLicenseFiles = uniquelist.Make(data.EffectiveLicenseFiles)
Yu Liu467d7c52024-09-18 21:54:44 +0000126 p.partition = data.Partition
127 p.skipInstall = data.SkipInstall
Colin Crossf0c1ede2025-01-23 13:30:36 -0800128 p.aconfigPaths = uniquelist.Make(data.AconfigPaths)
Yu Liu467d7c52024-09-18 21:54:44 +0000129 p.archType = data.ArchType
Colin Crossf0c1ede2025-01-23 13:30:36 -0800130 p.overrides = uniquelist.Make(data.Overrides)
Yu Liu467d7c52024-09-18 21:54:44 +0000131 p.owner = data.Owner
Jihoon Kangabec3ec2025-02-19 00:55:10 +0000132 p.variation = data.Variation
Yu Liu467d7c52024-09-18 21:54:44 +0000133}
134
135func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000136 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000137}
138
139func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000140 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000141}
142
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000143func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
144 if other == nil {
145 return false
146 }
147 if p.relPathInPackage != other.relPathInPackage {
148 return false
149 }
150 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
151 return false
152 }
153 if p.executable != other.executable {
154 return false
155 }
156 if p.partition != other.partition {
157 return false
158 }
159 return true
160}
161
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900162// Get file name of installed package
163func (p *PackagingSpec) FileName() string {
164 if p.relPathInPackage != "" {
165 return filepath.Base(p.relPathInPackage)
166 }
167
168 return ""
169}
170
Jiyong Park6446b622021-02-01 20:08:28 +0900171// Path relative to the root of the package
172func (p *PackagingSpec) RelPathInPackage() string {
173 return p.relPathInPackage
174}
175
Dan Willemsen9fe14102021-07-13 21:52:04 -0700176func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
177 p.relPathInPackage = relPathInPackage
178}
179
180func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800181 return p.effectiveLicenseFiles.ToSlice()
Dan Willemsen9fe14102021-07-13 21:52:04 -0700182}
183
Jooyung Han99c5fe62022-03-21 15:13:38 +0900184func (p *PackagingSpec) Partition() string {
185 return p.partition
186}
187
Inseob Kim3c0a0422024-11-05 17:21:37 +0900188func (p *PackagingSpec) SetPartition(partition string) {
189 p.partition = partition
190}
191
Jiyong Park4152b192024-04-30 21:24:21 +0900192func (p *PackagingSpec) SkipInstall() bool {
193 return p.skipInstall
194}
195
Justin Yun74f3f302024-05-07 14:32:14 +0900196// Paths of aconfig files for the built artifact
197func (p *PackagingSpec) GetAconfigPaths() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800198 return p.aconfigPaths.ToSlice()
Justin Yun74f3f302024-05-07 14:32:14 +0900199}
200
Cole Faust19fbb072025-01-30 18:19:29 -0800201// The path to the installed file in out/target/product. This is for legacy purposes, with
202// tools that want to interact with these files outside of the build. You should not use it
203// inside of the build. Will be nil if this module doesn't require a "full install".
204func (p *PackagingSpec) FullInstallPath() InstallPath {
205 return p.fullInstallPath
206}
207
208// If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
209// for the soong-only migration.
210func (p *PackagingSpec) RequiresFullInstall() bool {
211 return p.requiresFullInstall
212}
213
214// The source file to be copied to the FullInstallPath. Do not use, for the soong-only migration.
215func (p *PackagingSpec) SrcPath() Path {
216 return p.srcPath
217}
218
Cole Faustb052df52025-02-14 12:47:51 -0800219// The symlink target of the PackagingSpec. Do not use, for the soong-only migration.
220func (p *PackagingSpec) SymlinkTarget() string {
221 return p.symlinkTarget
222}
223
Jiyong Parkdda8f692020-11-09 18:38:48 +0900224type PackageModule interface {
225 Module
226 packagingBase() *PackagingBase
227
228 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900229 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
230 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900231 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900232
Jooyung Hana8834282022-03-25 11:40:12 +0900233 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
234 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900235 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900236 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900237
Jiyong Parkdda8f692020-11-09 18:38:48 +0900238 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900239 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900240 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
241 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900242 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900243}
244
245// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
246// include this struct and call InitPackageModule.
247type PackagingBase struct {
248 properties PackagingProperties
249
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900250 // Allows this module to skip missing dependencies. In most cases, this is not required, but
251 // for rare cases like when there's a dependency to a module which exists in certain repo
252 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900253 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900254
255 // If this is set to true by a module type inheriting PackagingBase, the deps property
256 // collects the first target only even with compile_multilib: true.
257 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000258
259 // If this is set to try by a module type inheriting PackagingBase, the module type is
260 // allowed to utilize High_priority_deps.
261 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900262}
263
Jihoon Kang79196c52024-10-30 18:49:47 +0000264type DepsProperty struct {
265 // Deps that have higher priority in packaging when there is a packaging conflict.
266 // For example, if multiple files are being installed to same filepath, the install file
267 // of the module listed in this property will have a higher priority over those in other
268 // deps properties.
269 High_priority_deps []string `android:"arch_variant"`
270
Jiyong Parkdda8f692020-11-09 18:38:48 +0900271 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900272 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900273}
274
275type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000276 First DepsProperty `android:"arch_variant"`
277 Common DepsProperty `android:"arch_variant"`
278 Lib32 DepsProperty `android:"arch_variant"`
279 Lib64 DepsProperty `android:"arch_variant"`
280 Both DepsProperty `android:"arch_variant"`
281 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900282}
283
Jiyong Park2136d152021-02-01 23:24:56 +0900284type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000285 Arm64 DepsProperty
286 Arm DepsProperty
287 X86_64 DepsProperty
288 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900289}
290
Jiyong Parkdda8f692020-11-09 18:38:48 +0900291type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000292 DepsProperty
293
294 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900295 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900296}
297
Jiyong Parkdda8f692020-11-09 18:38:48 +0900298func InitPackageModule(p PackageModule) {
299 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000300 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900301}
302
303func (p *PackagingBase) packagingBase() *PackagingBase {
304 return p
305}
306
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900307// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
308// the current archicture when this module is not configured for multi target. When configured for
309// multi target, deps is selected for each of the targets and is NOT selected for the current
310// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700311// It returns two lists, the normal and high priority deps, respectively.
312func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
313 var normalDeps []string
314 var highPriorityDeps []string
315
316 get := func(prop DepsProperty) {
317 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
318 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
319 }
320 has := func(prop DepsProperty) bool {
321 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000322 }
323
Jiyong Parkdda8f692020-11-09 18:38:48 +0900324 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700325 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900326 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700327 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900328 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700329 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900330 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700331 normalDeps = append(normalDeps, dep)
332 }
333 }
334 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
335 if checkIfOtherModuleSupportsLib32(ctx, dep) {
336 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900337 }
338 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900339 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700340 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900341 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700342 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900343 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700344 normalDeps = append(normalDeps, dep)
345 }
346 }
347 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
348 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
349 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900350 }
351 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900352 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700353 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900354 }
Jiyong Park2136d152021-02-01 23:24:56 +0900355
Jiyong Park3ea9b652024-05-15 23:01:54 +0900356 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700357 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900358 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
359 }
360 for i, t := range ctx.MultiTargets() {
361 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700362 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900363 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700364 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900365 }
366 }
367 }
368 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700369 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900370 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
371 }
372 for i, t := range ctx.MultiTargets() {
373 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700374 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900375 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700376 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900377 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900378 }
379 }
380 }
Jiyong Park2136d152021-02-01 23:24:56 +0900381
382 if ctx.Arch().ArchType == Common {
383 switch arch {
384 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700385 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900386 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700387 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900388 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700389 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900390 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700391 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900392 }
393 }
394
Cole Faust0c5eaed2024-11-01 11:05:00 -0700395 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
396 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
397 }
398
399 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900400}
401
Jiyong Parke6043782024-05-20 16:17:39 +0900402func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900403 var ret []Target
404 // The current and the common OS targets are always supported
405 ret = append(ret, ctx.Target())
406 if ctx.Arch().ArchType != Common {
407 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
408 }
409 // If this module is configured for multi targets, those should be supported as well
410 ret = append(ret, ctx.MultiTargets()...)
411 return ret
412}
413
Jiyong Parke6043782024-05-20 16:17:39 +0900414// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
415// module doesn't support 32-bit target, nil is returned.
416func getLib32Target(ctx BaseModuleContext) *Target {
417 for _, t := range getSupportedTargets(ctx) {
418 if t.Arch.ArchType.Multilib == "lib32" {
419 return &t
420 }
421 }
422 return nil
423}
424
425// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
426func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
427 t := getLib32Target(ctx)
428 if t == nil {
429 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
430 // or not.
431 return false
432 }
433 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
434}
435
Jooyung Han092ef812021-03-10 15:40:34 +0900436// PackagingItem is a marker interface for dependency tags.
437// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
438type PackagingItem interface {
439 // IsPackagingItem returns true if the dep is to be packaged
440 IsPackagingItem() bool
441}
442
Jihoon Kang79196c52024-10-30 18:49:47 +0000443var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
444
Jooyung Han092ef812021-03-10 15:40:34 +0900445// DepTag provides default implementation of PackagingItem interface.
446// PackagingBase-derived modules can define their own dependency tag by embedding this, which
447// can be passed to AddDeps() or AddDependencies().
448type PackagingItemAlwaysDepTag struct {
449}
450
451// IsPackagingItem returns true if the dep is to be packaged
452func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
453 return true
454}
455
Jihoon Kang79196c52024-10-30 18:49:47 +0000456type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000457 blueprint.BaseDependencyTag
458 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000459}
460
Jiyong Parkdda8f692020-11-09 18:38:48 +0900461// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900462func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700463 addDep := func(t Target, dep string, highPriority bool) {
464 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
465 return
466 }
467 targetVariation := t.Variations()
468 sharedVariation := blueprint.Variation{
469 Mutator: "link",
470 Variation: "shared",
471 }
472 // If a shared variation exists, use that. Static variants do not provide any standalone files
473 // for packaging.
474 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
475 targetVariation = append(targetVariation, sharedVariation)
476 }
477 depTagToUse := depTag
478 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000479 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700480 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000481
Cole Faust0c5eaed2024-11-01 11:05:00 -0700482 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
483 }
484 for _, t := range getSupportedTargets(ctx) {
485 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
486 for _, dep := range normalDeps {
487 addDep(t, dep, false)
488 }
489 for _, dep := range highPriorityDeps {
490 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900491 }
492 }
493}
494
Inseob Kim3c0a0422024-11-05 17:21:37 +0900495// See PackageModule.GatherPackagingSpecs
496func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000497 // packaging specs gathered from the dep that are not high priorities.
498 var regularPriorities []PackagingSpec
499
500 // all packaging specs gathered from the high priority deps.
501 var highPriorities []PackagingSpec
502
Spandan Das6c2b01d2024-10-22 22:16:04 +0000503 // Name of the dependency which requested the packaging spec.
504 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
505 // (the packaging spec might still be installed if there are some other deps which depend on it).
506 var depNames []string
507
Jiyong Parka574d532024-08-28 18:06:43 +0900508 // list of module names overridden
509 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900510
511 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900512 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900513 arches = append(arches, target.Arch.ArchType)
514 }
515
516 // filter out packaging specs for unsupported architecture
517 filterArch := func(ps PackagingSpec) bool {
518 for _, arch := range arches {
519 if arch == ps.archType {
520 return true
521 }
522 }
523 return false
524 }
525
Yu Liuac483e02024-11-11 22:29:30 +0000526 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000527 depTag := ctx.OtherModuleDependencyTag(child)
528 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900529 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900530 }
Yu Liubad1eef2024-08-21 22:37:35 +0000531 for _, ps := range OtherModuleProviderOrDefault(
532 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900533 if !filterArch(ps) {
534 continue
535 }
536
Jeongik Cha54bf8752024-02-08 10:44:37 +0900537 if filter != nil {
538 if !filter(ps) {
539 continue
540 }
541 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000542
Inseob Kim3c0a0422024-11-05 17:21:37 +0900543 if modifier != nil {
544 modifier(&ps)
545 }
546
Jihoon Kang79196c52024-10-30 18:49:47 +0000547 if _, ok := depTag.(highPriorityDepTag); ok {
548 highPriorities = append(highPriorities, ps)
549 } else {
550 regularPriorities = append(regularPriorities, ps)
551 }
552
Spandan Das6c2b01d2024-10-22 22:16:04 +0000553 depNames = append(depNames, child.Name())
Colin Crossf0c1ede2025-01-23 13:30:36 -0800554 overridden = append(overridden, ps.overrides.ToSlice()...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900555 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900556 })
Jiyong Parka574d532024-08-28 18:06:43 +0900557
Jihoon Kang79196c52024-10-30 18:49:47 +0000558 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
559 // input minus packaging specs that are overridden
560 var filtered []PackagingSpec
561 for index, ps := range input {
562 if ps.owner != "" && InList(ps.owner, overridden) {
563 continue
564 }
565 // The dependency which requested this packaging spec has been overridden.
566 if InList(depNames[index], overridden) {
567 continue
568 }
569 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900570 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000571 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900572 }
573
Jihoon Kang79196c52024-10-30 18:49:47 +0000574 filteredRegularPriority := filterOverridden(regularPriorities)
575
Jiyong Parka574d532024-08-28 18:06:43 +0900576 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000577 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900578 dstPath := ps.relPathInPackage
579 if existingPs, ok := m[dstPath]; ok {
580 if !existingPs.Equals(&ps) {
581 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
582 }
583 continue
584 }
585 m[dstPath] = ps
586 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000587
588 filteredHighPriority := filterOverridden(highPriorities)
589 highPriorityPs := make(map[string]PackagingSpec)
590 for _, ps := range filteredHighPriority {
591 dstPath := ps.relPathInPackage
592 if existingPs, ok := highPriorityPs[dstPath]; ok {
593 if !existingPs.Equals(&ps) {
594 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
595 }
596 continue
597 }
598 highPriorityPs[dstPath] = ps
599 m[dstPath] = ps
600 }
601
Jooyung Handf09d172021-05-11 11:13:30 +0900602 return m
603}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900604
Jeongik Cha54bf8752024-02-08 10:44:37 +0900605// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900606func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
607 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
608}
609
610// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900611func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
612 return p.GatherPackagingSpecsWithFilter(ctx, nil)
613}
614
Dan Willemsen9fe14102021-07-13 21:52:04 -0700615// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
616// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700617func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900618 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
619 dirsToSpecs[dir] = specs
Cole Fauste3845052025-02-13 12:45:35 -0800620 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false)
Inseob Kim33f95a92024-07-11 15:44:49 +0900621}
622
623// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
624// entries into corresponding directories.
Cole Fauste3845052025-02-13 12:45:35 -0800625func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900626 empty := true
627 for _, specs := range dirsToSpecs {
628 if len(specs) > 0 {
629 empty = false
630 break
631 }
632 }
633 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800634 return entries
635 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900636
Jiyong Parkdda8f692020-11-09 18:38:48 +0900637 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900638
639 dirs := make([]WritablePath, 0, len(dirsToSpecs))
640 for dir, _ := range dirsToSpecs {
641 dirs = append(dirs, dir)
642 }
643 sort.Slice(dirs, func(i, j int) bool {
644 return dirs[i].String() < dirs[j].String()
645 })
646
647 for _, dir := range dirs {
648 specs := dirsToSpecs[dir]
649 for _, k := range SortedKeys(specs) {
650 ps := specs[k]
651 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
652 destDir := filepath.Dir(destPath)
653 entries = append(entries, ps.relPathInPackage)
654 if _, ok := seenDir[destDir]; !ok {
655 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800656 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900657 }
658 if ps.symlinkTarget == "" {
Cole Fauste3845052025-02-13 12:45:35 -0800659 cmd := builder.Command().Text("cp")
660 if preserveTimestamps {
661 cmd.Flag("-p")
662 }
663 cmd.Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900664 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800665 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900666 }
667 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800668 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900669 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900670 }
671 }
672
Dan Willemsen9fe14102021-07-13 21:52:04 -0700673 return entries
674}
675
676// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900677func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700678 builder := NewRuleBuilder(pctx, ctx)
679
680 dir := PathForModuleOut(ctx, ".zip")
681 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
682 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900683 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700684
Jiyong Parkdda8f692020-11-09 18:38:48 +0900685 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800686 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900687 FlagWithOutput("-o ", zipOut).
688 FlagWithArg("-C ", dir.String()).
689 Flag("-L 0"). // no compression because this will be unzipped soon
690 FlagWithArg("-D ", dir.String())
691 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
692
Colin Crossf1a035e2020-11-16 17:32:30 -0800693 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900694 return entries
695}