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
diff --git a/java/app.go b/java/app.go
index 68e4d5c..fd1fe33 100644
--- a/java/app.go
+++ b/java/app.go
@@ -25,6 +25,10 @@
"android/soong/android"
)
+func init() {
+ android.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+}
+
// AAR prebuilts
// AndroidManifest.xml merging
// package splits
@@ -63,14 +67,14 @@
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) 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 @@
// 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 @@
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 @@
"*~",
}
-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...)
+ var assetFiles android.Paths
+ for _, dir := range assetDirs {
+ assetFiles = append(assetFiles, resourceGlob(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...)
- }
-
+ // App manifest file
var manifestFile string
if a.properties.Manifest == nil {
manifestFile = "AndroidManifest.xml"
@@ -230,50 +210,73 @@
}
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 @@
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
+ })
+}