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