blob: 68e4d5cc703e46da01b63fcd0b1f30713de68fab [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
Colin Cross76b5f0c2017-08-29 16:02:06 -070023 "github.com/google/blueprint/proptools"
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
Nan Zhangea568a42017-11-08 21:20:04 -080035 Certificate *string
Colin Cross7d5136f2015-05-11 13:39:40 -070036
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.
Nan Zhangea568a42017-11-08 21:20:04 -080042 Export_package_resources *bool
Colin Cross7d5136f2015-05-11 13:39:40 -070043
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
Colin Cross86a63ff2017-09-27 17:33:10 -070055 // Android resources
56 Resource_dirs []string
Colin Crosscb933592017-11-22 13:49:43 -080057
58 Instrumentation_for *string
Colin Cross7d5136f2015-05-11 13:39:40 -070059}
60
Colin Cross30e076a2015-04-13 13:58:27 -070061type AndroidApp struct {
Colin Cross46c9b8b2017-06-22 16:51:17 -070062 Module
Colin Cross30e076a2015-04-13 13:58:27 -070063
Colin Cross7d5136f2015-05-11 13:39:40 -070064 appProperties androidAppProperties
Colin Cross30e076a2015-04-13 13:58:27 -070065
Colin Cross635c3b02016-05-18 15:37:25 -070066 aaptJavaFileList android.Path
67 exportPackage android.Path
Colin Cross30e076a2015-04-13 13:58:27 -070068}
69
Colin Cross46c9b8b2017-06-22 16:51:17 -070070func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
71 a.Module.deps(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -070072
Colin Cross76b5f0c2017-08-29 16:02:06 -070073 if !proptools.Bool(a.properties.No_standard_libs) {
Nan Zhangea568a42017-11-08 21:20:04 -080074 switch String(a.deviceProperties.Sdk_version) { // TODO: Res_sdk_version?
Colin Cross30e076a2015-04-13 13:58:27 -070075 case "current", "system_current", "":
Colin Crossbe1da472017-07-07 15:59:46 -070076 ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
Colin Cross30e076a2015-04-13 13:58:27 -070077 default:
78 // We'll already have a dependency on an sdk prebuilt android.jar
79 }
80 }
Colin Cross30e076a2015-04-13 13:58:27 -070081}
82
Colin Cross46c9b8b2017-06-22 16:51:17 -070083func (a *AndroidApp) GenerateAndroidBuildActions(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
Colin Cross59149b62017-10-16 18:07:29 -070093 // TODO(ccross): export aapt generated java files as a src jar
Colin Cross30e076a2015-04-13 13:58:27 -070094
Nan Zhangea568a42017-11-08 21:20:04 -080095 if Bool(a.appProperties.Export_package_resources) {
Colin Cross30e076a2015-04-13 13:58:27 -070096 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,
Colin Crossface4e42017-10-30 17:32:15 -0700107 "--product "+ctx.AConfig().ProductAAPTCharacteristics())
Colin Cross30e076a2015-04-13 13:58:27 -0700108 }
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
Colin Cross46c9b8b2017-06-22 16:51:17 -0700117 // apps manifests are handled by aapt, don't let Module 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
Colin Crosscb933592017-11-22 13:49:43 -0800124 if String(a.appProperties.Instrumentation_for) == "" {
125 a.properties.Instrument = true
126 }
127
Colin Cross46c9b8b2017-06-22 16:51:17 -0700128 a.Module.compile(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -0700129
130 aaptPackageFlags := append([]string(nil), aaptFlags...)
131 var hasProduct bool
132 for _, f := range aaptPackageFlags {
133 if strings.HasPrefix(f, "--product") {
134 hasProduct = true
135 break
136 }
137 }
138
139 if !hasProduct {
140 aaptPackageFlags = append(aaptPackageFlags,
Colin Crossface4e42017-10-30 17:32:15 -0700141 "--product "+ctx.AConfig().ProductAAPTCharacteristics())
Colin Cross30e076a2015-04-13 13:58:27 -0700142 }
143
Nan Zhangea568a42017-11-08 21:20:04 -0800144 certificate := String(a.appProperties.Certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700145 if certificate == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700146 certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
Colin Cross30e076a2015-04-13 13:58:27 -0700147 } else if dir, _ := filepath.Split(certificate); dir == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700148 certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700149 } else {
Colin Cross635c3b02016-05-18 15:37:25 -0700150 certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700151 }
152
153 certificates := []string{certificate}
154 for _, c := range a.appProperties.Additional_certificates {
Colin Cross635c3b02016-05-18 15:37:25 -0700155 certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
Colin Cross30e076a2015-04-13 13:58:27 -0700156 }
157
158 a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
Colin Cross5c517922017-08-31 12:29:17 -0700159 ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
Colin Cross30e076a2015-04-13 13:58:27 -0700160}
161
162var aaptIgnoreFilenames = []string{
163 ".svn",
164 ".git",
165 ".ds_store",
166 "*.scc",
167 ".*",
168 "CVS",
169 "thumbs.db",
170 "picasa.ini",
171 "*~",
172}
173
Colin Cross635c3b02016-05-18 15:37:25 -0700174func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
Colin Cross30e076a2015-04-13 13:58:27 -0700175 aaptFlags := a.appProperties.Aaptflags
176 hasVersionCode := false
177 hasVersionName := false
178 for _, f := range aaptFlags {
179 if strings.HasPrefix(f, "--version-code") {
180 hasVersionCode = true
181 } else if strings.HasPrefix(f, "--version-name") {
182 hasVersionName = true
183 }
184 }
185
186 if true /* is not a test */ {
187 aaptFlags = append(aaptFlags, "-z")
188 }
189
Colin Cross635c3b02016-05-18 15:37:25 -0700190 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
Colin Cross86a63ff2017-09-27 17:33:10 -0700191 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
Colin Cross30e076a2015-04-13 13:58:27 -0700192
Colin Cross635c3b02016-05-18 15:37:25 -0700193 var overlayResourceDirs android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700194 // For every resource directory, check if there is an overlay directory with the same path.
195 // If found, it will be prepended to the list of resource directories.
196 for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
197 for _, resourceDir := range resourceDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700198 overlay := overlayDir.OverlayPath(ctx, resourceDir)
199 if overlay.Valid() {
200 overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700201 }
202 }
203 }
204
205 if len(overlayResourceDirs) > 0 {
206 resourceDirs = append(overlayResourceDirs, resourceDirs...)
207 }
208
209 // aapt needs to rerun if any files are added or modified in the assets or resource directories,
210 // use glob to create a filelist.
Colin Cross635c3b02016-05-18 15:37:25 -0700211 var aaptDeps android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700212 var hasResources bool
213 for _, d := range resourceDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700214 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700215 aaptDeps = append(aaptDeps, newDeps...)
216 if len(newDeps) > 0 {
217 hasResources = true
218 }
219 }
220 for _, d := range assetDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700221 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700222 aaptDeps = append(aaptDeps, newDeps...)
223 }
224
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700225 var manifestFile string
226 if a.properties.Manifest == nil {
Colin Cross30e076a2015-04-13 13:58:27 -0700227 manifestFile = "AndroidManifest.xml"
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700228 } else {
229 manifestFile = *a.properties.Manifest
Colin Cross30e076a2015-04-13 13:58:27 -0700230 }
231
Colin Cross635c3b02016-05-18 15:37:25 -0700232 manifestPath := android.PathForModuleSrc(ctx, manifestFile)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700233 aaptDeps = append(aaptDeps, manifestPath)
Colin Cross30e076a2015-04-13 13:58:27 -0700234
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700235 aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
Colin Cross635c3b02016-05-18 15:37:25 -0700236 aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
237 aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
Colin Cross30e076a2015-04-13 13:58:27 -0700238
Colin Crossd11fcda2017-10-23 17:59:01 -0700239 ctx.VisitDirectDeps(func(module android.Module) {
Colin Cross74d73e22017-08-02 11:05:49 -0700240 var depFiles android.Paths
Colin Crossfc3674a2017-09-18 17:41:52 -0700241 if javaDep, ok := module.(Dependency); ok {
Colin Cross30e076a2015-04-13 13:58:27 -0700242 if ctx.OtherModuleName(module) == "framework-res" {
Colin Cross74d73e22017-08-02 11:05:49 -0700243 depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
Colin Cross30e076a2015-04-13 13:58:27 -0700244 }
245 }
Colin Cross74d73e22017-08-02 11:05:49 -0700246
247 for _, dep := range depFiles {
248 aaptFlags = append(aaptFlags, "-I "+dep.String())
Colin Cross30e076a2015-04-13 13:58:27 -0700249 }
Colin Cross74d73e22017-08-02 11:05:49 -0700250 aaptDeps = append(aaptDeps, depFiles...)
Colin Cross30e076a2015-04-13 13:58:27 -0700251 })
252
Nan Zhangea568a42017-11-08 21:20:04 -0800253 sdkVersion := String(a.deviceProperties.Sdk_version)
Colin Cross30e076a2015-04-13 13:58:27 -0700254 if sdkVersion == "" {
255 sdkVersion = ctx.AConfig().PlatformSdkVersion()
256 }
257
258 aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
259 aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
260
261 if !hasVersionCode {
262 aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
263 }
264
265 if !hasVersionName {
266 aaptFlags = append(aaptFlags,
267 "--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
268 }
269
270 // TODO: LOCAL_PACKAGE_OVERRIDES
271 // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
272
273 // TODO: LOCAL_INSTRUMENTATION_FOR
274 // $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
275
276 return aaptFlags, aaptDeps, hasResources
277}
278
Colin Cross36242852017-06-23 15:06:31 -0700279func AndroidAppFactory() android.Module {
Colin Cross30e076a2015-04-13 13:58:27 -0700280 module := &AndroidApp{}
281
Colin Cross36242852017-06-23 15:06:31 -0700282 module.AddProperties(
Colin Cross540eff82017-06-22 17:01:52 -0700283 &module.Module.properties,
284 &module.Module.deviceProperties,
285 &module.appProperties)
Colin Cross36242852017-06-23 15:06:31 -0700286
287 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
288 return module
Colin Cross30e076a2015-04-13 13:58:27 -0700289}