2015-04-13 22:58:27 +02:00
|
|
|
// Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package java
|
|
|
|
|
|
|
|
// This file contains the module types for compiling Android apps.
|
|
|
|
|
|
|
|
import (
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
"android/soong/android"
|
2015-04-13 22:58:27 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// AAR prebuilts
|
|
|
|
// AndroidManifest.xml merging
|
|
|
|
// package splits
|
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
type androidAppProperties struct {
|
|
|
|
// path to a certificate, or the name of a certificate in the default
|
|
|
|
// certificate directory, or blank to use the default product certificate
|
|
|
|
Certificate string
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// paths to extra certificates to sign the apk with
|
|
|
|
Additional_certificates []string
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// If set, create package-export.apk, which other packages can
|
|
|
|
// use to get PRODUCT-agnostic resource data like IDs and type definitions.
|
|
|
|
Export_package_resources bool
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// flags passed to aapt when creating the apk
|
|
|
|
Aaptflags []string
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// list of resource labels to generate individual resource packages
|
|
|
|
Package_splits []string
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// list of directories relative to the Blueprints file containing assets.
|
|
|
|
// Defaults to "assets"
|
|
|
|
Asset_dirs []string
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
// list of directories relative to the Blueprints file containing
|
|
|
|
// Java resources
|
|
|
|
Android_resource_dirs []string
|
|
|
|
}
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-05-11 22:39:40 +02:00
|
|
|
type AndroidApp struct {
|
|
|
|
javaBase
|
|
|
|
|
|
|
|
appProperties androidAppProperties
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
aaptJavaFileList android.Path
|
|
|
|
exportPackage android.Path
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
|
2015-10-29 23:25:03 +01:00
|
|
|
func (a *AndroidApp) JavaDependencies(ctx AndroidJavaModuleContext) []string {
|
|
|
|
deps := a.javaBase.JavaDependencies(ctx)
|
2015-04-13 22:58:27 +02:00
|
|
|
|
|
|
|
if !a.properties.No_standard_libraries {
|
|
|
|
switch a.properties.Sdk_version { // TODO: Res_sdk_version?
|
|
|
|
case "current", "system_current", "":
|
|
|
|
deps = append(deps, "framework-res")
|
|
|
|
default:
|
|
|
|
// We'll already have a dependency on an sdk prebuilt android.jar
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return deps
|
|
|
|
}
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
func (a *AndroidApp) GenerateJavaBuildActions(ctx android.ModuleContext) {
|
2015-04-13 22:58:27 +02:00
|
|
|
aaptFlags, aaptDeps, hasResources := a.aaptFlags(ctx)
|
|
|
|
|
|
|
|
if hasResources {
|
|
|
|
// First generate R.java so we can build the .class files
|
|
|
|
aaptRJavaFlags := append([]string(nil), aaptFlags...)
|
|
|
|
|
|
|
|
publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
|
|
|
|
CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
|
|
|
|
a.aaptJavaFileList = aaptJavaFileList
|
|
|
|
a.ExtraSrcLists = append(a.ExtraSrcLists, aaptJavaFileList)
|
|
|
|
|
|
|
|
if a.appProperties.Export_package_resources {
|
|
|
|
aaptPackageFlags := append([]string(nil), aaptFlags...)
|
|
|
|
var hasProduct bool
|
|
|
|
for _, f := range aaptPackageFlags {
|
|
|
|
if strings.HasPrefix(f, "--product") {
|
|
|
|
hasProduct = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !hasProduct {
|
|
|
|
aaptPackageFlags = append(aaptPackageFlags,
|
|
|
|
"--product "+ctx.AConfig().ProductAaptCharacteristics())
|
|
|
|
}
|
|
|
|
a.exportPackage = CreateExportPackage(ctx, aaptPackageFlags, aaptDeps)
|
|
|
|
ctx.CheckbuildFile(a.exportPackage)
|
|
|
|
}
|
|
|
|
ctx.CheckbuildFile(publicResourcesFile)
|
|
|
|
ctx.CheckbuildFile(proguardOptionsFile)
|
|
|
|
ctx.CheckbuildFile(aaptJavaFileList)
|
|
|
|
}
|
|
|
|
|
|
|
|
// apps manifests are handled by aapt, don't let javaBase see them
|
2015-09-24 00:26:20 +02:00
|
|
|
a.properties.Manifest = nil
|
2015-04-13 22:58:27 +02:00
|
|
|
|
|
|
|
//if !ctx.ContainsProperty("proguard.enabled") {
|
|
|
|
// a.properties.Proguard.Enabled = true
|
|
|
|
//}
|
|
|
|
|
|
|
|
a.javaBase.GenerateJavaBuildActions(ctx)
|
|
|
|
|
|
|
|
aaptPackageFlags := append([]string(nil), aaptFlags...)
|
|
|
|
var hasProduct bool
|
|
|
|
for _, f := range aaptPackageFlags {
|
|
|
|
if strings.HasPrefix(f, "--product") {
|
|
|
|
hasProduct = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !hasProduct {
|
|
|
|
aaptPackageFlags = append(aaptPackageFlags,
|
|
|
|
"--product "+ctx.AConfig().ProductAaptCharacteristics())
|
|
|
|
}
|
|
|
|
|
|
|
|
certificate := a.appProperties.Certificate
|
|
|
|
if certificate == "" {
|
2015-09-24 00:26:20 +02:00
|
|
|
certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
|
2015-04-13 22:58:27 +02:00
|
|
|
} else if dir, _ := filepath.Split(certificate); dir == "" {
|
2015-09-24 00:26:20 +02:00
|
|
|
certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
|
2015-04-13 22:58:27 +02:00
|
|
|
} else {
|
2016-05-19 00:37:25 +02:00
|
|
|
certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
certificates := []string{certificate}
|
|
|
|
for _, c := range a.appProperties.Additional_certificates {
|
2016-05-19 00:37:25 +02:00
|
|
|
certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
|
2016-05-19 00:37:25 +02:00
|
|
|
ctx.InstallFileName(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var aaptIgnoreFilenames = []string{
|
|
|
|
".svn",
|
|
|
|
".git",
|
|
|
|
".ds_store",
|
|
|
|
"*.scc",
|
|
|
|
".*",
|
|
|
|
"CVS",
|
|
|
|
"thumbs.db",
|
|
|
|
"picasa.ini",
|
|
|
|
"*~",
|
|
|
|
}
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
|
2015-04-13 22:58:27 +02:00
|
|
|
aaptFlags := a.appProperties.Aaptflags
|
|
|
|
hasVersionCode := false
|
|
|
|
hasVersionName := false
|
|
|
|
for _, f := range aaptFlags {
|
|
|
|
if strings.HasPrefix(f, "--version-code") {
|
|
|
|
hasVersionCode = true
|
|
|
|
} else if strings.HasPrefix(f, "--version-name") {
|
|
|
|
hasVersionName = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if true /* is not a test */ {
|
|
|
|
aaptFlags = append(aaptFlags, "-z")
|
|
|
|
}
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
|
|
|
|
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Android_resource_dirs, "res")
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
var overlayResourceDirs android.Paths
|
2015-04-13 22:58:27 +02:00
|
|
|
// For every resource directory, check if there is an overlay directory with the same path.
|
|
|
|
// If found, it will be prepended to the list of resource directories.
|
|
|
|
for _, overlayDir := range ctx.AConfig().ResourceOverlays() {
|
|
|
|
for _, resourceDir := range resourceDirs {
|
2015-09-24 00:26:20 +02:00
|
|
|
overlay := overlayDir.OverlayPath(ctx, resourceDir)
|
|
|
|
if overlay.Valid() {
|
|
|
|
overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(overlayResourceDirs) > 0 {
|
|
|
|
resourceDirs = append(overlayResourceDirs, resourceDirs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// aapt needs to rerun if any files are added or modified in the assets or resource directories,
|
|
|
|
// use glob to create a filelist.
|
2016-05-19 00:37:25 +02:00
|
|
|
var aaptDeps android.Paths
|
2015-04-13 22:58:27 +02:00
|
|
|
var hasResources bool
|
|
|
|
for _, d := range resourceDirs {
|
2015-09-24 00:26:20 +02:00
|
|
|
newDeps := ctx.Glob("app_resources", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
2015-04-13 22:58:27 +02:00
|
|
|
aaptDeps = append(aaptDeps, newDeps...)
|
|
|
|
if len(newDeps) > 0 {
|
|
|
|
hasResources = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, d := range assetDirs {
|
2015-09-24 00:26:20 +02:00
|
|
|
newDeps := ctx.Glob("app_assets", filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
2015-04-13 22:58:27 +02:00
|
|
|
aaptDeps = append(aaptDeps, newDeps...)
|
|
|
|
}
|
|
|
|
|
2015-09-24 00:26:20 +02:00
|
|
|
var manifestFile string
|
|
|
|
if a.properties.Manifest == nil {
|
2015-04-13 22:58:27 +02:00
|
|
|
manifestFile = "AndroidManifest.xml"
|
2015-09-24 00:26:20 +02:00
|
|
|
} else {
|
|
|
|
manifestFile = *a.properties.Manifest
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
manifestPath := android.PathForModuleSrc(ctx, manifestFile)
|
2015-09-24 00:26:20 +02:00
|
|
|
aaptDeps = append(aaptDeps, manifestPath)
|
2015-04-13 22:58:27 +02:00
|
|
|
|
2015-09-24 00:26:20 +02:00
|
|
|
aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
|
2016-05-19 00:37:25 +02:00
|
|
|
aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
|
|
|
|
aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
|
2015-04-13 22:58:27 +02:00
|
|
|
|
|
|
|
ctx.VisitDirectDeps(func(module blueprint.Module) {
|
2016-05-19 00:37:25 +02:00
|
|
|
var depFile android.OptionalPath
|
2015-04-13 22:58:27 +02:00
|
|
|
if sdkDep, ok := module.(sdkDependency); ok {
|
2016-05-19 00:37:25 +02:00
|
|
|
depFile = android.OptionalPathForPath(sdkDep.ClasspathFile())
|
2015-04-13 22:58:27 +02:00
|
|
|
} else if javaDep, ok := module.(JavaDependency); ok {
|
|
|
|
if ctx.OtherModuleName(module) == "framework-res" {
|
2016-05-19 00:37:25 +02:00
|
|
|
depFile = android.OptionalPathForPath(javaDep.(*javaBase).module.(*AndroidApp).exportPackage)
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
}
|
2015-09-24 00:26:20 +02:00
|
|
|
if depFile.Valid() {
|
|
|
|
aaptFlags = append(aaptFlags, "-I "+depFile.String())
|
|
|
|
aaptDeps = append(aaptDeps, depFile.Path())
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
sdkVersion := a.properties.Sdk_version
|
|
|
|
if sdkVersion == "" {
|
|
|
|
sdkVersion = ctx.AConfig().PlatformSdkVersion()
|
|
|
|
}
|
|
|
|
|
|
|
|
aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
|
|
|
|
aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
|
|
|
|
|
|
|
|
if !hasVersionCode {
|
|
|
|
aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
|
|
|
|
}
|
|
|
|
|
|
|
|
if !hasVersionName {
|
|
|
|
aaptFlags = append(aaptFlags,
|
|
|
|
"--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: LOCAL_PACKAGE_OVERRIDES
|
|
|
|
// $(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
|
|
|
|
|
|
|
|
// TODO: LOCAL_INSTRUMENTATION_FOR
|
|
|
|
// $(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR))
|
|
|
|
|
|
|
|
return aaptFlags, aaptDeps, hasResources
|
|
|
|
}
|
|
|
|
|
|
|
|
func AndroidAppFactory() (blueprint.Module, []interface{}) {
|
|
|
|
module := &AndroidApp{}
|
|
|
|
|
|
|
|
module.properties.Dex = true
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
return NewJavaBase(&module.javaBase, module, android.DeviceSupported, &module.appProperties)
|
2015-04-13 22:58:27 +02:00
|
|
|
}
|