diff options
author | Colin Cross <ccross@android.com> | 2017-11-22 16:19:37 -0800 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2017-11-29 05:05:07 +0000 |
commit | 3bc7ffa59b8277b3a36eb9e16192583b3b9a93ea (patch) | |
tree | 1a768f402d17a3181a18177e17935dbd1d3c60b2 /java | |
parent | 0875c52de753b858b74a9ac285626536bee9cb57 (diff) | |
download | android_build_soong-3bc7ffa59b8277b3a36eb9e16192583b3b9a93ea.tar.gz android_build_soong-3bc7ffa59b8277b3a36eb9e16192583b3b9a93ea.tar.bz2 android_build_soong-3bc7ffa59b8277b3a36eb9e16192583b3b9a93ea.zip |
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
Diffstat (limited to 'java')
-rw-r--r-- | java/aapt2.go | 162 | ||||
-rw-r--r-- | java/app.go | 280 | ||||
-rw-r--r-- | java/app_builder.go | 92 | ||||
-rw-r--r-- | java/app_test.go | 90 | ||||
-rw-r--r-- | java/config/config.go | 18 | ||||
-rw-r--r-- | java/java.go | 10 | ||||
-rw-r--r-- | java/java_test.go | 1 |
7 files changed, 468 insertions, 185 deletions
diff --git a/java/aapt2.go b/java/aapt2.go new file mode 100644 index 00000000..ce307fe7 --- /dev/null +++ b/java/aapt2.go @@ -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(), + }, + }) +} diff --git a/java/app.go b/java/app.go index 68e4d5cc..fd1fe33f 100644 --- a/java/app.go +++ b/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,39 +85,30 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { - 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 - // 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 - } - } + linkFlags, linkDeps, resDirs, overlayDirs := a.aapt2Flags(ctx) - 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) + packageRes := android.PathForModuleOut(ctx, "package-res.apk") + srcJar := android.PathForModuleGen(ctx, "R.jar") + proguardOptionsFile := android.PathForModuleGen(ctx, "proguard.options") + + 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 - if len(overlayResourceDirs) > 0 { - resourceDirs = append(overlayResourceDirs, resourceDirs...) + // 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)...) } - // 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 + }) +} diff --git a/java/app_builder.go b/java/app_builder.go index ed7abce6..82574aef 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -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 - ctx.Build(pctx, android.BuildParams{ - Rule: aaptCreateAssetsPackage, - Description: "aapt export package", - Output: outputFile, - Implicits: deps, - Args: map[string]string{ - "aaptFlags": strings.Join(flags, " "), - }, - }) - - return outputFile -} + unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk") -func CreateAppPackage(ctx android.ModuleContext, flags []string, jarFile android.Path, - certificates []string) android.Path { - - resourceApk := android.PathForModuleOut(ctx, "resources.apk") + inputs := android.Paths{resJarFile} + if dexJarFile != nil { + inputs = append(inputs, dexJarFile) + } ctx.Build(pctx, android.BuildParams{ - Rule: aaptAddResources, - Description: "aapt package", - Output: resourceApk, - Input: jarFile, - Args: map[string]string{ - "aaptFlags": strings.Join(flags, " "), - }, + Rule: combineApk, + Inputs: inputs, + Output: unsignedApk, }) - 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 } diff --git a/java/app_test.go b/java/app_test.go new file mode 100644 index 00000000..0b1491e7 --- /dev/null +++ b/java/app_test.go @@ -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()) + } +} diff --git a/java/config/config.go b/java/config/config.go index 466563f5..603d43fe 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -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") } diff --git a/java/java.go b/java/java.go index 417cf741..0a3b9b40 100644 --- a/java/java.go +++ b/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 diff --git a/java/java_test.go b/java/java_test.go index 143e82cd..cf5047bb 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -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{ |