1// 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 ( 22 "path/filepath" 23 "strconv" 24 "strings" 25 26 "github.com/google/blueprint" 27 "github.com/google/blueprint/proptools" 28 29 "android/soong/android" 30 "android/soong/remoteexec" 31) 32 33var ( 34 pctx = android.NewPackageContext("android/soong/java") 35 36 // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name 37 // requirement leads to unpredictable generated source file names, and a single .java file 38 // will get compiled into multiple .class files if it contains inner classes. To work around 39 // this, all java rules write into separate directories and then are combined into a .jar file 40 // (if the rule produces .class files) or a .srcjar file (if the rule produces .java files). 41 // .srcjar files are unzipped into a temporary directory when compiled with javac. 42 // TODO(b/143658984): goma can't handle the --system argument to javac. 43 javac, javacRE = pctx.MultiCommandRemoteStaticRules("javac", 44 blueprint.RuleParams{ 45 Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" "$out" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + 46 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 47 `(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` + 48 `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` + 49 `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` + 50 `$processorpath $processor $javacFlags $bootClasspath $classpath ` + 51 `-source $javaVersion -target $javaVersion ` + 52 `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` + 53 `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` + 54 `rm -rf "$srcJarDir"`, 55 CommandDeps: []string{ 56 "${config.JavacCmd}", 57 "${config.SoongZipCmd}", 58 "${config.ZipSyncCmd}", 59 }, 60 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 61 Rspfile: "$out.rsp", 62 RspfileContent: "$in", 63 }, map[string]*remoteexec.REParams{ 64 "$javaTemplate": &remoteexec.REParams{ 65 Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"}, 66 ExecStrategy: "${config.REJavacExecStrategy}", 67 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 68 }, 69 "$zipTemplate": &remoteexec.REParams{ 70 Labels: map[string]string{"type": "tool", "name": "soong_zip"}, 71 Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, 72 OutputFiles: []string{"$out"}, 73 ExecStrategy: "${config.REJavacExecStrategy}", 74 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 75 }, 76 }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", 77 "outDir", "annoDir", "javaVersion"}, nil) 78 79 _ = pctx.VariableFunc("kytheCorpus", 80 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() }) 81 _ = pctx.VariableFunc("kytheCuEncoding", 82 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() }) 83 _ = pctx.VariableFunc("kytheCuJavaSourceMax", 84 func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuJavaSourceMax() }) 85 _ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json") 86 // Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about 87 // "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ... 88 // to field java.nio.Buffer.address" 89 kytheExtract = pctx.AndroidStaticRule("kythe", 90 blueprint.RuleParams{ 91 Command: `${config.ZipSyncCmd} -d $srcJarDir ` + 92 `-l $srcJarDir/list -f "*.java" $srcJars && ` + 93 `( [ ! -s $srcJarDir/list -a ! -s $out.rsp ] || ` + 94 `KYTHE_ROOT_DIRECTORY=. KYTHE_OUTPUT_FILE=$out ` + 95 `KYTHE_CORPUS=${kytheCorpus} ` + 96 `KYTHE_VNAMES=${kytheVnames} ` + 97 `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` + 98 `KYTHE_JAVA_SOURCE_BATCH_SIZE=${kytheCuJavaSourceMax} ` + 99 `${config.SoongJavacWrapper} ${config.JavaCmd} ` + 100 `--add-opens=java.base/java.nio=ALL-UNNAMED ` + 101 `-jar ${config.JavaKytheExtractorJar} ` + 102 `${config.JavacHeapFlags} ${config.CommonJdkFlags} ` + 103 `$processorpath $processor $javacFlags $bootClasspath $classpath ` + 104 `-source $javaVersion -target $javaVersion ` + 105 `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list)`, 106 CommandDeps: []string{ 107 "${config.JavaCmd}", 108 "${config.JavaKytheExtractorJar}", 109 "${kytheVnames}", 110 "${config.ZipSyncCmd}", 111 }, 112 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 113 Rspfile: "$out.rsp", 114 RspfileContent: "$in", 115 }, 116 "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", 117 "outDir", "annoDir", "javaVersion") 118 119 extractMatchingApks = pctx.StaticRule( 120 "extractMatchingApks", 121 blueprint.RuleParams{ 122 Command: `rm -rf "$out" && ` + 123 `${config.ExtractApksCmd} -o "${out}" -zip "${zip}" -allow-prereleased=${allow-prereleased} ` + 124 `-sdk-version=${sdk-version} -abis=${abis} ` + 125 `--screen-densities=${screen-densities} --stem=${stem} ` + 126 `-apkcerts=${apkcerts} -partition=${partition} ` + 127 `${in}`, 128 CommandDeps: []string{"${config.ExtractApksCmd}"}, 129 }, 130 "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition", "zip") 131 132 turbine, turbineRE = pctx.RemoteStaticRules("turbine", 133 blueprint.RuleParams{ 134 Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} $outputFlags ` + 135 `--sources @$out.rsp --source_jars $srcJars ` + 136 `--javacopts ${config.CommonJdkFlags} ` + 137 `$javacFlags -source $javaVersion -target $javaVersion -- $turbineFlags && ` + 138 `(for o in $outputs; do if cmp -s $${o}.tmp $${o} ; then rm $${o}.tmp ; else mv $${o}.tmp $${o} ; fi; done )`, 139 CommandDeps: []string{ 140 "${config.TurbineJar}", 141 "${config.JavaCmd}", 142 }, 143 Rspfile: "$out.rsp", 144 RspfileContent: "$in", 145 Restat: true, 146 }, 147 &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"}, 148 ExecStrategy: "${config.RETurbineExecStrategy}", 149 Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"}, 150 RSPFiles: []string{"${out}.rsp"}, 151 OutputFiles: []string{"$rbeOutputs"}, 152 ToolchainInputs: []string{"${config.JavaCmd}"}, 153 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 154 }, 155 []string{"javacFlags", "turbineFlags", "outputFlags", "javaVersion", "outputs", "rbeOutputs", "srcJars"}, []string{"implicits"}) 156 157 jar, jarRE = pctx.RemoteStaticRules("jar", 158 blueprint.RuleParams{ 159 Command: `$reTemplate${config.SoongZipCmd} -jar -o $out @$out.rsp`, 160 CommandDeps: []string{"${config.SoongZipCmd}"}, 161 Rspfile: "$out.rsp", 162 RspfileContent: "$jarArgs", 163 }, 164 &remoteexec.REParams{ 165 ExecStrategy: "${config.REJarExecStrategy}", 166 Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp"}, 167 RSPFiles: []string{"${out}.rsp"}, 168 OutputFiles: []string{"$out"}, 169 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 170 }, []string{"jarArgs"}, nil) 171 172 zip, zipRE = pctx.RemoteStaticRules("zip", 173 blueprint.RuleParams{ 174 Command: `${config.SoongZipCmd} -o $out @$out.rsp`, 175 CommandDeps: []string{"${config.SoongZipCmd}"}, 176 Rspfile: "$out.rsp", 177 RspfileContent: "$jarArgs", 178 }, 179 &remoteexec.REParams{ 180 ExecStrategy: "${config.REZipExecStrategy}", 181 Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp", "$implicits"}, 182 RSPFiles: []string{"${out}.rsp"}, 183 OutputFiles: []string{"$out"}, 184 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 185 }, []string{"jarArgs"}, []string{"implicits"}) 186 187 combineJar = pctx.AndroidStaticRule("combineJar", 188 blueprint.RuleParams{ 189 Command: `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out $in`, 190 CommandDeps: []string{"${config.MergeZipsCmd}"}, 191 }, 192 "jarArgs") 193 194 jarjar = pctx.AndroidStaticRule("jarjar", 195 blueprint.RuleParams{ 196 Command: "" + 197 // Jarjar doesn't exit with an error when the rules file contains a syntax error, 198 // leading to stale or missing files later in the build. Remove the output file 199 // before running jarjar. 200 "rm -f ${out} && " + 201 "${config.JavaCmd} ${config.JavaVmFlags}" + 202 // b/146418363 Enable Android specific jarjar transformer to drop compat annotations 203 // for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes 204 // avoids adding new hiddenapis after jarjar'ing. 205 " -DremoveAndroidCompatAnnotations=true" + 206 " -jar ${config.JarjarCmd} process $rulesFile $in $out && " + 207 // Turn a missing output file into a ninja error 208 `[ -e ${out} ] || (echo "Missing output file"; exit 1)`, 209 CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"}, 210 }, 211 "rulesFile") 212 213 packageCheck = pctx.AndroidStaticRule("packageCheck", 214 blueprint.RuleParams{ 215 Command: "rm -f $out && " + 216 "${config.PackageCheckCmd} $in $packages && " + 217 "touch $out", 218 CommandDeps: []string{"${config.PackageCheckCmd}"}, 219 }, 220 "packages") 221 222 jetifier = pctx.AndroidStaticRule("jetifier", 223 blueprint.RuleParams{ 224 Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JetifierJar} -l error -o $out -i $in", 225 CommandDeps: []string{"${config.JavaCmd}", "${config.JetifierJar}"}, 226 }, 227 ) 228 229 zipalign = pctx.AndroidStaticRule("zipalign", 230 blueprint.RuleParams{ 231 Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " + 232 "${config.ZipAlign} -f -p 4 $in $out; " + 233 "else " + 234 "cp -f $in $out; " + 235 "fi", 236 CommandDeps: []string{"${config.ZipAlign}"}, 237 }, 238 ) 239) 240 241func init() { 242 pctx.Import("android/soong/android") 243 pctx.Import("android/soong/java/config") 244} 245 246type javaBuilderFlags struct { 247 javacFlags string 248 249 // bootClasspath is the list of jars that form the boot classpath (generally the java.* and 250 // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses 251 // systemModules and java9Classpath instead. 252 bootClasspath classpath 253 254 // classpath is the list of jars that form the classpath for javac and kotlinc rules. It 255 // contains header jars for all static and non-static dependencies. 256 classpath classpath 257 258 // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains 259 // header jars for all non-static dependencies. Static dependencies have already been 260 // combined into the program jar. 261 dexClasspath classpath 262 263 // java9Classpath is the list of jars that will be added to the classpath when targeting 264 // 1.9 or higher. It generally contains the android.* classes, while the java.* classes 265 // are provided by systemModules. 266 java9Classpath classpath 267 268 processorPath classpath 269 processors []string 270 systemModules *systemModules 271 aidlFlags string 272 aidlDeps android.Paths 273 javaVersion javaVersion 274 275 errorProneExtraJavacFlags string 276 errorProneProcessorPath classpath 277 278 kotlincFlags string 279 kotlincClasspath classpath 280 kotlincDeps android.Paths 281 282 proto android.ProtoFlags 283} 284 285func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int, 286 srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) { 287 288 // Compile java sources into .class files 289 desc := "javac" 290 if shardIdx >= 0 { 291 desc += strconv.Itoa(shardIdx) 292 } 293 294 transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc) 295} 296 297// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars 298// to compile with given set of builder flags, etc. 299func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx int, 300 srcFiles, srcJars android.Paths, 301 flags javaBuilderFlags, deps android.Paths) { 302 303 deps = append(deps, srcJars...) 304 classpath := flags.classpath 305 306 var bootClasspath string 307 if flags.javaVersion.usesJavaModules() { 308 var systemModuleDeps android.Paths 309 bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) 310 deps = append(deps, systemModuleDeps...) 311 classpath = append(flags.java9Classpath, classpath...) 312 } else { 313 deps = append(deps, flags.bootClasspath...) 314 if len(flags.bootClasspath) == 0 && ctx.Device() { 315 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 316 // ensure java does not fall back to the default bootclasspath. 317 bootClasspath = `-bootclasspath ""` 318 } else { 319 bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") 320 } 321 } 322 323 deps = append(deps, classpath...) 324 deps = append(deps, flags.processorPath...) 325 326 processor := "-proc:none" 327 if len(flags.processors) > 0 { 328 processor = "-processor " + strings.Join(flags.processors, ",") 329 } 330 331 intermediatesDir := "xref" 332 if idx >= 0 { 333 intermediatesDir += strconv.Itoa(idx) 334 } 335 336 ctx.Build(pctx, 337 android.BuildParams{ 338 Rule: kytheExtract, 339 Description: "Xref Java extractor", 340 Output: xrefFile, 341 Inputs: srcFiles, 342 Implicits: deps, 343 Args: map[string]string{ 344 "annoDir": android.PathForModuleOut(ctx, intermediatesDir, "anno").String(), 345 "bootClasspath": bootClasspath, 346 "classpath": classpath.FormJavaClassPath("-classpath"), 347 "javacFlags": flags.javacFlags, 348 "javaVersion": flags.javaVersion.String(), 349 "outDir": android.PathForModuleOut(ctx, "javac", "classes.xref").String(), 350 "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"), 351 "processor": processor, 352 "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, "srcjars.xref").String(), 353 "srcJars": strings.Join(srcJars.Strings(), " "), 354 }, 355 }) 356} 357 358func turbineFlags(ctx android.ModuleContext, flags javaBuilderFlags) (string, android.Paths) { 359 var deps android.Paths 360 361 classpath := flags.classpath 362 363 var bootClasspath string 364 if flags.javaVersion.usesJavaModules() { 365 var systemModuleDeps android.Paths 366 bootClasspath, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device()) 367 deps = append(deps, systemModuleDeps...) 368 classpath = append(flags.java9Classpath, classpath...) 369 } else { 370 deps = append(deps, flags.bootClasspath...) 371 if len(flags.bootClasspath) == 0 && ctx.Device() { 372 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 373 // ensure turbine does not fall back to the default bootclasspath. 374 bootClasspath = `--bootclasspath ""` 375 } else { 376 bootClasspath = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ") 377 } 378 } 379 380 deps = append(deps, classpath...) 381 turbineFlags := bootClasspath + " " + classpath.FormTurbineClassPath("--classpath ") 382 383 return turbineFlags, deps 384} 385 386func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath, 387 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 388 389 turbineFlags, deps := turbineFlags(ctx, flags) 390 391 deps = append(deps, srcJars...) 392 393 rule := turbine 394 args := map[string]string{ 395 "javacFlags": flags.javacFlags, 396 "srcJars": strings.Join(srcJars.Strings(), " "), 397 "javaVersion": flags.javaVersion.String(), 398 "turbineFlags": turbineFlags, 399 "outputFlags": "--output " + outputFile.String() + ".tmp", 400 "outputs": outputFile.String(), 401 } 402 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") { 403 rule = turbineRE 404 args["implicits"] = strings.Join(deps.Strings(), ",") 405 args["rbeOutputs"] = outputFile.String() + ".tmp" 406 } 407 ctx.Build(pctx, android.BuildParams{ 408 Rule: rule, 409 Description: "turbine", 410 Output: outputFile, 411 Inputs: srcFiles, 412 Implicits: deps, 413 Args: args, 414 }) 415} 416 417// TurbineApt produces a rule to run annotation processors using turbine. 418func TurbineApt(ctx android.ModuleContext, outputSrcJar, outputResJar android.WritablePath, 419 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 420 421 turbineFlags, deps := turbineFlags(ctx, flags) 422 423 deps = append(deps, srcJars...) 424 425 deps = append(deps, flags.processorPath...) 426 turbineFlags += " " + flags.processorPath.FormTurbineClassPath("--processorpath ") 427 turbineFlags += " --processors " + strings.Join(flags.processors, " ") 428 429 outputs := android.WritablePaths{outputSrcJar, outputResJar} 430 outputFlags := "--gensrc_output " + outputSrcJar.String() + ".tmp " + 431 "--resource_output " + outputResJar.String() + ".tmp" 432 433 rule := turbine 434 args := map[string]string{ 435 "javacFlags": flags.javacFlags, 436 "srcJars": strings.Join(srcJars.Strings(), " "), 437 "javaVersion": flags.javaVersion.String(), 438 "turbineFlags": turbineFlags, 439 "outputFlags": outputFlags, 440 "outputs": strings.Join(outputs.Strings(), " "), 441 } 442 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_TURBINE") { 443 rule = turbineRE 444 args["implicits"] = strings.Join(deps.Strings(), ",") 445 args["rbeOutputs"] = outputSrcJar.String() + ".tmp," + outputResJar.String() + ".tmp" 446 } 447 ctx.Build(pctx, android.BuildParams{ 448 Rule: rule, 449 Description: "turbine apt", 450 Output: outputs[0], 451 ImplicitOutputs: outputs[1:], 452 Inputs: srcFiles, 453 Implicits: deps, 454 Args: args, 455 }) 456} 457 458// transformJavaToClasses takes source files and converts them to a jar containing .class files. 459// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain 460// sources. flags contains various command line flags to be passed to the compiler. 461// 462// This method may be used for different compilers, including javac and Error Prone. The rule 463// argument specifies which command line to use and desc sets the description of the rule that will 464// be printed at build time. The stem argument provides the file name of the output jar, and 465// suffix will be appended to various intermediate files and directories to avoid collisions when 466// this function is called twice in the same module directory. 467func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, 468 shardIdx int, srcFiles, srcJars android.Paths, 469 flags javaBuilderFlags, deps android.Paths, 470 intermediatesDir, desc string) { 471 472 deps = append(deps, srcJars...) 473 474 classpath := flags.classpath 475 476 var bootClasspath string 477 if flags.javaVersion.usesJavaModules() { 478 var systemModuleDeps android.Paths 479 bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) 480 deps = append(deps, systemModuleDeps...) 481 classpath = append(flags.java9Classpath, classpath...) 482 } else { 483 deps = append(deps, flags.bootClasspath...) 484 if len(flags.bootClasspath) == 0 && ctx.Device() { 485 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 486 // ensure java does not fall back to the default bootclasspath. 487 bootClasspath = `-bootclasspath ""` 488 } else { 489 bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") 490 } 491 } 492 493 deps = append(deps, classpath...) 494 deps = append(deps, flags.processorPath...) 495 496 processor := "-proc:none" 497 if len(flags.processors) > 0 { 498 processor = "-processor " + strings.Join(flags.processors, ",") 499 } 500 501 srcJarDir := "srcjars" 502 outDir := "classes" 503 annoDir := "anno" 504 if shardIdx >= 0 { 505 shardDir := "shard" + strconv.Itoa(shardIdx) 506 srcJarDir = filepath.Join(shardDir, srcJarDir) 507 outDir = filepath.Join(shardDir, outDir) 508 annoDir = filepath.Join(shardDir, annoDir) 509 } 510 rule := javac 511 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_JAVAC") { 512 rule = javacRE 513 } 514 ctx.Build(pctx, android.BuildParams{ 515 Rule: rule, 516 Description: desc, 517 Output: outputFile, 518 Inputs: srcFiles, 519 Implicits: deps, 520 Args: map[string]string{ 521 "javacFlags": flags.javacFlags, 522 "bootClasspath": bootClasspath, 523 "classpath": classpath.FormJavaClassPath("-classpath"), 524 "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"), 525 "processor": processor, 526 "srcJars": strings.Join(srcJars.Strings(), " "), 527 "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(), 528 "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(), 529 "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(), 530 "javaVersion": flags.javaVersion.String(), 531 }, 532 }) 533} 534 535func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath, 536 jarArgs []string, deps android.Paths) { 537 538 rule := jar 539 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_JAR") { 540 rule = jarRE 541 } 542 ctx.Build(pctx, android.BuildParams{ 543 Rule: rule, 544 Description: "jar", 545 Output: outputFile, 546 Implicits: deps, 547 Args: map[string]string{ 548 "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), 549 }, 550 }) 551} 552 553func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePath, desc string, 554 jars android.Paths, manifest android.OptionalPath, stripDirEntries bool, filesToStrip []string, 555 dirsToStrip []string) { 556 557 var deps android.Paths 558 559 var jarArgs []string 560 if manifest.Valid() { 561 jarArgs = append(jarArgs, "-m ", manifest.String()) 562 deps = append(deps, manifest.Path()) 563 } 564 565 for _, dir := range dirsToStrip { 566 jarArgs = append(jarArgs, "-stripDir ", dir) 567 } 568 569 for _, file := range filesToStrip { 570 jarArgs = append(jarArgs, "-stripFile ", file) 571 } 572 573 // Remove any module-info.class files that may have come from prebuilt jars, they cause problems 574 // for downstream tools like desugar. 575 jarArgs = append(jarArgs, "-stripFile module-info.class") 576 577 if stripDirEntries { 578 jarArgs = append(jarArgs, "-D") 579 } 580 581 ctx.Build(pctx, android.BuildParams{ 582 Rule: combineJar, 583 Description: desc, 584 Output: outputFile, 585 Inputs: jars, 586 Implicits: deps, 587 Args: map[string]string{ 588 "jarArgs": strings.Join(jarArgs, " "), 589 }, 590 }) 591} 592 593func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, 594 classesJar android.Path, rulesFile android.Path) { 595 ctx.Build(pctx, android.BuildParams{ 596 Rule: jarjar, 597 Description: "jarjar", 598 Output: outputFile, 599 Input: classesJar, 600 Implicit: rulesFile, 601 Args: map[string]string{ 602 "rulesFile": rulesFile.String(), 603 }, 604 }) 605} 606 607func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath, 608 classesJar android.Path, permittedPackages []string) { 609 ctx.Build(pctx, android.BuildParams{ 610 Rule: packageCheck, 611 Description: "packageCheck", 612 Output: outputFile, 613 Input: classesJar, 614 Args: map[string]string{ 615 "packages": strings.Join(permittedPackages, " "), 616 }, 617 }) 618} 619 620func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePath, 621 inputFile android.Path) { 622 ctx.Build(pctx, android.BuildParams{ 623 Rule: jetifier, 624 Description: "jetifier", 625 Output: outputFile, 626 Input: inputFile, 627 }) 628} 629 630func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) { 631 android.WriteFileRule(ctx, outputFile, "Main-Class: "+mainClass+"\n") 632} 633 634func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) { 635 ctx.Build(pctx, android.BuildParams{ 636 Rule: zipalign, 637 Description: "align", 638 Input: inputFile, 639 Output: outputFile, 640 }) 641} 642 643type classpath android.Paths 644 645func (x *classpath) formJoinedClassPath(optName string, sep string) string { 646 if optName != "" && !strings.HasSuffix(optName, "=") && !strings.HasSuffix(optName, " ") { 647 optName += " " 648 } 649 if len(*x) > 0 { 650 return optName + strings.Join(x.Strings(), sep) 651 } else { 652 return "" 653 } 654} 655func (x *classpath) FormJavaClassPath(optName string) string { 656 return x.formJoinedClassPath(optName, ":") 657} 658 659func (x *classpath) FormTurbineClassPath(optName string) string { 660 return x.formJoinedClassPath(optName, " ") 661} 662 663// FormRepeatedClassPath returns a list of arguments with the given optName prefixed to each element of the classpath. 664func (x *classpath) FormRepeatedClassPath(optName string) []string { 665 if x == nil || *x == nil { 666 return nil 667 } 668 flags := make([]string, len(*x)) 669 for i, v := range *x { 670 flags[i] = optName + v.String() 671 } 672 673 return flags 674} 675 676// Convert a classpath to an android.Paths 677func (x *classpath) Paths() android.Paths { 678 return append(android.Paths(nil), (*x)...) 679} 680 681func (x *classpath) Strings() []string { 682 if x == nil { 683 return nil 684 } 685 ret := make([]string, len(*x)) 686 for i, path := range *x { 687 ret[i] = path.String() 688 } 689 return ret 690} 691 692type systemModules struct { 693 dir android.Path 694 deps android.Paths 695} 696 697// Returns a --system argument in the form javac expects with -source 1.9 and the list of files to 698// depend on. If forceEmpty is true, returns --system=none if the list is empty to ensure javac 699// does not fall back to the default system modules. 700func (x *systemModules) FormJavaSystemModulesPath(forceEmpty bool) (string, android.Paths) { 701 if x != nil { 702 return "--system=" + x.dir.String(), x.deps 703 } else if forceEmpty { 704 return "--system=none", nil 705 } else { 706 return "", nil 707 } 708} 709 710// Returns a --system argument in the form turbine expects with -source 1.9 and the list of files to 711// depend on. If forceEmpty is true, returns --bootclasspath "" if the list is empty to ensure turbine 712// does not fall back to the default bootclasspath. 713func (x *systemModules) FormTurbineSystemModulesPath(forceEmpty bool) (string, android.Paths) { 714 if x != nil { 715 return "--system " + x.dir.String(), x.deps 716 } else if forceEmpty { 717 return `--bootclasspath ""`, nil 718 } else { 719 return "--system ${config.JavaHome}", nil 720 } 721} 722