blob: e40478a75aab91db2e8e69c193a44533332850cc [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 Cross76b5f0c2017-08-29 16:02:06 -070024 "github.com/google/blueprint/proptools"
Colin Cross30e076a2015-04-13 13:58:27 -070025
Colin Cross635c3b02016-05-18 15:37:25 -070026 "android/soong/android"
Colin Cross30e076a2015-04-13 13:58:27 -070027)
28
29// AAR prebuilts
30// AndroidManifest.xml merging
31// package splits
32
Colin Cross7d5136f2015-05-11 13:39:40 -070033type androidAppProperties struct {
34 // path to a certificate, or the name of a certificate in the default
35 // certificate directory, or blank to use the default product certificate
36 Certificate string
37
38 // paths to extra certificates to sign the apk with
39 Additional_certificates []string
40
41 // If set, create package-export.apk, which other packages can
42 // use to get PRODUCT-agnostic resource data like IDs and type definitions.
43 Export_package_resources bool
44
45 // flags passed to aapt when creating the apk
46 Aaptflags []string
47
48 // list of resource labels to generate individual resource packages
49 Package_splits []string
50
51 // list of directories relative to the Blueprints file containing assets.
52 // Defaults to "assets"
53 Asset_dirs []string
54
55 // list of directories relative to the Blueprints file containing
Colin Cross86a63ff2017-09-27 17:33:10 -070056 // Android resources
57 Resource_dirs []string
Colin Cross7d5136f2015-05-11 13:39:40 -070058}
59
Colin Cross30e076a2015-04-13 13:58:27 -070060type AndroidApp struct {
Colin Cross46c9b8b2017-06-22 16:51:17 -070061 Module
Colin Cross30e076a2015-04-13 13:58:27 -070062
Colin Cross7d5136f2015-05-11 13:39:40 -070063 appProperties androidAppProperties
Colin Cross30e076a2015-04-13 13:58:27 -070064
Colin Cross635c3b02016-05-18 15:37:25 -070065 aaptJavaFileList android.Path
66 exportPackage android.Path
Colin Cross30e076a2015-04-13 13:58:27 -070067}
68
Colin Cross46c9b8b2017-06-22 16:51:17 -070069func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
70 a.Module.deps(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -070071
Colin Cross76b5f0c2017-08-29 16:02:06 -070072 if !proptools.Bool(a.properties.No_standard_libs) {
Colin Cross540eff82017-06-22 17:01:52 -070073 switch a.deviceProperties.Sdk_version { // TODO: Res_sdk_version?
Colin Cross30e076a2015-04-13 13:58:27 -070074 case "current", "system_current", "":
Colin Crossbe1da472017-07-07 15:59:46 -070075 ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
Colin Cross30e076a2015-04-13 13:58:27 -070076 default:
77 // We'll already have a dependency on an sdk prebuilt android.jar
78 }
79 }
Colin Cross30e076a2015-04-13 13:58:27 -070080}
81
Colin Cross46c9b8b2017-06-22 16:51:17 -070082func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross30e076a2015-04-13 13:58:27 -070083 aaptFlags, aaptDeps, hasResources := a.aaptFlags(ctx)
84
85 if hasResources {
86 // First generate R.java so we can build the .class files
87 aaptRJavaFlags := append([]string(nil), aaptFlags...)
88
89 publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
90 CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
91 a.aaptJavaFileList = aaptJavaFileList
92 a.ExtraSrcLists = append(a.ExtraSrcLists, aaptJavaFileList)
93
94 if a.appProperties.Export_package_resources {
95 aaptPackageFlags := append([]string(nil), aaptFlags...)
96 var hasProduct bool
97 for _, f := range aaptPackageFlags {
98 if strings.HasPrefix(f, "--product") {
99 hasProduct = true
100 break
101 }
102 }
103
104 if !hasProduct {
105 aaptPackageFlags = append(aaptPackageFlags,
106 "--product "+ctx.AConfig().ProductAaptCharacteristics())
107 }
108 a.exportPackage = CreateExportPackage(ctx, aaptPackageFlags, aaptDeps)
109 ctx.CheckbuildFile(a.exportPackage)
110 }
111 ctx.CheckbuildFile(publicResourcesFile)
112 ctx.CheckbuildFile(proguardOptionsFile)
113 ctx.CheckbuildFile(aaptJavaFileList)
114 }
115
Colin Cross46c9b8b2017-06-22 16:51:17 -0700116 // apps manifests are handled by aapt, don't let Module see them
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700117 a.properties.Manifest = nil
Colin Cross30e076a2015-04-13 13:58:27 -0700118
119 //if !ctx.ContainsProperty("proguard.enabled") {
120 // a.properties.Proguard.Enabled = true
121 //}
122
Colin Cross46c9b8b2017-06-22 16:51:17 -0700123 a.Module.compile(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -0700124
125 aaptPackageFlags := append([]string(nil), aaptFlags...)
126 var hasProduct bool
127 for _, f := range aaptPackageFlags {
128 if strings.HasPrefix(f, "--product") {
129 hasProduct = true
130 break
131 }
132 }
133
134 if !hasProduct {
135 aaptPackageFlags = append(aaptPackageFlags,
136 "--product "+ctx.AConfig().ProductAaptCharacteristics())
137 }
138
139 certificate := a.appProperties.Certificate
140 if certificate == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700141 certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
Colin Cross30e076a2015-04-13 13:58:27 -0700142 } else if dir, _ := filepath.Split(certificate); dir == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700143 certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700144 } else {
Colin Cross635c3b02016-05-18 15:37:25 -0700145 certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700146 }
147
148 certificates := []string{certificate}
149 for _, c := range a.appProperties.Additional_certificates {
Colin Cross635c3b02016-05-18 15:37:25 -0700150 certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
Colin Cross30e076a2015-04-13 13:58:27 -0700151 }
152
153 a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
Colin Cross5c517922017-08-31 12:29:17 -0700154 ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
Colin Cross30e076a2015-04-13 13:58:27 -0700155}
156
157var aaptIgnoreFilenames = []string{
158 ".svn",
159 ".git",
160 ".ds_store",
161 "*.scc",
162 ".*",
163 "CVS",
164 "thumbs.db",
165 "picasa.ini",
166 "*~",
167}
168
Colin Cross635c3b02016-05-18 15:37:25 -0700169func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
Colin Cross30e076a2015-04-13 13:58:27 -0700170 aaptFlags := a.appProperties.Aaptflags
171 hasVersionCode := false
172 hasVersionName := false
173 for _, f := range aaptFlags {
174 if strings.HasPrefix(f, "--version-code") {
175 hasVersionCode = true
176 } else if strings.HasPrefix(f, "--version-name") {
177 hasVersionName = true
178 }
179 }
180
181 if true /* is not a test */ {
182 aaptFlags = append(aaptFlags, "-z")
183 }
184
Colin Cross635c3b02016-05-18 15:37:25 -0700185 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
Colin Cross86a63ff2017-09-27 17:33:10 -0700186 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
Colin Cross30e076a2015-04-13 13:58:27 -0700187
Colin Cross635c3b02016-05-18 15:37:25 -0700188 var overlayResourceDirs android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700189 // For every resource directory, check if there is an overlay directory with the same path.
190 // If found, it will be prepended to the list of resource directories.
191 for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
192 for _, resourceDir := range resourceDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700193 overlay := overlayDir.OverlayPath(ctx, resourceDir)
194 if overlay.Valid() {
195 overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700196 }
197 }
198 }
199
200 if len(overlayResourceDirs) > 0 {
201 resourceDirs = append(overlayResourceDirs, resourceDirs...)
202 }
203
204 // aapt needs to rerun if any files are added or modified in the assets or resource directories,
205 // use glob to create a filelist.
Colin Cross635c3b02016-05-18 15:37:25 -0700206 var aaptDeps android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700207 var hasResources bool
208 for _, d := range resourceDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700209 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700210 aaptDeps = append(aaptDeps, newDeps...)
211 if len(newDeps) > 0 {
212 hasResources = true
213 }
214 }
215 for _, d := range assetDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700216 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700217 aaptDeps = append(aaptDeps, newDeps...)
218 }
219
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700220 var manifestFile string
221 if a.properties.Manifest == nil {
Colin Cross30e076a2015-04-13 13:58:27 -0700222 manifestFile = "AndroidManifest.xml"
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700223 } else {
224 manifestFile = *a.properties.Manifest
Colin Cross30e076a2015-04-13 13:58:27 -0700225 }
226
Colin Cross635c3b02016-05-18 15:37:25 -0700227 manifestPath := android.PathForModuleSrc(ctx, manifestFile)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700228 aaptDeps = append(aaptDeps, manifestPath)
Colin Cross30e076a2015-04-13 13:58:27 -0700229
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700230 aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
Colin Cross635c3b02016-05-18 15:37:25 -0700231 aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
232 aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
Colin Cross30e076a2015-04-13 13:58:27 -0700233
234 ctx.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross74d73e22017-08-02 11:05:49 -0700235 var depFiles android.Paths
Colin Crossfc3674a2017-09-18 17:41:52 -0700236 if javaDep, ok := module.(Dependency); ok {
Colin Cross30e076a2015-04-13 13:58:27 -0700237 if ctx.OtherModuleName(module) == "framework-res" {
Colin Cross74d73e22017-08-02 11:05:49 -0700238 depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
Colin Cross30e076a2015-04-13 13:58:27 -0700239 }
240 }
Colin Cross74d73e22017-08-02 11:05:49 -0700241
242 for _, dep := range depFiles {
243 aaptFlags = append(aaptFlags, "-I "+dep.String())
Colin Cross30e076a2015-04-13 13:58:27 -0700244 }
Colin Cross74d73e22017-08-02 11:05:49 -0700245 aaptDeps = append(aaptDeps, depFiles...)
Colin Cross30e076a2015-04-13 13:58:27 -0700246 })
247
Colin Cross540eff82017-06-22 17:01:52 -0700248 sdkVersion := a.deviceProperties.Sdk_version
Colin Cross30e076a2015-04-13 13:58:27 -0700249 if sdkVersion == "" {
250 sdkVersion = ctx.AConfig().PlatformSdkVersion()
251 }
252
253 aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
254 aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
255
256 if !hasVersionCode {
257 aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
258 }
259
260 if !hasVersionName {
261 aaptFlags = append(aaptFlags,
262 "--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
263 }
264
265 // TODO: LOCAL_PACKAGE_OVERRIDES
266 // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
267
268 // TODO: LOCAL_INSTRUMENTATION_FOR
269 // $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
270
271 return aaptFlags, aaptDeps, hasResources
272}
273
Colin Cross36242852017-06-23 15:06:31 -0700274func AndroidAppFactory() android.Module {
Colin Cross30e076a2015-04-13 13:58:27 -0700275 module := &AndroidApp{}
276
Colin Cross540eff82017-06-22 17:01:52 -0700277 module.deviceProperties.Dex = true
Colin Cross30e076a2015-04-13 13:58:27 -0700278
Colin Cross36242852017-06-23 15:06:31 -0700279 module.AddProperties(
Colin Cross540eff82017-06-22 17:01:52 -0700280 &module.Module.properties,
281 &module.Module.deviceProperties,
282 &module.appProperties)
Colin Cross36242852017-06-23 15:06:31 -0700283
284 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
285 return module
Colin Cross30e076a2015-04-13 13:58:27 -0700286}