blob: 36f619d3170491dbbbde06fa0fb9c4fb7fcd54a1 [file] [log] [blame]
Colin Crossfabb6082018-02-20 17:22:23 -08001// Copyright 2018 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 java
16
17import (
18 "android/soong/android"
Colin Cross42b96642018-04-26 13:14:15 -070019 "strings"
Colin Crossfabb6082018-02-20 17:22:23 -080020
21 "github.com/google/blueprint"
Colin Cross42b96642018-04-26 13:14:15 -070022 "github.com/google/blueprint/proptools"
Colin Crossfabb6082018-02-20 17:22:23 -080023)
24
Colin Cross42b96642018-04-26 13:14:15 -070025type AndroidLibraryDependency interface {
26 Dependency
27 ExportPackage() android.Path
28}
29
30func init() {
31 android.RegisterModuleType("android_library_import", AARImportFactory)
32 android.RegisterModuleType("android_library", AndroidLibraryFactory)
33}
34
35//
36// AAR (android library)
37//
38
39type androidLibraryProperties struct {
40 BuildAAR bool `blueprint:"mutated"`
41}
42
43type aaptProperties struct {
44 // flags passed to aapt when creating the apk
45 Aaptflags []string
46
47 // list of directories relative to the Blueprints file containing assets.
48 // Defaults to "assets"
49 Asset_dirs []string
50
51 // list of directories relative to the Blueprints file containing
52 // Android resources
53 Resource_dirs []string
54
55 // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml".
56 Manifest *string
57}
58
59type aapt struct {
60 aaptSrcJar android.Path
61 exportPackage android.Path
62 manifestPath android.Path
63 proguardOptionsFile android.Path
64 rroDirs android.Paths
65 rTxt android.Path
66
67 aaptProperties aaptProperties
68}
69
70func (a *aapt) ExportPackage() android.Path {
71 return a.exportPackage
72}
73
74func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkVersion string) (flags []string, deps android.Paths,
75 resDirs, overlayDirs []globbedResourceDir, overlayFiles, rroDirs android.Paths, manifestPath android.Path) {
76
77 hasVersionCode := false
78 hasVersionName := false
79 hasProduct := false
80 for _, f := range a.aaptProperties.Aaptflags {
81 if strings.HasPrefix(f, "--version-code") {
82 hasVersionCode = true
83 } else if strings.HasPrefix(f, "--version-name") {
84 hasVersionName = true
85 } else if strings.HasPrefix(f, "--product") {
86 hasProduct = true
87 }
88 }
89
90 var linkFlags []string
91
92 // Flags specified in Android.bp
93 linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
94
95 linkFlags = append(linkFlags, "--no-static-lib-packages")
96
97 // Find implicit or explicit asset and resource dirs
98 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
99 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
100
101 var linkDeps android.Paths
102
103 // Glob directories into lists of paths
104 for _, dir := range resourceDirs {
105 resDirs = append(resDirs, globbedResourceDir{
106 dir: dir,
107 files: androidResourceGlob(ctx, dir),
108 })
109 resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
110 overlayDirs = append(overlayDirs, resOverlayDirs...)
111 rroDirs = append(rroDirs, resRRODirs...)
112 }
113
114 var assetFiles android.Paths
115 for _, dir := range assetDirs {
116 assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
117 }
118
119 // App manifest file
120 manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
121 manifestPath = android.PathForModuleSrc(ctx, manifestFile)
122 linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
123 linkDeps = append(linkDeps, manifestPath)
124
125 linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
126 linkDeps = append(linkDeps, assetFiles...)
127
128 staticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
129
130 overlayFiles = append(overlayFiles, staticLibs...)
131 linkDeps = append(linkDeps, libDeps...)
132 linkFlags = append(linkFlags, libFlags...)
133
134 // SDK version flags
135 switch sdkVersion {
136 case "", "current", "system_current", "test_current":
137 sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
138 }
139
140 linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
141 linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
142
143 // Product characteristics
144 if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
145 linkFlags = append(linkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
146 }
147
148 // Product AAPT config
149 for _, aaptConfig := range ctx.Config().ProductAAPTConfig() {
150 linkFlags = append(linkFlags, "-c", aaptConfig)
151 }
152
153 // Product AAPT preferred config
154 if len(ctx.Config().ProductAAPTPreferredConfig()) > 0 {
155 linkFlags = append(linkFlags, "--preferred-density", ctx.Config().ProductAAPTPreferredConfig())
156 }
157
158 // Version code
159 if !hasVersionCode {
160 linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
161 }
162
163 if !hasVersionName {
164 var versionName string
165 if ctx.ModuleName() == "framework-res" {
166 // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the
167 // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
168 // if it contains the build number. Use the DefaultAppTargetSdk instead.
169 versionName = ctx.Config().DefaultAppTargetSdk()
170 } else {
171 versionName = ctx.Config().AppsDefaultVersionName()
172 }
173 versionName = proptools.NinjaEscape([]string{versionName})[0]
174 linkFlags = append(linkFlags, "--version-name ", versionName)
175 }
176
177 return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
178}
179
180func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkVersion string) {
181 if !ctx.Config().UnbundledBuild() {
182 sdkDep := decodeSdkDep(ctx, sdkVersion)
183 if sdkDep.frameworkResModule != "" {
184 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
185 }
186 }
187}
188
189func (a *aapt) buildActions(ctx android.ModuleContext, sdkVersion string, extraLinkFlags ...string) {
190 linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkVersion)
191
192 linkFlags = append(linkFlags, extraLinkFlags...)
193
194 packageRes := android.PathForModuleOut(ctx, "package-res.apk")
195 srcJar := android.PathForModuleGen(ctx, "R.jar")
196 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
197 rTxt := android.PathForModuleOut(ctx, "R.txt")
198
199 var compiledRes, compiledOverlay android.Paths
200 for _, dir := range resDirs {
201 compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
202 }
203 for _, dir := range overlayDirs {
204 compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
205 }
206
207 compiledOverlay = append(compiledOverlay, overlayFiles...)
208
209 aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
210 linkFlags, linkDeps, compiledRes, compiledOverlay)
211
212 a.aaptSrcJar = srcJar
213 a.exportPackage = packageRes
214 a.manifestPath = manifestPath
215 a.proguardOptionsFile = proguardOptionsFile
216 a.rroDirs = rroDirs
217 a.rTxt = rTxt
218}
219
220// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
221func aaptLibs(ctx android.ModuleContext, sdkVersion string) (staticLibs, deps android.Paths, flags []string) {
222 var sharedLibs android.Paths
223
224 sdkDep := decodeSdkDep(ctx, sdkVersion)
225 if sdkDep.useFiles {
226 sharedLibs = append(sharedLibs, sdkDep.jar)
227 }
228
229 ctx.VisitDirectDeps(func(module android.Module) {
230 var exportPackage android.Path
231 if aarDep, ok := module.(AndroidLibraryDependency); ok {
232 exportPackage = aarDep.ExportPackage()
233 }
234
235 switch ctx.OtherModuleDependencyTag(module) {
236 case libTag, frameworkResTag:
237 if exportPackage != nil {
238 sharedLibs = append(sharedLibs, exportPackage)
239 }
240 case staticLibTag:
241 if exportPackage != nil {
242 staticLibs = append(staticLibs, exportPackage)
243 }
244 }
245 })
246
247 deps = append(deps, sharedLibs...)
248 deps = append(deps, staticLibs...)
249
250 if len(staticLibs) > 0 {
251 flags = append(flags, "--auto-add-overlay")
252 }
253
254 for _, sharedLib := range sharedLibs {
255 flags = append(flags, "-I "+sharedLib.String())
256 }
257
258 return staticLibs, deps, flags
259}
260
261type AndroidLibrary struct {
262 Library
263 aapt
264
265 androidLibraryProperties androidLibraryProperties
266
267 aarFile android.WritablePath
268}
269
270var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
271
272func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
273 a.Module.deps(ctx)
274 if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
275 a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
276 }
277}
278
279func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
280 a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), "--static-lib")
281
282 ctx.CheckbuildFile(a.proguardOptionsFile)
283 ctx.CheckbuildFile(a.exportPackage)
284 ctx.CheckbuildFile(a.aaptSrcJar)
285
286 // apps manifests are handled by aapt, don't let Module see them
287 a.properties.Manifest = nil
288
289 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
290 a.proguardOptionsFile)
291
292 a.Module.compile(ctx, a.aaptSrcJar)
293
294 a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
295 var res android.Paths
296 if a.androidLibraryProperties.BuildAAR {
297 BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
298 ctx.CheckbuildFile(a.aarFile)
299 }
300}
301
302func AndroidLibraryFactory() android.Module {
303 module := &AndroidLibrary{}
304
305 module.AddProperties(
306 &module.Module.properties,
307 &module.Module.deviceProperties,
308 &module.Module.protoProperties,
309 &module.aaptProperties,
310 &module.androidLibraryProperties)
311
312 module.androidLibraryProperties.BuildAAR = true
313
314 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
315 return module
316}
317
Colin Crossfabb6082018-02-20 17:22:23 -0800318//
319// AAR (android library) prebuilts
320//
Colin Crossfabb6082018-02-20 17:22:23 -0800321
322type AARImportProperties struct {
323 Aars []string
324
325 Sdk_version *string
Colin Cross42b96642018-04-26 13:14:15 -0700326
327 Static_libs []string
328 Libs []string
Colin Crossfabb6082018-02-20 17:22:23 -0800329}
330
331type AARImport struct {
332 android.ModuleBase
333 prebuilt android.Prebuilt
334
335 properties AARImportProperties
336
337 classpathFile android.WritablePath
338 proguardFlags android.WritablePath
339 exportPackage android.WritablePath
340}
341
Colin Cross42b96642018-04-26 13:14:15 -0700342var _ AndroidLibraryDependency = (*AARImport)(nil)
343
344func (a *AARImport) ExportPackage() android.Path {
345 return a.exportPackage
346}
347
Colin Crossfabb6082018-02-20 17:22:23 -0800348func (a *AARImport) Prebuilt() *android.Prebuilt {
349 return &a.prebuilt
350}
351
352func (a *AARImport) Name() string {
353 return a.prebuilt.Name(a.ModuleBase.Name())
354}
355
356func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
Colin Crossfabb6082018-02-20 17:22:23 -0800357 if !ctx.Config().UnbundledBuild() {
Colin Cross42b96642018-04-26 13:14:15 -0700358 sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
359 if sdkDep.useModule && sdkDep.frameworkResModule != "" {
360 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
Colin Crossfabb6082018-02-20 17:22:23 -0800361 }
362 }
Colin Cross42b96642018-04-26 13:14:15 -0700363
364 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Libs...)
365 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800366}
367
368// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
369// touched to create an empty file, and any directories in $expectedDirs will be created.
370var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
371 blueprint.RuleParams{
372 Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
373 `unzip -qo -d $outDir $in && touch $out`,
374 },
375 "expectedDirs", "outDir")
376
377func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
378 if len(a.properties.Aars) != 1 {
379 ctx.PropertyErrorf("aars", "exactly one aar is required")
380 return
381 }
382
383 aar := android.PathForModuleSrc(ctx, a.properties.Aars[0])
384
385 extractedAARDir := android.PathForModuleOut(ctx, "aar")
386 extractedResDir := extractedAARDir.Join(ctx, "res")
387 a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
388 a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
389 manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")
390
391 ctx.Build(pctx, android.BuildParams{
392 Rule: unzipAAR,
393 Input: aar,
394 Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, manifest},
395 Description: "unzip AAR",
396 Args: map[string]string{
397 "expectedDirs": extractedResDir.String(),
398 "outDir": extractedAARDir.String(),
399 },
400 })
401
402 compiledResDir := android.PathForModuleOut(ctx, "flat-res")
403 aaptCompileDeps := android.Paths{a.classpathFile}
404 aaptCompileDirs := android.Paths{extractedResDir}
405 flata := compiledResDir.Join(ctx, "gen_res.flata")
406 aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)
407
408 a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
409 srcJar := android.PathForModuleGen(ctx, "R.jar")
410 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
Colin Cross42b96642018-04-26 13:14:15 -0700411 rTxt := android.PathForModuleOut(ctx, "R.txt")
Colin Crossfabb6082018-02-20 17:22:23 -0800412
413 var linkDeps android.Paths
414
415 linkFlags := []string{
416 "--static-lib",
417 "--no-static-lib-packages",
418 "--auto-add-overlay",
419 }
420
421 linkFlags = append(linkFlags, "--manifest "+manifest.String())
422 linkDeps = append(linkDeps, manifest)
423
Colin Cross42b96642018-04-26 13:14:15 -0700424 staticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
Colin Crossfabb6082018-02-20 17:22:23 -0800425
Colin Cross42b96642018-04-26 13:14:15 -0700426 linkDeps = append(linkDeps, libDeps...)
427 linkFlags = append(linkFlags, libFlags...)
Colin Crossfabb6082018-02-20 17:22:23 -0800428
Colin Cross42b96642018-04-26 13:14:15 -0700429 overlayRes := append(android.Paths{flata}, staticLibs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800430
Colin Cross42b96642018-04-26 13:14:15 -0700431 aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt,
432 linkFlags, linkDeps, nil, overlayRes)
Colin Crossfabb6082018-02-20 17:22:23 -0800433}
434
435var _ Dependency = (*AARImport)(nil)
436
437func (a *AARImport) HeaderJars() android.Paths {
438 return android.Paths{a.classpathFile}
439}
440
441func (a *AARImport) ImplementationJars() android.Paths {
442 return android.Paths{a.classpathFile}
443}
444
445func (a *AARImport) AidlIncludeDirs() android.Paths {
446 return nil
447}
448
449var _ android.PrebuiltInterface = (*Import)(nil)
450
451func AARImportFactory() android.Module {
452 module := &AARImport{}
453
454 module.AddProperties(&module.properties)
455
456 android.InitPrebuiltModule(module, &module.properties.Aars)
457 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
458 return module
459}