blob: bf18409298deed1837749e8e63abbcd0ae4799cf [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
Yu Liu619b6ef2025-03-05 18:35:17 +000092 RequiresFullInstall bool
93 FullInstallPath InstallPath
Jihoon Kangabec3ec2025-02-19 00:55:10 +000094 Variation string
95}
96
97func (p *PackagingSpec) Owner() string {
98 return p.owner
99}
100
101func (p *PackagingSpec) Variation() string {
102 return p.variation
Yu Liu467d7c52024-09-18 21:54:44 +0000103}
Yu Liu26a716d2024-08-30 23:40:32 +0000104
Yu Liu467d7c52024-09-18 21:54:44 +0000105func (p *PackagingSpec) ToGob() *packagingSpecGob {
106 return &packagingSpecGob{
Yu Liu5246a7e2024-10-09 20:04:52 +0000107 RelPathInPackage: p.relPathInPackage,
108 SrcPath: p.srcPath,
109 SymlinkTarget: p.symlinkTarget,
110 Executable: p.executable,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800111 EffectiveLicenseFiles: p.effectiveLicenseFiles.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000112 Partition: p.partition,
113 SkipInstall: p.skipInstall,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800114 AconfigPaths: p.aconfigPaths.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000115 ArchType: p.archType,
Colin Crossf0c1ede2025-01-23 13:30:36 -0800116 Overrides: p.overrides.ToSlice(),
Yu Liu5246a7e2024-10-09 20:04:52 +0000117 Owner: p.owner,
Yu Liu619b6ef2025-03-05 18:35:17 +0000118 RequiresFullInstall: p.requiresFullInstall,
119 FullInstallPath: p.fullInstallPath,
Jihoon Kangabec3ec2025-02-19 00:55:10 +0000120 Variation: p.variation,
Yu Liu467d7c52024-09-18 21:54:44 +0000121 }
122}
123
124func (p *PackagingSpec) FromGob(data *packagingSpecGob) {
125 p.relPathInPackage = data.RelPathInPackage
126 p.srcPath = data.SrcPath
127 p.symlinkTarget = data.SymlinkTarget
128 p.executable = data.Executable
Colin Crossf0c1ede2025-01-23 13:30:36 -0800129 p.effectiveLicenseFiles = uniquelist.Make(data.EffectiveLicenseFiles)
Yu Liu467d7c52024-09-18 21:54:44 +0000130 p.partition = data.Partition
131 p.skipInstall = data.SkipInstall
Colin Crossf0c1ede2025-01-23 13:30:36 -0800132 p.aconfigPaths = uniquelist.Make(data.AconfigPaths)
Yu Liu467d7c52024-09-18 21:54:44 +0000133 p.archType = data.ArchType
Colin Crossf0c1ede2025-01-23 13:30:36 -0800134 p.overrides = uniquelist.Make(data.Overrides)
Yu Liu467d7c52024-09-18 21:54:44 +0000135 p.owner = data.Owner
Yu Liu619b6ef2025-03-05 18:35:17 +0000136 p.requiresFullInstall = data.RequiresFullInstall
137 p.fullInstallPath = data.FullInstallPath
Jihoon Kangabec3ec2025-02-19 00:55:10 +0000138 p.variation = data.Variation
Yu Liu467d7c52024-09-18 21:54:44 +0000139}
140
141func (p *PackagingSpec) GobEncode() ([]byte, error) {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000142 return gobtools.CustomGobEncode[packagingSpecGob](p)
Yu Liu26a716d2024-08-30 23:40:32 +0000143}
144
145func (p *PackagingSpec) GobDecode(data []byte) error {
Yu Liu3cadf7d2024-10-24 18:47:06 +0000146 return gobtools.CustomGobDecode[packagingSpecGob](data, p)
Yu Liu26a716d2024-08-30 23:40:32 +0000147}
148
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000149func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
150 if other == nil {
151 return false
152 }
153 if p.relPathInPackage != other.relPathInPackage {
154 return false
155 }
156 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
157 return false
158 }
159 if p.executable != other.executable {
160 return false
161 }
162 if p.partition != other.partition {
163 return false
164 }
165 return true
166}
167
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900168// Get file name of installed package
169func (p *PackagingSpec) FileName() string {
170 if p.relPathInPackage != "" {
171 return filepath.Base(p.relPathInPackage)
172 }
173
174 return ""
175}
176
Jiyong Park6446b622021-02-01 20:08:28 +0900177// Path relative to the root of the package
178func (p *PackagingSpec) RelPathInPackage() string {
179 return p.relPathInPackage
180}
181
Dan Willemsen9fe14102021-07-13 21:52:04 -0700182func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
183 p.relPathInPackage = relPathInPackage
184}
185
186func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800187 return p.effectiveLicenseFiles.ToSlice()
Dan Willemsen9fe14102021-07-13 21:52:04 -0700188}
189
Jooyung Han99c5fe62022-03-21 15:13:38 +0900190func (p *PackagingSpec) Partition() string {
191 return p.partition
192}
193
Inseob Kim3c0a0422024-11-05 17:21:37 +0900194func (p *PackagingSpec) SetPartition(partition string) {
195 p.partition = partition
196}
197
Jiyong Park4152b192024-04-30 21:24:21 +0900198func (p *PackagingSpec) SkipInstall() bool {
199 return p.skipInstall
200}
201
Justin Yun74f3f302024-05-07 14:32:14 +0900202// Paths of aconfig files for the built artifact
203func (p *PackagingSpec) GetAconfigPaths() Paths {
Colin Crossf0c1ede2025-01-23 13:30:36 -0800204 return p.aconfigPaths.ToSlice()
Justin Yun74f3f302024-05-07 14:32:14 +0900205}
206
Cole Faust19fbb072025-01-30 18:19:29 -0800207// The path to the installed file in out/target/product. This is for legacy purposes, with
208// tools that want to interact with these files outside of the build. You should not use it
209// inside of the build. Will be nil if this module doesn't require a "full install".
210func (p *PackagingSpec) FullInstallPath() InstallPath {
211 return p.fullInstallPath
212}
213
214// If the ninja rule creating the FullInstallPath has already been emitted or not. Do not use,
215// for the soong-only migration.
216func (p *PackagingSpec) RequiresFullInstall() bool {
217 return p.requiresFullInstall
218}
219
220// The source file to be copied to the FullInstallPath. Do not use, for the soong-only migration.
221func (p *PackagingSpec) SrcPath() Path {
222 return p.srcPath
223}
224
Cole Faustb052df52025-02-14 12:47:51 -0800225// The symlink target of the PackagingSpec. Do not use, for the soong-only migration.
226func (p *PackagingSpec) SymlinkTarget() string {
227 return p.symlinkTarget
228}
229
Jiyong Parkdda8f692020-11-09 18:38:48 +0900230type PackageModule interface {
231 Module
232 packagingBase() *PackagingBase
233
234 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900235 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
236 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900237 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900238
Jooyung Hana8834282022-03-25 11:40:12 +0900239 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
240 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900241 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Inseob Kim3c0a0422024-11-05 17:21:37 +0900242 GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900243
Jiyong Parkdda8f692020-11-09 18:38:48 +0900244 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900245 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900246 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
247 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900248 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900249}
250
251// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
252// include this struct and call InitPackageModule.
253type PackagingBase struct {
254 properties PackagingProperties
255
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900256 // Allows this module to skip missing dependencies. In most cases, this is not required, but
257 // for rare cases like when there's a dependency to a module which exists in certain repo
258 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900259 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900260
261 // If this is set to true by a module type inheriting PackagingBase, the deps property
262 // collects the first target only even with compile_multilib: true.
263 DepsCollectFirstTargetOnly bool
Jihoon Kang79196c52024-10-30 18:49:47 +0000264
265 // If this is set to try by a module type inheriting PackagingBase, the module type is
266 // allowed to utilize High_priority_deps.
267 AllowHighPriorityDeps bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900268}
269
Jihoon Kang79196c52024-10-30 18:49:47 +0000270type DepsProperty struct {
271 // Deps that have higher priority in packaging when there is a packaging conflict.
272 // For example, if multiple files are being installed to same filepath, the install file
273 // of the module listed in this property will have a higher priority over those in other
274 // deps properties.
275 High_priority_deps []string `android:"arch_variant"`
276
Jiyong Parkdda8f692020-11-09 18:38:48 +0900277 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900278 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900279}
280
281type packagingMultilibProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000282 First DepsProperty `android:"arch_variant"`
283 Common DepsProperty `android:"arch_variant"`
284 Lib32 DepsProperty `android:"arch_variant"`
285 Lib64 DepsProperty `android:"arch_variant"`
286 Both DepsProperty `android:"arch_variant"`
287 Prefer32 DepsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900288}
289
Jiyong Park2136d152021-02-01 23:24:56 +0900290type packagingArchProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000291 Arm64 DepsProperty
292 Arm DepsProperty
293 X86_64 DepsProperty
294 X86 DepsProperty
Jiyong Park2136d152021-02-01 23:24:56 +0900295}
296
Jiyong Parkdda8f692020-11-09 18:38:48 +0900297type PackagingProperties struct {
Jihoon Kang79196c52024-10-30 18:49:47 +0000298 DepsProperty
299
300 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900301 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900302}
303
Jiyong Parkdda8f692020-11-09 18:38:48 +0900304func InitPackageModule(p PackageModule) {
305 base := p.packagingBase()
Jihoon Kang79196c52024-10-30 18:49:47 +0000306 p.AddProperties(&base.properties, &base.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900307}
308
309func (p *PackagingBase) packagingBase() *PackagingBase {
310 return p
311}
312
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900313// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
314// the current archicture when this module is not configured for multi target. When configured for
315// multi target, deps is selected for each of the targets and is NOT selected for the current
316// architecture which would be Common.
Cole Faust0c5eaed2024-11-01 11:05:00 -0700317// It returns two lists, the normal and high priority deps, respectively.
318func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) ([]string, []string) {
319 var normalDeps []string
320 var highPriorityDeps []string
321
322 get := func(prop DepsProperty) {
323 normalDeps = append(normalDeps, prop.Deps.GetOrDefault(ctx, nil)...)
324 highPriorityDeps = append(highPriorityDeps, prop.High_priority_deps...)
325 }
326 has := func(prop DepsProperty) bool {
327 return len(prop.Deps.GetOrDefault(ctx, nil)) > 0 || len(prop.High_priority_deps) > 0
Jihoon Kang79196c52024-10-30 18:49:47 +0000328 }
329
Jiyong Parkdda8f692020-11-09 18:38:48 +0900330 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700331 get(p.properties.DepsProperty)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900332 } else if arch.Multilib == "lib32" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700333 get(p.properties.Multilib.Lib32)
Jiyong Parke6043782024-05-20 16:17:39 +0900334 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700335 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900336 if checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700337 normalDeps = append(normalDeps, dep)
338 }
339 }
340 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
341 if checkIfOtherModuleSupportsLib32(ctx, dep) {
342 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900343 }
344 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900345 } else if arch.Multilib == "lib64" {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700346 get(p.properties.Multilib.Lib64)
Jiyong Parke6043782024-05-20 16:17:39 +0900347 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
Cole Faust0c5eaed2024-11-01 11:05:00 -0700348 for _, dep := range p.properties.Multilib.Prefer32.Deps.GetOrDefault(ctx, nil) {
Jiyong Parke6043782024-05-20 16:17:39 +0900349 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700350 normalDeps = append(normalDeps, dep)
351 }
352 }
353 for _, dep := range p.properties.Multilib.Prefer32.High_priority_deps {
354 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
355 highPriorityDeps = append(highPriorityDeps, dep)
Jiyong Parke6043782024-05-20 16:17:39 +0900356 }
357 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900358 } else if arch == Common {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700359 get(p.properties.Multilib.Common)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900360 }
Jiyong Park2136d152021-02-01 23:24:56 +0900361
Jiyong Park3ea9b652024-05-15 23:01:54 +0900362 if p.DepsCollectFirstTargetOnly {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700363 if has(p.properties.Multilib.First) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900364 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
365 }
366 for i, t := range ctx.MultiTargets() {
367 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700368 get(p.properties.Multilib.Both)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900369 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700370 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900371 }
372 }
373 }
374 } else {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700375 if has(p.properties.Multilib.Both) {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900376 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
377 }
378 for i, t := range ctx.MultiTargets() {
379 if t.Arch.ArchType == arch {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700380 get(p.properties.DepsProperty)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900381 if i == 0 {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700382 get(p.properties.Multilib.First)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900383 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900384 }
385 }
386 }
Jiyong Park2136d152021-02-01 23:24:56 +0900387
388 if ctx.Arch().ArchType == Common {
389 switch arch {
390 case Arm64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700391 get(p.properties.Arch.Arm64)
Jiyong Park2136d152021-02-01 23:24:56 +0900392 case Arm:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700393 get(p.properties.Arch.Arm)
Jiyong Park2136d152021-02-01 23:24:56 +0900394 case X86_64:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700395 get(p.properties.Arch.X86_64)
Jiyong Park2136d152021-02-01 23:24:56 +0900396 case X86:
Cole Faust0c5eaed2024-11-01 11:05:00 -0700397 get(p.properties.Arch.X86)
Jiyong Park2136d152021-02-01 23:24:56 +0900398 }
399 }
400
Cole Faust0c5eaed2024-11-01 11:05:00 -0700401 if len(highPriorityDeps) > 0 && !p.AllowHighPriorityDeps {
402 ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
403 }
404
405 return FirstUniqueStrings(normalDeps), FirstUniqueStrings(highPriorityDeps)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900406}
407
Jiyong Parke6043782024-05-20 16:17:39 +0900408func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900409 var ret []Target
410 // The current and the common OS targets are always supported
411 ret = append(ret, ctx.Target())
412 if ctx.Arch().ArchType != Common {
413 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
414 }
415 // If this module is configured for multi targets, those should be supported as well
416 ret = append(ret, ctx.MultiTargets()...)
417 return ret
418}
419
Jiyong Parke6043782024-05-20 16:17:39 +0900420// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
421// module doesn't support 32-bit target, nil is returned.
422func getLib32Target(ctx BaseModuleContext) *Target {
423 for _, t := range getSupportedTargets(ctx) {
424 if t.Arch.ArchType.Multilib == "lib32" {
425 return &t
426 }
427 }
428 return nil
429}
430
431// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
432func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
433 t := getLib32Target(ctx)
434 if t == nil {
435 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
436 // or not.
437 return false
438 }
439 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
440}
441
Jooyung Han092ef812021-03-10 15:40:34 +0900442// PackagingItem is a marker interface for dependency tags.
443// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
444type PackagingItem interface {
445 // IsPackagingItem returns true if the dep is to be packaged
446 IsPackagingItem() bool
447}
448
Jihoon Kang79196c52024-10-30 18:49:47 +0000449var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
450
Jooyung Han092ef812021-03-10 15:40:34 +0900451// DepTag provides default implementation of PackagingItem interface.
452// PackagingBase-derived modules can define their own dependency tag by embedding this, which
453// can be passed to AddDeps() or AddDependencies().
454type PackagingItemAlwaysDepTag struct {
455}
456
457// IsPackagingItem returns true if the dep is to be packaged
458func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
459 return true
460}
461
Jihoon Kang79196c52024-10-30 18:49:47 +0000462type highPriorityDepTag struct {
Jihoon Kangade584c2024-11-14 19:45:47 +0000463 blueprint.BaseDependencyTag
464 PackagingItemAlwaysDepTag
Jihoon Kang79196c52024-10-30 18:49:47 +0000465}
466
Jiyong Parkdda8f692020-11-09 18:38:48 +0900467// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900468func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Cole Faust0c5eaed2024-11-01 11:05:00 -0700469 addDep := func(t Target, dep string, highPriority bool) {
470 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
471 return
472 }
473 targetVariation := t.Variations()
474 sharedVariation := blueprint.Variation{
475 Mutator: "link",
476 Variation: "shared",
477 }
478 // If a shared variation exists, use that. Static variants do not provide any standalone files
479 // for packaging.
480 if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
481 targetVariation = append(targetVariation, sharedVariation)
482 }
483 depTagToUse := depTag
484 if highPriority {
Jihoon Kangade584c2024-11-14 19:45:47 +0000485 depTagToUse = highPriorityDepTag{}
Cole Faust0c5eaed2024-11-01 11:05:00 -0700486 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000487
Cole Faust0c5eaed2024-11-01 11:05:00 -0700488 ctx.AddFarVariationDependencies(targetVariation, depTagToUse, dep)
489 }
490 for _, t := range getSupportedTargets(ctx) {
491 normalDeps, highPriorityDeps := p.getDepsForArch(ctx, t.Arch.ArchType)
492 for _, dep := range normalDeps {
493 addDep(t, dep, false)
494 }
495 for _, dep := range highPriorityDeps {
496 addDep(t, dep, true)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900497 }
498 }
499}
500
Inseob Kim3c0a0422024-11-05 17:21:37 +0900501// See PackageModule.GatherPackagingSpecs
502func (p *PackagingBase) GatherPackagingSpecsWithFilterAndModifier(ctx ModuleContext, filter func(PackagingSpec) bool, modifier func(*PackagingSpec)) map[string]PackagingSpec {
Jihoon Kang79196c52024-10-30 18:49:47 +0000503 // packaging specs gathered from the dep that are not high priorities.
504 var regularPriorities []PackagingSpec
505
506 // all packaging specs gathered from the high priority deps.
507 var highPriorities []PackagingSpec
508
Jiyong Parka574d532024-08-28 18:06:43 +0900509 // list of module names overridden
Inseob Kim76150492025-03-20 10:46:06 +0900510 overridden := make(map[string]bool)
511
512 // all installed modules which are not overridden.
513 modulesToInstall := make(map[string]bool)
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900514
515 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900516 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900517 arches = append(arches, target.Arch.ArchType)
518 }
519
520 // filter out packaging specs for unsupported architecture
521 filterArch := func(ps PackagingSpec) bool {
522 for _, arch := range arches {
523 if arch == ps.archType {
524 return true
525 }
526 }
527 return false
528 }
529
Inseob Kim76150492025-03-20 10:46:06 +0900530 // find all overridden modules and packaging specs
Yu Liuac483e02024-11-11 22:29:30 +0000531 ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
Jihoon Kang79196c52024-10-30 18:49:47 +0000532 depTag := ctx.OtherModuleDependencyTag(child)
533 if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
Jooyung Han092ef812021-03-10 15:40:34 +0900534 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900535 }
Yu Liubad1eef2024-08-21 22:37:35 +0000536 for _, ps := range OtherModuleProviderOrDefault(
537 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900538 if !filterArch(ps) {
539 continue
540 }
541
Jeongik Cha54bf8752024-02-08 10:44:37 +0900542 if filter != nil {
543 if !filter(ps) {
544 continue
545 }
546 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000547
Inseob Kim3c0a0422024-11-05 17:21:37 +0900548 if modifier != nil {
549 modifier(&ps)
550 }
551
Jihoon Kang79196c52024-10-30 18:49:47 +0000552 if _, ok := depTag.(highPriorityDepTag); ok {
553 highPriorities = append(highPriorities, ps)
554 } else {
555 regularPriorities = append(regularPriorities, ps)
556 }
557
Inseob Kim76150492025-03-20 10:46:06 +0900558 for o := range ps.overrides.Iter() {
559 overridden[o] = true
560 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900561 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900562 })
Jiyong Parka574d532024-08-28 18:06:43 +0900563
Inseob Kim76150492025-03-20 10:46:06 +0900564 // gather modules to install, skipping overridden modules
565 ctx.WalkDeps(func(child, parent Module) bool {
566 owner := ctx.OtherModuleName(child)
567 if o, ok := child.(OverridableModule); ok {
568 if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" {
569 owner = overriddenBy
Jihoon Kang79196c52024-10-30 18:49:47 +0000570 }
Inseob Kim76150492025-03-20 10:46:06 +0900571 }
572 if overridden[owner] {
573 return false
574 }
575 modulesToInstall[owner] = true
576 return true
577 })
578
579 filterOverridden := func(input []PackagingSpec) []PackagingSpec {
580 // input minus packaging specs that are not installed
581 var filtered []PackagingSpec
582 for _, ps := range input {
583 if !modulesToInstall[ps.owner] {
Jihoon Kang79196c52024-10-30 18:49:47 +0000584 continue
585 }
586 filtered = append(filtered, ps)
Jiyong Parka574d532024-08-28 18:06:43 +0900587 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000588 return filtered
Jiyong Parka574d532024-08-28 18:06:43 +0900589 }
590
Jihoon Kang79196c52024-10-30 18:49:47 +0000591 filteredRegularPriority := filterOverridden(regularPriorities)
592
Jiyong Parka574d532024-08-28 18:06:43 +0900593 m := make(map[string]PackagingSpec)
Jihoon Kang79196c52024-10-30 18:49:47 +0000594 for _, ps := range filteredRegularPriority {
Jiyong Parka574d532024-08-28 18:06:43 +0900595 dstPath := ps.relPathInPackage
596 if existingPs, ok := m[dstPath]; ok {
597 if !existingPs.Equals(&ps) {
598 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
599 }
600 continue
601 }
602 m[dstPath] = ps
603 }
Jihoon Kang79196c52024-10-30 18:49:47 +0000604
605 filteredHighPriority := filterOverridden(highPriorities)
606 highPriorityPs := make(map[string]PackagingSpec)
607 for _, ps := range filteredHighPriority {
608 dstPath := ps.relPathInPackage
609 if existingPs, ok := highPriorityPs[dstPath]; ok {
610 if !existingPs.Equals(&ps) {
611 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
612 }
613 continue
614 }
615 highPriorityPs[dstPath] = ps
616 m[dstPath] = ps
617 }
618
Jooyung Handf09d172021-05-11 11:13:30 +0900619 return m
620}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900621
Jeongik Cha54bf8752024-02-08 10:44:37 +0900622// See PackageModule.GatherPackagingSpecs
Inseob Kim3c0a0422024-11-05 17:21:37 +0900623func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
624 return p.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, nil)
625}
626
627// See PackageModule.GatherPackagingSpecs
Jeongik Cha54bf8752024-02-08 10:44:37 +0900628func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
629 return p.GatherPackagingSpecsWithFilter(ctx, nil)
630}
631
Dan Willemsen9fe14102021-07-13 21:52:04 -0700632// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
633// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700634func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900635 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
636 dirsToSpecs[dir] = specs
Cole Fauste3845052025-02-13 12:45:35 -0800637 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs, false)
Inseob Kim33f95a92024-07-11 15:44:49 +0900638}
639
640// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
641// entries into corresponding directories.
Cole Fauste3845052025-02-13 12:45:35 -0800642func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec, preserveTimestamps bool) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900643 empty := true
644 for _, specs := range dirsToSpecs {
645 if len(specs) > 0 {
646 empty = false
647 break
648 }
649 }
650 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800651 return entries
652 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900653
Jiyong Parkdda8f692020-11-09 18:38:48 +0900654 seenDir := make(map[string]bool)
Inseob Kim33f95a92024-07-11 15:44:49 +0900655
656 dirs := make([]WritablePath, 0, len(dirsToSpecs))
657 for dir, _ := range dirsToSpecs {
658 dirs = append(dirs, dir)
659 }
660 sort.Slice(dirs, func(i, j int) bool {
661 return dirs[i].String() < dirs[j].String()
662 })
663
664 for _, dir := range dirs {
665 specs := dirsToSpecs[dir]
666 for _, k := range SortedKeys(specs) {
667 ps := specs[k]
668 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
669 destDir := filepath.Dir(destPath)
670 entries = append(entries, ps.relPathInPackage)
671 if _, ok := seenDir[destDir]; !ok {
672 seenDir[destDir] = true
Cole Faustd7556eb2024-12-02 13:18:58 -0800673 builder.Command().Textf("mkdir -p %s", destDir)
Inseob Kim33f95a92024-07-11 15:44:49 +0900674 }
675 if ps.symlinkTarget == "" {
Cole Fauste3845052025-02-13 12:45:35 -0800676 cmd := builder.Command().Text("cp")
677 if preserveTimestamps {
678 cmd.Flag("-p")
679 }
680 cmd.Input(ps.srcPath).Text(destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900681 } else {
Cole Faustd7556eb2024-12-02 13:18:58 -0800682 builder.Command().Textf("ln -sf %s %s", ps.symlinkTarget, destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900683 }
684 if ps.executable {
Cole Faustd7556eb2024-12-02 13:18:58 -0800685 builder.Command().Textf("chmod a+x %s", destPath)
Inseob Kim33f95a92024-07-11 15:44:49 +0900686 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900687 }
688 }
689
Dan Willemsen9fe14102021-07-13 21:52:04 -0700690 return entries
691}
692
693// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900694func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700695 builder := NewRuleBuilder(pctx, ctx)
696
697 dir := PathForModuleOut(ctx, ".zip")
698 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
699 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900700 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700701
Jiyong Parkdda8f692020-11-09 18:38:48 +0900702 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800703 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900704 FlagWithOutput("-o ", zipOut).
705 FlagWithArg("-C ", dir.String()).
706 Flag("-L 0"). // no compression because this will be unzipped soon
707 FlagWithArg("-D ", dir.String())
708 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
709
Colin Crossf1a035e2020-11-16 17:32:30 -0800710 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900711 return entries
712}