blob: 0909936c66cf664099c820c2159c162213c70539 [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 (
Yu Liu26a716d2024-08-30 23:40:32 +000018 "bytes"
19 "encoding/gob"
20 "errors"
Jiyong Parkdda8f692020-11-09 18:38:48 +090021 "fmt"
22 "path/filepath"
Inseob Kim33f95a92024-07-11 15:44:49 +090023 "sort"
Jeongik Cha76e677f2023-12-21 16:39:15 +090024 "strings"
Jiyong Parkdda8f692020-11-09 18:38:48 +090025
26 "github.com/google/blueprint"
Jiyong Park105e11c2024-05-17 14:58:24 +090027 "github.com/google/blueprint/proptools"
Jiyong Parkdda8f692020-11-09 18:38:48 +090028)
29
Jiyong Parkcc1157c2020-11-25 11:31:13 +090030// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
31// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
32// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
33// running on a VM), or a zip archive for some of the host tools.
Jiyong Park073ea552020-11-09 14:08:34 +090034type PackagingSpec struct {
35 // Path relative to the root of the package
36 relPathInPackage string
37
38 // The path to the built artifact
39 srcPath Path
40
41 // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
42 // srcPath is of course ignored.)
43 symlinkTarget string
44
45 // Whether relPathInPackage should be marked as executable or not
46 executable bool
Dan Willemsen9fe14102021-07-13 21:52:04 -070047
48 effectiveLicenseFiles *Paths
Jooyung Han99c5fe62022-03-21 15:13:38 +090049
50 partition string
Jiyong Park4152b192024-04-30 21:24:21 +090051
52 // Whether this packaging spec represents an installation of the srcPath (i.e. this struct
53 // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via
54 // PackageFile).
55 skipInstall bool
Justin Yun74f3f302024-05-07 14:32:14 +090056
57 // Paths of aconfig files for the built artifact
58 aconfigPaths *Paths
Jiyong Parkc6a773d2024-05-14 21:49:11 +090059
60 // ArchType of the module which produced this packaging spec
61 archType ArchType
Jiyong Parka574d532024-08-28 18:06:43 +090062
63 // List of module names that this packaging spec overrides
64 overrides *[]string
65
66 // Name of the module where this packaging spec is output of
67 owner string
Jiyong Park073ea552020-11-09 14:08:34 +090068}
Jiyong Parkdda8f692020-11-09 18:38:48 +090069
Yu Liu26a716d2024-08-30 23:40:32 +000070func (p *PackagingSpec) GobEncode() ([]byte, error) {
71 w := new(bytes.Buffer)
72 encoder := gob.NewEncoder(w)
73 err := errors.Join(encoder.Encode(p.relPathInPackage), encoder.Encode(p.srcPath),
74 encoder.Encode(p.symlinkTarget), encoder.Encode(p.executable),
75 encoder.Encode(p.effectiveLicenseFiles), encoder.Encode(p.partition),
76 encoder.Encode(p.skipInstall), encoder.Encode(p.aconfigPaths),
77 encoder.Encode(p.archType))
78 if err != nil {
79 return nil, err
80 }
81
82 return w.Bytes(), nil
83}
84
85func (p *PackagingSpec) GobDecode(data []byte) error {
86 r := bytes.NewBuffer(data)
87 decoder := gob.NewDecoder(r)
88 err := errors.Join(decoder.Decode(&p.relPathInPackage), decoder.Decode(&p.srcPath),
89 decoder.Decode(&p.symlinkTarget), decoder.Decode(&p.executable),
90 decoder.Decode(&p.effectiveLicenseFiles), decoder.Decode(&p.partition),
91 decoder.Decode(&p.skipInstall), decoder.Decode(&p.aconfigPaths),
92 decoder.Decode(&p.archType))
93 if err != nil {
94 return err
95 }
96
97 return nil
98}
99
Jiyong Park16ef7ac2024-05-01 12:36:10 +0000100func (p *PackagingSpec) Equals(other *PackagingSpec) bool {
101 if other == nil {
102 return false
103 }
104 if p.relPathInPackage != other.relPathInPackage {
105 return false
106 }
107 if p.srcPath != other.srcPath || p.symlinkTarget != other.symlinkTarget {
108 return false
109 }
110 if p.executable != other.executable {
111 return false
112 }
113 if p.partition != other.partition {
114 return false
115 }
116 return true
117}
118
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900119// Get file name of installed package
120func (p *PackagingSpec) FileName() string {
121 if p.relPathInPackage != "" {
122 return filepath.Base(p.relPathInPackage)
123 }
124
125 return ""
126}
127
Jiyong Park6446b622021-02-01 20:08:28 +0900128// Path relative to the root of the package
129func (p *PackagingSpec) RelPathInPackage() string {
130 return p.relPathInPackage
131}
132
Dan Willemsen9fe14102021-07-13 21:52:04 -0700133func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
134 p.relPathInPackage = relPathInPackage
135}
136
137func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
138 if p.effectiveLicenseFiles == nil {
139 return Paths{}
140 }
141 return *p.effectiveLicenseFiles
142}
143
Jooyung Han99c5fe62022-03-21 15:13:38 +0900144func (p *PackagingSpec) Partition() string {
145 return p.partition
146}
147
Jiyong Park4152b192024-04-30 21:24:21 +0900148func (p *PackagingSpec) SkipInstall() bool {
149 return p.skipInstall
150}
151
Justin Yun74f3f302024-05-07 14:32:14 +0900152// Paths of aconfig files for the built artifact
153func (p *PackagingSpec) GetAconfigPaths() Paths {
154 return *p.aconfigPaths
155}
156
Jiyong Parkdda8f692020-11-09 18:38:48 +0900157type PackageModule interface {
158 Module
159 packagingBase() *PackagingBase
160
161 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jooyung Han092ef812021-03-10 15:40:34 +0900162 // When adding the dependencies, depTag is used as the tag. If `deps` modules are meant to
163 // be copied to a zip in CopyDepsToZip, `depTag` should implement PackagingItem marker interface.
Jiyong Park65b62242020-11-25 12:44:59 +0900164 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900165
Jooyung Hana8834282022-03-25 11:40:12 +0900166 // GatherPackagingSpecs gathers PackagingSpecs of transitive dependencies.
167 GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec
Jeongik Cha54bf8752024-02-08 10:44:37 +0900168 GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec
Jooyung Hana8834282022-03-25 11:40:12 +0900169
Jiyong Parkdda8f692020-11-09 18:38:48 +0900170 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900171 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +0900172 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
173 // etc.) from the extracted files
Jooyung Hana8834282022-03-25 11:40:12 +0900174 CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) []string
Jiyong Parkdda8f692020-11-09 18:38:48 +0900175}
176
177// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
178// include this struct and call InitPackageModule.
179type PackagingBase struct {
180 properties PackagingProperties
181
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900182 // Allows this module to skip missing dependencies. In most cases, this is not required, but
183 // for rare cases like when there's a dependency to a module which exists in certain repo
184 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900185 IgnoreMissingDependencies bool
Jiyong Park3ea9b652024-05-15 23:01:54 +0900186
187 // If this is set to true by a module type inheriting PackagingBase, the deps property
188 // collects the first target only even with compile_multilib: true.
189 DepsCollectFirstTargetOnly bool
Jiyong Parkdda8f692020-11-09 18:38:48 +0900190}
191
192type depsProperty struct {
193 // Modules to include in this package
Jiyong Park105e11c2024-05-17 14:58:24 +0900194 Deps proptools.Configurable[[]string] `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900195}
196
197type packagingMultilibProperties struct {
Jiyong Parke6043782024-05-20 16:17:39 +0900198 First depsProperty `android:"arch_variant"`
199 Common depsProperty `android:"arch_variant"`
200 Lib32 depsProperty `android:"arch_variant"`
201 Lib64 depsProperty `android:"arch_variant"`
202 Both depsProperty `android:"arch_variant"`
203 Prefer32 depsProperty `android:"arch_variant"`
Jiyong Parkdda8f692020-11-09 18:38:48 +0900204}
205
Jiyong Park2136d152021-02-01 23:24:56 +0900206type packagingArchProperties struct {
207 Arm64 depsProperty
208 Arm depsProperty
209 X86_64 depsProperty
210 X86 depsProperty
211}
212
Jiyong Parkdda8f692020-11-09 18:38:48 +0900213type PackagingProperties struct {
Jiyong Park105e11c2024-05-17 14:58:24 +0900214 Deps proptools.Configurable[[]string] `android:"arch_variant"`
215 Multilib packagingMultilibProperties `android:"arch_variant"`
Jiyong Park2136d152021-02-01 23:24:56 +0900216 Arch packagingArchProperties
Jiyong Parkdda8f692020-11-09 18:38:48 +0900217}
218
Jiyong Parkdda8f692020-11-09 18:38:48 +0900219func InitPackageModule(p PackageModule) {
220 base := p.packagingBase()
221 p.AddProperties(&base.properties)
222}
223
224func (p *PackagingBase) packagingBase() *PackagingBase {
225 return p
226}
227
Jiyong Parkcc1157c2020-11-25 11:31:13 +0900228// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
229// the current archicture when this module is not configured for multi target. When configured for
230// multi target, deps is selected for each of the targets and is NOT selected for the current
231// architecture which would be Common.
Jiyong Parkdda8f692020-11-09 18:38:48 +0900232func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
Jiyong Park105e11c2024-05-17 14:58:24 +0900233 get := func(prop proptools.Configurable[[]string]) []string {
234 return prop.GetOrDefault(ctx, nil)
235 }
236
Jiyong Parkdda8f692020-11-09 18:38:48 +0900237 var ret []string
238 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
Jiyong Park105e11c2024-05-17 14:58:24 +0900239 ret = append(ret, get(p.properties.Deps)...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900240 } else if arch.Multilib == "lib32" {
Jiyong Park105e11c2024-05-17 14:58:24 +0900241 ret = append(ret, get(p.properties.Multilib.Lib32.Deps)...)
Jiyong Parke6043782024-05-20 16:17:39 +0900242 // multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
243 for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
244 if checkIfOtherModuleSupportsLib32(ctx, dep) {
245 ret = append(ret, dep)
246 }
247 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900248 } else if arch.Multilib == "lib64" {
Jiyong Park105e11c2024-05-17 14:58:24 +0900249 ret = append(ret, get(p.properties.Multilib.Lib64.Deps)...)
Jiyong Parke6043782024-05-20 16:17:39 +0900250 // multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
251 for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
252 if !checkIfOtherModuleSupportsLib32(ctx, dep) {
253 ret = append(ret, dep)
254 }
255 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900256 } else if arch == Common {
Jiyong Park105e11c2024-05-17 14:58:24 +0900257 ret = append(ret, get(p.properties.Multilib.Common.Deps)...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900258 }
Jiyong Park2136d152021-02-01 23:24:56 +0900259
Jiyong Park3ea9b652024-05-15 23:01:54 +0900260 if p.DepsCollectFirstTargetOnly {
Jiyong Park105e11c2024-05-17 14:58:24 +0900261 if len(get(p.properties.Multilib.First.Deps)) > 0 {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900262 ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
263 }
264 for i, t := range ctx.MultiTargets() {
265 if t.Arch.ArchType == arch {
Jiyong Park105e11c2024-05-17 14:58:24 +0900266 ret = append(ret, get(p.properties.Multilib.Both.Deps)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900267 if i == 0 {
Jiyong Park105e11c2024-05-17 14:58:24 +0900268 ret = append(ret, get(p.properties.Deps)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900269 }
270 }
271 }
272 } else {
Jiyong Park105e11c2024-05-17 14:58:24 +0900273 if len(get(p.properties.Multilib.Both.Deps)) > 0 {
Jiyong Park3ea9b652024-05-15 23:01:54 +0900274 ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
275 }
276 for i, t := range ctx.MultiTargets() {
277 if t.Arch.ArchType == arch {
Jiyong Park105e11c2024-05-17 14:58:24 +0900278 ret = append(ret, get(p.properties.Deps)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900279 if i == 0 {
Jiyong Park105e11c2024-05-17 14:58:24 +0900280 ret = append(ret, get(p.properties.Multilib.First.Deps)...)
Jiyong Park3ea9b652024-05-15 23:01:54 +0900281 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900282 }
283 }
284 }
Jiyong Park2136d152021-02-01 23:24:56 +0900285
286 if ctx.Arch().ArchType == Common {
287 switch arch {
288 case Arm64:
Jiyong Park105e11c2024-05-17 14:58:24 +0900289 ret = append(ret, get(p.properties.Arch.Arm64.Deps)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900290 case Arm:
Jiyong Park105e11c2024-05-17 14:58:24 +0900291 ret = append(ret, get(p.properties.Arch.Arm.Deps)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900292 case X86_64:
Jiyong Park105e11c2024-05-17 14:58:24 +0900293 ret = append(ret, get(p.properties.Arch.X86_64.Deps)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900294 case X86:
Jiyong Park105e11c2024-05-17 14:58:24 +0900295 ret = append(ret, get(p.properties.Arch.X86.Deps)...)
Jiyong Park2136d152021-02-01 23:24:56 +0900296 }
297 }
298
Jiyong Parkdda8f692020-11-09 18:38:48 +0900299 return FirstUniqueStrings(ret)
300}
301
Jiyong Parke6043782024-05-20 16:17:39 +0900302func getSupportedTargets(ctx BaseModuleContext) []Target {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900303 var ret []Target
304 // The current and the common OS targets are always supported
305 ret = append(ret, ctx.Target())
306 if ctx.Arch().ArchType != Common {
307 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
308 }
309 // If this module is configured for multi targets, those should be supported as well
310 ret = append(ret, ctx.MultiTargets()...)
311 return ret
312}
313
Jiyong Parke6043782024-05-20 16:17:39 +0900314// getLib32Target returns the 32-bit target from the list of targets this module supports. If this
315// module doesn't support 32-bit target, nil is returned.
316func getLib32Target(ctx BaseModuleContext) *Target {
317 for _, t := range getSupportedTargets(ctx) {
318 if t.Arch.ArchType.Multilib == "lib32" {
319 return &t
320 }
321 }
322 return nil
323}
324
325// checkIfOtherModuleSUpportsLib32 returns true if 32-bit variant of dep exists.
326func checkIfOtherModuleSupportsLib32(ctx BaseModuleContext, dep string) bool {
327 t := getLib32Target(ctx)
328 if t == nil {
329 // This packaging module doesn't support 32bit. No point of checking if dep supports 32-bit
330 // or not.
331 return false
332 }
333 return ctx.OtherModuleFarDependencyVariantExists(t.Variations(), dep)
334}
335
Jooyung Han092ef812021-03-10 15:40:34 +0900336// PackagingItem is a marker interface for dependency tags.
337// Direct dependencies with a tag implementing PackagingItem are packaged in CopyDepsToZip().
338type PackagingItem interface {
339 // IsPackagingItem returns true if the dep is to be packaged
340 IsPackagingItem() bool
341}
342
343// DepTag provides default implementation of PackagingItem interface.
344// PackagingBase-derived modules can define their own dependency tag by embedding this, which
345// can be passed to AddDeps() or AddDependencies().
346type PackagingItemAlwaysDepTag struct {
347}
348
349// IsPackagingItem returns true if the dep is to be packaged
350func (PackagingItemAlwaysDepTag) IsPackagingItem() bool {
351 return true
352}
353
Jiyong Parkdda8f692020-11-09 18:38:48 +0900354// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900355func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Jiyong Parke6043782024-05-20 16:17:39 +0900356 for _, t := range getSupportedTargets(ctx) {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900357 for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
358 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
359 continue
360 }
361 ctx.AddFarVariationDependencies(t.Variations(), depTag, dep)
362 }
363 }
364}
365
Jeongik Cha54bf8752024-02-08 10:44:37 +0900366func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
Jiyong Parka574d532024-08-28 18:06:43 +0900367 // all packaging specs gathered from the dep.
368 var all []PackagingSpec
369 // list of module names overridden
370 var overridden []string
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900371
372 var arches []ArchType
Jiyong Parke6043782024-05-20 16:17:39 +0900373 for _, target := range getSupportedTargets(ctx) {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900374 arches = append(arches, target.Arch.ArchType)
375 }
376
377 // filter out packaging specs for unsupported architecture
378 filterArch := func(ps PackagingSpec) bool {
379 for _, arch := range arches {
380 if arch == ps.archType {
381 return true
382 }
383 }
384 return false
385 }
386
Jooyung Han092ef812021-03-10 15:40:34 +0900387 ctx.VisitDirectDeps(func(child Module) {
388 if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
389 return
Jiyong Parkdda8f692020-11-09 18:38:48 +0900390 }
Yu Liubad1eef2024-08-21 22:37:35 +0000391 for _, ps := range OtherModuleProviderOrDefault(
392 ctx, child, InstallFilesProvider).TransitivePackagingSpecs.ToList() {
Jiyong Parkc6a773d2024-05-14 21:49:11 +0900393 if !filterArch(ps) {
394 continue
395 }
396
Jeongik Cha54bf8752024-02-08 10:44:37 +0900397 if filter != nil {
398 if !filter(ps) {
399 continue
400 }
401 }
Jiyong Parka574d532024-08-28 18:06:43 +0900402 all = append(all, ps)
403 if ps.overrides != nil {
404 overridden = append(overridden, *ps.overrides...)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900405 }
406 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900407 })
Jiyong Parka574d532024-08-28 18:06:43 +0900408
409 // all minus packaging specs that are overridden
410 var filtered []PackagingSpec
411 for _, ps := range all {
412 if ps.owner != "" && InList(ps.owner, overridden) {
413 continue
414 }
415 filtered = append(filtered, ps)
416 }
417
418 m := make(map[string]PackagingSpec)
419 for _, ps := range filtered {
420 dstPath := ps.relPathInPackage
421 if existingPs, ok := m[dstPath]; ok {
422 if !existingPs.Equals(&ps) {
423 ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
424 }
425 continue
426 }
427 m[dstPath] = ps
428 }
Jooyung Handf09d172021-05-11 11:13:30 +0900429 return m
430}
Jiyong Parkdda8f692020-11-09 18:38:48 +0900431
Jeongik Cha54bf8752024-02-08 10:44:37 +0900432// See PackageModule.GatherPackagingSpecs
433func (p *PackagingBase) GatherPackagingSpecs(ctx ModuleContext) map[string]PackagingSpec {
434 return p.GatherPackagingSpecsWithFilter(ctx, nil)
435}
436
Dan Willemsen9fe14102021-07-13 21:52:04 -0700437// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
438// entries into the specified directory.
Peter Collingbourneff56c012023-03-15 22:24:03 -0700439func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
Inseob Kim33f95a92024-07-11 15:44:49 +0900440 dirsToSpecs := make(map[WritablePath]map[string]PackagingSpec)
441 dirsToSpecs[dir] = specs
442 return p.CopySpecsToDirs(ctx, builder, dirsToSpecs)
443}
444
445// CopySpecsToDirs is a helper that will add commands to the rule builder to copy the PackagingSpec
446// entries into corresponding directories.
447func (p *PackagingBase) CopySpecsToDirs(ctx ModuleContext, builder *RuleBuilder, dirsToSpecs map[WritablePath]map[string]PackagingSpec) (entries []string) {
448 empty := true
449 for _, specs := range dirsToSpecs {
450 if len(specs) > 0 {
451 empty = false
452 break
453 }
454 }
455 if empty {
Cole Faust3b3a0112024-01-03 15:16:55 -0800456 return entries
457 }
Inseob Kim33f95a92024-07-11 15:44:49 +0900458
Jiyong Parkdda8f692020-11-09 18:38:48 +0900459 seenDir := make(map[string]bool)
Jeongik Cha76e677f2023-12-21 16:39:15 +0900460 preparerPath := PathForModuleOut(ctx, "preparer.sh")
461 cmd := builder.Command().Tool(preparerPath)
462 var sb strings.Builder
Cole Faust3b3a0112024-01-03 15:16:55 -0800463 sb.WriteString("set -e\n")
Inseob Kim33f95a92024-07-11 15:44:49 +0900464
465 dirs := make([]WritablePath, 0, len(dirsToSpecs))
466 for dir, _ := range dirsToSpecs {
467 dirs = append(dirs, dir)
468 }
469 sort.Slice(dirs, func(i, j int) bool {
470 return dirs[i].String() < dirs[j].String()
471 })
472
473 for _, dir := range dirs {
474 specs := dirsToSpecs[dir]
475 for _, k := range SortedKeys(specs) {
476 ps := specs[k]
477 destPath := filepath.Join(dir.String(), ps.relPathInPackage)
478 destDir := filepath.Dir(destPath)
479 entries = append(entries, ps.relPathInPackage)
480 if _, ok := seenDir[destDir]; !ok {
481 seenDir[destDir] = true
482 sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
483 }
484 if ps.symlinkTarget == "" {
485 cmd.Implicit(ps.srcPath)
486 sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
487 } else {
488 sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
489 }
490 if ps.executable {
491 sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
492 }
Jiyong Parkdda8f692020-11-09 18:38:48 +0900493 }
494 }
495
Jeongik Cha76e677f2023-12-21 16:39:15 +0900496 WriteExecutableFileRuleVerbatim(ctx, preparerPath, sb.String())
497
Dan Willemsen9fe14102021-07-13 21:52:04 -0700498 return entries
499}
500
501// See PackageModule.CopyDepsToZip
Jooyung Hana8834282022-03-25 11:40:12 +0900502func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, specs map[string]PackagingSpec, zipOut WritablePath) (entries []string) {
Dan Willemsen9fe14102021-07-13 21:52:04 -0700503 builder := NewRuleBuilder(pctx, ctx)
504
505 dir := PathForModuleOut(ctx, ".zip")
506 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
507 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
Jooyung Hana8834282022-03-25 11:40:12 +0900508 entries = p.CopySpecsToDir(ctx, builder, specs, dir)
Dan Willemsen9fe14102021-07-13 21:52:04 -0700509
Jiyong Parkdda8f692020-11-09 18:38:48 +0900510 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800511 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900512 FlagWithOutput("-o ", zipOut).
513 FlagWithArg("-C ", dir.String()).
514 Flag("-L 0"). // no compression because this will be unzipped soon
515 FlagWithArg("-D ", dir.String())
516 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
517
Colin Crossf1a035e2020-11-16 17:32:30 -0800518 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900519 return entries
520}