blob: 73cc7c7835588e3f31243a2b28cd440160b4a102 [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
Jiyong Parkdda8f692020-11-09 18:38:48 +0900219type PackageModule interface {
220 Module
221 packagingBase() *PackagingBase
222
223 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900224 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
225 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900226 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900227
Jooyung Hana8834282022-03-25 11:40:12 +0900228 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
229 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900230 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900231 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900232
Jiyong Parkdda8f692020-11-09 18:38:48 +0900233 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900234 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900235 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
236 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900237 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900238}
239
240// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
241// include this struct and call InitPackageModule.
242type PackagingBase struct {
243 properties PackagingProperties
244
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900245 // Allows this module to skip missing dependencies. In most cases, this is not required, but
246 // for rare cases like when there's a dependency to a module which exists in certain repo
247 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900248 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900249
250 // If this is set to true by a module type inheriting PackagingBase, the deps property
251 // collects the first target only even with compile_multilib: true.
252 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000253
254 // If this is set to try by a module type inheriting PackagingBase, the module type is
255 // allowed to utilize High_priority_deps.
256 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900257}
258
Jihoon Kang79196c52024-10-30 18:49:47 +0000259type DepsProperty struct {
260 // Deps that have higher priority in packaging when there is a packaging conflict.
261 // For example, if multiple files are being installed to same filepath, the install file
262 // of the module listed in this property will have a higher priority over those in other
263 // deps properties.
264 High_priority_deps []string `android:"arch_variant"`
265
Jiyong Parkdda8f692020-11-09 18:38:48 +0900266 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900267 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900268}
269
270type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000271 First DepsProperty `android:"arch_variant"`
272 Common DepsProperty `android:"arch_variant"`
273 Lib32 DepsProperty `android:"arch_variant"`
274 Lib64 DepsProperty `android:"arch_variant"`
275 Both DepsProperty `android:"arch_variant"`
276 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900277}
278
Jiyong Park2136d152021-02-01 23:24:56 +0900279type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000280 Arm64 DepsProperty
281 Arm DepsProperty
282 X86_64 DepsProperty
283 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900284}
285
Jiyong Parkdda8f692020-11-09 18:38:48 +0900286type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000287 DepsProperty
288
289 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900290 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900291}
292
Jiyong Parkdda8f692020-11-09 18:38:48 +0900293func InitPackageModule(p PackageModule) {
294 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000295 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900296}
297
298func (p *PackagingBase) packagingBase() *PackagingBase {
299 return p
300}
301
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900302// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
303// the current archicture when this module is not configured for multi target. When configured for
304// multi target, deps is selected for each of the targets and is NOT selected for the current
305// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700306// It returns two lists, the normal and high priority deps, respectively.
307func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
308 var normalDeps []string
309 var highPriorityDeps []string
310
311 get := func(prop DepsProperty) {
312 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
313 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
314 }
315 has := func(prop DepsProperty) bool {
316 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000317 }
318
Jiyong Parkdda8f692020-11-09 18:38:48 +0900319 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700320 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900321 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700322 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900323 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700324 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900325 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700326 normalDeps = append(normalDeps, dep)
327 }
328 }
329 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
330 if checkIfOtherModuleSupportsLib32(ctx, dep) {
331 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900332 }
333 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900334 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700335 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900336 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700337 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900338 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700339 normalDeps = append(normalDeps, dep)
340 }
341 }
342 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
343 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
344 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900345 }
346 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900347 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700348 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900349 }
Jiyong Park2136d152021-02-01 23:24:56 +0900350
Jiyong Park3ea9b652024-05-15 23:01:54 +0900351 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700352 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900353 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
354 }
355 for i, t := range ctx.MultiTargets() {
356 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700357 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900358 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700359 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900360 }
361 }
362 }
363 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700364 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900365 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
366 }
367 for i, t := range ctx.MultiTargets() {
368 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700369 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900370 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700371 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900372 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900373 }
374 }
375 }
Jiyong Park2136d152021-02-01 23:24:56 +0900376
377 if ctx.Arch().ArchType == Common {
378 switch arch {
379 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700380 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900381 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700382 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900383 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700384 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900385 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700386 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900387 }
388 }
389
Cole Faust0c5eaed2024-11-01 11:05:00 -0700390 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
391 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
392 }
393
394 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900395}
396
Jiyong Parke6043782024-05-20 16:17:39 +0900397func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900398 var ret []Target
399 // The current and the common OS targets are always supported
400 ret = append(ret, ctx.Target())
401 if ctx.Arch().ArchType != Common {
402 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
403 }
404 // If this module is configured for multi targets, those should be supported as well
405 ret = append(ret, ctx.MultiTargets()...)
406 return ret
407}
408
Jiyong Parke6043782024-05-20 16:17:39 +0900409// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
410// module doesn't support 32-bit target, nil is returned.
411func getLib32Target(ctx BaseModuleContext) *Target {
412 for _, t := range getSupportedTargets(ctx) {
413 if t.Arch.ArchType.Multilib == "lib32" {
414 return &t
415 }
416 }
417 return nil
418}
419
420// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
421func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
422 t := getLib32Target(ctx)
423 if t == nil {
424 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
425 // or not.
426 return false
427 }
428 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
429}
430
Jooyung Han092ef812021-03-10 15:40:34 +0900431// PackagingItem is a marker interface for dependency tags.
432// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
433type PackagingItem interface {
434 // IsPackagingItem returns true if the dep is to be packaged
435 IsPackagingItem() bool
436}
437
Jihoon Kang79196c52024-10-30 18:49:47 +0000438var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
439
Jooyung Han092ef812021-03-10 15:40:34 +0900440// DepTag provides default implementation of PackagingItem interface.
441// PackagingBase-derived modules can define their own dependency tag by embedding this, which
442// can be passed to AddDeps() or AddDependencies().
443type PackagingItemAlwaysDepTag struct {
444}
445
446// IsPackagingItem returns true if the dep is to be packaged
447func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
448 return true
449}
450
Jihoon Kang79196c52024-10-30 18:49:47 +0000451type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000452 blueprint.BaseDependencyTag
453 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000454}
455
Jiyong Parkdda8f692020-11-09 18:38:48 +0900456// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900457func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700458 addDep := func(t Target, dep string, highPriority bool) {
459 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
460 return
461 }
462 targetVariation := t.Variations()
463 sharedVariation := blueprint.Variation{
464 Mutator: "link",
465 Variation: "shared",
466 }
467 // If a shared variation exists, use that. Static variants do not provide any standalone files
468 // for packaging.
469 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
470 targetVariation = append(targetVariation, sharedVariation)
471 }
472 depTagToUse := depTag
473 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000474 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700475 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000476
Cole Faust0c5eaed2024-11-01 11:05:00 -0700477 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
478 }
479 for _, t := range getSupportedTargets(ctx) {
480 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
481 for _, dep := range normalDeps {
482 addDep(t, dep, false)
483 }
484 for _, dep := range highPriorityDeps {
485 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900486 }
487 }
488}
489
Inseob Kim3c0a0422024-11-05 17:21:37 +0900490// See PackageModule.GatherPackagingSpecs
491func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000492 // packaging specs gathered from the dep that are not high priorities.
493 var regularPriorities []PackagingSpec
494
495 // all packaging specs gathered from the high priority deps.
496 var highPriorities []PackagingSpec
497
Spandan Das6c2b01d2024-10-22 22:16:04 +0000498 // Name of the dependency which requested the packaging spec.
499 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
500 // (the packaging spec might still be installed if there are some other deps which depend on it).
501 var depNames []string
502
Jiyong Parka574d532024-08-28 18:06:43 +0900503 // list of module names overridden
504 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900505
506 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900507 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900508 arches = append(arches, target.Arch.ArchType)
509 }
510
511 // filter out packaging specs for unsupported architecture
512 filterArch := func(ps PackagingSpec) bool {
513 for _, arch := range arches {
514 if arch == ps.archType {
515 return true
516 }
517 }
518 return false
519 }
520
Yu Liuac483e02024-11-11 22:29:30 +0000521 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000522 depTag := ctx.OtherModuleDependencyTag(child)
523 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900524 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900525 }
Yu Liubad1eef2024-08-21 22:37:35 +0000526 for _, ps := range OtherModuleProviderOrDefault(
527 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900528 if !filterArch(ps) {
529 continue
530 }
531
Jeongik Cha54bf8752024-02-08 10:44:37 +0900532 if filter != nil {
533 if !filter(ps) {
534 continue
535 }
536 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000537
Inseob Kim3c0a0422024-11-05 17:21:37 +0900538 if modifier != nil {
539 modifier(&ps)
540 }
541
Jihoon Kang79196c52024-10-30 18:49:47 +0000542 if _, ok := depTag.(highPriorityDepTag); ok {
543 highPriorities = append(highPriorities, ps)
544 } else {
545 regularPriorities = append(regularPriorities, ps)
546 }
547
Spandan Das6c2b01d2024-10-22 22:16:04 +0000548 depNames = append(depNames, child.Name())
Colin Crossf0c1ede2025-01-23 13:30:36 -0800549 overridden = append(overridden, ps.overrides.ToSlice()...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900550 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900551 })
Jiyong Parka574d532024-08-28 18:06:43 +0900552
Jihoon Kang79196c52024-10-30 18:49:47 +0000553 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
554 // input minus packaging specs that are overridden
555 var filtered []PackagingSpec
556 for index, ps := range input {
557 if ps.owner != "" && InList(ps.owner, overridden) {
558 continue
559 }
560 // The dependency which requested this packaging spec has been overridden.
561 if InList(depNames[index], overridden) {
562 continue
563 }
564 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900565 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000566 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900567 }
568
Jihoon Kang79196c52024-10-30 18:49:47 +0000569 filteredRegularPriority := filterOverridden(regularPriorities)
570
Jiyong Parka574d532024-08-28 18:06:43 +0900571 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000572 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900573 dstPath := ps.relPathInPackage
574 if existingPs, ok := m[dstPath]; ok {
575 if !existingPs.Equals(&ps) {
576 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
577 }
578 continue
579 }
580 m[dstPath] = ps
581 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000582
583 filteredHighPriority := filterOverridden(highPriorities)
584 highPriorityPs := make(map[string]PackagingSpec)
585 for _, ps := range filteredHighPriority {
586 dstPath := ps.relPathInPackage
587 if existingPs, ok := highPriorityPs[dstPath]; ok {
588 if !existingPs.Equals(&ps) {
589 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
590 }
591 continue
592 }
593 highPriorityPs[dstPath] = ps
594 m[dstPath] = ps
595 }
596
Jooyung Handf09d172021-05-11 11:13:30 +0900597 return m
598}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900599
Jeongik Cha54bf8752024-02-08 10:44:37 +0900600// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900601func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
602 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
603}
604
605// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900606func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
607 return p.GatherPackagingSpecsWithFilter(ctx, nil)
608}
609
Dan Willemsen9fe14102021-07-13 21:52:04 -0700610// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
611// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700612func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900613 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
614 dirsToSpecs[dir] = specs
Cole Fauste3845052025-02-13 12:45:35 -0800615 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false)
Inseob Kim33f95a92024-07-11 15:44:49 +0900616}
617
618// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
619// entries into corresponding directories.
Cole Fauste3845052025-02-13 12:45:35 -0800620func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900621 empty := true
622 for _, specs := range dirsToSpecs {
623 if len(specs) > 0 {
624 empty = false
625 break
626 }
627 }
628 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800629 return entries
630 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900631
Jiyong Parkdda8f692020-11-09 18:38:48 +0900632 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900633
634 dirs := make([]WritablePath, 0, len(dirsToSpecs))
635 for dir, _ := range dirsToSpecs {
636 dirs = append(dirs, dir)
637 }
638 sort.Slice(dirs, func(i, j int) bool {
639 return dirs[i].String() < dirs[j].String()
640 })
641
642 for _, dir := range dirs {
643 specs := dirsToSpecs[dir]
644 for _, k := range SortedKeys(specs) {
645 ps := specs[k]
646 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
647 destDir := filepath.Dir(destPath)
648 entries = append(entries, ps.relPathInPackage)
649 if _, ok := seenDir[destDir]; !ok {
650 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800651 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900652 }
653 if ps.symlinkTarget == "" {
Cole Fauste3845052025-02-13 12:45:35 -0800654 cmd := builder.Command().Text("cp")
655 if preserveTimestamps {
656 cmd.Flag("-p")
657 }
658 cmd.Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900659 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800660 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900661 }
662 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800663 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900664 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900665 }
666 }
667
Dan Willemsen9fe14102021-07-13 21:52:04 -0700668 return entries
669}
670
671// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900672func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700673 builder := NewRuleBuilder(pctx, ctx)
674
675 dir := PathForModuleOut(ctx, ".zip")
676 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
677 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900678 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700679
Jiyong Parkdda8f692020-11-09 18:38:48 +0900680 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800681 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900682 FlagWithOutput("-o ", zipOut).
683 FlagWithArg("-C ", dir.String()).
684 Flag("-L 0"). // no compression because this will be unzipped soon
685 FlagWithArg("-D ", dir.String())
686 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
687
Colin Crossf1a035e2020-11-16 17:32:30 -0800688 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900689 return entries
690}