blob: db2f18218414db35f90b1673f336611bb0eb5bcb [file] [log] [blame]
Colin Cross30e076a2015-04-13 13:58:27 -07001// Copyright 2015 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
17// This file contains the module types for compiling Android apps.
18
19import (
Colin Cross30e076a2015-04-13 13:58:27 -070020 "path/filepath"
21 "strings"
22
23 "github.com/google/blueprint"
Colin Cross30e076a2015-04-13 13:58:27 -070024
Colin Cross635c3b02016-05-18 15:37:25 -070025 "android/soong/android"
Colin Cross30e076a2015-04-13 13:58:27 -070026)
27
28// AAR prebuilts
29// AndroidManifest.xml merging
30// package splits
31
Colin Cross7d5136f2015-05-11 13:39:40 -070032type androidAppProperties struct {
33 // path to a certificate, or the name of a certificate in the default
34 // certificate directory, or blank to use the default product certificate
35 Certificate string
36
37 // paths to extra certificates to sign the apk with
38 Additional_certificates []string
39
40 // If set, create package-export.apk, which other packages can
41 // use to get PRODUCT-agnostic resource data like IDs and type definitions.
42 Export_package_resources bool
43
44 // flags passed to aapt when creating the apk
45 Aaptflags []string
46
47 // list of resource labels to generate individual resource packages
48 Package_splits []string
49
50 // list of directories relative to the Blueprints file containing assets.
51 // Defaults to "assets"
52 Asset_dirs []string
53
54 // list of directories relative to the Blueprints file containing
55 // Java resources
56 Android_resource_dirs []string
57}
58
Colin Cross30e076a2015-04-13 13:58:27 -070059type AndroidApp struct {
60 javaBase
61
Colin Cross7d5136f2015-05-11 13:39:40 -070062 appProperties androidAppProperties
Colin Cross30e076a2015-04-13 13:58:27 -070063
Colin Cross635c3b02016-05-18 15:37:25 -070064 aaptJavaFileList android.Path
65 exportPackage android.Path
Colin Cross30e076a2015-04-13 13:58:27 -070066}
67
Colin Cross6362e272015-10-29 15:25:03 -070068func (a *AndroidApp) JavaDependencies(ctx AndroidJavaModuleContext) []string {
69 deps := a.javaBase.JavaDependencies(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -070070
71 if !a.properties.No_standard_libraries {
72 switch a.properties.Sdk_version { // TODO: Res_sdk_version?
73 case "current", "system_current", "":
74 deps = append(deps, "framework-res")
75 default:
76 // We'll already have a dependency on an sdk prebuilt android.jar
77 }
78 }
79
80 return deps
81}
82
Colin Cross635c3b02016-05-18 15:37:25 -070083func (a *AndroidApp) GenerateJavaBuildActions(ctx android.ModuleContext) {
Colin Cross30e076a2015-04-13 13:58:27 -070084 aaptFlags, aaptDeps, hasResources := a.aaptFlags(ctx)
85
86 if hasResources {
87 // First generate R.java so we can build the .class files
88 aaptRJavaFlags := append([]string(nil), aaptFlags...)
89
90 publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
91 CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
92 a.aaptJavaFileList = aaptJavaFileList
93 a.ExtraSrcLists = append(a.ExtraSrcLists, aaptJavaFileList)
94
95 if a.appProperties.Export_package_resources {
96 aaptPackageFlags := append([]string(nil), aaptFlags...)
97 var hasProduct bool
98 for _, f := range aaptPackageFlags {
99 if strings.HasPrefix(f, "--product") {
100 hasProduct = true
101 break
102 }
103 }
104
105 if !hasProduct {
106 aaptPackageFlags = append(aaptPackageFlags,
107 "--product "+ctx.AConfig().ProductAaptCharacteristics())
108 }
109 a.exportPackage = CreateExportPackage(ctx, aaptPackageFlags, aaptDeps)
110 ctx.CheckbuildFile(a.exportPackage)
111 }
112 ctx.CheckbuildFile(publicResourcesFile)
113 ctx.CheckbuildFile(proguardOptionsFile)
114 ctx.CheckbuildFile(aaptJavaFileList)
115 }
116
117 // apps manifests are handled by aapt, don't let javaBase see them
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700118 a.properties.Manifest = nil
Colin Cross30e076a2015-04-13 13:58:27 -0700119
120 //if !ctx.ContainsProperty("proguard.enabled") {
121 // a.properties.Proguard.Enabled = true
122 //}
123
124 a.javaBase.GenerateJavaBuildActions(ctx)
125
126 aaptPackageFlags := append([]string(nil), aaptFlags...)
127 var hasProduct bool
128 for _, f := range aaptPackageFlags {
129 if strings.HasPrefix(f, "--product") {
130 hasProduct = true
131 break
132 }
133 }
134
135 if !hasProduct {
136 aaptPackageFlags = append(aaptPackageFlags,
137 "--product "+ctx.AConfig().ProductAaptCharacteristics())
138 }
139
140 certificate := a.appProperties.Certificate
141 if certificate == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700142 certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
Colin Cross30e076a2015-04-13 13:58:27 -0700143 } else if dir, _ := filepath.Split(certificate); dir == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700144 certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700145 } else {
Colin Cross635c3b02016-05-18 15:37:25 -0700146 certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700147 }
148
149 certificates := []string{certificate}
150 for _, c := range a.appProperties.Additional_certificates {
Colin Cross635c3b02016-05-18 15:37:25 -0700151 certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
Colin Cross30e076a2015-04-13 13:58:27 -0700152 }
153
154 a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
Colin Cross635c3b02016-05-18 15:37:25 -0700155 ctx.InstallFileName(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
Colin Cross30e076a2015-04-13 13:58:27 -0700156}
157
158var aaptIgnoreFilenames = []string{
159 ".svn",
160 ".git",
161 ".ds_store",
162 "*.scc",
163 ".*",
164 "CVS",
165 "thumbs.db",
166 "picasa.ini",
167 "*~",
168}
169
Colin Cross635c3b02016-05-18 15:37:25 -0700170func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
Colin Cross30e076a2015-04-13 13:58:27 -0700171 aaptFlags := a.appProperties.Aaptflags
172 hasVersionCode := false
173 hasVersionName := false
174 for _, f := range aaptFlags {
175 if strings.HasPrefix(f, "--version-code") {
176 hasVersionCode = true
177 } else if strings.HasPrefix(f, "--version-name") {
178 hasVersionName = true
179 }
180 }
181
182 if true /* is not a test */ {
183 aaptFlags = append(aaptFlags, "-z")
184 }
185
Colin Cross635c3b02016-05-18 15:37:25 -0700186 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
187 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Android_resource_dirs, "res")
Colin Cross30e076a2015-04-13 13:58:27 -0700188
Colin Cross635c3b02016-05-18 15:37:25 -0700189 var overlayResourceDirs android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700190 // For every resource directory, check if there is an overlay directory with the same path.
191 // If found, it will be prepended to the list of resource directories.
192 for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
193 for _, resourceDir := range resourceDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700194 overlay := overlayDir.OverlayPath(ctx, resourceDir)
195 if overlay.Valid() {
196 overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700197 }
198 }
199 }
200
201 if len(overlayResourceDirs) > 0 {
202 resourceDirs = append(overlayResourceDirs, resourceDirs...)
203 }
204
205 // aapt needs to rerun if any files are added or modified in the assets or resource directories,
206 // use glob to create a filelist.
Colin Cross635c3b02016-05-18 15:37:25 -0700207 var aaptDeps android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700208 var hasResources bool
209 for _, d := range resourceDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700210 newDeps := ctx.Glob("app_resources", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700211 aaptDeps = append(aaptDeps, newDeps...)
212 if len(newDeps) > 0 {
213 hasResources = true
214 }
215 }
216 for _, d := range assetDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700217 newDeps := ctx.Glob("app_assets", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700218 aaptDeps = append(aaptDeps, newDeps...)
219 }
220
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700221 var manifestFile string
222 if a.properties.Manifest == nil {
Colin Cross30e076a2015-04-13 13:58:27 -0700223 manifestFile = "AndroidManifest.xml"
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700224 } else {
225 manifestFile = *a.properties.Manifest
Colin Cross30e076a2015-04-13 13:58:27 -0700226 }
227
Colin Cross635c3b02016-05-18 15:37:25 -0700228 manifestPath := android.PathForModuleSrc(ctx, manifestFile)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700229 aaptDeps = append(aaptDeps, manifestPath)
Colin Cross30e076a2015-04-13 13:58:27 -0700230
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700231 aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
Colin Cross635c3b02016-05-18 15:37:25 -0700232 aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
233 aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
Colin Cross30e076a2015-04-13 13:58:27 -0700234
235 ctx.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross635c3b02016-05-18 15:37:25 -0700236 var depFile android.OptionalPath
Colin Cross30e076a2015-04-13 13:58:27 -0700237 if sdkDep, ok := module.(sdkDependency); ok {
Colin Cross635c3b02016-05-18 15:37:25 -0700238 depFile = android.OptionalPathForPath(sdkDep.ClasspathFile())
Colin Cross30e076a2015-04-13 13:58:27 -0700239 } else if javaDep, ok := module.(JavaDependency); ok {
240 if ctx.OtherModuleName(module) == "framework-res" {
Colin Cross635c3b02016-05-18 15:37:25 -0700241 depFile = android.OptionalPathForPath(javaDep.(*javaBase).module.(*AndroidApp).exportPackage)
Colin Cross30e076a2015-04-13 13:58:27 -0700242 }
243 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700244 if depFile.Valid() {
245 aaptFlags = append(aaptFlags, "-I "+depFile.String())
246 aaptDeps = append(aaptDeps, depFile.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700247 }
248 })
249
250 sdkVersion := a.properties.Sdk_version
251 if sdkVersion == "" {
252 sdkVersion = ctx.AConfig().PlatformSdkVersion()
253 }
254
255 aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
256 aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
257
258 if !hasVersionCode {
259 aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
260 }
261
262 if !hasVersionName {
263 aaptFlags = append(aaptFlags,
264 "--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
265 }
266
267 // TODO: LOCAL_PACKAGE_OVERRIDES
268 // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
269
270 // TODO: LOCAL_INSTRUMENTATION_FOR
271 // $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
272
273 return aaptFlags, aaptDeps, hasResources
274}
275
276func AndroidAppFactory() (blueprint.Module, []interface{}) {
277 module := &AndroidApp{}
278
279 module.properties.Dex = true
280
Colin Cross635c3b02016-05-18 15:37:25 -0700281 return NewJavaBase(&module.javaBase, module, android.DeviceSupported, &module.appProperties)
Colin Cross30e076a2015-04-13 13:58:27 -0700282}