Replace aapt support with aapt2
Use aapt2 instead of aapt to compile Android app resources. Also generate all files into srcjars instead of individual sources. Test: m checkbuild Change-Id: I5a67991a0daf0017e8159b46fcff7d5564a91468
This commit is contained in:
parent
0875c52de7
commit
3bc7ffa59b
10 changed files with 498 additions and 198 deletions
|
@ -209,6 +209,7 @@ bootstrap_go_package {
|
|||
"soong-java-config",
|
||||
],
|
||||
srcs: [
|
||||
"java/aapt2.go",
|
||||
"java/androidmk.go",
|
||||
"java/app_builder.go",
|
||||
"java/app.go",
|
||||
|
|
|
@ -175,7 +175,12 @@ func saveToConfigFile(config jsonConfigurable, filename string) error {
|
|||
func TestConfig(buildDir string, env map[string]string) Config {
|
||||
config := &config{
|
||||
ProductVariables: productVariables{
|
||||
DeviceName: stringPtr("test_device"),
|
||||
DeviceName: stringPtr("test_device"),
|
||||
Platform_sdk_version: intPtr(26),
|
||||
AAPTConfig: &[]string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
|
||||
AAPTPreferredConfig: stringPtr("xhdpi"),
|
||||
AAPTCharacteristics: stringPtr("nosdcard"),
|
||||
AAPTPrebuiltDPI: &[]string{"xhdpi", "xxhdpi"},
|
||||
},
|
||||
|
||||
buildDir: buildDir,
|
||||
|
@ -417,12 +422,11 @@ func (c *config) DeviceUsesClang() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (c *config) ResourceOverlays() []SourcePath {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *config) PlatformVersion() string {
|
||||
return "M"
|
||||
func (c *config) ResourceOverlays() []string {
|
||||
if c.ProductVariables.ResourceOverlays == nil {
|
||||
return nil
|
||||
}
|
||||
return *c.ProductVariables.ResourceOverlays
|
||||
}
|
||||
|
||||
func (c *config) PlatformSdkVersionInt() int {
|
||||
|
@ -445,6 +449,10 @@ func (c *config) DefaultAppTargetSdkInt() int {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *config) AppsDefaultVersionName() string {
|
||||
return String(c.ProductVariables.AppsDefaultVersionName)
|
||||
}
|
||||
|
||||
// Codenames that are active in the current lunch target.
|
||||
func (c *config) PlatformVersionActiveCodenames() []string {
|
||||
return c.ProductVariables.Platform_version_active_codenames
|
||||
|
@ -466,10 +474,6 @@ func (c *config) PlatformVersionCombinedCodenames() []string {
|
|||
return combined
|
||||
}
|
||||
|
||||
func (c *config) BuildNumber() string {
|
||||
return "000000"
|
||||
}
|
||||
|
||||
func (c *config) ProductAAPTConfig() []string {
|
||||
return *c.ProductVariables.AAPTConfig
|
||||
}
|
||||
|
|
|
@ -428,6 +428,18 @@ func (p WritablePaths) Strings() []string {
|
|||
return ret
|
||||
}
|
||||
|
||||
// Paths returns the WritablePaths as a Paths
|
||||
func (p WritablePaths) Paths() Paths {
|
||||
if p == nil {
|
||||
return nil
|
||||
}
|
||||
ret := make(Paths, len(p))
|
||||
for i, path := range p {
|
||||
ret[i] = path
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type basePath struct {
|
||||
path string
|
||||
config Config
|
||||
|
|
162
java/aapt2.go
Normal file
162
java/aapt2.go
Normal file
|
@ -0,0 +1,162 @@
|
|||
// Copyright 2017 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
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
const AAPT2_SHARD_SIZE = 100
|
||||
|
||||
// Convert input resource file path to output file path.
|
||||
// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
|
||||
// For other resource file, just replace the last "/" with "_" and
|
||||
// add .flat extension.
|
||||
func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
|
||||
|
||||
name := res.Base()
|
||||
subDir := filepath.Dir(res.String())
|
||||
subDir, lastDir := filepath.Split(subDir)
|
||||
if strings.HasPrefix(lastDir, "values") {
|
||||
name = strings.TrimSuffix(name, ".xml") + ".arsc"
|
||||
}
|
||||
name = lastDir + "_" + name + ".flat"
|
||||
return android.PathForModuleOut(ctx, "aapt2", subDir, name)
|
||||
}
|
||||
|
||||
func pathsToAapt2Paths(ctx android.ModuleContext, resPaths android.Paths) android.WritablePaths {
|
||||
outPaths := make(android.WritablePaths, len(resPaths))
|
||||
|
||||
for i, res := range resPaths {
|
||||
outPaths[i] = pathToAapt2Path(ctx, res)
|
||||
}
|
||||
|
||||
return outPaths
|
||||
}
|
||||
|
||||
var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile",
|
||||
blueprint.RuleParams{
|
||||
Command: `${config.Aapt2Cmd compile -o $outDir $cFlags --legacy $in`,
|
||||
CommandDeps: []string{"${config.Aapt2Cmd}"},
|
||||
},
|
||||
"outDir", "cFlags")
|
||||
|
||||
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths) android.WritablePaths {
|
||||
shards := shardPaths(paths, AAPT2_SHARD_SIZE)
|
||||
|
||||
ret := make(android.WritablePaths, 0, len(paths))
|
||||
|
||||
for i, shard := range shards {
|
||||
outPaths := pathsToAapt2Paths(ctx, shard)
|
||||
ret = append(ret, outPaths...)
|
||||
|
||||
shardDesc := ""
|
||||
if i != 0 {
|
||||
shardDesc = " " + strconv.Itoa(i+1)
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aapt2CompileRule,
|
||||
Description: "aapt2 compile " + dir.String() + shardDesc,
|
||||
Inputs: shard,
|
||||
Outputs: outPaths,
|
||||
Args: map[string]string{
|
||||
"outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
|
||||
"cFlags": "--pseudo-localize",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
|
||||
blueprint.RuleParams{
|
||||
Command: `$aapt2Cmd link -o $out $flags --java $genDir --proguard $proguardOptions $inFlags && ` +
|
||||
`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir`,
|
||||
CommandDeps: []string{
|
||||
"$aapt2Cmd",
|
||||
"${config.SoongZipCmd}",
|
||||
},
|
||||
Restat: true,
|
||||
},
|
||||
"flags", "inFlags", "proguardOptions", "genDir", "genJar")
|
||||
|
||||
var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
|
||||
blueprint.RuleParams{
|
||||
Command: `cp $out.rsp $out`,
|
||||
Rspfile: "$out.rsp",
|
||||
RspfileContent: "$in",
|
||||
})
|
||||
|
||||
func aapt2Link(ctx android.ModuleContext,
|
||||
packageRes, genJar, proguardOptions android.WritablePath,
|
||||
flags []string, deps android.Paths,
|
||||
compiledRes, compiledOverlay android.Paths) {
|
||||
|
||||
genDir := android.PathForModuleGen(ctx, "aapt2", "R")
|
||||
|
||||
var inFlags []string
|
||||
|
||||
if len(compiledRes) > 0 {
|
||||
resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list")
|
||||
// Write out file lists to files
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: fileListToFileRule,
|
||||
Description: "resource file list",
|
||||
Inputs: compiledRes,
|
||||
Output: resFileList,
|
||||
})
|
||||
|
||||
deps = append(deps, compiledRes...)
|
||||
deps = append(deps, resFileList)
|
||||
inFlags = append(inFlags, "@"+resFileList.String())
|
||||
}
|
||||
|
||||
if len(compiledOverlay) > 0 {
|
||||
overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list")
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: fileListToFileRule,
|
||||
Description: "overlay resource file list",
|
||||
Inputs: compiledOverlay,
|
||||
Output: overlayFileList,
|
||||
})
|
||||
|
||||
deps = append(deps, compiledOverlay...)
|
||||
deps = append(deps, overlayFileList)
|
||||
inFlags = append(inFlags, "-R", "@"+overlayFileList.String())
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aapt2LinkRule,
|
||||
Description: "aapt2 link",
|
||||
Implicits: deps,
|
||||
Output: packageRes,
|
||||
ImplicitOutputs: android.WritablePaths{proguardOptions, genJar},
|
||||
Args: map[string]string{
|
||||
"flags": strings.Join(flags, " "),
|
||||
"inFlags": strings.Join(inFlags, " "),
|
||||
"proguardOptions": proguardOptions.String(),
|
||||
"genDir": genDir.String(),
|
||||
"genJar": genJar.String(),
|
||||
},
|
||||
})
|
||||
}
|
280
java/app.go
280
java/app.go
|
@ -25,6 +25,10 @@ import (
|
|||
"android/soong/android"
|
||||
)
|
||||
|
||||
func init() {
|
||||
android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
|
||||
}
|
||||
|
||||
// AAR prebuilts
|
||||
// AndroidManifest.xml merging
|
||||
// package splits
|
||||
|
@ -63,14 +67,14 @@ type AndroidApp struct {
|
|||
|
||||
appProperties androidAppProperties
|
||||
|
||||
aaptJavaFileList android.Path
|
||||
exportPackage android.Path
|
||||
aaptSrcJar android.Path
|
||||
exportPackage android.Path
|
||||
}
|
||||
|
||||
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
a.Module.deps(ctx)
|
||||
|
||||
if !proptools.Bool(a.properties.No_standard_libs) {
|
||||
if !Bool(a.properties.No_framework_libs) && !Bool(a.properties.No_standard_libs) {
|
||||
switch String(a.deviceProperties.Sdk_version) { // TODO: Res_sdk_version?
|
||||
case "current", "system_current", "":
|
||||
ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
|
||||
|
@ -81,38 +85,29 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
}
|
||||
|
||||
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
aaptFlags, aaptDeps, hasResources := a.aaptFlags(ctx)
|
||||
linkFlags, linkDeps, resDirs, overlayDirs := a.aapt2Flags(ctx)
|
||||
|
||||
if hasResources {
|
||||
// First generate R.java so we can build the .class files
|
||||
aaptRJavaFlags := append([]string(nil), aaptFlags...)
|
||||
packageRes := android.PathForModuleOut(ctx, "package-res.apk")
|
||||
srcJar := android.PathForModuleGen(ctx, "R.jar")
|
||||
proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options")
|
||||
|
||||
publicResourcesFile, proguardOptionsFile, aaptJavaFileList :=
|
||||
CreateResourceJavaFiles(ctx, aaptRJavaFlags, aaptDeps)
|
||||
a.aaptJavaFileList = aaptJavaFileList
|
||||
// TODO(ccross): export aapt generated java files as a src jar
|
||||
|
||||
if Bool(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)
|
||||
var compiledRes, compiledOverlay android.Paths
|
||||
for _, dir := range resDirs {
|
||||
compiledRes = append(compiledRes, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
|
||||
}
|
||||
for _, dir := range overlayDirs {
|
||||
compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files).Paths()...)
|
||||
}
|
||||
|
||||
aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile,
|
||||
linkFlags, linkDeps, compiledRes, compiledOverlay)
|
||||
|
||||
a.exportPackage = packageRes
|
||||
a.aaptSrcJar = srcJar
|
||||
|
||||
ctx.CheckbuildFile(proguardOptionsFile)
|
||||
ctx.CheckbuildFile(a.exportPackage)
|
||||
ctx.CheckbuildFile(a.aaptSrcJar)
|
||||
|
||||
// apps manifests are handled by aapt, don't let Module see them
|
||||
a.properties.Manifest = nil
|
||||
|
@ -121,26 +116,8 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
// a.properties.Proguard.Enabled = true
|
||||
//}
|
||||
|
||||
if String(a.appProperties.Instrumentation_for) == "" {
|
||||
a.properties.Instrument = true
|
||||
}
|
||||
|
||||
a.Module.compile(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 := String(a.appProperties.Certificate)
|
||||
if certificate == "" {
|
||||
certificate = ctx.AConfig().DefaultAppCertificate(ctx).String()
|
||||
|
@ -155,7 +132,12 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
certificates = append(certificates, filepath.Join(android.PathForSource(ctx).String(), c))
|
||||
}
|
||||
|
||||
a.outputFile = CreateAppPackage(ctx, aaptPackageFlags, a.outputFile, certificates)
|
||||
packageFile := android.PathForModuleOut(ctx, "package.apk")
|
||||
|
||||
CreateAppPackage(ctx, packageFile, a.exportPackage, a.outputFile, certificates)
|
||||
|
||||
a.outputFile = packageFile
|
||||
|
||||
ctx.InstallFile(android.PathForModuleInstall(ctx, "app"), ctx.ModuleName()+".apk", a.outputFile)
|
||||
}
|
||||
|
||||
|
@ -171,57 +153,55 @@ var aaptIgnoreFilenames = []string{
|
|||
"*~",
|
||||
}
|
||||
|
||||
func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Paths, bool) {
|
||||
aaptFlags := a.appProperties.Aaptflags
|
||||
type globbedResourceDir struct {
|
||||
dir android.Path
|
||||
files android.Paths
|
||||
}
|
||||
|
||||
func (a *AndroidApp) aapt2Flags(ctx android.ModuleContext) (flags []string, deps android.Paths,
|
||||
resDirs, overlayDirs []globbedResourceDir) {
|
||||
|
||||
hasVersionCode := false
|
||||
hasVersionName := false
|
||||
for _, f := range aaptFlags {
|
||||
hasProduct := false
|
||||
for _, f := range a.appProperties.Aaptflags {
|
||||
if strings.HasPrefix(f, "--version-code") {
|
||||
hasVersionCode = true
|
||||
} else if strings.HasPrefix(f, "--version-name") {
|
||||
hasVersionName = true
|
||||
} else if strings.HasPrefix(f, "--product") {
|
||||
hasProduct = true
|
||||
}
|
||||
}
|
||||
|
||||
if true /* is not a test */ {
|
||||
aaptFlags = append(aaptFlags, "-z")
|
||||
}
|
||||
var linkFlags []string
|
||||
|
||||
// Flags specified in Android.bp
|
||||
linkFlags = append(linkFlags, a.appProperties.Aaptflags...)
|
||||
|
||||
linkFlags = append(linkFlags, "--no-static-lib-packages")
|
||||
|
||||
// Find implicit or explicit asset and resource dirs
|
||||
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Asset_dirs, "assets")
|
||||
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.appProperties.Resource_dirs, "res")
|
||||
|
||||
var overlayResourceDirs android.Paths
|
||||
// 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 {
|
||||
overlay := overlayDir.OverlayPath(ctx, resourceDir)
|
||||
if overlay.Valid() {
|
||||
overlayResourceDirs = append(overlayResourceDirs, overlay.Path())
|
||||
}
|
||||
}
|
||||
var linkDeps android.Paths
|
||||
|
||||
// Glob directories into lists of paths
|
||||
for _, dir := range resourceDirs {
|
||||
resDirs = append(resDirs, globbedResourceDir{
|
||||
dir: dir,
|
||||
files: resourceGlob(ctx, dir),
|
||||
})
|
||||
overlayDirs = append(overlayDirs, overlayResourceGlob(ctx, dir)...)
|
||||
}
|
||||
|
||||
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.
|
||||
var aaptDeps android.Paths
|
||||
var hasResources bool
|
||||
for _, d := range resourceDirs {
|
||||
newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
||||
aaptDeps = append(aaptDeps, newDeps...)
|
||||
if len(newDeps) > 0 {
|
||||
hasResources = true
|
||||
}
|
||||
}
|
||||
for _, d := range assetDirs {
|
||||
newDeps := ctx.Glob(filepath.Join(d.String(), "**/*"), aaptIgnoreFilenames)
|
||||
aaptDeps = append(aaptDeps, newDeps...)
|
||||
var assetFiles android.Paths
|
||||
for _, dir := range assetDirs {
|
||||
assetFiles = append(assetFiles, resourceGlob(ctx, dir)...)
|
||||
}
|
||||
|
||||
// App manifest file
|
||||
var manifestFile string
|
||||
if a.properties.Manifest == nil {
|
||||
manifestFile = "AndroidManifest.xml"
|
||||
|
@ -230,50 +210,73 @@ func (a *AndroidApp) aaptFlags(ctx android.ModuleContext) ([]string, android.Pat
|
|||
}
|
||||
|
||||
manifestPath := android.PathForModuleSrc(ctx, manifestFile)
|
||||
aaptDeps = append(aaptDeps, manifestPath)
|
||||
linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
|
||||
linkDeps = append(linkDeps, manifestPath)
|
||||
|
||||
aaptFlags = append(aaptFlags, "-M "+manifestPath.String())
|
||||
aaptFlags = append(aaptFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
|
||||
aaptFlags = append(aaptFlags, android.JoinWithPrefix(resourceDirs.Strings(), "-S "))
|
||||
linkFlags = append(linkFlags, android.JoinWithPrefix(assetDirs.Strings(), "-A "))
|
||||
linkDeps = append(linkDeps, assetFiles...)
|
||||
|
||||
// Include dirs
|
||||
ctx.VisitDirectDeps(func(module android.Module) {
|
||||
var depFiles android.Paths
|
||||
if javaDep, ok := module.(Dependency); ok {
|
||||
// TODO: shared android libraries
|
||||
if ctx.OtherModuleName(module) == "framework-res" {
|
||||
depFiles = android.Paths{javaDep.(*AndroidApp).exportPackage}
|
||||
}
|
||||
}
|
||||
|
||||
for _, dep := range depFiles {
|
||||
aaptFlags = append(aaptFlags, "-I "+dep.String())
|
||||
linkFlags = append(linkFlags, "-I "+dep.String())
|
||||
}
|
||||
aaptDeps = append(aaptDeps, depFiles...)
|
||||
linkDeps = append(linkDeps, depFiles...)
|
||||
})
|
||||
|
||||
// SDK version flags
|
||||
sdkVersion := String(a.deviceProperties.Sdk_version)
|
||||
if sdkVersion == "" {
|
||||
sdkVersion = ctx.AConfig().PlatformSdkVersion()
|
||||
switch sdkVersion {
|
||||
case "", "current", "system_current", "test_current":
|
||||
sdkVersion = ctx.AConfig().AppsDefaultVersionName()
|
||||
}
|
||||
|
||||
aaptFlags = append(aaptFlags, "--min-sdk-version "+sdkVersion)
|
||||
aaptFlags = append(aaptFlags, "--target-sdk-version "+sdkVersion)
|
||||
linkFlags = append(linkFlags, "--min-sdk-version "+sdkVersion)
|
||||
linkFlags = append(linkFlags, "--target-sdk-version "+sdkVersion)
|
||||
|
||||
// Product characteristics
|
||||
if !hasProduct && len(ctx.AConfig().ProductAAPTCharacteristics()) > 0 {
|
||||
linkFlags = append(linkFlags, "--product", ctx.AConfig().ProductAAPTCharacteristics())
|
||||
}
|
||||
|
||||
// Product AAPT config
|
||||
for _, aaptConfig := range ctx.AConfig().ProductAAPTConfig() {
|
||||
linkFlags = append(linkFlags, "-c", aaptConfig)
|
||||
}
|
||||
|
||||
// Product AAPT preferred config
|
||||
if len(ctx.AConfig().ProductAAPTPreferredConfig()) > 0 {
|
||||
linkFlags = append(linkFlags, "--preferred-density", ctx.AConfig().ProductAAPTPreferredConfig())
|
||||
}
|
||||
|
||||
// Version code
|
||||
if !hasVersionCode {
|
||||
aaptFlags = append(aaptFlags, "--version-code "+ctx.AConfig().PlatformSdkVersion())
|
||||
linkFlags = append(linkFlags, "--version-code", ctx.AConfig().PlatformSdkVersion())
|
||||
}
|
||||
|
||||
if !hasVersionName {
|
||||
aaptFlags = append(aaptFlags,
|
||||
"--version-name "+ctx.AConfig().PlatformVersion()+"-"+ctx.AConfig().BuildNumber())
|
||||
versionName := proptools.NinjaEscape([]string{ctx.AConfig().AppsDefaultVersionName()})[0]
|
||||
linkFlags = append(linkFlags, "--version-name ", versionName)
|
||||
}
|
||||
|
||||
if String(a.appProperties.Instrumentation_for) != "" {
|
||||
linkFlags = append(linkFlags,
|
||||
"--rename-instrumentation-target-package",
|
||||
String(a.appProperties.Instrumentation_for))
|
||||
}
|
||||
|
||||
// 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
|
||||
return linkFlags, linkDeps, resDirs, overlayDirs
|
||||
}
|
||||
|
||||
func AndroidAppFactory() android.Module {
|
||||
|
@ -287,3 +290,76 @@ func AndroidAppFactory() android.Module {
|
|||
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
||||
return module
|
||||
}
|
||||
|
||||
func resourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
|
||||
var ret android.Paths
|
||||
files := ctx.Glob(filepath.Join(dir.String(), "**/*"), aaptIgnoreFilenames)
|
||||
for _, f := range files {
|
||||
if isDir, err := ctx.Fs().IsDir(f.String()); err != nil {
|
||||
ctx.ModuleErrorf("error in IsDir(%s): %s", f.String(), err.Error())
|
||||
return nil
|
||||
} else if !isDir {
|
||||
ret = append(ret, f)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type overlayGlobResult struct {
|
||||
dir string
|
||||
paths android.DirectorySortedPaths
|
||||
}
|
||||
|
||||
const overlayDataKey = "overlayDataKey"
|
||||
|
||||
func overlayResourceGlob(ctx android.ModuleContext, dir android.Path) []globbedResourceDir {
|
||||
overlayData := ctx.AConfig().Get(overlayDataKey).([]overlayGlobResult)
|
||||
|
||||
var ret []globbedResourceDir
|
||||
|
||||
for _, data := range overlayData {
|
||||
files := data.paths.PathsInDirectory(filepath.Join(data.dir, dir.String()))
|
||||
if len(files) > 0 {
|
||||
ret = append(ret, globbedResourceDir{
|
||||
dir: android.PathForSource(ctx, data.dir, dir.String()),
|
||||
files: files,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func OverlaySingletonFactory() android.Singleton {
|
||||
return overlaySingleton{}
|
||||
}
|
||||
|
||||
type overlaySingleton struct{}
|
||||
|
||||
func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||
var overlayData []overlayGlobResult
|
||||
for _, overlay := range ctx.Config().(android.Config).ResourceOverlays() {
|
||||
var result overlayGlobResult
|
||||
result.dir = overlay
|
||||
files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), aaptIgnoreFilenames)
|
||||
if err != nil {
|
||||
ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
|
||||
continue
|
||||
}
|
||||
var paths android.Paths
|
||||
for _, f := range files {
|
||||
if isDir, err := ctx.Fs().IsDir(f); err != nil {
|
||||
ctx.Errorf("error in IsDir(%s): %s", f, err.Error())
|
||||
return
|
||||
} else if !isDir {
|
||||
paths = append(paths, android.PathForSource(ctx, f))
|
||||
}
|
||||
}
|
||||
result.paths = android.PathsToDirectorySortedPaths(paths)
|
||||
overlayData = append(overlayData, result)
|
||||
}
|
||||
|
||||
ctx.Config().(android.Config).Once(overlayDataKey, func() interface{} {
|
||||
return overlayData
|
||||
})
|
||||
}
|
||||
|
|
|
@ -27,31 +27,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
aaptCreateResourceJavaFile = pctx.AndroidStaticRule("aaptCreateResourceJavaFile",
|
||||
blueprint.RuleParams{
|
||||
Command: `rm -rf "$javaDir" && mkdir -p "$javaDir" && ` +
|
||||
`$aaptCmd package -m $aaptFlags -P $publicResourcesFile -G $proguardOptionsFile ` +
|
||||
`-J $javaDir || ( rm -rf "$javaDir/*"; exit 41 ) && ` +
|
||||
`find $javaDir -name "*.java" > $javaFileList`,
|
||||
CommandDeps: []string{"$aaptCmd"},
|
||||
},
|
||||
"aaptFlags", "publicResourcesFile", "proguardOptionsFile", "javaDir", "javaFileList")
|
||||
|
||||
aaptCreateAssetsPackage = pctx.AndroidStaticRule("aaptCreateAssetsPackage",
|
||||
blueprint.RuleParams{
|
||||
Command: `rm -f $out && $aaptCmd package $aaptFlags -F $out`,
|
||||
CommandDeps: []string{"$aaptCmd"},
|
||||
},
|
||||
"aaptFlags", "publicResourcesFile", "proguardOptionsFile", "javaDir", "javaFileList")
|
||||
|
||||
aaptAddResources = pctx.AndroidStaticRule("aaptAddResources",
|
||||
blueprint.RuleParams{
|
||||
// TODO: add-jni-shared-libs-to-package
|
||||
Command: `cp -f $in $out.tmp && $aaptCmd package -u $aaptFlags -F $out.tmp && mv $out.tmp $out`,
|
||||
CommandDeps: []string{"$aaptCmd"},
|
||||
},
|
||||
"aaptFlags")
|
||||
|
||||
signapk = pctx.AndroidStaticRule("signapk",
|
||||
blueprint.RuleParams{
|
||||
Command: `java -jar $signapkCmd $certificates $in $out`,
|
||||
|
@ -75,63 +50,30 @@ func init() {
|
|||
pctx.HostJavaToolVariable("signapkCmd", "signapk.jar")
|
||||
}
|
||||
|
||||
func CreateResourceJavaFiles(ctx android.ModuleContext, flags []string,
|
||||
deps android.Paths) (android.Path, android.Path, android.Path) {
|
||||
javaDir := android.PathForModuleGen(ctx, "R")
|
||||
javaFileList := android.PathForModuleOut(ctx, "R.filelist")
|
||||
publicResourcesFile := android.PathForModuleOut(ctx, "public_resources.xml")
|
||||
proguardOptionsFile := android.PathForModuleOut(ctx, "proguard.options")
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aaptCreateResourceJavaFile,
|
||||
Description: "aapt create R.java",
|
||||
Outputs: android.WritablePaths{publicResourcesFile, proguardOptionsFile, javaFileList},
|
||||
Implicits: deps,
|
||||
Args: map[string]string{
|
||||
"aaptFlags": strings.Join(flags, " "),
|
||||
"publicResourcesFile": publicResourcesFile.String(),
|
||||
"proguardOptionsFile": proguardOptionsFile.String(),
|
||||
"javaDir": javaDir.String(),
|
||||
"javaFileList": javaFileList.String(),
|
||||
},
|
||||
var combineApk = pctx.AndroidStaticRule("combineApk",
|
||||
blueprint.RuleParams{
|
||||
Command: `${config.MergeZipsCmd} $out $in`,
|
||||
CommandDeps: []string{"${config.MergeZipsCmd}"},
|
||||
})
|
||||
|
||||
return publicResourcesFile, proguardOptionsFile, javaFileList
|
||||
}
|
||||
func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
|
||||
resJarFile, dexJarFile android.Path, certificates []string) {
|
||||
|
||||
func CreateExportPackage(ctx android.ModuleContext, flags []string, deps android.Paths) android.ModuleOutPath {
|
||||
outputFile := android.PathForModuleOut(ctx, "package-export.apk")
|
||||
// TODO(ccross): JNI libs
|
||||
|
||||
unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
|
||||
|
||||
inputs := android.Paths{resJarFile}
|
||||
if dexJarFile != nil {
|
||||
inputs = append(inputs, dexJarFile)
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aaptCreateAssetsPackage,
|
||||
Description: "aapt export package",
|
||||
Output: outputFile,
|
||||
Implicits: deps,
|
||||
Args: map[string]string{
|
||||
"aaptFlags": strings.Join(flags, " "),
|
||||
},
|
||||
Rule: combineApk,
|
||||
Inputs: inputs,
|
||||
Output: unsignedApk,
|
||||
})
|
||||
|
||||
return outputFile
|
||||
}
|
||||
|
||||
func CreateAppPackage(ctx android.ModuleContext, flags []string, jarFile android.Path,
|
||||
certificates []string) android.Path {
|
||||
|
||||
resourceApk := android.PathForModuleOut(ctx, "resources.apk")
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: aaptAddResources,
|
||||
Description: "aapt package",
|
||||
Output: resourceApk,
|
||||
Input: jarFile,
|
||||
Args: map[string]string{
|
||||
"aaptFlags": strings.Join(flags, " "),
|
||||
},
|
||||
})
|
||||
|
||||
outputFile := android.PathForModuleOut(ctx, "package.apk")
|
||||
|
||||
var certificateArgs []string
|
||||
for _, c := range certificates {
|
||||
certificateArgs = append(certificateArgs, c+".x509.pem", c+".pk8")
|
||||
|
@ -141,11 +83,9 @@ func CreateAppPackage(ctx android.ModuleContext, flags []string, jarFile android
|
|||
Rule: signapk,
|
||||
Description: "signapk",
|
||||
Output: outputFile,
|
||||
Input: resourceApk,
|
||||
Input: unsignedApk,
|
||||
Args: map[string]string{
|
||||
"certificates": strings.Join(certificateArgs, " "),
|
||||
},
|
||||
})
|
||||
|
||||
return outputFile
|
||||
}
|
||||
|
|
90
java/app_test.go
Normal file
90
java/app_test.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2017 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
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
resourceFiles = []string{
|
||||
"res/layout/layout.xml",
|
||||
"res/values/strings.xml",
|
||||
"res/values-en-rUS/strings.xml",
|
||||
}
|
||||
|
||||
compiledResourceFiles = []string{
|
||||
"aapt2/res/layout_layout.xml.flat",
|
||||
"aapt2/res/values_strings.arsc.flat",
|
||||
"aapt2/res/values-en-rUS_strings.arsc.flat",
|
||||
}
|
||||
)
|
||||
|
||||
func testApp(t *testing.T, bp string) *android.TestContext {
|
||||
bp += `
|
||||
android_app {
|
||||
name: "framework-res",
|
||||
no_framework_libs: true,
|
||||
}
|
||||
`
|
||||
|
||||
appFs := map[string][]byte{
|
||||
"AndroidManifest.xml": nil,
|
||||
"build/target/product/security/testkey": nil,
|
||||
}
|
||||
|
||||
for _, file := range resourceFiles {
|
||||
appFs[file] = nil
|
||||
}
|
||||
|
||||
return testJavaWithEnvFs(t, bp, nil, appFs)
|
||||
}
|
||||
|
||||
func TestApp(t *testing.T) {
|
||||
ctx := testApp(t, `
|
||||
android_app {
|
||||
name: "foo",
|
||||
srcs: ["a.java"],
|
||||
}
|
||||
`)
|
||||
|
||||
foo := ctx.ModuleForTests("foo", "android_common")
|
||||
|
||||
expectedLinkImplicits := []string{"AndroidManifest.xml"}
|
||||
|
||||
frameworkRes := ctx.ModuleForTests("framework-res", "android_common")
|
||||
expectedLinkImplicits = append(expectedLinkImplicits,
|
||||
frameworkRes.Output("package-res.apk").Output.String())
|
||||
|
||||
// Test the mapping from input files to compiled output file names
|
||||
compile := foo.Output(compiledResourceFiles[0])
|
||||
if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) {
|
||||
t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v",
|
||||
resourceFiles, compile.Inputs.Strings())
|
||||
}
|
||||
expectedLinkImplicits = append(expectedLinkImplicits, compile.Outputs.Strings()...)
|
||||
|
||||
list := foo.Output("aapt2/res.list")
|
||||
expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
|
||||
|
||||
// Check that the link rule uses
|
||||
res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk")
|
||||
if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) {
|
||||
t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v",
|
||||
expectedLinkImplicits, res.Implicits.Strings())
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
_ "github.com/google/blueprint/bootstrap"
|
||||
|
@ -130,4 +132,20 @@ func init() {
|
|||
})
|
||||
|
||||
pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar")
|
||||
|
||||
hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) {
|
||||
pctx.VariableFunc(name, func(config android.Config) (string, error) {
|
||||
if config.UnbundledBuild() || config.IsPdkBuild() {
|
||||
return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool), nil
|
||||
} else {
|
||||
if path, err := pctx.HostBinToolPath(config, tool); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return path.String(), nil
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
hostBinToolVariableWithPrebuilt("Aapt2Cmd", "prebuilt/sdk/tools", "aapt2")
|
||||
}
|
||||
|
|
10
java/java.go
10
java/java.go
|
@ -204,10 +204,6 @@ type Module struct {
|
|||
|
||||
logtagsSrcs android.Paths
|
||||
|
||||
// jars containing source files that should be included in the javac command line,
|
||||
// for example R.java generated by aapt for android apps
|
||||
ExtraSrcJars android.Paths
|
||||
|
||||
// installed file for binary dependency
|
||||
installFile android.Path
|
||||
}
|
||||
|
@ -487,7 +483,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||
if ctx.ModuleName() == "framework" {
|
||||
// framework.jar has a one-off dependency on the R.java and Manifest.java files
|
||||
// generated by framework-res.apk
|
||||
// TODO(ccross): aapt java files should go in a src jar
|
||||
deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
|
||||
}
|
||||
case kotlinStdlibTag:
|
||||
deps.kotlinStdlib = dep.HeaderJars()
|
||||
|
@ -555,7 +551,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
|
|||
return flags
|
||||
}
|
||||
|
||||
func (j *Module) compile(ctx android.ModuleContext) {
|
||||
func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path) {
|
||||
|
||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
||||
|
||||
|
@ -574,7 +570,7 @@ func (j *Module) compile(ctx android.ModuleContext) {
|
|||
|
||||
srcJars := srcFiles.FilterByExt(".srcjar")
|
||||
srcJars = append(srcJars, deps.srcJars...)
|
||||
srcJars = append(srcJars, j.ExtraSrcJars...)
|
||||
srcJars = append(srcJars, extraSrcJars...)
|
||||
|
||||
var jars android.Paths
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ func testJavaWithEnvFs(t *testing.T, bp string,
|
|||
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
|
||||
ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
|
||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||
ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
|
||||
ctx.Register()
|
||||
|
||||
extraModules := []string{
|
||||
|
|
Loading…
Reference in a new issue