blob: 57c752c6ef9a068256ade1ecf88b3032a4e9d046 [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 Crossa97c5d32018-03-28 14:58:31 -070019 "strings"
Colin Crossfabb6082018-02-20 17:22:23 -080020
21 "github.com/google/blueprint"
Colin Crossa97c5d32018-03-28 14:58:31 -070022 "github.com/google/blueprint/proptools"
Colin Crossfabb6082018-02-20 17:22:23 -080023)
24
Colin Crossa97c5d32018-03-28 14:58:31 -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().AppsDefaultVersionName()})[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 versionName := proptools.NinjaEscape([]string{ctx.Config().AppsDefaultVersionName()})[0]
165 linkFlags = append(linkFlags, "--version-name ", versionName)
166 }
167
168 return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
169}
170
171func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkVersion string) {
172 if !ctx.Config().UnbundledBuild() {
173 sdkDep := decodeSdkDep(ctx, sdkVersion)
174 if sdkDep.frameworkResModule != "" {
175 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
176 }
177 }
178}
179
180func (a *aapt) buildActions(ctx android.ModuleContext, sdkVersion string, extraLinkFlags ...string) {
181 linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkVersion)
182
183 linkFlags = append(linkFlags, extraLinkFlags...)
184
185 packageRes := android.PathForModuleOut(ctx, "package-res.apk")
186 srcJar := android.PathForModuleGen(ctx, "R.jar")
187 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
188 rTxt := android.PathForModuleOut(ctx, "R.txt")
189
190 var compiledRes, compiledOverlay android.Paths
191 for _, dir := range resDirs {
192 compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
193 }
194 for _, dir := range overlayDirs {
195 compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
196 }
197
198 compiledOverlay = append(compiledOverlay, overlayFiles...)
199
200 aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
201 linkFlags, linkDeps, compiledRes, compiledOverlay)
202
203 a.aaptSrcJar = srcJar
204 a.exportPackage = packageRes
205 a.manifestPath = manifestPath
206 a.proguardOptionsFile = proguardOptionsFile
207 a.rroDirs = rroDirs
208 a.rTxt = rTxt
209}
210
211// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
212func aaptLibs(ctx android.ModuleContext, sdkVersion string) (staticLibs, deps android.Paths, flags []string) {
213 var sharedLibs android.Paths
214
215 sdkDep := decodeSdkDep(ctx, sdkVersion)
216 if sdkDep.useFiles {
217 sharedLibs = append(sharedLibs, sdkDep.jar)
218 }
219
220 ctx.VisitDirectDeps(func(module android.Module) {
221 var exportPackage android.Path
222 if aarDep, ok := module.(AndroidLibraryDependency); ok {
223 exportPackage = aarDep.ExportPackage()
224 }
225
226 switch ctx.OtherModuleDependencyTag(module) {
227 case libTag, frameworkResTag:
228 if exportPackage != nil {
229 sharedLibs = append(sharedLibs, exportPackage)
230 }
231 case staticLibTag:
232 if exportPackage != nil {
233 staticLibs = append(staticLibs, exportPackage)
234 }
235 }
236 })
237
238 deps = append(deps, sharedLibs...)
239 deps = append(deps, staticLibs...)
240
241 if len(staticLibs) > 0 {
242 flags = append(flags, "--auto-add-overlay")
243 }
244
245 for _, sharedLib := range sharedLibs {
246 flags = append(flags, "-I "+sharedLib.String())
247 }
248
249 return staticLibs, deps, flags
250}
251
252type AndroidLibrary struct {
253 Library
254 aapt
255
256 androidLibraryProperties androidLibraryProperties
257
258 aarFile android.WritablePath
259}
260
261var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
262
263func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
264 a.Module.deps(ctx)
265 if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
266 a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
267 }
268}
269
270func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
271 a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), "--static-lib")
272
273 ctx.CheckbuildFile(a.proguardOptionsFile)
274 ctx.CheckbuildFile(a.exportPackage)
275 ctx.CheckbuildFile(a.aaptSrcJar)
276
277 // apps manifests are handled by aapt, don't let Module see them
278 a.properties.Manifest = nil
279
280 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
281 a.proguardOptionsFile)
282
283 a.Module.compile(ctx, a.aaptSrcJar)
284
285 a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
286 var res android.Paths
287 if a.androidLibraryProperties.BuildAAR {
288 BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
289 ctx.CheckbuildFile(a.aarFile)
290 }
291}
292
293func AndroidLibraryFactory() android.Module {
294 module := &AndroidLibrary{}
295
296 module.AddProperties(
297 &module.Module.properties,
298 &module.Module.deviceProperties,
299 &module.Module.protoProperties,
300 &module.aaptProperties,
301 &module.androidLibraryProperties)
302
303 module.androidLibraryProperties.BuildAAR = true
304
305 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
306 return module
307}
308
Colin Crossfabb6082018-02-20 17:22:23 -0800309//
310// AAR (android library) prebuilts
311//
Colin Crossfabb6082018-02-20 17:22:23 -0800312
313type AARImportProperties struct {
314 Aars []string
315
316 Sdk_version *string
Colin Crossa97c5d32018-03-28 14:58:31 -0700317
318 Static_libs []string
319 Libs []string
Colin Crossfabb6082018-02-20 17:22:23 -0800320}
321
322type AARImport struct {
323 android.ModuleBase
324 prebuilt android.Prebuilt
325
326 properties AARImportProperties
327
328 classpathFile android.WritablePath
329 proguardFlags android.WritablePath
330 exportPackage android.WritablePath
331}
332
Colin Crossa97c5d32018-03-28 14:58:31 -0700333var _ AndroidLibraryDependency = (*AARImport)(nil)
334
335func (a *AARImport) ExportPackage() android.Path {
336 return a.exportPackage
337}
338
Colin Crossfabb6082018-02-20 17:22:23 -0800339func (a *AARImport) Prebuilt() *android.Prebuilt {
340 return &a.prebuilt
341}
342
343func (a *AARImport) Name() string {
344 return a.prebuilt.Name(a.ModuleBase.Name())
345}
346
347func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
Colin Crossfabb6082018-02-20 17:22:23 -0800348 if !ctx.Config().UnbundledBuild() {
Colin Crossa97c5d32018-03-28 14:58:31 -0700349 sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
350 if sdkDep.useModule && sdkDep.frameworkResModule != "" {
351 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
Colin Crossfabb6082018-02-20 17:22:23 -0800352 }
353 }
Colin Crossa97c5d32018-03-28 14:58:31 -0700354
355 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Libs...)
356 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800357}
358
359// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
360// touched to create an empty file, and any directories in $expectedDirs will be created.
361var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
362 blueprint.RuleParams{
363 Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
364 `unzip -qo -d $outDir $in && touch $out`,
365 },
366 "expectedDirs", "outDir")
367
368func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
369 if len(a.properties.Aars) != 1 {
370 ctx.PropertyErrorf("aars", "exactly one aar is required")
371 return
372 }
373
374 aar := android.PathForModuleSrc(ctx, a.properties.Aars[0])
375
376 extractedAARDir := android.PathForModuleOut(ctx, "aar")
377 extractedResDir := extractedAARDir.Join(ctx, "res")
378 a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
379 a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
380 manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")
381
382 ctx.Build(pctx, android.BuildParams{
383 Rule: unzipAAR,
384 Input: aar,
385 Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, manifest},
386 Description: "unzip AAR",
387 Args: map[string]string{
388 "expectedDirs": extractedResDir.String(),
389 "outDir": extractedAARDir.String(),
390 },
391 })
392
393 compiledResDir := android.PathForModuleOut(ctx, "flat-res")
394 aaptCompileDeps := android.Paths{a.classpathFile}
395 aaptCompileDirs := android.Paths{extractedResDir}
396 flata := compiledResDir.Join(ctx, "gen_res.flata")
397 aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)
398
399 a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
400 srcJar := android.PathForModuleGen(ctx, "R.jar")
401 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
Colin Crossa97c5d32018-03-28 14:58:31 -0700402 rTxt := android.PathForModuleOut(ctx, "R.txt")
Colin Crossfabb6082018-02-20 17:22:23 -0800403
404 var linkDeps android.Paths
405
406 linkFlags := []string{
407 "--static-lib",
408 "--no-static-lib-packages",
409 "--auto-add-overlay",
410 }
411
412 linkFlags = append(linkFlags, "--manifest "+manifest.String())
413 linkDeps = append(linkDeps, manifest)
414
Colin Crossa97c5d32018-03-28 14:58:31 -0700415 staticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
Colin Crossfabb6082018-02-20 17:22:23 -0800416
Colin Crossa97c5d32018-03-28 14:58:31 -0700417 linkDeps = append(linkDeps, libDeps...)
418 linkFlags = append(linkFlags, libFlags...)
Colin Crossfabb6082018-02-20 17:22:23 -0800419
Colin Crossa97c5d32018-03-28 14:58:31 -0700420 overlayRes := append(android.Paths{flata}, staticLibs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800421
Colin Crossa97c5d32018-03-28 14:58:31 -0700422 aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt,
423 linkFlags, linkDeps, nil, overlayRes)
Colin Crossfabb6082018-02-20 17:22:23 -0800424}
425
426var _ Dependency = (*AARImport)(nil)
427
428func (a *AARImport) HeaderJars() android.Paths {
429 return android.Paths{a.classpathFile}
430}
431
432func (a *AARImport) ImplementationJars() android.Paths {
433 return android.Paths{a.classpathFile}
434}
435
436func (a *AARImport) AidlIncludeDirs() android.Paths {
437 return nil
438}
439
440var _ android.PrebuiltInterface = (*Import)(nil)
441
442func AARImportFactory() android.Module {
443 module := &AARImport{}
444
445 module.AddProperties(&module.properties)
446
447 android.InitPrebuiltModule(module, &module.properties.Aars)
448 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
449 return module
450}