platform_build_soong/java/aapt2.go
Jaewoong Jung 6431ca7a3a Add rules to handle asset resources.
AAPT2 ignores assets in overlay resource inputs, so separate rules are
required to extract and merge assets from dependencies.

Test: app_test.go
Test: Added assets to Settings-core for testing
Test: Confirmed Settings.apk contains them with this change.
Fixes: 146655310
Change-Id: Iab8bc61b719541dae64f0e3502bc9cb45a353687
2020-01-16 12:19:49 -08:00

240 lines
7.3 KiB
Go

// 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"
"sort"
"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 $in`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
},
"outDir", "cFlags")
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
flags []string) android.WritablePaths {
shards := android.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": strings.Join(flags, " "),
},
})
}
sort.Slice(ret, func(i, j int) bool {
return ret[i].String() < ret[j].String()
})
return ret
}
var aapt2CompileZipRule = pctx.AndroidStaticRule("aapt2CompileZip",
blueprint.RuleParams{
Command: `${config.ZipSyncCmd} -d $resZipDir $zipSyncFlags $in && ` +
`${config.Aapt2Cmd} compile -o $out $cFlags --dir $resZipDir`,
CommandDeps: []string{
"${config.Aapt2Cmd}",
"${config.ZipSyncCmd}",
},
}, "cFlags", "resZipDir", "zipSyncFlags")
func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string,
flags []string) {
if zipPrefix != "" {
zipPrefix = "--zip-prefix " + zipPrefix
}
ctx.Build(pctx, android.BuildParams{
Rule: aapt2CompileZipRule,
Description: "aapt2 compile zip",
Input: zip,
Output: flata,
Args: map[string]string{
"cFlags": strings.Join(flags, " "),
"resZipDir": android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(),
"zipSyncFlags": zipPrefix,
},
})
}
var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
blueprint.RuleParams{
Command: `rm -rf $genDir && ` +
`${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
`--output-text-symbols ${rTxt} $inFlags && ` +
`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
`${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
CommandDeps: []string{
"${config.Aapt2Cmd}",
"${config.SoongZipCmd}",
"${config.ExtractJarPackagesCmd}",
},
Restat: true,
},
"flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
blueprint.RuleParams{
Command: `cp $out.rsp $out`,
Rspfile: "$out.rsp",
RspfileContent: "$in",
})
var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
blueprint.RuleParams{
Command: `${config.MergeZipsCmd} ${out} ${in}`,
CommandDeps: []string{"${config.MergeZipsCmd}"},
})
func aapt2Link(ctx android.ModuleContext,
packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
flags []string, deps android.Paths,
compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
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())
}
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{
Rule: aapt2LinkRule,
Description: "aapt2 link",
Implicits: deps,
Output: linkOutput,
ImplicitOutputs: implicitOutputs,
Args: map[string]string{
"flags": strings.Join(flags, " "),
"inFlags": strings.Join(inFlags, " "),
"proguardOptions": proguardOptions.String(),
"genDir": genDir.String(),
"genJar": genJar.String(),
"rTxt": rTxt.String(),
"extraPackages": extraPackages.String(),
},
})
}
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{
Command: `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
})
func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,
Input: in,
Output: out,
Description: "convert to proto",
})
}