blob: d216c0c181b5d62d067a54a1f87c3082a062f482 [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
Jiyong Park073ea552020-11-09 14:08:34 +090075}
Jiyong Parkdda8f692020-11-09 18:38:48 +090076
Yu Liu467d7c52024-09-18 21:54:44 +000077type packagingSpecGob struct {
Yu Liu5246a7e2024-10-09 20:04:52 +000078 RelPathInPackage string
79 SrcPath Path
80 SymlinkTarget string
81 Executable bool
Colin Crossf0c1ede2025-01-23 13:30:36 -080082 EffectiveLicenseFiles Paths
Yu Liu5246a7e2024-10-09 20:04:52 +000083 Partition string
84 SkipInstall bool
Colin Crossf0c1ede2025-01-23 13:30:36 -080085 AconfigPaths Paths
Yu Liu5246a7e2024-10-09 20:04:52 +000086 ArchType ArchType
Colin Crossf0c1ede2025-01-23 13:30:36 -080087 Overrides []string
Yu Liu5246a7e2024-10-09 20:04:52 +000088 Owner string
Yu Liu467d7c52024-09-18 21:54:44 +000089}
Yu Liu26a716d2024-08-30 23:40:32 +000090
Yu Liu467d7c52024-09-18 21:54:44 +000091func (p *PackagingSpec) ToGob() *packagingSpecGob {
92 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +000093 RelPathInPackage: p.relPathInPackage,
94 SrcPath: p.srcPath,
95 SymlinkTarget: p.symlinkTarget,
96 Executable: p.executable,
Colin Crossf0c1ede2025-01-23 13:30:36 -080097 EffectiveLicenseFiles: p.effectiveLicenseFiles.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +000098 Partition: p.partition,
99 SkipInstall: p.skipInstall,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800100 AconfigPaths: p.aconfigPaths.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000101 ArchType: p.archType,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800102 Overrides: p.overrides.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000103 Owner: p.owner,
Yu Liu467d7c52024-09-18 21:54:44 +0000104 }
105}
106
107func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
108 p.relPathInPackage = data.RelPathInPackage
109 p.srcPath = data.SrcPath
110 p.symlinkTarget = data.SymlinkTarget
111 p.executable = data.Executable
Colin Crossf0c1ede2025-01-23 13:30:36 -0800112 p.effectiveLicenseFiles = uniquelist.Make(data.EffectiveLicenseFiles)
Yu Liu467d7c52024-09-18 21:54:44 +0000113 p.partition = data.Partition
114 p.skipInstall = data.SkipInstall
Colin Crossf0c1ede2025-01-23 13:30:36 -0800115 p.aconfigPaths = uniquelist.Make(data.AconfigPaths)
Yu Liu467d7c52024-09-18 21:54:44 +0000116 p.archType = data.ArchType
Colin Crossf0c1ede2025-01-23 13:30:36 -0800117 p.overrides = uniquelist.Make(data.Overrides)
Yu Liu467d7c52024-09-18 21:54:44 +0000118 p.owner = data.Owner
119}
120
121func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000122 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000123}
124
125func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000126 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000127}
128
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000129func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
130 if other == nil {
131 return false
132 }
133 if p.relPathInPackage != other.relPathInPackage {
134 return false
135 }
136 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
137 return false
138 }
139 if p.executable != other.executable {
140 return false
141 }
142 if p.partition != other.partition {
143 return false
144 }
145 return true
146}
147
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900148// Get file name of installed package
149func (p *PackagingSpec) FileName() string {
150 if p.relPathInPackage != "" {
151 return filepath.Base(p.relPathInPackage)
152 }
153
154 return ""
155}
156
Jiyong Park6446b622021-02-01 20:08:28 +0900157// Path relative to the root of the package
158func (p *PackagingSpec) RelPathInPackage() string {
159 return p.relPathInPackage
160}
161
Dan Willemsen9fe14102021-07-13 21:52:04 -0700162func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
163 p.relPathInPackage = relPathInPackage
164}
165
166func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800167 return p.effectiveLicenseFiles.ToSlice()
Dan Willemsen9fe14102021-07-13 21:52:04 -0700168}
169
Jooyung Han99c5fe62022-03-21 15:13:38 +0900170func (p *PackagingSpec) Partition() string {
171 return p.partition
172}
173
Inseob Kim3c0a0422024-11-05 17:21:37 +0900174func (p *PackagingSpec) SetPartition(partition string) {
175 p.partition = partition
176}
177
Jiyong Park4152b192024-04-30 21:24:21 +0900178func (p *PackagingSpec) SkipInstall() bool {
179 return p.skipInstall
180}
181
Justin Yun74f3f302024-05-07 14:32:14 +0900182// Paths of aconfig files for the built artifact
183func (p *PackagingSpec) GetAconfigPaths() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800184 return p.aconfigPaths.ToSlice()
Justin Yun74f3f302024-05-07 14:32:14 +0900185}
186
Cole Faust19fbb072025-01-30 18:19:29 -0800187// The path to the installed file in out/target/product. This is for legacy purposes, with
188// tools that want to interact with these files outside of the build. You should not use it
189// inside of the build. Will be nil if this module doesn't require a "full install".
190func (p *PackagingSpec) FullInstallPath() InstallPath {
191 return p.fullInstallPath
192}
193
194// If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
195// for the soong-only migration.
196func (p *PackagingSpec) RequiresFullInstall() bool {
197 return p.requiresFullInstall
198}
199
200// The source file to be copied to the FullInstallPath. Do not use, for the soong-only migration.
201func (p *PackagingSpec) SrcPath() Path {
202 return p.srcPath
203}
204
Jiyong Parkdda8f692020-11-09 18:38:48 +0900205type PackageModule interface {
206 Module
207 packagingBase() *PackagingBase
208
209 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900210 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
211 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900212 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900213
Jooyung Hana8834282022-03-25 11:40:12 +0900214 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
215 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900216 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900217 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900218
Jiyong Parkdda8f692020-11-09 18:38:48 +0900219 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900220 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900221 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
222 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900223 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900224}
225
226// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
227// include this struct and call InitPackageModule.
228type PackagingBase struct {
229 properties PackagingProperties
230
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900231 // Allows this module to skip missing dependencies. In most cases, this is not required, but
232 // for rare cases like when there's a dependency to a module which exists in certain repo
233 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900234 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900235
236 // If this is set to true by a module type inheriting PackagingBase, the deps property
237 // collects the first target only even with compile_multilib: true.
238 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000239
240 // If this is set to try by a module type inheriting PackagingBase, the module type is
241 // allowed to utilize High_priority_deps.
242 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900243}
244
Jihoon Kang79196c52024-10-30 18:49:47 +0000245type DepsProperty struct {
246 // Deps that have higher priority in packaging when there is a packaging conflict.
247 // For example, if multiple files are being installed to same filepath, the install file
248 // of the module listed in this property will have a higher priority over those in other
249 // deps properties.
250 High_priority_deps []string `android:"arch_variant"`
251
Jiyong Parkdda8f692020-11-09 18:38:48 +0900252 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900253 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900254}
255
256type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000257 First DepsProperty `android:"arch_variant"`
258 Common DepsProperty `android:"arch_variant"`
259 Lib32 DepsProperty `android:"arch_variant"`
260 Lib64 DepsProperty `android:"arch_variant"`
261 Both DepsProperty `android:"arch_variant"`
262 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900263}
264
Jiyong Park2136d152021-02-01 23:24:56 +0900265type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000266 Arm64 DepsProperty
267 Arm DepsProperty
268 X86_64 DepsProperty
269 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900270}
271
Jiyong Parkdda8f692020-11-09 18:38:48 +0900272type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000273 DepsProperty
274
275 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900276 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900277}
278
Jiyong Parkdda8f692020-11-09 18:38:48 +0900279func InitPackageModule(p PackageModule) {
280 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000281 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900282}
283
284func (p *PackagingBase) packagingBase() *PackagingBase {
285 return p
286}
287
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900288// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
289// the current archicture when this module is not configured for multi target. When configured for
290// multi target, deps is selected for each of the targets and is NOT selected for the current
291// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700292// It returns two lists, the normal and high priority deps, respectively.
293func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
294 var normalDeps []string
295 var highPriorityDeps []string
296
297 get := func(prop DepsProperty) {
298 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
299 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
300 }
301 has := func(prop DepsProperty) bool {
302 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000303 }
304
Jiyong Parkdda8f692020-11-09 18:38:48 +0900305 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700306 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900307 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700308 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900309 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700310 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900311 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700312 normalDeps = append(normalDeps, dep)
313 }
314 }
315 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
316 if checkIfOtherModuleSupportsLib32(ctx, dep) {
317 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900318 }
319 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900320 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700321 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900322 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700323 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900324 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700325 normalDeps = append(normalDeps, dep)
326 }
327 }
328 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
329 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
330 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900331 }
332 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900333 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700334 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900335 }
Jiyong Park2136d152021-02-01 23:24:56 +0900336
Jiyong Park3ea9b652024-05-15 23:01:54 +0900337 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700338 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900339 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
340 }
341 for i, t := range ctx.MultiTargets() {
342 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700343 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900344 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700345 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900346 }
347 }
348 }
349 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700350 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900351 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
352 }
353 for i, t := range ctx.MultiTargets() {
354 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700355 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900356 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700357 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900358 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900359 }
360 }
361 }
Jiyong Park2136d152021-02-01 23:24:56 +0900362
363 if ctx.Arch().ArchType == Common {
364 switch arch {
365 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700366 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900367 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700368 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900369 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700370 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900371 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700372 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900373 }
374 }
375
Cole Faust0c5eaed2024-11-01 11:05:00 -0700376 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
377 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
378 }
379
380 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900381}
382
Jiyong Parke6043782024-05-20 16:17:39 +0900383func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900384 var ret []Target
385 // The current and the common OS targets are always supported
386 ret = append(ret, ctx.Target())
387 if ctx.Arch().ArchType != Common {
388 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
389 }
390 // If this module is configured for multi targets, those should be supported as well
391 ret = append(ret, ctx.MultiTargets()...)
392 return ret
393}
394
Jiyong Parke6043782024-05-20 16:17:39 +0900395// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
396// module doesn't support 32-bit target, nil is returned.
397func getLib32Target(ctx BaseModuleContext) *Target {
398 for _, t := range getSupportedTargets(ctx) {
399 if t.Arch.ArchType.Multilib == "lib32" {
400 return &t
401 }
402 }
403 return nil
404}
405
406// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
407func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
408 t := getLib32Target(ctx)
409 if t == nil {
410 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
411 // or not.
412 return false
413 }
414 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
415}
416
Jooyung Han092ef812021-03-10 15:40:34 +0900417// PackagingItem is a marker interface for dependency tags.
418// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
419type PackagingItem interface {
420 // IsPackagingItem returns true if the dep is to be packaged
421 IsPackagingItem() bool
422}
423
Jihoon Kang79196c52024-10-30 18:49:47 +0000424var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
425
Jooyung Han092ef812021-03-10 15:40:34 +0900426// DepTag provides default implementation of PackagingItem interface.
427// PackagingBase-derived modules can define their own dependency tag by embedding this, which
428// can be passed to AddDeps() or AddDependencies().
429type PackagingItemAlwaysDepTag struct {
430}
431
432// IsPackagingItem returns true if the dep is to be packaged
433func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
434 return true
435}
436
Jihoon Kang79196c52024-10-30 18:49:47 +0000437type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000438 blueprint.BaseDependencyTag
439 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000440}
441
Jiyong Parkdda8f692020-11-09 18:38:48 +0900442// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900443func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700444 addDep := func(t Target, dep string, highPriority bool) {
445 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
446 return
447 }
448 targetVariation := t.Variations()
449 sharedVariation := blueprint.Variation{
450 Mutator: "link",
451 Variation: "shared",
452 }
453 // If a shared variation exists, use that. Static variants do not provide any standalone files
454 // for packaging.
455 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
456 targetVariation = append(targetVariation, sharedVariation)
457 }
458 depTagToUse := depTag
459 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000460 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700461 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000462
Cole Faust0c5eaed2024-11-01 11:05:00 -0700463 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
464 }
465 for _, t := range getSupportedTargets(ctx) {
466 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
467 for _, dep := range normalDeps {
468 addDep(t, dep, false)
469 }
470 for _, dep := range highPriorityDeps {
471 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900472 }
473 }
474}
475
Inseob Kim3c0a0422024-11-05 17:21:37 +0900476// See PackageModule.GatherPackagingSpecs
477func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000478 // packaging specs gathered from the dep that are not high priorities.
479 var regularPriorities []PackagingSpec
480
481 // all packaging specs gathered from the high priority deps.
482 var highPriorities []PackagingSpec
483
Spandan Das6c2b01d2024-10-22 22:16:04 +0000484 // Name of the dependency which requested the packaging spec.
485 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
486 // (the packaging spec might still be installed if there are some other deps which depend on it).
487 var depNames []string
488
Jiyong Parka574d532024-08-28 18:06:43 +0900489 // list of module names overridden
490 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900491
492 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900493 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900494 arches = append(arches, target.Arch.ArchType)
495 }
496
497 // filter out packaging specs for unsupported architecture
498 filterArch := func(ps PackagingSpec) bool {
499 for _, arch := range arches {
500 if arch == ps.archType {
501 return true
502 }
503 }
504 return false
505 }
506
Yu Liuac483e02024-11-11 22:29:30 +0000507 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000508 depTag := ctx.OtherModuleDependencyTag(child)
509 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900510 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900511 }
Yu Liubad1eef2024-08-21 22:37:35 +0000512 for _, ps := range OtherModuleProviderOrDefault(
513 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900514 if !filterArch(ps) {
515 continue
516 }
517
Jeongik Cha54bf8752024-02-08 10:44:37 +0900518 if filter != nil {
519 if !filter(ps) {
520 continue
521 }
522 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000523
Inseob Kim3c0a0422024-11-05 17:21:37 +0900524 if modifier != nil {
525 modifier(&ps)
526 }
527
Jihoon Kang79196c52024-10-30 18:49:47 +0000528 if _, ok := depTag.(highPriorityDepTag); ok {
529 highPriorities = append(highPriorities, ps)
530 } else {
531 regularPriorities = append(regularPriorities, ps)
532 }
533
Spandan Das6c2b01d2024-10-22 22:16:04 +0000534 depNames = append(depNames, child.Name())
Colin Crossf0c1ede2025-01-23 13:30:36 -0800535 overridden = append(overridden, ps.overrides.ToSlice()...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900536 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900537 })
Jiyong Parka574d532024-08-28 18:06:43 +0900538
Jihoon Kang79196c52024-10-30 18:49:47 +0000539 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
540 // input minus packaging specs that are overridden
541 var filtered []PackagingSpec
542 for index, ps := range input {
543 if ps.owner != "" && InList(ps.owner, overridden) {
544 continue
545 }
546 // The dependency which requested this packaging spec has been overridden.
547 if InList(depNames[index], overridden) {
548 continue
549 }
550 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900551 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000552 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900553 }
554
Jihoon Kang79196c52024-10-30 18:49:47 +0000555 filteredRegularPriority := filterOverridden(regularPriorities)
556
Jiyong Parka574d532024-08-28 18:06:43 +0900557 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000558 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900559 dstPath := ps.relPathInPackage
560 if existingPs, ok := m[dstPath]; ok {
561 if !existingPs.Equals(&ps) {
562 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
563 }
564 continue
565 }
566 m[dstPath] = ps
567 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000568
569 filteredHighPriority := filterOverridden(highPriorities)
570 highPriorityPs := make(map[string]PackagingSpec)
571 for _, ps := range filteredHighPriority {
572 dstPath := ps.relPathInPackage
573 if existingPs, ok := highPriorityPs[dstPath]; ok {
574 if !existingPs.Equals(&ps) {
575 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
576 }
577 continue
578 }
579 highPriorityPs[dstPath] = ps
580 m[dstPath] = ps
581 }
582
Jooyung Handf09d172021-05-11 11:13:30 +0900583 return m
584}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900585
Jeongik Cha54bf8752024-02-08 10:44:37 +0900586// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900587func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
588 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
589}
590
591// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900592func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
593 return p.GatherPackagingSpecsWithFilter(ctx, nil)
594}
595
Dan Willemsen9fe14102021-07-13 21:52:04 -0700596// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
597// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700598func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900599 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
600 dirsToSpecs[dir] = specs
601 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
602}
603
604// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
605// entries into corresponding directories.
606func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
607 empty := true
608 for _, specs := range dirsToSpecs {
609 if len(specs) > 0 {
610 empty = false
611 break
612 }
613 }
614 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800615 return entries
616 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900617
Jiyong Parkdda8f692020-11-09 18:38:48 +0900618 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900619
620 dirs := make([]WritablePath, 0, len(dirsToSpecs))
621 for dir, _ := range dirsToSpecs {
622 dirs = append(dirs, dir)
623 }
624 sort.Slice(dirs, func(i, j int) bool {
625 return dirs[i].String() < dirs[j].String()
626 })
627
628 for _, dir := range dirs {
629 specs := dirsToSpecs[dir]
630 for _, k := range SortedKeys(specs) {
631 ps := specs[k]
632 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
633 destDir := filepath.Dir(destPath)
634 entries = append(entries, ps.relPathInPackage)
635 if _, ok := seenDir[destDir]; !ok {
636 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800637 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900638 }
639 if ps.symlinkTarget == "" {
Cole Faustd7556eb2024-12-02 13:18:58 -0800640 builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900641 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800642 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900643 }
644 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800645 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900646 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900647 }
648 }
649
Dan Willemsen9fe14102021-07-13 21:52:04 -0700650 return entries
651}
652
653// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900654func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700655 builder := NewRuleBuilder(pctx, ctx)
656
657 dir := PathForModuleOut(ctx, ".zip")
658 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
659 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900660 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700661
Jiyong Parkdda8f692020-11-09 18:38:48 +0900662 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800663 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900664 FlagWithOutput("-o ", zipOut).
665 FlagWithArg("-C ", dir.String()).
666 Flag("-L 0"). // no compression because this will be unzipped soon
667 FlagWithArg("-D ", dir.String())
668 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
669
Colin Crossf1a035e2020-11-16 17:32:30 -0800670 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900671 return entries
672}