blob: 04e4de52cd60be4af9923372ecfe9ccd53084a08 [file] [log] [blame]
Colin Cross3bc7ffa2017-11-22 16:19:37 -08001// 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"
Colin Crossb69301e2017-12-01 10:48:26 -080019 "sort"
Colin Cross3bc7ffa2017-11-22 16:19:37 -080020 "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{
Colin Cross4215cfd2019-06-20 16:53:30 -070058 Command: `${config.Aapt2Cmd} compile -o $outDir $cFlags $in`,
Colin Cross3bc7ffa2017-11-22 16:19:37 -080059 CommandDeps: []string{"${config.Aapt2Cmd}"},
60 },
61 "outDir", "cFlags")
62
Colin Crossa0ba2f52019-06-22 12:59:27 -070063func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
64 flags []string) android.WritablePaths {
65
Colin Cross0a2f7192019-09-23 14:33:09 -070066 shards := android.ShardPaths(paths, AAPT2_SHARD_SIZE)
Colin Cross3bc7ffa2017-11-22 16:19:37 -080067
68 ret := make(android.WritablePaths, 0, len(paths))
69
70 for i, shard := range shards {
71 outPaths := pathsToAapt2Paths(ctx, shard)
72 ret = append(ret, outPaths...)
73
74 shardDesc := ""
75 if i != 0 {
76 shardDesc = " " + strconv.Itoa(i+1)
77 }
78
79 ctx.Build(pctx, android.BuildParams{
80 Rule: aapt2CompileRule,
81 Description: "aapt2 compile " + dir.String() + shardDesc,
82 Inputs: shard,
83 Outputs: outPaths,
84 Args: map[string]string{
85 "outDir": android.PathForModuleOut(ctx, "aapt2", dir.String()).String(),
Colin Crossa0ba2f52019-06-22 12:59:27 -070086 "cFlags": strings.Join(flags, " "),
Colin Cross3bc7ffa2017-11-22 16:19:37 -080087 },
88 })
89 }
90
Colin Crossb69301e2017-12-01 10:48:26 -080091 sort.Slice(ret, func(i, j int) bool {
92 return ret[i].String() < ret[j].String()
93 })
Colin Cross3bc7ffa2017-11-22 16:19:37 -080094 return ret
95}
96
Colin Crossa592e3e2019-02-19 16:59:53 -080097var aapt2CompileZipRule = pctx.AndroidStaticRule("aapt2CompileZip",
98 blueprint.RuleParams{
Dan Willemsen304cfec2019-05-28 14:49:06 -070099 Command: `${config.ZipSyncCmd} -d $resZipDir $zipSyncFlags $in && ` +
Colin Cross4215cfd2019-06-20 16:53:30 -0700100 `${config.Aapt2Cmd} compile -o $out $cFlags --dir $resZipDir`,
Colin Crossa592e3e2019-02-19 16:59:53 -0800101 CommandDeps: []string{
102 "${config.Aapt2Cmd}",
103 "${config.ZipSyncCmd}",
104 },
Dan Willemsen304cfec2019-05-28 14:49:06 -0700105 }, "cFlags", "resZipDir", "zipSyncFlags")
Colin Crossa592e3e2019-02-19 16:59:53 -0800106
Colin Crossa0ba2f52019-06-22 12:59:27 -0700107func aapt2CompileZip(ctx android.ModuleContext, flata android.WritablePath, zip android.Path, zipPrefix string,
108 flags []string) {
109
Dan Willemsen304cfec2019-05-28 14:49:06 -0700110 if zipPrefix != "" {
111 zipPrefix = "--zip-prefix " + zipPrefix
112 }
Colin Crossa592e3e2019-02-19 16:59:53 -0800113 ctx.Build(pctx, android.BuildParams{
114 Rule: aapt2CompileZipRule,
115 Description: "aapt2 compile zip",
116 Input: zip,
117 Output: flata,
118 Args: map[string]string{
Colin Crossa0ba2f52019-06-22 12:59:27 -0700119 "cFlags": strings.Join(flags, " "),
Dan Willemsen304cfec2019-05-28 14:49:06 -0700120 "resZipDir": android.PathForModuleOut(ctx, "aapt2", "reszip", flata.Base()).String(),
121 "zipSyncFlags": zipPrefix,
Colin Crossa592e3e2019-02-19 16:59:53 -0800122 },
123 })
124}
125
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800126var aapt2LinkRule = pctx.AndroidStaticRule("aapt2Link",
127 blueprint.RuleParams{
Colin Cross78e3cb02018-10-17 15:42:59 -0700128 Command: `rm -rf $genDir && ` +
129 `${config.Aapt2Cmd} link -o $out $flags --java $genDir --proguard $proguardOptions ` +
Colin Crossa97c5d32018-03-28 14:58:31 -0700130 `--output-text-symbols ${rTxt} $inFlags && ` +
Colin Cross66f78822018-05-02 12:58:28 -0700131 `${config.SoongZipCmd} -write_if_changed -jar -o $genJar -C $genDir -D $genDir &&` +
132 `${config.ExtractJarPackagesCmd} -i $genJar -o $extraPackages --prefix '--extra-packages '`,
133
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800134 CommandDeps: []string{
Colin Cross44f06682017-11-29 00:17:36 -0800135 "${config.Aapt2Cmd}",
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800136 "${config.SoongZipCmd}",
Colin Cross66f78822018-05-02 12:58:28 -0700137 "${config.ExtractJarPackagesCmd}",
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800138 },
139 Restat: true,
140 },
Colin Cross66f78822018-05-02 12:58:28 -0700141 "flags", "inFlags", "proguardOptions", "genDir", "genJar", "rTxt", "extraPackages")
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800142
143var fileListToFileRule = pctx.AndroidStaticRule("fileListToFile",
144 blueprint.RuleParams{
145 Command: `cp $out.rsp $out`,
146 Rspfile: "$out.rsp",
147 RspfileContent: "$in",
148 })
149
Jaewoong Jung6431ca72020-01-15 14:15:10 -0800150var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
151 blueprint.RuleParams{
152 Command: `${config.MergeZipsCmd} ${out} ${in}`,
153 CommandDeps: []string{"${config.MergeZipsCmd}"},
154 })
155
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800156func aapt2Link(ctx android.ModuleContext,
Colin Cross66f78822018-05-02 12:58:28 -0700157 packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800158 flags []string, deps android.Paths,
Jaewoong Jung6431ca72020-01-15 14:15:10 -0800159 compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800160
161 genDir := android.PathForModuleGen(ctx, "aapt2", "R")
162
163 var inFlags []string
164
165 if len(compiledRes) > 0 {
166 resFileList := android.PathForModuleOut(ctx, "aapt2", "res.list")
167 // Write out file lists to files
168 ctx.Build(pctx, android.BuildParams{
169 Rule: fileListToFileRule,
170 Description: "resource file list",
171 Inputs: compiledRes,
172 Output: resFileList,
173 })
174
175 deps = append(deps, compiledRes...)
176 deps = append(deps, resFileList)
177 inFlags = append(inFlags, "@"+resFileList.String())
178 }
179
180 if len(compiledOverlay) > 0 {
181 overlayFileList := android.PathForModuleOut(ctx, "aapt2", "overlay.list")
182 ctx.Build(pctx, android.BuildParams{
183 Rule: fileListToFileRule,
184 Description: "overlay resource file list",
185 Inputs: compiledOverlay,
186 Output: overlayFileList,
187 })
188
189 deps = append(deps, compiledOverlay...)
190 deps = append(deps, overlayFileList)
191 inFlags = append(inFlags, "-R", "@"+overlayFileList.String())
192 }
193
Colin Crosse560c4a2019-03-19 16:03:11 -0700194 implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
Jaewoong Jung6431ca72020-01-15 14:15:10 -0800195 linkOutput := packageRes
196
197 // AAPT2 ignores assets in overlays. Merge them after linking.
198 if len(assetPackages) > 0 {
199 linkOutput = android.PathForModuleOut(ctx, "aapt2", "package-res.apk")
200 inputZips := append(android.Paths{linkOutput}, assetPackages...)
201 ctx.Build(pctx, android.BuildParams{
202 Rule: mergeAssetsRule,
203 Inputs: inputZips,
204 Output: packageRes,
205 Description: "merge assets from dependencies",
206 })
207 }
Colin Crosse560c4a2019-03-19 16:03:11 -0700208
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800209 ctx.Build(pctx, android.BuildParams{
210 Rule: aapt2LinkRule,
211 Description: "aapt2 link",
212 Implicits: deps,
Jaewoong Jung6431ca72020-01-15 14:15:10 -0800213 Output: linkOutput,
Colin Crosse560c4a2019-03-19 16:03:11 -0700214 ImplicitOutputs: implicitOutputs,
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800215 Args: map[string]string{
216 "flags": strings.Join(flags, " "),
217 "inFlags": strings.Join(inFlags, " "),
218 "proguardOptions": proguardOptions.String(),
219 "genDir": genDir.String(),
220 "genJar": genJar.String(),
Colin Crossa97c5d32018-03-28 14:58:31 -0700221 "rTxt": rTxt.String(),
Colin Cross66f78822018-05-02 12:58:28 -0700222 "extraPackages": extraPackages.String(),
Colin Cross3bc7ffa2017-11-22 16:19:37 -0800223 },
224 })
225}
Colin Crossf6237212018-10-29 23:14:58 -0700226
227var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
228 blueprint.RuleParams{
229 Command: `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
230 CommandDeps: []string{"${config.Aapt2Cmd}"},
231 })
232
233func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
234 ctx.Build(pctx, android.BuildParams{
235 Rule: aapt2ConvertRule,
236 Input: in,
237 Output: out,
238 Description: "convert to proto",
239 })
240}