Merge "Add rules to handle asset resources." am: 387ad5c576

Change-Id: Iae9ef6b005b3d36fe24a805233ae9d1eeb2ad70b
This commit is contained in:
Automerger Merge Worker
2020-02-05 23:24:49 +00:00
5 changed files with 176 additions and 10 deletions

View File

@@ -121,8 +121,19 @@ func InList(s string, list []string) bool {
return IndexList(s, list) != -1 return IndexList(s, list) != -1
} }
func PrefixInList(s string, list []string) bool { // Returns true if the given string s is prefixed with any string in the given prefix list.
for _, prefix := range list { func PrefixInList(s string, prefixList []string) bool {
for _, prefix := range prefixList {
if strings.HasPrefix(s, prefix) {
return true
}
}
return false
}
// Returns true if any string in the given list has the given prefix.
func PrefixedStringInList(list []string, prefix string) bool {
for _, s := range list {
if strings.HasPrefix(s, prefix) { if strings.HasPrefix(s, prefix) {
return true return true
} }

View File

@@ -147,10 +147,16 @@ var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
RspfileContent: "$in", RspfileContent: "$in",
}) })
var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
blueprint.RuleParams{
Command: `${config.MergeZipsCmd} ${out} ${in}`,
CommandDeps: []string{"${config.MergeZipsCmd}"},
})
func aapt2Link(ctx android.ModuleContext, func aapt2Link(ctx android.ModuleContext,
packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath, packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
flags []string, deps android.Paths, flags []string, deps android.Paths,
compiledRes, compiledOverlay android.Paths, splitPackages android.WritablePaths) { compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
genDir := android.PathForModuleGen(ctx, "aapt2", "R") genDir := android.PathForModuleGen(ctx, "aapt2", "R")
@@ -186,12 +192,25 @@ func aapt2Link(ctx android.ModuleContext,
} }
implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages) implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
linkOutput := packageRes
// AAPT2 ignores assets in overlays. Merge them after linking.
if len(assetPackages) > 0 {
linkOutput = android.PathForModuleOut(ctx, "aapt2", "package-res.apk")
inputZips := append(android.Paths{linkOutput}, assetPackages...)
ctx.Build(pctx, android.BuildParams{
Rule: mergeAssetsRule,
Inputs: inputZips,
Output: packageRes,
Description: "merge assets from dependencies",
})
}
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
Rule: aapt2LinkRule, Rule: aapt2LinkRule,
Description: "aapt2 link", Description: "aapt2 link",
Implicits: deps, Implicits: deps,
Output: packageRes, Output: linkOutput,
ImplicitOutputs: implicitOutputs, ImplicitOutputs: implicitOutputs,
Args: map[string]string{ Args: map[string]string{
"flags": strings.Join(flags, " "), "flags": strings.Join(flags, " "),

View File

@@ -32,6 +32,7 @@ type AndroidLibraryDependency interface {
ExportedRRODirs() []rroDir ExportedRRODirs() []rroDir
ExportedStaticPackages() android.Paths ExportedStaticPackages() android.Paths
ExportedManifests() android.Paths ExportedManifests() android.Paths
ExportedAssets() android.OptionalPath
} }
func init() { func init() {
@@ -93,6 +94,7 @@ type aapt struct {
extraAaptPackagesFile android.Path extraAaptPackagesFile android.Path
mergedManifestFile android.Path mergedManifestFile android.Path
noticeFile android.OptionalPath noticeFile android.OptionalPath
assetPackage android.OptionalPath
isLibrary bool isLibrary bool
useEmbeddedNativeLibs bool useEmbeddedNativeLibs bool
useEmbeddedDex bool useEmbeddedDex bool
@@ -124,6 +126,10 @@ func (a *aapt) ExportedManifests() android.Paths {
return a.transitiveManifestPaths return a.transitiveManifestPaths
} }
func (a *aapt) ExportedAssets() android.OptionalPath {
return a.assetPackage
}
func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext, func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths, manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) { resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -219,9 +225,15 @@ func (a *aapt) deps(ctx android.BottomUpMutatorContext, sdkDep sdkDep) {
} }
} }
var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
blueprint.RuleParams{
Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`,
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) { func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries := transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
aaptLibs(ctx, sdkContext) aaptLibs(ctx, sdkContext)
// App manifest file // App manifest file
@@ -321,7 +333,20 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
} }
aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages, aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
linkFlags, linkDeps, compiledRes, compiledOverlay, splitPackages) linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
if android.PrefixedStringInList(linkFlags, "-A ") || len(assetPackages) > 0 {
assets := android.PathForModuleOut(ctx, "assets.zip")
ctx.Build(pctx, android.BuildParams{
Rule: extractAssetsRule,
Input: packageRes,
Output: assets,
Description: "extract assets from built resource file",
})
a.assetPackage = android.OptionalPathForPath(assets)
}
a.aaptSrcJar = srcJar a.aaptSrcJar = srcJar
a.exportPackage = packageRes a.exportPackage = packageRes
@@ -335,7 +360,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths, func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
staticRRODirs []rroDir, deps android.Paths, flags []string, sdkLibraries []string) { staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) {
var sharedLibs android.Paths var sharedLibs android.Paths
@@ -373,6 +398,9 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage) transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...) transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...) sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path())
}
outer: outer:
for _, d := range aarDep.ExportedRRODirs() { for _, d := range aarDep.ExportedRRODirs() {
@@ -402,7 +430,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests) transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
sdkLibraries = android.FirstUniqueStrings(sdkLibraries) sdkLibraries = android.FirstUniqueStrings(sdkLibraries)
return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags, sdkLibraries return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
} }
type AndroidLibrary struct { type AndroidLibrary struct {
@@ -572,6 +600,11 @@ func (a *AARImport) ExportedManifests() android.Paths {
return android.Paths{a.manifest} return android.Paths{a.manifest}
} }
// TODO(jungjw): Decide whether we want to implement this.
func (a *AARImport) ExportedAssets() android.OptionalPath {
return android.OptionalPath{}
}
func (a *AARImport) Prebuilt() *android.Prebuilt { func (a *AARImport) Prebuilt() *android.Prebuilt {
return &a.prebuilt return &a.prebuilt
} }
@@ -660,7 +693,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
linkFlags = append(linkFlags, "--manifest "+a.manifest.String()) linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
linkDeps = append(linkDeps, a.manifest) linkDeps = append(linkDeps, a.manifest)
transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries := transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags, sdkLibraries :=
aaptLibs(ctx, sdkContext(a)) aaptLibs(ctx, sdkContext(a))
_ = staticLibManifests _ = staticLibManifests
@@ -673,7 +706,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
overlayRes := append(android.Paths{flata}, transitiveStaticLibs...) overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile, aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
linkFlags, linkDeps, nil, overlayRes, nil) linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
} }
var _ Dependency = (*AARImport)(nil) var _ Dependency = (*AARImport)(nil)

View File

@@ -323,6 +323,107 @@ func TestResourceDirs(t *testing.T) {
} }
} }
func TestLibraryAssets(t *testing.T) {
bp := `
android_app {
name: "foo",
sdk_version: "current",
static_libs: ["lib1", "lib2", "lib3"],
}
android_library {
name: "lib1",
sdk_version: "current",
asset_dirs: ["assets_a"],
}
android_library {
name: "lib2",
sdk_version: "current",
}
android_library {
name: "lib3",
sdk_version: "current",
static_libs: ["lib4"],
}
android_library {
name: "lib4",
sdk_version: "current",
asset_dirs: ["assets_b"],
}
`
testCases := []struct {
name string
assetFlag string
assetPackages []string
}{
{
name: "foo",
// lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
assetPackages: []string{
buildDir + "/.intermediates/foo/android_common/aapt2/package-res.apk",
buildDir + "/.intermediates/lib1/android_common/assets.zip",
buildDir + "/.intermediates/lib3/android_common/assets.zip",
},
},
{
name: "lib1",
assetFlag: "-A assets_a",
},
{
name: "lib2",
},
{
name: "lib3",
assetPackages: []string{
buildDir + "/.intermediates/lib3/android_common/aapt2/package-res.apk",
buildDir + "/.intermediates/lib4/android_common/assets.zip",
},
},
{
name: "lib4",
assetFlag: "-A assets_b",
},
}
ctx := testApp(t, bp)
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
m := ctx.ModuleForTests(test.name, "android_common")
// Check asset flag in aapt2 link flags
var aapt2link android.TestingBuildParams
if len(test.assetPackages) > 0 {
aapt2link = m.Output("aapt2/package-res.apk")
} else {
aapt2link = m.Output("package-res.apk")
}
aapt2Flags := aapt2link.Args["flags"]
if test.assetFlag != "" {
if !strings.Contains(aapt2Flags, test.assetFlag) {
t.Errorf("Can't find asset flag %q in aapt2 link flags %q", test.assetFlag, aapt2Flags)
}
} else {
if strings.Contains(aapt2Flags, " -A ") {
t.Errorf("aapt2 link flags %q contain unexpected asset flag", aapt2Flags)
}
}
// Check asset merge rule.
if len(test.assetPackages) > 0 {
mergeAssets := m.Output("package-res.apk")
if !reflect.DeepEqual(test.assetPackages, mergeAssets.Inputs.Strings()) {
t.Errorf("Unexpected mergeAssets inputs: %v, expected: %v",
mergeAssets.Inputs.Strings(), test.assetPackages)
}
}
})
}
}
func TestAndroidResources(t *testing.T) { func TestAndroidResources(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string

View File

@@ -49,6 +49,8 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
"api/test-current.txt": nil, "api/test-current.txt": nil,
"api/test-removed.txt": nil, "api/test-removed.txt": nil,
"framework/aidl/a.aidl": nil, "framework/aidl/a.aidl": nil,
"assets_a/a": nil,
"assets_b/b": nil,
"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil, "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil,