blob: 3a7025cf6b146b00775ef741500a48fc9053ee0f [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 {
Colin Cross46c9b8b2017-06-22 16:51:17 -070060 Module
Colin Cross30e076a2015-04-13 13:58:27 -070061
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 Cross46c9b8b2017-06-22 16:51:17 -070068func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
69 a.Module.deps(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -070070
Colin Cross46c9b8b2017-06-22 16:51:17 -070071 var deps []string
Colin Cross30e076a2015-04-13 13:58:27 -070072 if !a.properties.No_standard_libraries {
73 switch a.properties.Sdk_version { // TODO: Res_sdk_version?
74 case "current", "system_current", "":
75 deps = append(deps, "framework-res")
76 default:
77 // We'll already have a dependency on an sdk prebuilt android.jar
78 }
79 }
80
Colin Cross46c9b8b2017-06-22 16:51:17 -070081 ctx.AddDependency(ctx.Module(), nil, deps...)
Colin Cross30e076a2015-04-13 13:58:27 -070082}
83
Colin Cross46c9b8b2017-06-22 16:51:17 -070084func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross30e076a2015-04-13 13:58:27 -070085 aaptFlags, aaptDeps, hasResources := a.aaptFlags(ctx)
86
87 if hasResources {
88 // First generate R.java so we can build the .class files
89 aaptRJavaFlags := append([]string(nil), aaptFlags...)
90
91 publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
92 CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
93 a.aaptJavaFileList = aaptJavaFileList
94 a.ExtraSrcLists = append(a.ExtraSrcLists, aaptJavaFileList)
95
96 if a.appProperties.Export_package_resources {
97 aaptPackageFlags := append([]string(nil), aaptFlags...)
98 var hasProduct bool
99 for _, f := range aaptPackageFlags {
100 if strings.HasPrefix(f, "--product") {
101 hasProduct = true
102 break
103 }
104 }
105
106 if !hasProduct {
107 aaptPackageFlags = append(aaptPackageFlags,
108 "--product "+ctx.AConfig().ProductAaptCharacteristics())
109 }
110 a.exportPackage = CreateExportPackage(ctx, aaptPackageFlags, aaptDeps)
111 ctx.CheckbuildFile(a.exportPackage)
112 }
113 ctx.CheckbuildFile(publicResourcesFile)
114 ctx.CheckbuildFile(proguardOptionsFile)
115 ctx.CheckbuildFile(aaptJavaFileList)
116 }
117
Colin Cross46c9b8b2017-06-22 16:51:17 -0700118 // apps manifests are handled by aapt, don't let Module see them
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700119 a.properties.Manifest = nil
Colin Cross30e076a2015-04-13 13:58:27 -0700120
121 //if !ctx.ContainsProperty("proguard.enabled") {
122 // a.properties.Proguard.Enabled = true
123 //}
124
Colin Cross46c9b8b2017-06-22 16:51:17 -0700125 a.Module.compile(ctx)
Colin Cross30e076a2015-04-13 13:58:27 -0700126
127 aaptPackageFlags := append([]string(nil), aaptFlags...)
128 var hasProduct bool
129 for _, f := range aaptPackageFlags {
130 if strings.HasPrefix(f, "--product") {
131 hasProduct = true
132 break
133 }
134 }
135
136 if !hasProduct {
137 aaptPackageFlags = append(aaptPackageFlags,
138 "--product "+ctx.AConfig().ProductAaptCharacteristics())
139 }
140
141 certificate := a.appProperties.Certificate
142 if certificate == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700143 certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
Colin Cross30e076a2015-04-13 13:58:27 -0700144 } else if dir, _ := filepath.Split(certificate); dir == "" {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700145 certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700146 } else {
Colin Cross635c3b02016-05-18 15:37:25 -0700147 certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
Colin Cross30e076a2015-04-13 13:58:27 -0700148 }
149
150 certificates := []string{certificate}
151 for _, c := range a.appProperties.Additional_certificates {
Colin Cross635c3b02016-05-18 15:37:25 -0700152 certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
Colin Cross30e076a2015-04-13 13:58:27 -0700153 }
154
155 a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
Colin Cross635c3b02016-05-18 15:37:25 -0700156 ctx.InstallFileName(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
Colin Cross30e076a2015-04-13 13:58:27 -0700157}
158
159var aaptIgnoreFilenames = []string{
160 ".svn",
161 ".git",
162 ".ds_store",
163 "*.scc",
164 ".*",
165 "CVS",
166 "thumbs.db",
167 "picasa.ini",
168 "*~",
169}
170
Colin Cross635c3b02016-05-18 15:37:25 -0700171func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
Colin Cross30e076a2015-04-13 13:58:27 -0700172 aaptFlags := a.appProperties.Aaptflags
173 hasVersionCode := false
174 hasVersionName := false
175 for _, f := range aaptFlags {
176 if strings.HasPrefix(f, "--version-code") {
177 hasVersionCode = true
178 } else if strings.HasPrefix(f, "--version-name") {
179 hasVersionName = true
180 }
181 }
182
183 if true /* is not a test */ {
184 aaptFlags = append(aaptFlags, "-z")
185 }
186
Colin Cross635c3b02016-05-18 15:37:25 -0700187 assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
188 resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Android_resource_dirs, "res")
Colin Cross30e076a2015-04-13 13:58:27 -0700189
Colin Cross635c3b02016-05-18 15:37:25 -0700190 var overlayResourceDirs android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700191 // For every resource directory, check if there is an overlay directory with the same path.
192 // If found, it will be prepended to the list of resource directories.
193 for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
194 for _, resourceDir := range resourceDirs {
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700195 overlay := overlayDir.OverlayPath(ctx, resourceDir)
196 if overlay.Valid() {
197 overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700198 }
199 }
200 }
201
202 if len(overlayResourceDirs) > 0 {
203 resourceDirs = append(overlayResourceDirs, resourceDirs...)
204 }
205
206 // aapt needs to rerun if any files are added or modified in the assets or resource directories,
207 // use glob to create a filelist.
Colin Cross635c3b02016-05-18 15:37:25 -0700208 var aaptDeps android.Paths
Colin Cross30e076a2015-04-13 13:58:27 -0700209 var hasResources bool
210 for _, d := range resourceDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700211 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700212 aaptDeps = append(aaptDeps, newDeps...)
213 if len(newDeps) > 0 {
214 hasResources = true
215 }
216 }
217 for _, d := range assetDirs {
Colin Cross7f19f372016-11-01 11:10:25 -0700218 newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
Colin Cross30e076a2015-04-13 13:58:27 -0700219 aaptDeps = append(aaptDeps, newDeps...)
220 }
221
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700222 var manifestFile string
223 if a.properties.Manifest == nil {
Colin Cross30e076a2015-04-13 13:58:27 -0700224 manifestFile = "AndroidManifest.xml"
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700225 } else {
226 manifestFile = *a.properties.Manifest
Colin Cross30e076a2015-04-13 13:58:27 -0700227 }
228
Colin Cross635c3b02016-05-18 15:37:25 -0700229 manifestPath := android.PathForModuleSrc(ctx, manifestFile)
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700230 aaptDeps = append(aaptDeps, manifestPath)
Colin Cross30e076a2015-04-13 13:58:27 -0700231
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700232 aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
Colin Cross635c3b02016-05-18 15:37:25 -0700233 aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
234 aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
Colin Cross30e076a2015-04-13 13:58:27 -0700235
236 ctx.VisitDirectDeps(func(module blueprint.Module) {
Colin Cross635c3b02016-05-18 15:37:25 -0700237 var depFile android.OptionalPath
Colin Cross30e076a2015-04-13 13:58:27 -0700238 if sdkDep, ok := module.(sdkDependency); ok {
Colin Cross635c3b02016-05-18 15:37:25 -0700239 depFile = android.OptionalPathForPath(sdkDep.ClasspathFile())
Colin Cross30e076a2015-04-13 13:58:27 -0700240 } else if javaDep, ok := module.(JavaDependency); ok {
241 if ctx.OtherModuleName(module) == "framework-res" {
Colin Cross46c9b8b2017-06-22 16:51:17 -0700242 depFile = android.OptionalPathForPath(javaDep.(*AndroidApp).exportPackage)
Colin Cross30e076a2015-04-13 13:58:27 -0700243 }
244 }
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700245 if depFile.Valid() {
246 aaptFlags = append(aaptFlags, "-I "+depFile.String())
247 aaptDeps = append(aaptDeps, depFile.Path())
Colin Cross30e076a2015-04-13 13:58:27 -0700248 }
249 })
250
251 sdkVersion := a.properties.Sdk_version
252 if sdkVersion == "" {
253 sdkVersion = ctx.AConfig().PlatformSdkVersion()
254 }
255
256 aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
257 aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
258
259 if !hasVersionCode {
260 aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
261 }
262
263 if !hasVersionName {
264 aaptFlags = append(aaptFlags,
265 "--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
266 }
267
268 // TODO: LOCAL_PACKAGE_OVERRIDES
269 // $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
270
271 // TODO: LOCAL_INSTRUMENTATION_FOR
272 // $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
273
274 return aaptFlags, aaptDeps, hasResources
275}
276
277func AndroidAppFactory() (blueprint.Module, []interface{}) {
278 module := &AndroidApp{}
279
280 module.properties.Dex = true
281
Colin Cross46c9b8b2017-06-22 16:51:17 -0700282 return android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon,
283 &module.Module.properties, &module.appProperties)
Colin Cross30e076a2015-04-13 13:58:27 -0700284}