blob: 03266c55e864b00978794c0c117ea05c33a2741c [file] [log] [blame]
Jiyong Park09d77522019-11-18 11:16:27 +09001// Copyright (C) 2019 The Android Open Source Project
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 apex
16
17import (
18 "fmt"
Jaewoong Jungfa00c062020-05-14 14:15:24 -070019 "strconv"
Jiyong Park09d77522019-11-18 11:16:27 +090020 "strings"
21
22 "android/soong/android"
Jaewoong Jungfa00c062020-05-14 14:15:24 -070023 "android/soong/java"
24 "github.com/google/blueprint"
Jiyong Park09d77522019-11-18 11:16:27 +090025
26 "github.com/google/blueprint/proptools"
27)
28
Jaewoong Jungfa00c062020-05-14 14:15:24 -070029var (
30 extractMatchingApex = pctx.StaticRule(
31 "extractMatchingApex",
32 blueprint.RuleParams{
33 Command: `rm -rf "$out" && ` +
34 `${extract_apks} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
35 `-sdk-version=${sdk-version} -abis=${abis} -screen-densities=all -extract-single ` +
36 `${in}`,
37 CommandDeps: []string{"${extract_apks}"},
38 },
39 "abis", "allow-prereleased", "sdk-version")
40)
41
Jiyong Park09d77522019-11-18 11:16:27 +090042type Prebuilt struct {
43 android.ModuleBase
44 prebuilt android.Prebuilt
45
46 properties PrebuiltProperties
47
48 inputApex android.Path
49 installDir android.InstallPath
50 installFilename string
51 outputApex android.WritablePath
Jooyung Han002ab682020-01-08 01:57:58 +090052
53 // list of commands to create symlinks for backward compatibility.
54 // these commands will be attached as LOCAL_POST_INSTALL_CMD
55 compatSymlinks []string
Jiyong Park09d77522019-11-18 11:16:27 +090056}
57
58type PrebuiltProperties struct {
59 // the path to the prebuilt .apex file to import.
60 Source string `blueprint:"mutated"`
61 ForceDisable bool `blueprint:"mutated"`
62
63 Src *string
64 Arch struct {
65 Arm struct {
66 Src *string
67 }
68 Arm64 struct {
69 Src *string
70 }
71 X86 struct {
72 Src *string
73 }
74 X86_64 struct {
75 Src *string
76 }
77 }
78
79 Installable *bool
80 // Optional name for the installed apex. If unspecified, name of the
81 // module is used as the file name
82 Filename *string
83
84 // Names of modules to be overridden. Listed modules can only be other binaries
85 // (in Make or Soong).
86 // This does not completely prevent installation of the overridden binaries, but if both
87 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
88 // from PRODUCT_PACKAGES.
89 Overrides []string
90}
91
92func (p *Prebuilt) installable() bool {
93 return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
94}
95
96func (p *Prebuilt) isForceDisabled() bool {
97 return p.properties.ForceDisable
98}
99
100func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) {
101 switch tag {
102 case "":
103 return android.Paths{p.outputApex}, nil
104 default:
105 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
106 }
107}
108
109func (p *Prebuilt) InstallFilename() string {
110 return proptools.StringDefault(p.properties.Filename, p.BaseModuleName()+imageApexSuffix)
111}
112
113func (p *Prebuilt) Prebuilt() *android.Prebuilt {
114 return &p.prebuilt
115}
116
117func (p *Prebuilt) Name() string {
118 return p.prebuilt.Name(p.ModuleBase.Name())
119}
120
121// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
122func PrebuiltFactory() android.Module {
123 module := &Prebuilt{}
124 module.AddProperties(&module.properties)
125 android.InitSingleSourcePrebuiltModule(module, &module.properties, "Source")
126 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
127 return module
128}
129
130func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
131 // If the device is configured to use flattened APEX, force disable the prebuilt because
132 // the prebuilt is a non-flattened one.
133 forceDisable := ctx.Config().FlattenApex()
134
135 // Force disable the prebuilts when we are doing unbundled build. We do unbundled build
136 // to build the prebuilts themselves.
137 forceDisable = forceDisable || ctx.Config().UnbundledBuild()
138
139 // Force disable the prebuilts when coverage is enabled.
140 forceDisable = forceDisable || ctx.DeviceConfig().NativeCoverageEnabled()
141 forceDisable = forceDisable || ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
142
143 // b/137216042 don't use prebuilts when address sanitizer is on
144 forceDisable = forceDisable || android.InList("address", ctx.Config().SanitizeDevice()) ||
145 android.InList("hwaddress", ctx.Config().SanitizeDevice())
146
147 if forceDisable && p.prebuilt.SourceExists() {
148 p.properties.ForceDisable = true
149 return
150 }
151
152 // This is called before prebuilt_select and prebuilt_postdeps mutators
153 // The mutators requires that src to be set correctly for each arch so that
154 // arch variants are disabled when src is not provided for the arch.
155 if len(ctx.MultiTargets()) != 1 {
156 ctx.ModuleErrorf("compile_multilib shouldn't be \"both\" for prebuilt_apex")
157 return
158 }
159 var src string
160 switch ctx.MultiTargets()[0].Arch.ArchType {
161 case android.Arm:
162 src = String(p.properties.Arch.Arm.Src)
163 case android.Arm64:
164 src = String(p.properties.Arch.Arm64.Src)
165 case android.X86:
166 src = String(p.properties.Arch.X86.Src)
167 case android.X86_64:
168 src = String(p.properties.Arch.X86_64.Src)
169 default:
170 ctx.ModuleErrorf("prebuilt_apex does not support %q", ctx.MultiTargets()[0].Arch.String())
171 return
172 }
173 if src == "" {
174 src = String(p.properties.Src)
175 }
176 p.properties.Source = src
177}
178
179func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
180 if p.properties.ForceDisable {
181 return
182 }
183
184 // TODO(jungjw): Check the key validity.
185 p.inputApex = p.Prebuilt().SingleSourcePath(ctx)
186 p.installDir = android.PathForModuleInstall(ctx, "apex")
187 p.installFilename = p.InstallFilename()
188 if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
189 ctx.ModuleErrorf("filename should end in %s for prebuilt_apex", imageApexSuffix)
190 }
191 p.outputApex = android.PathForModuleOut(ctx, p.installFilename)
192 ctx.Build(pctx, android.BuildParams{
193 Rule: android.Cp,
194 Input: p.inputApex,
195 Output: p.outputApex,
196 })
197 if p.installable() {
198 ctx.InstallFile(p.installDir, p.installFilename, p.inputApex)
199 }
200
Jooyung Han002ab682020-01-08 01:57:58 +0900201 // in case that prebuilt_apex replaces source apex (using prefer: prop)
202 p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx)
203 // or that prebuilt_apex overrides other apexes (using overrides: prop)
204 for _, overridden := range p.properties.Overrides {
205 p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
206 }
Jiyong Park09d77522019-11-18 11:16:27 +0900207}
208
Jiyong Park0b0e1b92019-12-03 13:24:29 +0900209func (p *Prebuilt) AndroidMkEntries() []android.AndroidMkEntries {
210 return []android.AndroidMkEntries{android.AndroidMkEntries{
Jiyong Park09d77522019-11-18 11:16:27 +0900211 Class: "ETC",
212 OutputFile: android.OptionalPathForPath(p.inputApex),
213 Include: "$(BUILD_PREBUILT)",
214 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
215 func(entries *android.AndroidMkEntries) {
216 entries.SetString("LOCAL_MODULE_PATH", p.installDir.ToMakePath().String())
217 entries.SetString("LOCAL_MODULE_STEM", p.installFilename)
218 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
219 entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.properties.Overrides...)
Jooyung Han002ab682020-01-08 01:57:58 +0900220 if len(p.compatSymlinks) > 0 {
221 entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(p.compatSymlinks, " && "))
222 }
Jiyong Park09d77522019-11-18 11:16:27 +0900223 },
224 },
Jiyong Park0b0e1b92019-12-03 13:24:29 +0900225 }}
Jiyong Park09d77522019-11-18 11:16:27 +0900226}
Jaewoong Jungfa00c062020-05-14 14:15:24 -0700227
228type ApexSet struct {
229 android.ModuleBase
230 prebuilt android.Prebuilt
231
232 properties ApexSetProperties
233
234 installDir android.InstallPath
235 installFilename string
236 outputApex android.WritablePath
237
238 // list of commands to create symlinks for backward compatibility.
239 // these commands will be attached as LOCAL_POST_INSTALL_CMD
240 compatSymlinks []string
241}
242
243type ApexSetProperties struct {
244 // the .apks file path that contains prebuilt apex files to be extracted.
245 Set *string
246
247 // whether the extracted apex file installable.
248 Installable *bool
249
250 // optional name for the installed apex. If unspecified, name of the
251 // module is used as the file name
252 Filename *string
253
254 // names of modules to be overridden. Listed modules can only be other binaries
255 // (in Make or Soong).
256 // This does not completely prevent installation of the overridden binaries, but if both
257 // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
258 // from PRODUCT_PACKAGES.
259 Overrides []string
260
261 // apexes in this set use prerelease SDK version
262 Prerelease *bool
263}
264
265func (a *ApexSet) installable() bool {
266 return a.properties.Installable == nil || proptools.Bool(a.properties.Installable)
267}
268
269func (a *ApexSet) InstallFilename() string {
270 return proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+imageApexSuffix)
271}
272
273func (a *ApexSet) Prebuilt() *android.Prebuilt {
274 return &a.prebuilt
275}
276
277func (a *ApexSet) Name() string {
278 return a.prebuilt.Name(a.ModuleBase.Name())
279}
280
281// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
282func apexSetFactory() android.Module {
283 module := &ApexSet{}
284 module.AddProperties(&module.properties)
285 android.InitSingleSourcePrebuiltModule(module, &module.properties, "Set")
286 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
287 return module
288}
289
290func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
291 a.installFilename = a.InstallFilename()
292 if !strings.HasSuffix(a.installFilename, imageApexSuffix) {
293 ctx.ModuleErrorf("filename should end in %s for apex_set", imageApexSuffix)
294 }
295
296 apexSet := a.prebuilt.SingleSourcePath(ctx)
297 a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
298 ctx.Build(pctx,
299 android.BuildParams{
300 Rule: extractMatchingApex,
301 Description: "Extract an apex from an apex set",
302 Inputs: android.Paths{apexSet},
303 Output: a.outputApex,
304 Args: map[string]string{
305 "abis": strings.Join(java.SupportedAbis(ctx), ","),
306 "allow-prereleased": strconv.FormatBool(proptools.Bool(a.properties.Prerelease)),
307 "sdk-version": ctx.Config().PlatformSdkVersion(),
308 },
309 })
310 a.installDir = android.PathForModuleInstall(ctx, "apex")
311 if a.installable() {
312 ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
313 }
314
315 // in case that apex_set replaces source apex (using prefer: prop)
316 a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
317 // or that apex_set overrides other apexes (using overrides: prop)
318 for _, overridden := range a.properties.Overrides {
319 a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...)
320 }
321}
322
323func (a *ApexSet) AndroidMkEntries() []android.AndroidMkEntries {
324 return []android.AndroidMkEntries{android.AndroidMkEntries{
325 Class: "ETC",
326 OutputFile: android.OptionalPathForPath(a.outputApex),
327 Include: "$(BUILD_PREBUILT)",
328 ExtraEntries: []android.AndroidMkExtraEntriesFunc{
329 func(entries *android.AndroidMkEntries) {
330 entries.SetString("LOCAL_MODULE_PATH", a.installDir.ToMakePath().String())
331 entries.SetString("LOCAL_MODULE_STEM", a.installFilename)
332 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !a.installable())
333 entries.AddStrings("LOCAL_OVERRIDES_MODULES", a.properties.Overrides...)
334 if len(a.compatSymlinks) > 0 {
335 entries.SetString("LOCAL_POST_INSTALL_CMD", strings.Join(a.compatSymlinks, " && "))
336 }
337 },
338 },
339 }}
340}