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