blob: 4e0c74a12907ae326b572f411ae812748b8acf55 [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
Cole Faustb052df52025-02-14 12:47:51 -0800205// The symlink target of the PackagingSpec. Do not use, for the soong-only migration.
206func (p *PackagingSpec) SymlinkTarget() string {
207 return p.symlinkTarget
208}
209
Jiyong Parkdda8f692020-11-09 18:38:48 +0900210type PackageModule interface {
211 Module
212 packagingBase() *PackagingBase
213
214 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900215 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
216 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900217 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900218
Jooyung Hana8834282022-03-25 11:40:12 +0900219 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
220 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900221 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900222 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900223
Jiyong Parkdda8f692020-11-09 18:38:48 +0900224 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900225 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900226 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
227 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900228 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900229}
230
231// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
232// include this struct and call InitPackageModule.
233type PackagingBase struct {
234 properties PackagingProperties
235
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900236 // Allows this module to skip missing dependencies. In most cases, this is not required, but
237 // for rare cases like when there's a dependency to a module which exists in certain repo
238 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900239 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900240
241 // If this is set to true by a module type inheriting PackagingBase, the deps property
242 // collects the first target only even with compile_multilib: true.
243 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000244
245 // If this is set to try by a module type inheriting PackagingBase, the module type is
246 // allowed to utilize High_priority_deps.
247 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900248}
249
Jihoon Kang79196c52024-10-30 18:49:47 +0000250type DepsProperty struct {
251 // Deps that have higher priority in packaging when there is a packaging conflict.
252 // For example, if multiple files are being installed to same filepath, the install file
253 // of the module listed in this property will have a higher priority over those in other
254 // deps properties.
255 High_priority_deps []string `android:"arch_variant"`
256
Jiyong Parkdda8f692020-11-09 18:38:48 +0900257 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900258 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900259}
260
261type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000262 First DepsProperty `android:"arch_variant"`
263 Common DepsProperty `android:"arch_variant"`
264 Lib32 DepsProperty `android:"arch_variant"`
265 Lib64 DepsProperty `android:"arch_variant"`
266 Both DepsProperty `android:"arch_variant"`
267 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900268}
269
Jiyong Park2136d152021-02-01 23:24:56 +0900270type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000271 Arm64 DepsProperty
272 Arm DepsProperty
273 X86_64 DepsProperty
274 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900275}
276
Jiyong Parkdda8f692020-11-09 18:38:48 +0900277type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000278 DepsProperty
279
280 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900281 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900282}
283
Jiyong Parkdda8f692020-11-09 18:38:48 +0900284func InitPackageModule(p PackageModule) {
285 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000286 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900287}
288
289func (p *PackagingBase) packagingBase() *PackagingBase {
290 return p
291}
292
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900293// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
294// the current archicture when this module is not configured for multi target. When configured for
295// multi target, deps is selected for each of the targets and is NOT selected for the current
296// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700297// It returns two lists, the normal and high priority deps, respectively.
298func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
299 var normalDeps []string
300 var highPriorityDeps []string
301
302 get := func(prop DepsProperty) {
303 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
304 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
305 }
306 has := func(prop DepsProperty) bool {
307 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000308 }
309
Jiyong Parkdda8f692020-11-09 18:38:48 +0900310 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700311 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900312 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700313 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900314 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700315 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900316 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700317 normalDeps = append(normalDeps, dep)
318 }
319 }
320 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
321 if checkIfOtherModuleSupportsLib32(ctx, dep) {
322 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900323 }
324 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900325 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700326 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900327 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700328 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900329 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700330 normalDeps = append(normalDeps, dep)
331 }
332 }
333 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
334 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
335 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900336 }
337 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900338 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700339 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900340 }
Jiyong Park2136d152021-02-01 23:24:56 +0900341
Jiyong Park3ea9b652024-05-15 23:01:54 +0900342 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700343 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900344 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
345 }
346 for i, t := range ctx.MultiTargets() {
347 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700348 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900349 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700350 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900351 }
352 }
353 }
354 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700355 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900356 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
357 }
358 for i, t := range ctx.MultiTargets() {
359 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700360 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900361 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700362 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900363 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900364 }
365 }
366 }
Jiyong Park2136d152021-02-01 23:24:56 +0900367
368 if ctx.Arch().ArchType == Common {
369 switch arch {
370 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700371 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900372 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700373 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900374 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700375 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900376 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700377 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900378 }
379 }
380
Cole Faust0c5eaed2024-11-01 11:05:00 -0700381 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
382 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
383 }
384
385 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900386}
387
Jiyong Parke6043782024-05-20 16:17:39 +0900388func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900389 var ret []Target
390 // The current and the common OS targets are always supported
391 ret = append(ret, ctx.Target())
392 if ctx.Arch().ArchType != Common {
393 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
394 }
395 // If this module is configured for multi targets, those should be supported as well
396 ret = append(ret, ctx.MultiTargets()...)
397 return ret
398}
399
Jiyong Parke6043782024-05-20 16:17:39 +0900400// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
401// module doesn't support 32-bit target, nil is returned.
402func getLib32Target(ctx BaseModuleContext) *Target {
403 for _, t := range getSupportedTargets(ctx) {
404 if t.Arch.ArchType.Multilib == "lib32" {
405 return &t
406 }
407 }
408 return nil
409}
410
411// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
412func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
413 t := getLib32Target(ctx)
414 if t == nil {
415 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
416 // or not.
417 return false
418 }
419 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
420}
421
Jooyung Han092ef812021-03-10 15:40:34 +0900422// PackagingItem is a marker interface for dependency tags.
423// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
424type PackagingItem interface {
425 // IsPackagingItem returns true if the dep is to be packaged
426 IsPackagingItem() bool
427}
428
Jihoon Kang79196c52024-10-30 18:49:47 +0000429var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
430
Jooyung Han092ef812021-03-10 15:40:34 +0900431// DepTag provides default implementation of PackagingItem interface.
432// PackagingBase-derived modules can define their own dependency tag by embedding this, which
433// can be passed to AddDeps() or AddDependencies().
434type PackagingItemAlwaysDepTag struct {
435}
436
437// IsPackagingItem returns true if the dep is to be packaged
438func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
439 return true
440}
441
Jihoon Kang79196c52024-10-30 18:49:47 +0000442type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000443 blueprint.BaseDependencyTag
444 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000445}
446
Jiyong Parkdda8f692020-11-09 18:38:48 +0900447// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900448func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700449 addDep := func(t Target, dep string, highPriority bool) {
450 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
451 return
452 }
453 targetVariation := t.Variations()
454 sharedVariation := blueprint.Variation{
455 Mutator: "link",
456 Variation: "shared",
457 }
458 // If a shared variation exists, use that. Static variants do not provide any standalone files
459 // for packaging.
460 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
461 targetVariation = append(targetVariation, sharedVariation)
462 }
463 depTagToUse := depTag
464 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000465 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700466 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000467
Cole Faust0c5eaed2024-11-01 11:05:00 -0700468 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
469 }
470 for _, t := range getSupportedTargets(ctx) {
471 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
472 for _, dep := range normalDeps {
473 addDep(t, dep, false)
474 }
475 for _, dep := range highPriorityDeps {
476 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900477 }
478 }
479}
480
Inseob Kim3c0a0422024-11-05 17:21:37 +0900481// See PackageModule.GatherPackagingSpecs
482func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000483 // packaging specs gathered from the dep that are not high priorities.
484 var regularPriorities []PackagingSpec
485
486 // all packaging specs gathered from the high priority deps.
487 var highPriorities []PackagingSpec
488
Spandan Das6c2b01d2024-10-22 22:16:04 +0000489 // Name of the dependency which requested the packaging spec.
490 // If this dep is overridden, the packaging spec will not be installed via this dependency chain.
491 // (the packaging spec might still be installed if there are some other deps which depend on it).
492 var depNames []string
493
Jiyong Parka574d532024-08-28 18:06:43 +0900494 // list of module names overridden
495 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900496
497 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900498 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900499 arches = append(arches, target.Arch.ArchType)
500 }
501
502 // filter out packaging specs for unsupported architecture
503 filterArch := func(ps PackagingSpec) bool {
504 for _, arch := range arches {
505 if arch == ps.archType {
506 return true
507 }
508 }
509 return false
510 }
511
Yu Liuac483e02024-11-11 22:29:30 +0000512 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000513 depTag := ctx.OtherModuleDependencyTag(child)
514 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900515 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900516 }
Yu Liubad1eef2024-08-21 22:37:35 +0000517 for _, ps := range OtherModuleProviderOrDefault(
518 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900519 if !filterArch(ps) {
520 continue
521 }
522
Jeongik Cha54bf8752024-02-08 10:44:37 +0900523 if filter != nil {
524 if !filter(ps) {
525 continue
526 }
527 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000528
Inseob Kim3c0a0422024-11-05 17:21:37 +0900529 if modifier != nil {
530 modifier(&ps)
531 }
532
Jihoon Kang79196c52024-10-30 18:49:47 +0000533 if _, ok := depTag.(highPriorityDepTag); ok {
534 highPriorities = append(highPriorities, ps)
535 } else {
536 regularPriorities = append(regularPriorities, ps)
537 }
538
Spandan Das6c2b01d2024-10-22 22:16:04 +0000539 depNames = append(depNames, child.Name())
Colin Crossf0c1ede2025-01-23 13:30:36 -0800540 overridden = append(overridden, ps.overrides.ToSlice()...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900541 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900542 })
Jiyong Parka574d532024-08-28 18:06:43 +0900543
Jihoon Kang79196c52024-10-30 18:49:47 +0000544 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
545 // input minus packaging specs that are overridden
546 var filtered []PackagingSpec
547 for index, ps := range input {
548 if ps.owner != "" && InList(ps.owner, overridden) {
549 continue
550 }
551 // The dependency which requested this packaging spec has been overridden.
552 if InList(depNames[index], overridden) {
553 continue
554 }
555 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900556 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000557 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900558 }
559
Jihoon Kang79196c52024-10-30 18:49:47 +0000560 filteredRegularPriority := filterOverridden(regularPriorities)
561
Jiyong Parka574d532024-08-28 18:06:43 +0900562 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000563 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900564 dstPath := ps.relPathInPackage
565 if existingPs, ok := m[dstPath]; ok {
566 if !existingPs.Equals(&ps) {
567 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
568 }
569 continue
570 }
571 m[dstPath] = ps
572 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000573
574 filteredHighPriority := filterOverridden(highPriorities)
575 highPriorityPs := make(map[string]PackagingSpec)
576 for _, ps := range filteredHighPriority {
577 dstPath := ps.relPathInPackage
578 if existingPs, ok := highPriorityPs[dstPath]; ok {
579 if !existingPs.Equals(&ps) {
580 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
581 }
582 continue
583 }
584 highPriorityPs[dstPath] = ps
585 m[dstPath] = ps
586 }
587
Jooyung Handf09d172021-05-11 11:13:30 +0900588 return m
589}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900590
Jeongik Cha54bf8752024-02-08 10:44:37 +0900591// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900592func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
593 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
594}
595
596// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900597func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
598 return p.GatherPackagingSpecsWithFilter(ctx, nil)
599}
600
Dan Willemsen9fe14102021-07-13 21:52:04 -0700601// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
602// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700603func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900604 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
605 dirsToSpecs[dir] = specs
Cole Fauste3845052025-02-13 12:45:35 -0800606 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false)
Inseob Kim33f95a92024-07-11 15:44:49 +0900607}
608
609// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
610// entries into corresponding directories.
Cole Fauste3845052025-02-13 12:45:35 -0800611func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900612 empty := true
613 for _, specs := range dirsToSpecs {
614 if len(specs) > 0 {
615 empty = false
616 break
617 }
618 }
619 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800620 return entries
621 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900622
Jiyong Parkdda8f692020-11-09 18:38:48 +0900623 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900624
625 dirs := make([]WritablePath, 0, len(dirsToSpecs))
626 for dir, _ := range dirsToSpecs {
627 dirs = append(dirs, dir)
628 }
629 sort.Slice(dirs, func(i, j int) bool {
630 return dirs[i].String() < dirs[j].String()
631 })
632
633 for _, dir := range dirs {
634 specs := dirsToSpecs[dir]
635 for _, k := range SortedKeys(specs) {
636 ps := specs[k]
637 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
638 destDir := filepath.Dir(destPath)
639 entries = append(entries, ps.relPathInPackage)
640 if _, ok := seenDir[destDir]; !ok {
641 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800642 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900643 }
644 if ps.symlinkTarget == "" {
Cole Fauste3845052025-02-13 12:45:35 -0800645 cmd := builder.Command().Text("cp")
646 if preserveTimestamps {
647 cmd.Flag("-p")
648 }
649 cmd.Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900650 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800651 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900652 }
653 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800654 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900655 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900656 }
657 }
658
Dan Willemsen9fe14102021-07-13 21:52:04 -0700659 return entries
660}
661
662// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900663func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700664 builder := NewRuleBuilder(pctx, ctx)
665
666 dir := PathForModuleOut(ctx, ".zip")
667 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
668 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900669 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700670
Jiyong Parkdda8f692020-11-09 18:38:48 +0900671 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800672 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900673 FlagWithOutput("-o ", zipOut).
674 FlagWithArg("-C ", dir.String()).
675 Flag("-L 0"). // no compression because this will be unzipped soon
676 FlagWithArg("-D ", dir.String())
677 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
678
Colin Crossf1a035e2020-11-16 17:32:30 -0800679 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900680 return entries
681}