Merge "Add rules to handle asset resources."
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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, " "),
|
||||||
|
45
java/aar.go
45
java/aar.go
@@ -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)
|
||||||
|
101
java/app_test.go
101
java/app_test.go
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user