blob: b8332ad0a19c9c3f79b2c51e708c3328d660cd1e [file] [log] [blame]
Colin Cross2fe66872015-03-30 17:20:39 -07001// Copyright 2015 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
17// This file generates the final rules for compiling all Java. All properties related to
18// compiling should have been translated into javaBuilderFlags or another argument to the Transform*
19// functions.
20
21import (
Colin Cross2fe66872015-03-30 17:20:39 -070022 "strings"
23
Colin Cross2fe66872015-03-30 17:20:39 -070024 "github.com/google/blueprint"
Colin Crossfee57cb2017-09-05 13:16:45 -070025
26 "android/soong/android"
27 "android/soong/java/config"
Colin Cross2fe66872015-03-30 17:20:39 -070028)
29
30var (
Colin Cross635c3b02016-05-18 15:37:25 -070031 pctx = android.NewPackageContext("android/soong/java")
Colin Cross2fe66872015-03-30 17:20:39 -070032
33 // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name
34 // requirement leads to unpredictable generated source file names, and a single .java file
35 // will get compiled into multiple .class files if it contains inner classes. To work around
36 // this, all java rules write into separate directories and then a post-processing step lists
37 // the files in the the directory into a list file that later rules depend on (and sometimes
38 // read from directly using @<listfile>)
Yoshisato Yanagisawa572324a2017-06-05 17:41:50 +090039 javac = pctx.AndroidGomaStaticRule("javac",
Colin Cross2fe66872015-03-30 17:20:39 -070040 blueprint.RuleParams{
Colin Cross64162712017-08-08 13:17:59 -070041 Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
Colin Cross3203dde2017-08-28 17:23:21 -070042 `${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
Colin Cross64162712017-08-08 13:17:59 -070043 `$javacFlags $bootClasspath $classpath ` +
44 `-source $javaVersion -target $javaVersion ` +
Colin Crossb852a582017-08-10 17:58:12 -070045 `-d $outDir -s $annoDir @$out.rsp && ` +
Colin Cross0a6e0072017-08-30 14:24:55 -070046 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
47 CommandDeps: []string{"${config.JavacCmd}", "${config.SoongZipCmd}"},
Colin Cross2fe66872015-03-30 17:20:39 -070048 Rspfile: "$out.rsp",
49 RspfileContent: "$in",
Colin Cross2fe66872015-03-30 17:20:39 -070050 },
Colin Cross64162712017-08-08 13:17:59 -070051 "javacFlags", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
Colin Cross2fe66872015-03-30 17:20:39 -070052
Colin Crossc6bbef32017-08-14 14:16:06 -070053 errorprone = pctx.AndroidStaticRule("errorprone",
54 blueprint.RuleParams{
55 Command: `rm -rf "$outDir" "$annoDir" && mkdir -p "$outDir" "$annoDir" && ` +
Colin Cross3a5de652017-09-11 23:10:21 -070056 `${config.ErrorProneCmd} ` +
Colin Crossc6bbef32017-08-14 14:16:06 -070057 `$javacFlags $bootClasspath $classpath ` +
58 `-source $javaVersion -target $javaVersion ` +
59 `-d $outDir -s $annoDir @$out.rsp && ` +
Colin Cross0a6e0072017-08-30 14:24:55 -070060 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
Colin Crossc6bbef32017-08-14 14:16:06 -070061 CommandDeps: []string{
62 "${config.JavaCmd}",
63 "${config.ErrorProneJavacJar}",
64 "${config.ErrorProneJar}",
Colin Cross0a6e0072017-08-30 14:24:55 -070065 "${config.SoongZipCmd}",
Colin Crossc6bbef32017-08-14 14:16:06 -070066 },
67 Rspfile: "$out.rsp",
68 RspfileContent: "$in",
69 },
70 "javacFlags", "bootClasspath", "classpath", "outDir", "annoDir", "javaVersion")
71
Colin Cross9d45bb72016-08-29 16:14:13 -070072 jar = pctx.AndroidStaticRule("jar",
Colin Cross2fe66872015-03-30 17:20:39 -070073 blueprint.RuleParams{
Colin Cross0a6e0072017-08-30 14:24:55 -070074 Command: `${config.SoongZipCmd} -jar -o $out $jarArgs`,
75 CommandDeps: []string{"${config.SoongZipCmd}"},
Colin Cross2fe66872015-03-30 17:20:39 -070076 },
Colin Cross0a6e0072017-08-30 14:24:55 -070077 "jarArgs")
78
79 combineJar = pctx.AndroidStaticRule("combineJar",
80 blueprint.RuleParams{
Colin Cross635acc92017-09-12 22:50:46 -070081 Command: `${config.MergeZipsCmd} -j $jarArgs $out $in`,
Colin Cross0a6e0072017-08-30 14:24:55 -070082 CommandDeps: []string{"${config.MergeZipsCmd}"},
83 },
Colin Cross635acc92017-09-12 22:50:46 -070084 "jarArgs")
Colin Cross2fe66872015-03-30 17:20:39 -070085
Colin Cross6ade34f2017-09-15 13:00:47 -070086 desugar = pctx.AndroidStaticRule("desugar",
87 blueprint.RuleParams{
88 Command: `rm -rf $dumpDir && mkdir -p $dumpDir && ` +
89 `${config.JavaCmd} ` +
90 `-Djdk.internal.lambda.dumpProxyClasses=$$(cd $dumpDir && pwd) ` +
91 `$javaFlags ` +
92 `-jar ${config.DesugarJar} $classpathFlags $desugarFlags ` +
93 `-i $in -o $out`,
94 CommandDeps: []string{"${config.DesugarJar}"},
95 },
96 "javaFlags", "classpathFlags", "desugarFlags", "dumpDir")
97
Colin Cross9d45bb72016-08-29 16:14:13 -070098 dx = pctx.AndroidStaticRule("dx",
Colin Cross2fe66872015-03-30 17:20:39 -070099 blueprint.RuleParams{
Colin Cross6d1e72d2015-04-10 17:44:24 -0700100 Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
Colin Cross6ade34f2017-09-15 13:00:47 -0700101 `${config.DxCmd} --dex --output=$outDir $dxFlags $in && ` +
102 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
103 CommandDeps: []string{
104 "${config.DxCmd}",
105 "${config.SoongZipCmd}",
106 },
Colin Cross2fe66872015-03-30 17:20:39 -0700107 },
108 "outDir", "dxFlags")
Colin Crosse1d62a82015-04-03 16:53:05 -0700109
Colin Cross9d45bb72016-08-29 16:14:13 -0700110 jarjar = pctx.AndroidStaticRule("jarjar",
Colin Cross65bf4f22015-04-03 16:54:17 -0700111 blueprint.RuleParams{
Colin Cross64162712017-08-08 13:17:59 -0700112 Command: "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out",
113 CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
Colin Cross65bf4f22015-04-03 16:54:17 -0700114 },
115 "rulesFile")
Colin Cross2fe66872015-03-30 17:20:39 -0700116)
117
118func init() {
Colin Cross64162712017-08-08 13:17:59 -0700119 pctx.Import("android/soong/java/config")
Colin Cross2fe66872015-03-30 17:20:39 -0700120}
121
122type javaBuilderFlags struct {
123 javacFlags string
124 dxFlags string
Colin Cross6ade34f2017-09-15 13:00:47 -0700125 bootClasspath classpath
126 classpath classpath
127 desugarFlags string
Colin Crossc0b06f12015-04-08 13:03:43 -0700128 aidlFlags string
Colin Cross64162712017-08-08 13:17:59 -0700129 javaVersion string
Colin Cross2fe66872015-03-30 17:20:39 -0700130}
131
132type jarSpec struct {
Colin Cross0a6e0072017-08-30 14:24:55 -0700133 fileList, dir android.Path
Colin Cross2fe66872015-03-30 17:20:39 -0700134}
135
Colin Cross0a6e0072017-08-30 14:24:55 -0700136func (j jarSpec) soongJarArgs() string {
137 return "-C " + j.dir.String() + " -l " + j.fileList.String()
Colin Crossb852a582017-08-10 17:58:12 -0700138}
139
Colin Cross0a6e0072017-08-30 14:24:55 -0700140func TransformJavaToClasses(ctx android.ModuleContext, srcFiles, srcFileLists android.Paths,
141 flags javaBuilderFlags, deps android.Paths) android.ModuleOutPath {
Colin Cross2fe66872015-03-30 17:20:39 -0700142
Colin Cross635c3b02016-05-18 15:37:25 -0700143 classDir := android.PathForModuleOut(ctx, "classes")
Colin Cross64162712017-08-08 13:17:59 -0700144 annoDir := android.PathForModuleOut(ctx, "anno")
Colin Cross635acc92017-09-12 22:50:46 -0700145 classJar := android.PathForModuleOut(ctx, "classes-compiled.jar")
Colin Cross2fe66872015-03-30 17:20:39 -0700146
Colin Cross635c3b02016-05-18 15:37:25 -0700147 javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700148
149 deps = append(deps, srcFileLists...)
Colin Cross6ade34f2017-09-15 13:00:47 -0700150 deps = append(deps, flags.bootClasspath...)
151 deps = append(deps, flags.classpath...)
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700152
Colin Cross635c3b02016-05-18 15:37:25 -0700153 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -0700154 Rule: javac,
155 Description: "javac",
Colin Cross0a6e0072017-08-30 14:24:55 -0700156 Output: classJar,
Colin Cross67a5c132017-05-09 13:45:28 -0700157 Inputs: srcFiles,
158 Implicits: deps,
Colin Cross2fe66872015-03-30 17:20:39 -0700159 Args: map[string]string{
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700160 "javacFlags": javacFlags,
Colin Cross6ade34f2017-09-15 13:00:47 -0700161 "bootClasspath": flags.bootClasspath.JavaBootClasspath(ctx.Device()),
162 "classpath": flags.classpath.JavaClasspath(),
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700163 "outDir": classDir.String(),
Colin Cross64162712017-08-08 13:17:59 -0700164 "annoDir": annoDir.String(),
165 "javaVersion": flags.javaVersion,
Colin Cross2fe66872015-03-30 17:20:39 -0700166 },
167 })
168
Colin Cross0a6e0072017-08-30 14:24:55 -0700169 return classJar
Colin Cross2fe66872015-03-30 17:20:39 -0700170}
171
Colin Crossc6bbef32017-08-14 14:16:06 -0700172func RunErrorProne(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths,
173 flags javaBuilderFlags, deps android.Paths) android.Path {
174
Colin Crossfee57cb2017-09-05 13:16:45 -0700175 if config.ErrorProneJar == "" {
176 ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
177 return nil
178 }
179
Colin Crossc6bbef32017-08-14 14:16:06 -0700180 classDir := android.PathForModuleOut(ctx, "classes-errorprone")
181 annoDir := android.PathForModuleOut(ctx, "anno-errorprone")
182 classFileList := android.PathForModuleOut(ctx, "classes-errorprone.list")
183
184 javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@")
185
186 deps = append(deps, srcFileLists...)
Colin Cross6ade34f2017-09-15 13:00:47 -0700187 deps = append(deps, flags.bootClasspath...)
188 deps = append(deps, flags.classpath...)
Colin Crossc6bbef32017-08-14 14:16:06 -0700189
190 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
191 Rule: errorprone,
192 Description: "errorprone",
193 Output: classFileList,
194 Inputs: srcFiles,
195 Implicits: deps,
196 Args: map[string]string{
197 "javacFlags": javacFlags,
Colin Cross6ade34f2017-09-15 13:00:47 -0700198 "bootClasspath": flags.bootClasspath.JavaBootClasspath(ctx.Device()),
199 "classpath": flags.classpath.JavaClasspath(),
Colin Crossc6bbef32017-08-14 14:16:06 -0700200 "outDir": classDir.String(),
201 "annoDir": annoDir.String(),
202 "javaVersion": flags.javaVersion,
203 },
204 })
205
206 return classFileList
207}
208
Colin Cross0a6e0072017-08-30 14:24:55 -0700209func TransformResourcesToJar(ctx android.ModuleContext, resources []jarSpec,
Colin Cross635acc92017-09-12 22:50:46 -0700210 deps android.Paths) android.Path {
Colin Cross2fe66872015-03-30 17:20:39 -0700211
Colin Cross0a6e0072017-08-30 14:24:55 -0700212 outputFile := android.PathForModuleOut(ctx, "res.jar")
Colin Cross2fe66872015-03-30 17:20:39 -0700213
Colin Cross2fe66872015-03-30 17:20:39 -0700214 jarArgs := []string{}
215
Colin Cross0a6e0072017-08-30 14:24:55 -0700216 for _, j := range resources {
217 deps = append(deps, j.fileList)
218 jarArgs = append(jarArgs, j.soongJarArgs())
Colin Cross2fe66872015-03-30 17:20:39 -0700219 }
220
Colin Cross635c3b02016-05-18 15:37:25 -0700221 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -0700222 Rule: jar,
223 Description: "jar",
224 Output: outputFile,
225 Implicits: deps,
Colin Cross2fe66872015-03-30 17:20:39 -0700226 Args: map[string]string{
Colin Cross0a6e0072017-08-30 14:24:55 -0700227 "jarArgs": strings.Join(jarArgs, " "),
Colin Cross2fe66872015-03-30 17:20:39 -0700228 },
229 })
230
231 return outputFile
232}
233
Colin Cross635acc92017-09-12 22:50:46 -0700234func TransformJarsToJar(ctx android.ModuleContext, stem string, jars android.Paths,
235 manifest android.OptionalPath, stripDirs bool) android.Path {
Colin Cross0a6e0072017-08-30 14:24:55 -0700236
237 outputFile := android.PathForModuleOut(ctx, stem)
238
Colin Cross635acc92017-09-12 22:50:46 -0700239 if len(jars) == 1 && !manifest.Valid() {
Colin Cross0a6e0072017-08-30 14:24:55 -0700240 return jars[0]
241 }
242
Colin Cross635acc92017-09-12 22:50:46 -0700243 var deps android.Paths
244
245 var jarArgs []string
246 if manifest.Valid() {
247 jarArgs = append(jarArgs, "-m "+manifest.String())
248 deps = append(deps, manifest.Path())
249 }
250
251 if stripDirs {
252 jarArgs = append(jarArgs, "-D")
253 }
254
Colin Cross0a6e0072017-08-30 14:24:55 -0700255 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
256 Rule: combineJar,
257 Description: "combine jars",
258 Output: outputFile,
259 Inputs: jars,
Colin Cross635acc92017-09-12 22:50:46 -0700260 Implicits: deps,
261 Args: map[string]string{
262 "jarArgs": strings.Join(jarArgs, " "),
263 },
Colin Cross0a6e0072017-08-30 14:24:55 -0700264 })
265
266 return outputFile
267}
268
Colin Cross6ade34f2017-09-15 13:00:47 -0700269func TransformDesugar(ctx android.ModuleContext, classesJar android.Path,
270 flags javaBuilderFlags) android.Path {
271
272 outputFile := android.PathForModuleOut(ctx, "classes-desugar.jar")
273 dumpDir := android.PathForModuleOut(ctx, "desugar_dumped_classes")
274
275 javaFlags := ""
276 if ctx.AConfig().Getenv("EXPERIMENTAL_USE_OPENJDK9") != "" {
277 javaFlags = "--add-opens java.base/java.lang.invoke=ALL-UNNAMED"
278 }
279
280 var desugarFlags []string
281 desugarFlags = append(desugarFlags, flags.bootClasspath.DesugarBootClasspath()...)
282 desugarFlags = append(desugarFlags, flags.classpath.DesugarClasspath()...)
283
284 var deps android.Paths
285 deps = append(deps, flags.bootClasspath...)
286 deps = append(deps, flags.classpath...)
287
288 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
289 Rule: desugar,
290 Description: "desugar",
291 Output: outputFile,
292 Input: classesJar,
293 Implicits: deps,
294 Args: map[string]string{
295 "dumpDir": dumpDir.String(),
296 "javaFlags": javaFlags,
297 "classpathFlags": strings.Join(desugarFlags, " "),
298 "desugarFlags": flags.desugarFlags,
299 },
300 })
301
302 return outputFile
303}
304
305func TransformClassesJarToDexJar(ctx android.ModuleContext, classesJar android.Path,
306 flags javaBuilderFlags) android.Path {
Colin Cross2fe66872015-03-30 17:20:39 -0700307
Colin Cross635c3b02016-05-18 15:37:25 -0700308 outDir := android.PathForModuleOut(ctx, "dex")
Colin Cross6ade34f2017-09-15 13:00:47 -0700309 outputFile := android.PathForModuleOut(ctx, "classes.dex.jar")
Colin Cross2fe66872015-03-30 17:20:39 -0700310
Colin Cross635c3b02016-05-18 15:37:25 -0700311 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -0700312 Rule: dx,
313 Description: "dx",
314 Output: outputFile,
315 Input: classesJar,
Colin Cross2fe66872015-03-30 17:20:39 -0700316 Args: map[string]string{
317 "dxFlags": flags.dxFlags,
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700318 "outDir": outDir.String(),
Colin Cross2fe66872015-03-30 17:20:39 -0700319 },
320 })
321
Colin Cross2fe66872015-03-30 17:20:39 -0700322 return outputFile
323}
Colin Crosse1d62a82015-04-03 16:53:05 -0700324
Colin Cross0a6e0072017-08-30 14:24:55 -0700325func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.ModuleOutPath {
Colin Cross635c3b02016-05-18 15:37:25 -0700326 outputFile := android.PathForModuleOut(ctx, "classes-jarjar.jar")
327 ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Colin Cross67a5c132017-05-09 13:45:28 -0700328 Rule: jarjar,
329 Description: "jarjar",
330 Output: outputFile,
331 Input: classesJar,
332 Implicit: rulesFile,
Colin Cross65bf4f22015-04-03 16:54:17 -0700333 Args: map[string]string{
Dan Willemsen34cc69e2015-09-23 15:26:20 -0700334 "rulesFile": rulesFile.String(),
Colin Cross65bf4f22015-04-03 16:54:17 -0700335 },
336 })
337
338 return outputFile
339}
Colin Cross6ade34f2017-09-15 13:00:47 -0700340
341type classpath []android.Path
342
343// Returns a -classpath argument in the form java or javac expects
344func (x *classpath) JavaClasspath() string {
345 if len(*x) > 0 {
346 return "-classpath " + strings.Join(x.Strings(), ":")
347 } else {
348 return ""
349 }
350}
351
352// Returns a -processorpath argument in the form java or javac expects
353func (x *classpath) JavaProcessorpath() string {
354 if len(*x) > 0 {
355 return "-processorpath " + strings.Join(x.Strings(), ":")
356 } else {
357 return ""
358 }
359}
360
361// Returns a -bootclasspath argument in the form java or javac expects. If forceEmpty is true,
362// returns -bootclasspath "" if the bootclasspath is empty to ensure javac does not fall back to the
363// default bootclasspath.
364func (x *classpath) JavaBootClasspath(forceEmpty bool) string {
365 if len(*x) > 0 {
366 return "-bootclasspath " + strings.Join(x.Strings(), ":")
367 } else if forceEmpty {
368 return `-bootclasspath ""`
369 } else {
370 return ""
371 }
372}
373
374func (x *classpath) DesugarBootClasspath() []string {
375 if x == nil || *x == nil {
376 return nil
377 }
378 flags := make([]string, len(*x))
379 for i, v := range *x {
380 flags[i] = "--bootclasspath_entry " + v.String()
381 }
382
383 return flags
384}
385
386func (x *classpath) DesugarClasspath() []string {
387 if x == nil || *x == nil {
388 return nil
389 }
390 flags := make([]string, len(*x))
391 for i, v := range *x {
392 flags[i] = "--classpath_entry " + v.String()
393 }
394
395 return flags
396}
397
398// Append an android.Paths to the end of the classpath list
399func (x *classpath) AddPaths(paths android.Paths) {
400 for _, path := range paths {
401 *x = append(*x, path)
402 }
403}
404
405// Convert a classpath to an android.Paths
406func (x *classpath) Paths() android.Paths {
407 return append(android.Paths(nil), (*x)...)
408}
409
410func (x *classpath) Strings() []string {
411 if x == nil {
412 return nil
413 }
414 ret := make([]string, len(*x))
415 for i, path := range *x {
416 ret[i] = path.String()
417 }
418 return ret
419}