xref: /aosp_15_r20/build/soong/java/aapt2.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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