blob: 16d82af4535dd8b7a62bf4c7311c8eeb75eaf8aa [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
Colin Crossa97c5d32018-03-28 14:58:31 -070079 for _, f := range a.aaptProperties.Aaptflags {
80 if strings.HasPrefix(f, "--version-code") {
81 hasVersionCode = true
82 } else if strings.HasPrefix(f, "--version-name") {
83 hasVersionName = true
Colin Crossa97c5d32018-03-28 14:58:31 -070084 }
85 }
86
87 var linkFlags []string
88
89 // Flags specified in Android.bp
90 linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
91
92 linkFlags = append(linkFlags, "--no-static-lib-packages")
93
94 // Find implicit or explicit asset and resource dirs
95 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
96 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
97
98 var linkDeps android.Paths
99
100 // Glob directories into lists of paths
101 for _, dir := range resourceDirs {
102 resDirs = append(resDirs, globbedResourceDir{
103 dir: dir,
104 files: androidResourceGlob(ctx, dir),
105 })
106 resOverlayDirs, resRRODirs := overlayResourceGlob(ctx, dir)
107 overlayDirs = append(overlayDirs, resOverlayDirs...)
108 rroDirs = append(rroDirs, resRRODirs...)
109 }
110
111 var assetFiles android.Paths
112 for _, dir := range assetDirs {
113 assetFiles = append(assetFiles, androidResourceGlob(ctx, dir)...)
114 }
115
116 // App manifest file
117 manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
118 manifestPath = android.PathForModuleSrc(ctx, manifestFile)
119 linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
120 linkDeps = append(linkDeps, manifestPath)
121
122 linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
123 linkDeps = append(linkDeps, assetFiles...)
124
125 staticLibs, libDeps, libFlags := aaptLibs(ctx, sdkVersion)
126
127 overlayFiles = append(overlayFiles, staticLibs...)
128 linkDeps = append(linkDeps, libDeps...)
129 linkFlags = append(linkFlags, libFlags...)
130
131 // SDK version flags
132 switch sdkVersion {
133 case "", "current", "system_current", "test_current":
Colin Crossd09b0b62018-04-18 11:06:47 -0700134 sdkVersion = proptools.NinjaEscape([]string{ctx.Config().DefaultAppTargetSdk()})[0]
Colin Crossa97c5d32018-03-28 14:58:31 -0700135 }
136
137 linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
138 linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
139
Colin Crossa97c5d32018-03-28 14:58:31 -0700140 // Version code
141 if !hasVersionCode {
142 linkFlags = append(linkFlags, "--version-code", ctx.Config().PlatformSdkVersion())
143 }
144
145 if !hasVersionName {
Colin Cross402d5e02018-04-25 14:54:06 -0700146 var versionName string
147 if ctx.ModuleName() == "framework-res" {
148 // Some builds set AppsDefaultVersionName() to include the build number ("O-123456"). aapt2 copies the
149 // version name of framework-res into app manifests as compileSdkVersionCodename, which confuses things
150 // if it contains the build number. Use the DefaultAppTargetSdk instead.
151 versionName = ctx.Config().DefaultAppTargetSdk()
152 } else {
153 versionName = ctx.Config().AppsDefaultVersionName()
154 }
155 versionName = proptools.NinjaEscape([]string{versionName})[0]
Colin Crossa97c5d32018-03-28 14:58:31 -0700156 linkFlags = append(linkFlags, "--version-name ", versionName)
157 }
158
159 return linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath
160}
161
162func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkVersion string) {
163 if !ctx.Config().UnbundledBuild() {
164 sdkDep := decodeSdkDep(ctx, sdkVersion)
165 if sdkDep.frameworkResModule != "" {
166 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
167 }
168 }
169}
170
171func (a *aapt) buildActions(ctx android.ModuleContext, sdkVersion string, extraLinkFlags ...string) {
172 linkFlags, linkDeps, resDirs, overlayDirs, overlayFiles, rroDirs, manifestPath := a.aapt2Flags(ctx, sdkVersion)
173
174 linkFlags = append(linkFlags, extraLinkFlags...)
175
176 packageRes := android.PathForModuleOut(ctx, "package-res.apk")
177 srcJar := android.PathForModuleGen(ctx, "R.jar")
178 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
179 rTxt := android.PathForModuleOut(ctx, "R.txt")
180
181 var compiledRes, compiledOverlay android.Paths
182 for _, dir := range resDirs {
183 compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
184 }
185 for _, dir := range overlayDirs {
186 compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
187 }
188
189 compiledOverlay = append(compiledOverlay, overlayFiles...)
190
191 aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
192 linkFlags, linkDeps, compiledRes, compiledOverlay)
193
194 a.aaptSrcJar = srcJar
195 a.exportPackage = packageRes
196 a.manifestPath = manifestPath
197 a.proguardOptionsFile = proguardOptionsFile
198 a.rroDirs = rroDirs
199 a.rTxt = rTxt
200}
201
202// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
203func aaptLibs(ctx android.ModuleContext, sdkVersion string) (staticLibs, deps android.Paths, flags []string) {
204 var sharedLibs android.Paths
205
206 sdkDep := decodeSdkDep(ctx, sdkVersion)
207 if sdkDep.useFiles {
208 sharedLibs = append(sharedLibs, sdkDep.jar)
209 }
210
211 ctx.VisitDirectDeps(func(module android.Module) {
212 var exportPackage android.Path
213 if aarDep, ok := module.(AndroidLibraryDependency); ok {
214 exportPackage = aarDep.ExportPackage()
215 }
216
217 switch ctx.OtherModuleDependencyTag(module) {
218 case libTag, frameworkResTag:
219 if exportPackage != nil {
220 sharedLibs = append(sharedLibs, exportPackage)
221 }
222 case staticLibTag:
223 if exportPackage != nil {
224 staticLibs = append(staticLibs, exportPackage)
225 }
226 }
227 })
228
229 deps = append(deps, sharedLibs...)
230 deps = append(deps, staticLibs...)
231
232 if len(staticLibs) > 0 {
233 flags = append(flags, "--auto-add-overlay")
234 }
235
236 for _, sharedLib := range sharedLibs {
237 flags = append(flags, "-I "+sharedLib.String())
238 }
239
240 return staticLibs, deps, flags
241}
242
243type AndroidLibrary struct {
244 Library
245 aapt
246
247 androidLibraryProperties androidLibraryProperties
248
249 aarFile android.WritablePath
250}
251
252var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
253
254func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
255 a.Module.deps(ctx)
256 if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
257 a.aapt.deps(ctx, String(a.deviceProperties.Sdk_version))
258 }
259}
260
261func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
262 a.aapt.buildActions(ctx, String(a.deviceProperties.Sdk_version), "--static-lib")
263
264 ctx.CheckbuildFile(a.proguardOptionsFile)
265 ctx.CheckbuildFile(a.exportPackage)
266 ctx.CheckbuildFile(a.aaptSrcJar)
267
268 // apps manifests are handled by aapt, don't let Module see them
269 a.properties.Manifest = nil
270
271 a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
272 a.proguardOptionsFile)
273
274 a.Module.compile(ctx, a.aaptSrcJar)
275
276 a.aarFile = android.PathForOutput(ctx, ctx.ModuleName()+".aar")
277 var res android.Paths
278 if a.androidLibraryProperties.BuildAAR {
279 BuildAAR(ctx, a.aarFile, a.outputFile, a.manifestPath, a.rTxt, res)
280 ctx.CheckbuildFile(a.aarFile)
281 }
282}
283
284func AndroidLibraryFactory() android.Module {
285 module := &AndroidLibrary{}
286
287 module.AddProperties(
288 &module.Module.properties,
289 &module.Module.deviceProperties,
290 &module.Module.protoProperties,
291 &module.aaptProperties,
292 &module.androidLibraryProperties)
293
294 module.androidLibraryProperties.BuildAAR = true
295
296 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
297 return module
298}
299
Colin Crossfabb6082018-02-20 17:22:23 -0800300//
301// AAR (android library) prebuilts
302//
Colin Crossfabb6082018-02-20 17:22:23 -0800303
304type AARImportProperties struct {
305 Aars []string
306
307 Sdk_version *string
Colin Crossa97c5d32018-03-28 14:58:31 -0700308
309 Static_libs []string
310 Libs []string
Colin Crossfabb6082018-02-20 17:22:23 -0800311}
312
313type AARImport struct {
314 android.ModuleBase
315 prebuilt android.Prebuilt
316
317 properties AARImportProperties
318
319 classpathFile android.WritablePath
320 proguardFlags android.WritablePath
321 exportPackage android.WritablePath
322}
323
Colin Crossa97c5d32018-03-28 14:58:31 -0700324var _ AndroidLibraryDependency = (*AARImport)(nil)
325
326func (a *AARImport) ExportPackage() android.Path {
327 return a.exportPackage
328}
329
Colin Crossfabb6082018-02-20 17:22:23 -0800330func (a *AARImport) Prebuilt() *android.Prebuilt {
331 return &a.prebuilt
332}
333
334func (a *AARImport) Name() string {
335 return a.prebuilt.Name(a.ModuleBase.Name())
336}
337
338func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
Colin Crossfabb6082018-02-20 17:22:23 -0800339 if !ctx.Config().UnbundledBuild() {
Colin Crossa97c5d32018-03-28 14:58:31 -0700340 sdkDep := decodeSdkDep(ctx, String(a.properties.Sdk_version))
341 if sdkDep.useModule && sdkDep.frameworkResModule != "" {
342 ctx.AddDependency(ctx.Module(), frameworkResTag, sdkDep.frameworkResModule)
Colin Crossfabb6082018-02-20 17:22:23 -0800343 }
344 }
Colin Crossa97c5d32018-03-28 14:58:31 -0700345
346 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Libs...)
347 ctx.AddDependency(ctx.Module(), staticLibTag, a.properties.Static_libs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800348}
349
350// Unzip an AAR into its constituent files and directories. Any files in Outputs that don't exist in the AAR will be
351// touched to create an empty file, and any directories in $expectedDirs will be created.
352var unzipAAR = pctx.AndroidStaticRule("unzipAAR",
353 blueprint.RuleParams{
354 Command: `rm -rf $outDir && mkdir -p $outDir $expectedDirs && ` +
355 `unzip -qo -d $outDir $in && touch $out`,
356 },
357 "expectedDirs", "outDir")
358
359func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
360 if len(a.properties.Aars) != 1 {
361 ctx.PropertyErrorf("aars", "exactly one aar is required")
362 return
363 }
364
365 aar := android.PathForModuleSrc(ctx, a.properties.Aars[0])
366
367 extractedAARDir := android.PathForModuleOut(ctx, "aar")
368 extractedResDir := extractedAARDir.Join(ctx, "res")
369 a.classpathFile = extractedAARDir.Join(ctx, "classes.jar")
370 a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
371 manifest := extractedAARDir.Join(ctx, "AndroidManifest.xml")
372
373 ctx.Build(pctx, android.BuildParams{
374 Rule: unzipAAR,
375 Input: aar,
376 Outputs: android.WritablePaths{a.classpathFile, a.proguardFlags, manifest},
377 Description: "unzip AAR",
378 Args: map[string]string{
379 "expectedDirs": extractedResDir.String(),
380 "outDir": extractedAARDir.String(),
381 },
382 })
383
384 compiledResDir := android.PathForModuleOut(ctx, "flat-res")
385 aaptCompileDeps := android.Paths{a.classpathFile}
386 aaptCompileDirs := android.Paths{extractedResDir}
387 flata := compiledResDir.Join(ctx, "gen_res.flata")
388 aapt2CompileDirs(ctx, flata, aaptCompileDirs, aaptCompileDeps)
389
390 a.exportPackage = android.PathForModuleOut(ctx, "package-res.apk")
391 srcJar := android.PathForModuleGen(ctx, "R.jar")
392 proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
Colin Crossa97c5d32018-03-28 14:58:31 -0700393 rTxt := android.PathForModuleOut(ctx, "R.txt")
Colin Crossfabb6082018-02-20 17:22:23 -0800394
395 var linkDeps android.Paths
396
397 linkFlags := []string{
398 "--static-lib",
399 "--no-static-lib-packages",
400 "--auto-add-overlay",
401 }
402
403 linkFlags = append(linkFlags, "--manifest "+manifest.String())
404 linkDeps = append(linkDeps, manifest)
405
Colin Crossa97c5d32018-03-28 14:58:31 -0700406 staticLibs, libDeps, libFlags := aaptLibs(ctx, String(a.properties.Sdk_version))
Colin Crossfabb6082018-02-20 17:22:23 -0800407
Colin Crossa97c5d32018-03-28 14:58:31 -0700408 linkDeps = append(linkDeps, libDeps...)
409 linkFlags = append(linkFlags, libFlags...)
Colin Crossfabb6082018-02-20 17:22:23 -0800410
Colin Crossa97c5d32018-03-28 14:58:31 -0700411 overlayRes := append(android.Paths{flata}, staticLibs...)
Colin Crossfabb6082018-02-20 17:22:23 -0800412
Colin Crossa97c5d32018-03-28 14:58:31 -0700413 aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt,
414 linkFlags, linkDeps, nil, overlayRes)
Colin Crossfabb6082018-02-20 17:22:23 -0800415}
416
417var _ Dependency = (*AARImport)(nil)
418
419func (a *AARImport) HeaderJars() android.Paths {
420 return android.Paths{a.classpathFile}
421}
422
423func (a *AARImport) ImplementationJars() android.Paths {
424 return android.Paths{a.classpathFile}
425}
426
427func (a *AARImport) AidlIncludeDirs() android.Paths {
428 return nil
429}
430
431var _ android.PrebuiltInterface = (*Import)(nil)
432
433func AARImportFactory() android.Module {
434 module := &AARImport{}
435
436 module.AddProperties(&module.properties)
437
438 android.InitPrebuiltModule(module, &module.properties.Aars)
439 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
440 return module
441}