blob: 77554016b030eef462b7ea51f35e2143c959cda5 [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"
20
21 "github.com/google/blueprint"
22)
23
Jiyong Parkcc1157c2020-11-25 11:31:13 +090024// PackagingSpec abstracts a request to place a built artifact at a certain path in a package. A
25// package can be the traditional <partition>.img, but isn't limited to those. Other examples could
26// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS
27// running on a VM), or a zip archive for some of the host tools.
Jiyong Park073ea552020-11-09 14:08:34 +090028type PackagingSpec struct {
29 // Path relative to the root of the package
30 relPathInPackage string
31
32 // The path to the built artifact
33 srcPath Path
34
35 // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
36 // srcPath is of course ignored.)
37 symlinkTarget string
38
39 // Whether relPathInPackage should be marked as executable or not
40 executable bool
41}
Jiyong Parkdda8f692020-11-09 18:38:48 +090042
43type PackageModule interface {
44 Module
45 packagingBase() *PackagingBase
46
47 // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
Jiyong Park65b62242020-11-25 12:44:59 +090048 // When adding the dependencies, depTag is used as the tag.
49 AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag)
Jiyong Parkdda8f692020-11-09 18:38:48 +090050
51 // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
Jiyong Parkcc1157c2020-11-25 11:31:13 +090052 // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
Jiyong Parkdda8f692020-11-09 18:38:48 +090053 // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
54 // etc.) from the extracted files
55 CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) []string
56}
57
58// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
59// include this struct and call InitPackageModule.
60type PackagingBase struct {
61 properties PackagingProperties
62
Jiyong Parkcc1157c2020-11-25 11:31:13 +090063 // Allows this module to skip missing dependencies. In most cases, this is not required, but
64 // for rare cases like when there's a dependency to a module which exists in certain repo
65 // checkouts, this is needed.
Jiyong Parkdda8f692020-11-09 18:38:48 +090066 IgnoreMissingDependencies bool
67}
68
69type depsProperty struct {
70 // Modules to include in this package
71 Deps []string `android:"arch_variant"`
72}
73
74type packagingMultilibProperties struct {
75 First depsProperty `android:"arch_variant"`
76 Common depsProperty `android:"arch_variant"`
77 Lib32 depsProperty `android:"arch_variant"`
78 Lib64 depsProperty `android:"arch_variant"`
79}
80
81type PackagingProperties struct {
82 Deps []string `android:"arch_variant"`
83 Multilib packagingMultilibProperties `android:"arch_variant"`
84}
85
Jiyong Parkdda8f692020-11-09 18:38:48 +090086func InitPackageModule(p PackageModule) {
87 base := p.packagingBase()
88 p.AddProperties(&base.properties)
89}
90
91func (p *PackagingBase) packagingBase() *PackagingBase {
92 return p
93}
94
Jiyong Parkcc1157c2020-11-25 11:31:13 +090095// From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
96// the current archicture when this module is not configured for multi target. When configured for
97// multi target, deps is selected for each of the targets and is NOT selected for the current
98// architecture which would be Common.
Jiyong Parkdda8f692020-11-09 18:38:48 +090099func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
100 var ret []string
101 if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
102 ret = append(ret, p.properties.Deps...)
103 } else if arch.Multilib == "lib32" {
104 ret = append(ret, p.properties.Multilib.Lib32.Deps...)
105 } else if arch.Multilib == "lib64" {
106 ret = append(ret, p.properties.Multilib.Lib64.Deps...)
107 } else if arch == Common {
108 ret = append(ret, p.properties.Multilib.Common.Deps...)
109 }
110 for i, t := range ctx.MultiTargets() {
111 if t.Arch.ArchType == arch {
112 ret = append(ret, p.properties.Deps...)
113 if i == 0 {
114 ret = append(ret, p.properties.Multilib.First.Deps...)
115 }
116 }
117 }
118 return FirstUniqueStrings(ret)
119}
120
121func (p *PackagingBase) getSupportedTargets(ctx BaseModuleContext) []Target {
122 var ret []Target
123 // The current and the common OS targets are always supported
124 ret = append(ret, ctx.Target())
125 if ctx.Arch().ArchType != Common {
126 ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
127 }
128 // If this module is configured for multi targets, those should be supported as well
129 ret = append(ret, ctx.MultiTargets()...)
130 return ret
131}
132
133// See PackageModule.AddDeps
Jiyong Park65b62242020-11-25 12:44:59 +0900134func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
Jiyong Parkdda8f692020-11-09 18:38:48 +0900135 for _, t := range p.getSupportedTargets(ctx) {
136 for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
137 if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
138 continue
139 }
140 ctx.AddFarVariationDependencies(t.Variations(), depTag, dep)
141 }
142 }
143}
144
145// See PackageModule.CopyDepsToZip
146func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) (entries []string) {
147 var supportedArches []string
148 for _, t := range p.getSupportedTargets(ctx) {
149 supportedArches = append(supportedArches, t.Arch.ArchType.String())
150 }
151 m := make(map[string]PackagingSpec)
152 ctx.WalkDeps(func(child Module, parent Module) bool {
153 // Don't track modules with unsupported arch
154 // TODO(jiyong): remove this when aosp/1501613 lands.
155 if !InList(child.Target().Arch.ArchType.String(), supportedArches) {
156 return false
157 }
158 for _, ps := range child.PackagingSpecs() {
159 if _, ok := m[ps.relPathInPackage]; !ok {
160 m[ps.relPathInPackage] = ps
161 }
162 }
163 return true
164 })
165
Colin Crossf1a035e2020-11-16 17:32:30 -0800166 builder := NewRuleBuilder(pctx, ctx)
Jiyong Parkdda8f692020-11-09 18:38:48 +0900167
168 dir := PathForModuleOut(ctx, ".zip").OutputPath
169 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
170 builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
171
172 seenDir := make(map[string]bool)
173 for _, k := range SortedStringKeys(m) {
174 ps := m[k]
175 destPath := dir.Join(ctx, ps.relPathInPackage).String()
176 destDir := filepath.Dir(destPath)
177 entries = append(entries, ps.relPathInPackage)
178 if _, ok := seenDir[destDir]; !ok {
179 seenDir[destDir] = true
180 builder.Command().Text("mkdir").Flag("-p").Text(destDir)
181 }
182 if ps.symlinkTarget == "" {
183 builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
184 } else {
185 builder.Command().Text("ln").Flag("-sf").Text(ps.symlinkTarget).Text(destPath)
186 }
187 if ps.executable {
188 builder.Command().Text("chmod").Flag("a+x").Text(destPath)
189 }
190 }
191
192 builder.Command().
Colin Crossf1a035e2020-11-16 17:32:30 -0800193 BuiltTool("soong_zip").
Jiyong Parkdda8f692020-11-09 18:38:48 +0900194 FlagWithOutput("-o ", zipOut).
195 FlagWithArg("-C ", dir.String()).
196 Flag("-L 0"). // no compression because this will be unzipped soon
197 FlagWithArg("-D ", dir.String())
198 builder.Command().Text("rm").Flag("-rf").Text(dir.String())
199
Colin Crossf1a035e2020-11-16 17:32:30 -0800200 builder.Build("zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
Jiyong Parkdda8f692020-11-09 18:38:48 +0900201 return entries
202}