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