1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage java 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "path/filepath" 20*333d2b36SAndroid Build Coastguard Worker "regexp" 21*333d2b36SAndroid Build Coastguard Worker "sort" 22*333d2b36SAndroid Build Coastguard Worker "strconv" 23*333d2b36SAndroid Build Coastguard Worker "strings" 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 26*333d2b36SAndroid Build Coastguard Worker 27*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 28*333d2b36SAndroid Build Coastguard Worker) 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Workerfunc isPathValueResource(res android.Path) bool { 31*333d2b36SAndroid Build Coastguard Worker subDir := filepath.Dir(res.String()) 32*333d2b36SAndroid Build Coastguard Worker subDir, lastDir := filepath.Split(subDir) 33*333d2b36SAndroid Build Coastguard Worker return strings.HasPrefix(lastDir, "values") 34*333d2b36SAndroid Build Coastguard Worker} 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workerfunc isFlagsPath(subDir string) bool { 37*333d2b36SAndroid Build Coastguard Worker re := regexp.MustCompile(`flag\(!?([a-zA-Z_-]+\.)*[a-zA-Z0-9_-]+\)`) 38*333d2b36SAndroid Build Coastguard Worker lastDir := filepath.Base(subDir) 39*333d2b36SAndroid Build Coastguard Worker return re.MatchString(lastDir) 40*333d2b36SAndroid Build Coastguard Worker} 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker// Convert input resource file path to output file path. 43*333d2b36SAndroid Build Coastguard Worker// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat; 44*333d2b36SAndroid Build Coastguard Worker// flag(fully.qualified.flag_name)/values-[config]/<file>.xml -> /values-[config]_<file>.(fully.qualified.flag_name).arsc.flat; 45*333d2b36SAndroid Build Coastguard Worker// For other resource file, just replace the last "/" with "_" and add .flat extension. 46*333d2b36SAndroid Build Coastguard Workerfunc pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath { 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Worker extension := filepath.Ext(res.Base()) 49*333d2b36SAndroid Build Coastguard Worker name := strings.TrimSuffix(res.Base(), extension) 50*333d2b36SAndroid Build Coastguard Worker if isPathValueResource(res) { 51*333d2b36SAndroid Build Coastguard Worker extension = ".arsc" 52*333d2b36SAndroid Build Coastguard Worker } 53*333d2b36SAndroid Build Coastguard Worker subDir := filepath.Dir(res.String()) 54*333d2b36SAndroid Build Coastguard Worker subDir, lastDir := filepath.Split(subDir) 55*333d2b36SAndroid Build Coastguard Worker if isFlagsPath(subDir) { 56*333d2b36SAndroid Build Coastguard Worker var flag string 57*333d2b36SAndroid Build Coastguard Worker subDir, flag = filepath.Split(filepath.Dir(subDir)) 58*333d2b36SAndroid Build Coastguard Worker flag = strings.TrimPrefix(flag, "flag") 59*333d2b36SAndroid Build Coastguard Worker name = fmt.Sprintf("%s_%s.%s%s.flat", lastDir, name, flag, extension) 60*333d2b36SAndroid Build Coastguard Worker } else { 61*333d2b36SAndroid Build Coastguard Worker name = fmt.Sprintf("%s_%s%s.flat", lastDir, name, extension) 62*333d2b36SAndroid Build Coastguard Worker } 63*333d2b36SAndroid Build Coastguard Worker out := android.PathForModuleOut(ctx, "aapt2", subDir, name) 64*333d2b36SAndroid Build Coastguard Worker return out 65*333d2b36SAndroid Build Coastguard Worker} 66*333d2b36SAndroid Build Coastguard Worker 67*333d2b36SAndroid Build Coastguard Worker// pathsToAapt2Paths Calls pathToAapt2Path on each entry of the given Paths, i.e. []Path. 68*333d2b36SAndroid Build Coastguard Workerfunc pathsToAapt2Paths(ctx android.ModuleContext, resPaths android.Paths) android.WritablePaths { 69*333d2b36SAndroid Build Coastguard Worker outPaths := make(android.WritablePaths, len(resPaths)) 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker for i, res := range resPaths { 72*333d2b36SAndroid Build Coastguard Worker outPaths[i] = pathToAapt2Path(ctx, res) 73*333d2b36SAndroid Build Coastguard Worker } 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker return outPaths 76*333d2b36SAndroid Build Coastguard Worker} 77*333d2b36SAndroid Build Coastguard Worker 78*333d2b36SAndroid Build Coastguard Worker// Shard resource files for efficiency. See aapt2Compile for details. 79*333d2b36SAndroid Build Coastguard Workerconst AAPT2_SHARD_SIZE = 100 80*333d2b36SAndroid Build Coastguard Worker 81*333d2b36SAndroid Build Coastguard Workervar aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile", 82*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 83*333d2b36SAndroid Build Coastguard Worker Command: `${config.Aapt2Cmd} compile -o $outDir $cFlags $in`, 84*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{"${config.Aapt2Cmd}"}, 85*333d2b36SAndroid Build Coastguard Worker }, 86*333d2b36SAndroid Build Coastguard Worker "outDir", "cFlags") 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Worker// aapt2Compile compiles resources and puts the results in the requested directory. 89*333d2b36SAndroid Build Coastguard Workerfunc aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths, 90*333d2b36SAndroid Build Coastguard Worker flags []string, productToFilter string, featureFlagsPaths android.Paths) android.WritablePaths { 91*333d2b36SAndroid Build Coastguard Worker if productToFilter != "" && productToFilter != "default" { 92*333d2b36SAndroid Build Coastguard Worker // --filter-product leaves only product-specific resources. Product-specific resources only exist 93*333d2b36SAndroid Build Coastguard Worker // in value resources (values/*.xml), so filter value resource files only. Ignore other types of 94*333d2b36SAndroid Build Coastguard Worker // resources as they don't need to be in product characteristics RRO (and they will cause aapt2 95*333d2b36SAndroid Build Coastguard Worker // compile errors) 96*333d2b36SAndroid Build Coastguard Worker filteredPaths := android.Paths{} 97*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 98*333d2b36SAndroid Build Coastguard Worker if isPathValueResource(path) { 99*333d2b36SAndroid Build Coastguard Worker filteredPaths = append(filteredPaths, path) 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker } 102*333d2b36SAndroid Build Coastguard Worker paths = filteredPaths 103*333d2b36SAndroid Build Coastguard Worker flags = append([]string{"--filter-product " + productToFilter}, flags...) 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Worker for _, featureFlagsPath := range android.SortedUniquePaths(featureFlagsPaths) { 107*333d2b36SAndroid Build Coastguard Worker flags = append(flags, "--feature-flags", "@"+featureFlagsPath.String()) 108*333d2b36SAndroid Build Coastguard Worker } 109*333d2b36SAndroid Build Coastguard Worker 110*333d2b36SAndroid Build Coastguard Worker // Shard the input paths so that they can be processed in parallel. If we shard them into too 111*333d2b36SAndroid Build Coastguard Worker // small chunks, the additional cost of spinning up aapt2 outweighs the performance gain. The 112*333d2b36SAndroid Build Coastguard Worker // current shard size, 100, seems to be a good balance between the added cost and the gain. 113*333d2b36SAndroid Build Coastguard Worker // The aapt2 compile actions are trivially short, but each action in ninja takes on the order of 114*333d2b36SAndroid Build Coastguard Worker // ~10 ms to run. frameworks/base/core/res/res has >10k resource files, so compiling each one 115*333d2b36SAndroid Build Coastguard Worker // with an individual action could take 100 CPU seconds. Sharding them reduces the overhead of 116*333d2b36SAndroid Build Coastguard Worker // starting actions by a factor of 100, at the expense of recompiling more files when one 117*333d2b36SAndroid Build Coastguard Worker // changes. Since the individual compiles are trivial it's a good tradeoff. 118*333d2b36SAndroid Build Coastguard Worker shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE) 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker ret := make(android.WritablePaths, 0, len(paths)) 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Worker for i, shard := range shards { 123*333d2b36SAndroid Build Coastguard Worker // This should be kept in sync with pathToAapt2Path. The aapt2 compile command takes an 124*333d2b36SAndroid Build Coastguard Worker // output directory path, but not output file paths. So, outPaths is just where we expect 125*333d2b36SAndroid Build Coastguard Worker // the output files will be located. 126*333d2b36SAndroid Build Coastguard Worker outPaths := pathsToAapt2Paths(ctx, shard) 127*333d2b36SAndroid Build Coastguard Worker ret = append(ret, outPaths...) 128*333d2b36SAndroid Build Coastguard Worker 129*333d2b36SAndroid Build Coastguard Worker shardDesc := "" 130*333d2b36SAndroid Build Coastguard Worker if i != 0 { 131*333d2b36SAndroid Build Coastguard Worker shardDesc = " " + strconv.Itoa(i+1) 132*333d2b36SAndroid Build Coastguard Worker } 133*333d2b36SAndroid Build Coastguard Worker 134*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 135*333d2b36SAndroid Build Coastguard Worker Rule: aapt2CompileRule, 136*333d2b36SAndroid Build Coastguard Worker Description: "aapt2 compile " + dir.String() + shardDesc, 137*333d2b36SAndroid Build Coastguard Worker Implicits: featureFlagsPaths, 138*333d2b36SAndroid Build Coastguard Worker Inputs: shard, 139*333d2b36SAndroid Build Coastguard Worker Outputs: outPaths, 140*333d2b36SAndroid Build Coastguard Worker Args: map[string]string{ 141*333d2b36SAndroid Build Coastguard Worker // The aapt2 compile command takes an output directory path, but not output file paths. 142*333d2b36SAndroid Build Coastguard Worker // outPaths specified above is only used for dependency management purposes. In order for 143*333d2b36SAndroid Build Coastguard Worker // the outPaths values to match the actual outputs from aapt2, the dir parameter value 144*333d2b36SAndroid Build Coastguard Worker // must be a common prefix path of the paths values, and the top-level path segment used 145*333d2b36SAndroid Build Coastguard Worker // below, "aapt2", must always be kept in sync with the one in pathToAapt2Path. 146*333d2b36SAndroid Build Coastguard Worker // TODO(b/174505750): Make this easier and robust to use. 147*333d2b36SAndroid Build Coastguard Worker "outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(), 148*333d2b36SAndroid Build Coastguard Worker "cFlags": strings.Join(flags, " "), 149*333d2b36SAndroid Build Coastguard Worker }, 150*333d2b36SAndroid Build Coastguard Worker }) 151*333d2b36SAndroid Build Coastguard Worker } 152*333d2b36SAndroid Build Coastguard Worker 153*333d2b36SAndroid Build Coastguard Worker sort.Slice(ret, func(i, j int) bool { 154*333d2b36SAndroid Build Coastguard Worker return ret[i].String() < ret[j].String() 155*333d2b36SAndroid Build Coastguard Worker }) 156*333d2b36SAndroid Build Coastguard Worker return ret 157*333d2b36SAndroid Build Coastguard Worker} 158*333d2b36SAndroid Build Coastguard Worker 159*333d2b36SAndroid Build Coastguard Workervar aapt2CompileZipRule = pctx.AndroidStaticRule("aapt2CompileZip", 160*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 161*333d2b36SAndroid Build Coastguard Worker Command: `${config.ZipSyncCmd} -d $resZipDir $zipSyncFlags $in && ` + 162*333d2b36SAndroid Build Coastguard Worker `${config.Aapt2Cmd} compile -o $out $cFlags --dir $resZipDir`, 163*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{ 164*333d2b36SAndroid Build Coastguard Worker "${config.Aapt2Cmd}", 165*333d2b36SAndroid Build Coastguard Worker "${config.ZipSyncCmd}", 166*333d2b36SAndroid Build Coastguard Worker }, 167*333d2b36SAndroid Build Coastguard Worker }, "cFlags", "resZipDir", "zipSyncFlags") 168*333d2b36SAndroid Build Coastguard Worker 169*333d2b36SAndroid Build Coastguard Worker// Unzips the given compressed file and compiles the resource source files in it. The zipPrefix 170*333d2b36SAndroid Build Coastguard Worker// parameter points to the subdirectory in the zip file where the resource files are located. 171*333d2b36SAndroid Build Coastguard Workerfunc aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string, 172*333d2b36SAndroid Build Coastguard Worker flags []string) { 173*333d2b36SAndroid Build Coastguard Worker 174*333d2b36SAndroid Build Coastguard Worker if zipPrefix != "" { 175*333d2b36SAndroid Build Coastguard Worker zipPrefix = "--zip-prefix " + zipPrefix 176*333d2b36SAndroid Build Coastguard Worker } 177*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 178*333d2b36SAndroid Build Coastguard Worker Rule: aapt2CompileZipRule, 179*333d2b36SAndroid Build Coastguard Worker Description: "aapt2 compile zip", 180*333d2b36SAndroid Build Coastguard Worker Input: zip, 181*333d2b36SAndroid Build Coastguard Worker Output: flata, 182*333d2b36SAndroid Build Coastguard Worker Args: map[string]string{ 183*333d2b36SAndroid Build Coastguard Worker "cFlags": strings.Join(flags, " "), 184*333d2b36SAndroid Build Coastguard Worker "resZipDir": android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(), 185*333d2b36SAndroid Build Coastguard Worker "zipSyncFlags": zipPrefix, 186*333d2b36SAndroid Build Coastguard Worker }, 187*333d2b36SAndroid Build Coastguard Worker }) 188*333d2b36SAndroid Build Coastguard Worker} 189*333d2b36SAndroid Build Coastguard Worker 190*333d2b36SAndroid Build Coastguard Workervar aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link", 191*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 192*333d2b36SAndroid Build Coastguard Worker Command: `$preamble` + 193*333d2b36SAndroid Build Coastguard Worker `${config.Aapt2Cmd} link -o $out $flags --proguard $proguardOptions ` + 194*333d2b36SAndroid Build Coastguard Worker `--output-text-symbols ${rTxt} $inFlags` + 195*333d2b36SAndroid Build Coastguard Worker `$postamble`, 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{ 198*333d2b36SAndroid Build Coastguard Worker "${config.Aapt2Cmd}", 199*333d2b36SAndroid Build Coastguard Worker "${config.SoongZipCmd}", 200*333d2b36SAndroid Build Coastguard Worker }, 201*333d2b36SAndroid Build Coastguard Worker Restat: true, 202*333d2b36SAndroid Build Coastguard Worker }, 203*333d2b36SAndroid Build Coastguard Worker "flags", "inFlags", "proguardOptions", "rTxt", "extraPackages", "preamble", "postamble") 204*333d2b36SAndroid Build Coastguard Worker 205*333d2b36SAndroid Build Coastguard Workervar aapt2ExtractExtraPackagesRule = pctx.AndroidStaticRule("aapt2ExtractExtraPackages", 206*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 207*333d2b36SAndroid Build Coastguard Worker Command: `${config.ExtractJarPackagesCmd} -i $in -o $out --prefix '--extra-packages '`, 208*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{"${config.ExtractJarPackagesCmd}"}, 209*333d2b36SAndroid Build Coastguard Worker Restat: true, 210*333d2b36SAndroid Build Coastguard Worker }) 211*333d2b36SAndroid Build Coastguard Worker 212*333d2b36SAndroid Build Coastguard Workervar fileListToFileRule = pctx.AndroidStaticRule("fileListToFile", 213*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 214*333d2b36SAndroid Build Coastguard Worker Command: `cp $out.rsp $out`, 215*333d2b36SAndroid Build Coastguard Worker Rspfile: "$out.rsp", 216*333d2b36SAndroid Build Coastguard Worker RspfileContent: "$in", 217*333d2b36SAndroid Build Coastguard Worker }) 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Workervar mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets", 220*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 221*333d2b36SAndroid Build Coastguard Worker Command: `${config.MergeZipsCmd} ${out} ${in}`, 222*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{"${config.MergeZipsCmd}"}, 223*333d2b36SAndroid Build Coastguard Worker }) 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Workerfunc aapt2Link(ctx android.ModuleContext, 226*333d2b36SAndroid Build Coastguard Worker packageRes, genJar, proguardOptions, rTxt android.WritablePath, 227*333d2b36SAndroid Build Coastguard Worker flags []string, deps android.Paths, 228*333d2b36SAndroid Build Coastguard Worker compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths, 229*333d2b36SAndroid Build Coastguard Worker featureFlagsPaths android.Paths) { 230*333d2b36SAndroid Build Coastguard Worker 231*333d2b36SAndroid Build Coastguard Worker var inFlags []string 232*333d2b36SAndroid Build Coastguard Worker 233*333d2b36SAndroid Build Coastguard Worker if len(compiledRes) > 0 { 234*333d2b36SAndroid Build Coastguard Worker // Create a file that contains the list of all compiled resource file paths. 235*333d2b36SAndroid Build Coastguard Worker resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list") 236*333d2b36SAndroid Build Coastguard Worker // Write out file lists to files 237*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 238*333d2b36SAndroid Build Coastguard Worker Rule: fileListToFileRule, 239*333d2b36SAndroid Build Coastguard Worker Description: "resource file list", 240*333d2b36SAndroid Build Coastguard Worker Inputs: compiledRes, 241*333d2b36SAndroid Build Coastguard Worker Output: resFileList, 242*333d2b36SAndroid Build Coastguard Worker }) 243*333d2b36SAndroid Build Coastguard Worker 244*333d2b36SAndroid Build Coastguard Worker deps = append(deps, compiledRes...) 245*333d2b36SAndroid Build Coastguard Worker deps = append(deps, resFileList) 246*333d2b36SAndroid Build Coastguard Worker // aapt2 filepath arguments that start with "@" mean file-list files. 247*333d2b36SAndroid Build Coastguard Worker inFlags = append(inFlags, "@"+resFileList.String()) 248*333d2b36SAndroid Build Coastguard Worker } 249*333d2b36SAndroid Build Coastguard Worker 250*333d2b36SAndroid Build Coastguard Worker if len(compiledOverlay) > 0 { 251*333d2b36SAndroid Build Coastguard Worker // Compiled overlay files are processed the same way as compiled resources. 252*333d2b36SAndroid Build Coastguard Worker overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list") 253*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 254*333d2b36SAndroid Build Coastguard Worker Rule: fileListToFileRule, 255*333d2b36SAndroid Build Coastguard Worker Description: "overlay resource file list", 256*333d2b36SAndroid Build Coastguard Worker Inputs: compiledOverlay, 257*333d2b36SAndroid Build Coastguard Worker Output: overlayFileList, 258*333d2b36SAndroid Build Coastguard Worker }) 259*333d2b36SAndroid Build Coastguard Worker 260*333d2b36SAndroid Build Coastguard Worker deps = append(deps, compiledOverlay...) 261*333d2b36SAndroid Build Coastguard Worker deps = append(deps, overlayFileList) 262*333d2b36SAndroid Build Coastguard Worker // Compiled overlay files are passed over to aapt2 using -R option. 263*333d2b36SAndroid Build Coastguard Worker inFlags = append(inFlags, "-R", "@"+overlayFileList.String()) 264*333d2b36SAndroid Build Coastguard Worker } 265*333d2b36SAndroid Build Coastguard Worker 266*333d2b36SAndroid Build Coastguard Worker // Set auxiliary outputs as implicit outputs to establish correct dependency chains. 267*333d2b36SAndroid Build Coastguard Worker implicitOutputs := append(splitPackages, proguardOptions, rTxt) 268*333d2b36SAndroid Build Coastguard Worker linkOutput := packageRes 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Worker // AAPT2 ignores assets in overlays. Merge them after linking. 271*333d2b36SAndroid Build Coastguard Worker if len(assetPackages) > 0 { 272*333d2b36SAndroid Build Coastguard Worker linkOutput = android.PathForModuleOut(ctx, "aapt2", "package-res.apk") 273*333d2b36SAndroid Build Coastguard Worker inputZips := append(android.Paths{linkOutput}, assetPackages...) 274*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 275*333d2b36SAndroid Build Coastguard Worker Rule: mergeAssetsRule, 276*333d2b36SAndroid Build Coastguard Worker Inputs: inputZips, 277*333d2b36SAndroid Build Coastguard Worker Output: packageRes, 278*333d2b36SAndroid Build Coastguard Worker Description: "merge assets from dependencies", 279*333d2b36SAndroid Build Coastguard Worker }) 280*333d2b36SAndroid Build Coastguard Worker } 281*333d2b36SAndroid Build Coastguard Worker 282*333d2b36SAndroid Build Coastguard Worker for _, featureFlagsPath := range featureFlagsPaths { 283*333d2b36SAndroid Build Coastguard Worker deps = append(deps, featureFlagsPath) 284*333d2b36SAndroid Build Coastguard Worker inFlags = append(inFlags, "--feature-flags", "@"+featureFlagsPath.String()) 285*333d2b36SAndroid Build Coastguard Worker } 286*333d2b36SAndroid Build Coastguard Worker 287*333d2b36SAndroid Build Coastguard Worker // Note the absence of splitPackages. The caller is supposed to compose and provide --split flag 288*333d2b36SAndroid Build Coastguard Worker // values via the flags parameter when it wants to split outputs. 289*333d2b36SAndroid Build Coastguard Worker // TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably 290*333d2b36SAndroid Build Coastguard Worker // tidy. 291*333d2b36SAndroid Build Coastguard Worker args := map[string]string{ 292*333d2b36SAndroid Build Coastguard Worker "flags": strings.Join(flags, " "), 293*333d2b36SAndroid Build Coastguard Worker "inFlags": strings.Join(inFlags, " "), 294*333d2b36SAndroid Build Coastguard Worker "proguardOptions": proguardOptions.String(), 295*333d2b36SAndroid Build Coastguard Worker "rTxt": rTxt.String(), 296*333d2b36SAndroid Build Coastguard Worker } 297*333d2b36SAndroid Build Coastguard Worker 298*333d2b36SAndroid Build Coastguard Worker if genJar != nil { 299*333d2b36SAndroid Build Coastguard Worker // Generating java source files from aapt2 was requested, use aapt2LinkAndGenRule and pass it 300*333d2b36SAndroid Build Coastguard Worker // genJar and genDir args. 301*333d2b36SAndroid Build Coastguard Worker genDir := android.PathForModuleGen(ctx, "aapt2", "R") 302*333d2b36SAndroid Build Coastguard Worker ctx.Variable(pctx, "aapt2GenDir", genDir.String()) 303*333d2b36SAndroid Build Coastguard Worker ctx.Variable(pctx, "aapt2GenJar", genJar.String()) 304*333d2b36SAndroid Build Coastguard Worker implicitOutputs = append(implicitOutputs, genJar) 305*333d2b36SAndroid Build Coastguard Worker args["preamble"] = `rm -rf $aapt2GenDir && ` 306*333d2b36SAndroid Build Coastguard Worker args["postamble"] = `&& ${config.SoongZipCmd} -write_if_changed -jar -o $aapt2GenJar -C $aapt2GenDir -D $aapt2GenDir && ` + 307*333d2b36SAndroid Build Coastguard Worker `rm -rf $aapt2GenDir` 308*333d2b36SAndroid Build Coastguard Worker args["flags"] += " --java $aapt2GenDir" 309*333d2b36SAndroid Build Coastguard Worker } 310*333d2b36SAndroid Build Coastguard Worker 311*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 312*333d2b36SAndroid Build Coastguard Worker Rule: aapt2LinkRule, 313*333d2b36SAndroid Build Coastguard Worker Description: "aapt2 link", 314*333d2b36SAndroid Build Coastguard Worker Implicits: deps, 315*333d2b36SAndroid Build Coastguard Worker Output: linkOutput, 316*333d2b36SAndroid Build Coastguard Worker ImplicitOutputs: implicitOutputs, 317*333d2b36SAndroid Build Coastguard Worker Args: args, 318*333d2b36SAndroid Build Coastguard Worker }) 319*333d2b36SAndroid Build Coastguard Worker} 320*333d2b36SAndroid Build Coastguard Worker 321*333d2b36SAndroid Build Coastguard Worker// aapt2ExtractExtraPackages takes a srcjar generated by aapt2 or a classes jar generated by ResourceProcessorBusyBox 322*333d2b36SAndroid Build Coastguard Worker// and converts it to a text file containing a list of --extra_package arguments for passing to Make modules so they 323*333d2b36SAndroid Build Coastguard Worker// correctly generate R.java entries for packages provided by transitive dependencies. 324*333d2b36SAndroid Build Coastguard Workerfunc aapt2ExtractExtraPackages(ctx android.ModuleContext, out android.WritablePath, in android.Path) { 325*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 326*333d2b36SAndroid Build Coastguard Worker Rule: aapt2ExtractExtraPackagesRule, 327*333d2b36SAndroid Build Coastguard Worker Description: "aapt2 extract extra packages", 328*333d2b36SAndroid Build Coastguard Worker Input: in, 329*333d2b36SAndroid Build Coastguard Worker Output: out, 330*333d2b36SAndroid Build Coastguard Worker }) 331*333d2b36SAndroid Build Coastguard Worker} 332*333d2b36SAndroid Build Coastguard Worker 333*333d2b36SAndroid Build Coastguard Workervar aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert", 334*333d2b36SAndroid Build Coastguard Worker blueprint.RuleParams{ 335*333d2b36SAndroid Build Coastguard Worker Command: `${config.Aapt2Cmd} convert --enable-compact-entries ` + 336*333d2b36SAndroid Build Coastguard Worker `--output-format $format $in -o $out`, 337*333d2b36SAndroid Build Coastguard Worker CommandDeps: []string{"${config.Aapt2Cmd}"}, 338*333d2b36SAndroid Build Coastguard Worker }, "format", 339*333d2b36SAndroid Build Coastguard Worker) 340*333d2b36SAndroid Build Coastguard Worker 341*333d2b36SAndroid Build Coastguard Worker// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto 342*333d2b36SAndroid Build Coastguard Worker// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto. 343*333d2b36SAndroid Build Coastguard Workerfunc aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path, format string) { 344*333d2b36SAndroid Build Coastguard Worker ctx.Build(pctx, android.BuildParams{ 345*333d2b36SAndroid Build Coastguard Worker Rule: aapt2ConvertRule, 346*333d2b36SAndroid Build Coastguard Worker Input: in, 347*333d2b36SAndroid Build Coastguard Worker Output: out, 348*333d2b36SAndroid Build Coastguard Worker Description: "convert to " + format, 349*333d2b36SAndroid Build Coastguard Worker Args: map[string]string{ 350*333d2b36SAndroid Build Coastguard Worker "format": format, 351*333d2b36SAndroid Build Coastguard Worker }, 352*333d2b36SAndroid Build Coastguard Worker }) 353*333d2b36SAndroid Build Coastguard Worker} 354