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 = remoteexec.MultiCommandStaticRules(pctx, "javac", 44 blueprint.RuleParams{ 45 Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && 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.SourcePathVariable("kytheVnames", "build/soong/vnames.json") 84 // Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about 85 // "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ... 86 // to field java.nio.Buffer.address" 87 kytheExtract = pctx.AndroidStaticRule("kythe", 88 blueprint.RuleParams{ 89 Command: `${config.ZipSyncCmd} -d $srcJarDir ` + 90 `-l $srcJarDir/list -f "*.java" $srcJars && ` + 91 `( [ ! -s $srcJarDir/list -a ! -s $out.rsp ] || ` + 92 `KYTHE_ROOT_DIRECTORY=. KYTHE_OUTPUT_FILE=$out ` + 93 `KYTHE_CORPUS=${kytheCorpus} ` + 94 `KYTHE_VNAMES=${kytheVnames} ` + 95 `KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` + 96 `${config.SoongJavacWrapper} ${config.JavaCmd} ` + 97 `--add-opens=java.base/java.nio=ALL-UNNAMED ` + 98 `-jar ${config.JavaKytheExtractorJar} ` + 99 `${config.JavacHeapFlags} ${config.CommonJdkFlags} ` + 100 `$processorpath $processor $javacFlags $bootClasspath $classpath ` + 101 `-source $javaVersion -target $javaVersion ` + 102 `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list)`, 103 CommandDeps: []string{ 104 "${config.JavaCmd}", 105 "${config.JavaKytheExtractorJar}", 106 "${kytheVnames}", 107 "${config.ZipSyncCmd}", 108 }, 109 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 110 Rspfile: "$out.rsp", 111 RspfileContent: "$in", 112 }, 113 "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", 114 "outDir", "annoDir", "javaVersion") 115 116 extractMatchingApks = pctx.StaticRule( 117 "extractMatchingApks", 118 blueprint.RuleParams{ 119 Command: `rm -rf "$out" && ` + 120 `${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` + 121 `-sdk-version=${sdk-version} -abis=${abis} ` + 122 `--screen-densities=${screen-densities} --stem=${stem} ` + 123 `-apkcerts=${apkcerts} -partition=${partition} ` + 124 `${in}`, 125 CommandDeps: []string{"${config.ExtractApksCmd}"}, 126 }, 127 "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition") 128 129 turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine", 130 blueprint.RuleParams{ 131 Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + 132 `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` + 133 `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` + 134 `--javacopts ${config.CommonJdkFlags} ` + 135 `$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` + 136 `${config.Ziptime} $out.tmp && ` + 137 `(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`, 138 CommandDeps: []string{ 139 "${config.TurbineJar}", 140 "${config.JavaCmd}", 141 "${config.Ziptime}", 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 RSPFile: "${out}.rsp", 151 OutputFiles: []string{"$out.tmp"}, 152 OutputDirectories: []string{"$outDir"}, 153 ToolchainInputs: []string{"${config.JavaCmd}"}, 154 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 155 }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"}) 156 157 jar, jarRE = remoteexec.StaticRules(pctx, "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 RSPFile: "${out}.rsp", 168 OutputFiles: []string{"$out"}, 169 Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, 170 }, []string{"jarArgs"}, nil) 171 172 zip, zipRE = remoteexec.StaticRules(pctx, "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 RSPFile: "${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: "${config.JavaCmd} ${config.JavaVmFlags}" + 197 // b/146418363 Enable Android specific jarjar transformer to drop compat annotations 198 // for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes 199 // avoids adding new hiddenapis after jarjar'ing. 200 " -DremoveAndroidCompatAnnotations=true" + 201 " -jar ${config.JarjarCmd} process $rulesFile $in $out", 202 CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"}, 203 }, 204 "rulesFile") 205 206 packageCheck = pctx.AndroidStaticRule("packageCheck", 207 blueprint.RuleParams{ 208 Command: "rm -f $out && " + 209 "${config.PackageCheckCmd} $in $packages && " + 210 "touch $out", 211 CommandDeps: []string{"${config.PackageCheckCmd}"}, 212 }, 213 "packages") 214 215 jetifier = pctx.AndroidStaticRule("jetifier", 216 blueprint.RuleParams{ 217 Command: "${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JetifierJar} -l error -o $out -i $in", 218 CommandDeps: []string{"${config.JavaCmd}", "${config.JetifierJar}"}, 219 }, 220 ) 221 222 zipalign = pctx.AndroidStaticRule("zipalign", 223 blueprint.RuleParams{ 224 Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " + 225 "${config.ZipAlign} -f -p 4 $in $out; " + 226 "else " + 227 "cp -f $in $out; " + 228 "fi", 229 CommandDeps: []string{"${config.ZipAlign}"}, 230 }, 231 ) 232) 233 234func init() { 235 pctx.Import("android/soong/android") 236 pctx.Import("android/soong/java/config") 237 pctx.Import("android/soong/remoteexec") 238} 239 240type javaBuilderFlags struct { 241 javacFlags string 242 bootClasspath classpath 243 classpath classpath 244 java9Classpath classpath 245 processorPath classpath 246 processors []string 247 systemModules *systemModules 248 aidlFlags string 249 aidlDeps android.Paths 250 javaVersion javaVersion 251 252 errorProneExtraJavacFlags string 253 errorProneProcessorPath classpath 254 255 kotlincFlags string 256 kotlincClasspath classpath 257 258 proto android.ProtoFlags 259} 260 261func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int, 262 srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) { 263 264 // Compile java sources into .class files 265 desc := "javac" 266 if shardIdx >= 0 { 267 desc += strconv.Itoa(shardIdx) 268 } 269 270 transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc) 271} 272 273func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath, 274 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 275 276 flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...) 277 278 if len(flags.errorProneExtraJavacFlags) > 0 { 279 if len(flags.javacFlags) > 0 { 280 flags.javacFlags += " " + flags.errorProneExtraJavacFlags 281 } else { 282 flags.javacFlags = flags.errorProneExtraJavacFlags 283 } 284 } 285 286 transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil, 287 "errorprone", "errorprone") 288} 289 290// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars 291// to compile with given set of builder flags, etc. 292func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx int, 293 srcFiles, srcJars android.Paths, 294 flags javaBuilderFlags, deps android.Paths) { 295 296 deps = append(deps, srcJars...) 297 classpath := flags.classpath 298 299 var bootClasspath string 300 if flags.javaVersion.usesJavaModules() { 301 var systemModuleDeps android.Paths 302 bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) 303 deps = append(deps, systemModuleDeps...) 304 classpath = append(flags.java9Classpath, classpath...) 305 } else { 306 deps = append(deps, flags.bootClasspath...) 307 if len(flags.bootClasspath) == 0 && ctx.Device() { 308 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 309 // ensure java does not fall back to the default bootclasspath. 310 bootClasspath = `-bootclasspath ""` 311 } else { 312 bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") 313 } 314 } 315 316 deps = append(deps, classpath...) 317 deps = append(deps, flags.processorPath...) 318 319 processor := "-proc:none" 320 if len(flags.processors) > 0 { 321 processor = "-processor " + strings.Join(flags.processors, ",") 322 } 323 324 intermediatesDir := "xref" 325 if idx >= 0 { 326 intermediatesDir += strconv.Itoa(idx) 327 } 328 329 ctx.Build(pctx, 330 android.BuildParams{ 331 Rule: kytheExtract, 332 Description: "Xref Java extractor", 333 Output: xrefFile, 334 Inputs: srcFiles, 335 Implicits: deps, 336 Args: map[string]string{ 337 "annoDir": android.PathForModuleOut(ctx, intermediatesDir, "anno").String(), 338 "bootClasspath": bootClasspath, 339 "classpath": classpath.FormJavaClassPath("-classpath"), 340 "javacFlags": flags.javacFlags, 341 "javaVersion": flags.javaVersion.String(), 342 "outDir": android.PathForModuleOut(ctx, "javac", "classes.xref").String(), 343 "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"), 344 "processor": processor, 345 "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, "srcjars.xref").String(), 346 "srcJars": strings.Join(srcJars.Strings(), " "), 347 }, 348 }) 349} 350 351func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath, 352 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 353 354 var deps android.Paths 355 deps = append(deps, srcJars...) 356 357 classpath := flags.classpath 358 359 var bootClasspath string 360 if flags.javaVersion.usesJavaModules() { 361 var systemModuleDeps android.Paths 362 bootClasspath, systemModuleDeps = flags.systemModules.FormTurbineSystemModulesPath(ctx.Device()) 363 deps = append(deps, systemModuleDeps...) 364 classpath = append(flags.java9Classpath, classpath...) 365 } else { 366 deps = append(deps, flags.bootClasspath...) 367 if len(flags.bootClasspath) == 0 && ctx.Device() { 368 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 369 // ensure turbine does not fall back to the default bootclasspath. 370 bootClasspath = `--bootclasspath ""` 371 } else { 372 bootClasspath = flags.bootClasspath.FormTurbineClassPath("--bootclasspath ") 373 } 374 } 375 376 deps = append(deps, classpath...) 377 deps = append(deps, flags.processorPath...) 378 379 rule := turbine 380 args := map[string]string{ 381 "javacFlags": flags.javacFlags, 382 "bootClasspath": bootClasspath, 383 "srcJars": strings.Join(srcJars.Strings(), " "), 384 "classpath": classpath.FormTurbineClassPath("--classpath "), 385 "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), 386 "javaVersion": flags.javaVersion.String(), 387 } 388 if ctx.Config().IsEnvTrue("RBE_TURBINE") { 389 rule = turbineRE 390 args["implicits"] = strings.Join(deps.Strings(), ",") 391 } 392 ctx.Build(pctx, android.BuildParams{ 393 Rule: rule, 394 Description: "turbine", 395 Output: outputFile, 396 Inputs: srcFiles, 397 Implicits: deps, 398 Args: args, 399 }) 400} 401 402// transformJavaToClasses takes source files and converts them to a jar containing .class files. 403// srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain 404// sources. flags contains various command line flags to be passed to the compiler. 405// 406// This method may be used for different compilers, including javac and Error Prone. The rule 407// argument specifies which command line to use and desc sets the description of the rule that will 408// be printed at build time. The stem argument provides the file name of the output jar, and 409// suffix will be appended to various intermediate files and directories to avoid collisions when 410// this function is called twice in the same module directory. 411func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, 412 shardIdx int, srcFiles, srcJars android.Paths, 413 flags javaBuilderFlags, deps android.Paths, 414 intermediatesDir, desc string) { 415 416 deps = append(deps, srcJars...) 417 418 classpath := flags.classpath 419 420 var bootClasspath string 421 if flags.javaVersion.usesJavaModules() { 422 var systemModuleDeps android.Paths 423 bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) 424 deps = append(deps, systemModuleDeps...) 425 classpath = append(flags.java9Classpath, classpath...) 426 } else { 427 deps = append(deps, flags.bootClasspath...) 428 if len(flags.bootClasspath) == 0 && ctx.Device() { 429 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 430 // ensure java does not fall back to the default bootclasspath. 431 bootClasspath = `-bootclasspath ""` 432 } else { 433 bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") 434 } 435 } 436 437 deps = append(deps, classpath...) 438 deps = append(deps, flags.processorPath...) 439 440 processor := "-proc:none" 441 if len(flags.processors) > 0 { 442 processor = "-processor " + strings.Join(flags.processors, ",") 443 } 444 445 srcJarDir := "srcjars" 446 outDir := "classes" 447 annoDir := "anno" 448 if shardIdx >= 0 { 449 shardDir := "shard" + strconv.Itoa(shardIdx) 450 srcJarDir = filepath.Join(shardDir, srcJarDir) 451 outDir = filepath.Join(shardDir, outDir) 452 annoDir = filepath.Join(shardDir, annoDir) 453 } 454 rule := javac 455 if ctx.Config().IsEnvTrue("RBE_JAVAC") { 456 rule = javacRE 457 } 458 ctx.Build(pctx, android.BuildParams{ 459 Rule: rule, 460 Description: desc, 461 Output: outputFile, 462 Inputs: srcFiles, 463 Implicits: deps, 464 Args: map[string]string{ 465 "javacFlags": flags.javacFlags, 466 "bootClasspath": bootClasspath, 467 "classpath": classpath.FormJavaClassPath("-classpath"), 468 "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"), 469 "processor": processor, 470 "srcJars": strings.Join(srcJars.Strings(), " "), 471 "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(), 472 "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(), 473 "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(), 474 "javaVersion": flags.javaVersion.String(), 475 }, 476 }) 477} 478 479func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath, 480 jarArgs []string, deps android.Paths) { 481 482 rule := jar 483 if ctx.Config().IsEnvTrue("RBE_JAR") { 484 rule = jarRE 485 } 486 ctx.Build(pctx, android.BuildParams{ 487 Rule: rule, 488 Description: "jar", 489 Output: outputFile, 490 Implicits: deps, 491 Args: map[string]string{ 492 "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), 493 }, 494 }) 495} 496 497func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePath, desc string, 498 jars android.Paths, manifest android.OptionalPath, stripDirEntries bool, filesToStrip []string, 499 dirsToStrip []string) { 500 501 var deps android.Paths 502 503 var jarArgs []string 504 if manifest.Valid() { 505 jarArgs = append(jarArgs, "-m ", manifest.String()) 506 deps = append(deps, manifest.Path()) 507 } 508 509 for _, dir := range dirsToStrip { 510 jarArgs = append(jarArgs, "-stripDir ", dir) 511 } 512 513 for _, file := range filesToStrip { 514 jarArgs = append(jarArgs, "-stripFile ", file) 515 } 516 517 // Remove any module-info.class files that may have come from prebuilt jars, they cause problems 518 // for downstream tools like desugar. 519 jarArgs = append(jarArgs, "-stripFile module-info.class") 520 521 if stripDirEntries { 522 jarArgs = append(jarArgs, "-D") 523 } 524 525 ctx.Build(pctx, android.BuildParams{ 526 Rule: combineJar, 527 Description: desc, 528 Output: outputFile, 529 Inputs: jars, 530 Implicits: deps, 531 Args: map[string]string{ 532 "jarArgs": strings.Join(jarArgs, " "), 533 }, 534 }) 535} 536 537func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, 538 classesJar android.Path, rulesFile android.Path) { 539 ctx.Build(pctx, android.BuildParams{ 540 Rule: jarjar, 541 Description: "jarjar", 542 Output: outputFile, 543 Input: classesJar, 544 Implicit: rulesFile, 545 Args: map[string]string{ 546 "rulesFile": rulesFile.String(), 547 }, 548 }) 549} 550 551func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath, 552 classesJar android.Path, permittedPackages []string) { 553 ctx.Build(pctx, android.BuildParams{ 554 Rule: packageCheck, 555 Description: "packageCheck", 556 Output: outputFile, 557 Input: classesJar, 558 Args: map[string]string{ 559 "packages": strings.Join(permittedPackages, " "), 560 }, 561 }) 562} 563 564func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePath, 565 inputFile android.Path) { 566 ctx.Build(pctx, android.BuildParams{ 567 Rule: jetifier, 568 Description: "jetifier", 569 Output: outputFile, 570 Input: inputFile, 571 }) 572} 573 574func GenerateMainClassManifest(ctx android.ModuleContext, outputFile android.WritablePath, mainClass string) { 575 ctx.Build(pctx, android.BuildParams{ 576 Rule: android.WriteFile, 577 Description: "manifest", 578 Output: outputFile, 579 Args: map[string]string{ 580 "content": "Main-Class: " + mainClass + "\n", 581 }, 582 }) 583} 584 585func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePath, inputFile android.Path) { 586 ctx.Build(pctx, android.BuildParams{ 587 Rule: zipalign, 588 Description: "align", 589 Input: inputFile, 590 Output: outputFile, 591 }) 592} 593 594type classpath android.Paths 595 596func (x *classpath) formJoinedClassPath(optName string, sep string) string { 597 if optName != "" && !strings.HasSuffix(optName, "=") && !strings.HasSuffix(optName, " ") { 598 optName += " " 599 } 600 if len(*x) > 0 { 601 return optName + strings.Join(x.Strings(), sep) 602 } else { 603 return "" 604 } 605} 606func (x *classpath) FormJavaClassPath(optName string) string { 607 return x.formJoinedClassPath(optName, ":") 608} 609 610func (x *classpath) FormTurbineClassPath(optName string) string { 611 return x.formJoinedClassPath(optName, " ") 612} 613 614// FormRepeatedClassPath returns a list of arguments with the given optName prefixed to each element of the classpath. 615func (x *classpath) FormRepeatedClassPath(optName string) []string { 616 if x == nil || *x == nil { 617 return nil 618 } 619 flags := make([]string, len(*x)) 620 for i, v := range *x { 621 flags[i] = optName + v.String() 622 } 623 624 return flags 625} 626 627// Convert a classpath to an android.Paths 628func (x *classpath) Paths() android.Paths { 629 return append(android.Paths(nil), (*x)...) 630} 631 632func (x *classpath) Strings() []string { 633 if x == nil { 634 return nil 635 } 636 ret := make([]string, len(*x)) 637 for i, path := range *x { 638 ret[i] = path.String() 639 } 640 return ret 641} 642 643type systemModules struct { 644 dir android.Path 645 deps android.Paths 646} 647 648// Returns a --system argument in the form javac expects with -source 1.9 and the list of files to 649// depend on. If forceEmpty is true, returns --system=none if the list is empty to ensure javac 650// does not fall back to the default system modules. 651func (x *systemModules) FormJavaSystemModulesPath(forceEmpty bool) (string, android.Paths) { 652 if x != nil { 653 return "--system=" + x.dir.String(), x.deps 654 } else if forceEmpty { 655 return "--system=none", nil 656 } else { 657 return "", nil 658 } 659} 660 661// Returns a --system argument in the form turbine expects with -source 1.9 and the list of files to 662// depend on. If forceEmpty is true, returns --bootclasspath "" if the list is empty to ensure turbine 663// does not fall back to the default bootclasspath. 664func (x *systemModules) FormTurbineSystemModulesPath(forceEmpty bool) (string, android.Paths) { 665 if x != nil { 666 return "--system " + x.dir.String(), x.deps 667 } else if forceEmpty { 668 return `--bootclasspath ""`, nil 669 } else { 670 return "", nil 671 } 672} 673