• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18	"path/filepath"
19	"sort"
20	"strconv"
21	"strings"
22
23	"github.com/google/blueprint"
24
25	"android/soong/android"
26)
27
28const AAPT2_SHARD_SIZE = 100
29
30// Convert input resource file path to output file path.
31// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
32// For other resource file, just replace the last "/" with "_" and
33// add .flat extension.
34func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
35
36	name := res.Base()
37	subDir := filepath.Dir(res.String())
38	subDir, lastDir := filepath.Split(subDir)
39	if strings.HasPrefix(lastDir, "values") {
40		name = strings.TrimSuffix(name, ".xml") + ".arsc"
41	}
42	name = lastDir + "_" + name + ".flat"
43	return android.PathForModuleOut(ctx, "aapt2", subDir, name)
44}
45
46func pathsToAapt2Paths(ctx android.ModuleContext, resPaths android.Paths) android.WritablePaths {
47	outPaths := make(android.WritablePaths, len(resPaths))
48
49	for i, res := range resPaths {
50		outPaths[i] = pathToAapt2Path(ctx, res)
51	}
52
53	return outPaths
54}
55
56var aapt2CompileRule = pctx.AndroidStaticRule("aapt2Compile",
57	blueprint.RuleParams{
58		Command:     `${config.Aapt2Cmd} compile -o $outDir $cFlags --legacy $in`,
59		CommandDeps: []string{"${config.Aapt2Cmd}"},
60	},
61	"outDir", "cFlags")
62
63func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths) android.WritablePaths {
64	shards := shardPaths(paths, AAPT2_SHARD_SIZE)
65
66	ret := make(android.WritablePaths, 0, len(paths))
67
68	for i, shard := range shards {
69		outPaths := pathsToAapt2Paths(ctx, shard)
70		ret = append(ret, outPaths...)
71
72		shardDesc := ""
73		if i != 0 {
74			shardDesc = " " + strconv.Itoa(i+1)
75		}
76
77		ctx.Build(pctx, android.BuildParams{
78			Rule:        aapt2CompileRule,
79			Description: "aapt2 compile " + dir.String() + shardDesc,
80			Inputs:      shard,
81			Outputs:     outPaths,
82			Args: map[string]string{
83				"outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
84				// Always set --pseudo-localize, it will be stripped out later for release
85				// builds that don't want it.
86				"cFlags": "--pseudo-localize",
87			},
88		})
89	}
90
91	sort.Slice(ret, func(i, j int) bool {
92		return ret[i].String() < ret[j].String()
93	})
94	return ret
95}
96
97func aapt2CompileDirs(ctx android.ModuleContext, flata android.WritablePath, dirs android.Paths, deps android.Paths) {
98	ctx.Build(pctx, android.BuildParams{
99		Rule:        aapt2CompileRule,
100		Description: "aapt2 compile dirs",
101		Implicits:   deps,
102		Output:      flata,
103		Args: map[string]string{
104			"outDir": flata.String(),
105			// Always set --pseudo-localize, it will be stripped out later for release
106			// builds that don't want it.
107			"cFlags": "--pseudo-localize " + android.JoinWithPrefix(dirs.Strings(), "--dir "),
108		},
109	})
110}
111
112var aapt2CompileZipRule = pctx.AndroidStaticRule("aapt2CompileZip",
113	blueprint.RuleParams{
114		Command: `${config.ZipSyncCmd} -d $resZipDir $in && ` +
115			`${config.Aapt2Cmd} compile -o $out $cFlags --legacy --dir $resZipDir`,
116		CommandDeps: []string{
117			"${config.Aapt2Cmd}",
118			"${config.ZipSyncCmd}",
119		},
120	}, "cFlags", "resZipDir")
121
122func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path) {
123	ctx.Build(pctx, android.BuildParams{
124		Rule:        aapt2CompileZipRule,
125		Description: "aapt2 compile zip",
126		Input:       zip,
127		Output:      flata,
128		Args: map[string]string{
129			// Always set --pseudo-localize, it will be stripped out later for release
130			// builds that don't want it.
131			"cFlags":    "--pseudo-localize",
132			"resZipDir": android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(),
133		},
134	})
135}
136
137var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
138	blueprint.RuleParams{
139		Command: `rm -rf $genDir && ` +
140			`${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
141			`--output-text-symbols ${rTxt} $inFlags && ` +
142			`${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
143			`${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
144
145		CommandDeps: []string{
146			"${config.Aapt2Cmd}",
147			"${config.SoongZipCmd}",
148			"${config.ExtractJarPackagesCmd}",
149		},
150		Restat: true,
151	},
152	"flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
153
154var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
155	blueprint.RuleParams{
156		Command:        `cp $out.rsp $out`,
157		Rspfile:        "$out.rsp",
158		RspfileContent: "$in",
159	})
160
161func aapt2Link(ctx android.ModuleContext,
162	packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
163	flags []string, deps android.Paths,
164	compiledRes, compiledOverlay android.Paths, splitPackages android.WritablePaths) {
165
166	genDir := android.PathForModuleGen(ctx, "aapt2", "R")
167
168	var inFlags []string
169
170	if len(compiledRes) > 0 {
171		resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list")
172		// Write out file lists to files
173		ctx.Build(pctx, android.BuildParams{
174			Rule:        fileListToFileRule,
175			Description: "resource file list",
176			Inputs:      compiledRes,
177			Output:      resFileList,
178		})
179
180		deps = append(deps, compiledRes...)
181		deps = append(deps, resFileList)
182		inFlags = append(inFlags, "@"+resFileList.String())
183	}
184
185	if len(compiledOverlay) > 0 {
186		overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list")
187		ctx.Build(pctx, android.BuildParams{
188			Rule:        fileListToFileRule,
189			Description: "overlay resource file list",
190			Inputs:      compiledOverlay,
191			Output:      overlayFileList,
192		})
193
194		deps = append(deps, compiledOverlay...)
195		deps = append(deps, overlayFileList)
196		inFlags = append(inFlags, "-R", "@"+overlayFileList.String())
197	}
198
199	implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
200
201	ctx.Build(pctx, android.BuildParams{
202		Rule:            aapt2LinkRule,
203		Description:     "aapt2 link",
204		Implicits:       deps,
205		Output:          packageRes,
206		ImplicitOutputs: implicitOutputs,
207		Args: map[string]string{
208			"flags":           strings.Join(flags, " "),
209			"inFlags":         strings.Join(inFlags, " "),
210			"proguardOptions": proguardOptions.String(),
211			"genDir":          genDir.String(),
212			"genJar":          genJar.String(),
213			"rTxt":            rTxt.String(),
214			"extraPackages":   extraPackages.String(),
215		},
216	})
217}
218
219var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
220	blueprint.RuleParams{
221		Command:     `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
222		CommandDeps: []string{"${config.Aapt2Cmd}"},
223	})
224
225func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
226	ctx.Build(pctx, android.BuildParams{
227		Rule:        aapt2ConvertRule,
228		Input:       in,
229		Output:      out,
230		Description: "convert to proto",
231	})
232}
233