2015-04-14 04:58:27 +08: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"
|
|
|
|
|
2017-08-30 07:02:06 +08:00
|
|
|
"github.com/google/blueprint/proptools"
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2016-05-19 06:37:25 +08:00
|
|
|
"android/soong/android"
|
2015-04-14 04:58:27 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// AAR prebuilts
|
|
|
|
// AndroidManifest.xml merging
|
|
|
|
// package splits
|
|
|
|
|
2015-05-12 04:39:40 +08: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-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
// paths to extra certificates to sign the apk with
|
|
|
|
Additional_certificates []string
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08: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-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
// flags passed to aapt when creating the apk
|
|
|
|
Aaptflags []string
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
// list of resource labels to generate individual resource packages
|
|
|
|
Package_splits []string
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
// list of directories relative to the Blueprints file containing assets.
|
|
|
|
// Defaults to "assets"
|
|
|
|
Asset_dirs []string
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
// list of directories relative to the Blueprints file containing
|
2017-09-28 08:33:10 +08:00
|
|
|
// Android resources
|
|
|
|
Resource_dirs []string
|
2015-05-12 04:39:40 +08:00
|
|
|
}
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-05-12 04:39:40 +08:00
|
|
|
type AndroidApp struct {
|
2017-06-23 07:51:17 +08:00
|
|
|
Module
|
2015-05-12 04:39:40 +08:00
|
|
|
|
|
|
|
appProperties androidAppProperties
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2016-05-19 06:37:25 +08:00
|
|
|
aaptJavaFileList android.Path
|
|
|
|
exportPackage android.Path
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
|
2017-06-23 07:51:17 +08:00
|
|
|
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|
|
|
a.Module.deps(ctx)
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2017-08-30 07:02:06 +08:00
|
|
|
if !proptools.Bool(a.properties.No_standard_libs) {
|
2017-06-23 08:01:52 +08:00
|
|
|
switch a.deviceProperties.Sdk_version { // TODO: Res_sdk_version?
|
2015-04-14 04:58:27 +08:00
|
|
|
case "current", "system_current", "":
|
2017-07-08 06:59:46 +08:00
|
|
|
ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
|
2015-04-14 04:58:27 +08:00
|
|
|
default:
|
|
|
|
// We'll already have a dependency on an sdk prebuilt android.jar
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-23 07:51:17 +08:00
|
|
|
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
2015-04-14 04:58:27 +08: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
|
2017-10-17 09:07:29 +08:00
|
|
|
// TODO(ccross): export aapt generated java files as a src jar
|
2015-04-14 04:58:27 +08:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2017-06-23 07:51:17 +08:00
|
|
|
// apps manifests are handled by aapt, don't let Module see them
|
2015-09-24 06:26:20 +08:00
|
|
|
a.properties.Manifest = nil
|
2015-04-14 04:58:27 +08:00
|
|
|
|
|
|
|
//if !ctx.ContainsProperty("proguard.enabled") {
|
|
|
|
// a.properties.Proguard.Enabled = true
|
|
|
|
//}
|
|
|
|
|
2017-06-23 07:51:17 +08:00
|
|
|
a.Module.compile(ctx)
|
2015-04-14 04:58:27 +08:00
|
|
|
|
|
|
|
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 06:26:20 +08:00
|
|
|
certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
|
2015-04-14 04:58:27 +08:00
|
|
|
} else if dir, _ := filepath.Split(certificate); dir == "" {
|
2015-09-24 06:26:20 +08:00
|
|
|
certificate = filepath.Join(ctx.AConfig().DefaultAppCertificateDir(ctx).String(), certificate)
|
2015-04-14 04:58:27 +08:00
|
|
|
} else {
|
2016-05-19 06:37:25 +08:00
|
|
|
certificate = filepath.Join(android.PathForSource(ctx).String(), certificate)
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
certificates := []string{certificate}
|
|
|
|
for _, c := range a.appProperties.Additional_certificates {
|
2016-05-19 06:37:25 +08:00
|
|
|
certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
|
2017-09-01 03:29:17 +08:00
|
|
|
ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var aaptIgnoreFilenames = []string{
|
|
|
|
".svn",
|
|
|
|
".git",
|
|
|
|
".ds_store",
|
|
|
|
"*.scc",
|
|
|
|
".*",
|
|
|
|
"CVS",
|
|
|
|
"thumbs.db",
|
|
|
|
"picasa.ini",
|
|
|
|
"*~",
|
|
|
|
}
|
|
|
|
|
2016-05-19 06:37:25 +08:00
|
|
|
func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
|
2015-04-14 04:58:27 +08: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 06:37:25 +08:00
|
|
|
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
|
2017-09-28 08:33:10 +08:00
|
|
|
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2016-05-19 06:37:25 +08:00
|
|
|
var overlayResourceDirs android.Paths
|
2015-04-14 04:58:27 +08: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 06:26:20 +08:00
|
|
|
overlay := overlayDir.OverlayPath(ctx, resourceDir)
|
|
|
|
if overlay.Valid() {
|
|
|
|
overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
|
2015-04-14 04:58:27 +08: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 06:37:25 +08:00
|
|
|
var aaptDeps android.Paths
|
2015-04-14 04:58:27 +08:00
|
|
|
var hasResources bool
|
|
|
|
for _, d := range resourceDirs {
|
2016-11-02 02:10:25 +08:00
|
|
|
newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
2015-04-14 04:58:27 +08:00
|
|
|
aaptDeps = append(aaptDeps, newDeps...)
|
|
|
|
if len(newDeps) > 0 {
|
|
|
|
hasResources = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for _, d := range assetDirs {
|
2016-11-02 02:10:25 +08:00
|
|
|
newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
2015-04-14 04:58:27 +08:00
|
|
|
aaptDeps = append(aaptDeps, newDeps...)
|
|
|
|
}
|
|
|
|
|
2015-09-24 06:26:20 +08:00
|
|
|
var manifestFile string
|
|
|
|
if a.properties.Manifest == nil {
|
2015-04-14 04:58:27 +08:00
|
|
|
manifestFile = "AndroidManifest.xml"
|
2015-09-24 06:26:20 +08:00
|
|
|
} else {
|
|
|
|
manifestFile = *a.properties.Manifest
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
|
2016-05-19 06:37:25 +08:00
|
|
|
manifestPath := android.PathForModuleSrc(ctx, manifestFile)
|
2015-09-24 06:26:20 +08:00
|
|
|
aaptDeps = append(aaptDeps, manifestPath)
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2015-09-24 06:26:20 +08:00
|
|
|
aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
|
2016-05-19 06:37:25 +08:00
|
|
|
aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
|
|
|
|
aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
|
2015-04-14 04:58:27 +08:00
|
|
|
|
2017-10-24 08:59:01 +08:00
|
|
|
ctx.VisitDirectDeps(func(module android.Module) {
|
2017-08-03 02:05:49 +08:00
|
|
|
var depFiles android.Paths
|
2017-09-19 08:41:52 +08:00
|
|
|
if javaDep, ok := module.(Dependency); ok {
|
2015-04-14 04:58:27 +08:00
|
|
|
if ctx.OtherModuleName(module) == "framework-res" {
|
2017-08-03 02:05:49 +08:00
|
|
|
depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
|
|
|
}
|
2017-08-03 02:05:49 +08:00
|
|
|
|
|
|
|
for _, dep := range depFiles {
|
|
|
|
aaptFlags = append(aaptFlags, "-I "+dep.String())
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|
2017-08-03 02:05:49 +08:00
|
|
|
aaptDeps = append(aaptDeps, depFiles...)
|
2015-04-14 04:58:27 +08:00
|
|
|
})
|
|
|
|
|
2017-06-23 08:01:52 +08:00
|
|
|
sdkVersion := a.deviceProperties.Sdk_version
|
2015-04-14 04:58:27 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2017-06-24 06:06:31 +08:00
|
|
|
func AndroidAppFactory() android.Module {
|
2015-04-14 04:58:27 +08:00
|
|
|
module := &AndroidApp{}
|
|
|
|
|
2017-06-24 06:06:31 +08:00
|
|
|
module.AddProperties(
|
2017-06-23 08:01:52 +08:00
|
|
|
&module.Module.properties,
|
|
|
|
&module.Module.deviceProperties,
|
|
|
|
&module.appProperties)
|
2017-06-24 06:06:31 +08:00
|
|
|
|
|
|
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
|
|
|
return module
|
2015-04-14 04:58:27 +08:00
|
|
|
}
|