github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/java/builder.go (about) 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 15 package 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 21 import ( 22 "path/filepath" 23 "strconv" 24 "strings" 25 26 "github.com/google/blueprint" 27 28 "android/soong/android" 29 "android/soong/java/config" 30 ) 31 32 var ( 33 pctx = android.NewPackageContext("android/soong/java") 34 35 // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name 36 // requirement leads to unpredictable generated source file names, and a single .java file 37 // will get compiled into multiple .class files if it contains inner classes. To work around 38 // this, all java rules write into separate directories and then are combined into a .jar file 39 // (if the rule produces .class files) or a .srcjar file (if the rule produces .java files). 40 // .srcjar files are unzipped into a temporary directory when compiled with javac. 41 javac = pctx.AndroidGomaStaticRule("javac", 42 blueprint.RuleParams{ 43 Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + 44 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 45 `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` + 46 `$javacFlags $bootClasspath $classpath ` + 47 `-source $javaVersion -target $javaVersion ` + 48 `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` + 49 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`, 50 CommandDeps: []string{ 51 "${config.JavacCmd}", 52 "${config.SoongZipCmd}", 53 "${config.ZipSyncCmd}", 54 }, 55 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 56 Rspfile: "$out.rsp", 57 RspfileContent: "$in", 58 }, 59 "javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir", 60 "outDir", "annoDir", "javaVersion") 61 62 kotlinc = pctx.AndroidGomaStaticRule("kotlinc", 63 blueprint.RuleParams{ 64 Command: `rm -rf "$outDir" "$srcJarDir" && mkdir -p "$outDir" "$srcJarDir" && ` + 65 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 66 `${config.GenKotlinBuildFileCmd} $classpath $outDir $out.rsp $srcJarDir/list > $outDir/kotlinc-build.xml &&` + 67 `${config.KotlincCmd} $kotlincFlags ` + 68 `-jvm-target $kotlinJvmTarget -Xbuild-file=$outDir/kotlinc-build.xml && ` + 69 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`, 70 CommandDeps: []string{ 71 "${config.KotlincCmd}", 72 "${config.KotlinCompilerJar}", 73 "${config.GenKotlinBuildFileCmd}", 74 "${config.SoongZipCmd}", 75 "${config.ZipSyncCmd}", 76 }, 77 Rspfile: "$out.rsp", 78 RspfileContent: `$in`, 79 }, 80 "kotlincFlags", "classpath", "srcJars", "srcJarDir", "outDir", "kotlinJvmTarget") 81 82 errorprone = pctx.AndroidStaticRule("errorprone", 83 blueprint.RuleParams{ 84 Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + 85 `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + 86 `${config.SoongJavacWrapper} ${config.ErrorProneCmd} ` + 87 `$javacFlags $bootClasspath $classpath ` + 88 `-source $javaVersion -target $javaVersion ` + 89 `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` + 90 `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`, 91 CommandDeps: []string{ 92 "${config.JavaCmd}", 93 "${config.ErrorProneJavacJar}", 94 "${config.ErrorProneJar}", 95 "${config.SoongZipCmd}", 96 "${config.ZipSyncCmd}", 97 }, 98 CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, 99 Rspfile: "$out.rsp", 100 RspfileContent: "$in", 101 }, 102 "javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir", 103 "outDir", "annoDir", "javaVersion") 104 105 turbine = pctx.AndroidStaticRule("turbine", 106 blueprint.RuleParams{ 107 Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + 108 `${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` + 109 `--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` + 110 `--javacopts ${config.CommonJdkFlags} ` + 111 `$javacFlags -source $javaVersion -target $javaVersion $bootClasspath $classpath && ` + 112 `${config.Ziptime} $out.tmp && ` + 113 `(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`, 114 CommandDeps: []string{ 115 "${config.TurbineJar}", 116 "${config.JavaCmd}", 117 "${config.Ziptime}", 118 }, 119 Rspfile: "$out.rsp", 120 RspfileContent: "$in", 121 Restat: true, 122 }, 123 "javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion") 124 125 jar = pctx.AndroidStaticRule("jar", 126 blueprint.RuleParams{ 127 Command: `${config.SoongZipCmd} -jar -o $out @$out.rsp`, 128 CommandDeps: []string{"${config.SoongZipCmd}"}, 129 Rspfile: "$out.rsp", 130 RspfileContent: "$jarArgs", 131 }, 132 "jarArgs") 133 134 combineJar = pctx.AndroidStaticRule("combineJar", 135 blueprint.RuleParams{ 136 Command: `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out $in`, 137 CommandDeps: []string{"${config.MergeZipsCmd}"}, 138 }, 139 "jarArgs") 140 141 jarjar = pctx.AndroidStaticRule("jarjar", 142 blueprint.RuleParams{ 143 Command: "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out", 144 CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"}, 145 }, 146 "rulesFile") 147 ) 148 149 func init() { 150 pctx.Import("android/soong/java/config") 151 } 152 153 type javaBuilderFlags struct { 154 javacFlags string 155 bootClasspath classpath 156 classpath classpath 157 systemModules classpath 158 aidlFlags string 159 javaVersion string 160 161 errorProneExtraJavacFlags string 162 163 kotlincFlags string 164 kotlincClasspath classpath 165 166 protoFlags []string 167 protoOutTypeFlag string // The flag itself: --java_out 168 protoOutParams string // Parameters to that flag: --java_out=$protoOutParams:$outDir 169 protoRoot bool 170 } 171 172 func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath, 173 srcFiles, srcJars android.Paths, 174 flags javaBuilderFlags) { 175 176 inputs := append(android.Paths(nil), srcFiles...) 177 178 var deps android.Paths 179 deps = append(deps, flags.kotlincClasspath...) 180 deps = append(deps, srcJars...) 181 182 ctx.Build(pctx, android.BuildParams{ 183 Rule: kotlinc, 184 Description: "kotlinc", 185 Output: outputFile, 186 Inputs: inputs, 187 Implicits: deps, 188 Args: map[string]string{ 189 "classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"), 190 "kotlincFlags": flags.kotlincFlags, 191 "srcJars": strings.Join(srcJars.Strings(), " "), 192 "outDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(), 193 "srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(), 194 // http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8 195 "kotlinJvmTarget": "1.8", 196 }, 197 }) 198 } 199 200 func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int, 201 srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) { 202 203 // Compile java sources into .class files 204 desc := "javac" 205 if shardIdx >= 0 { 206 desc += strconv.Itoa(shardIdx) 207 } 208 209 transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc, javac) 210 } 211 212 func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath, 213 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 214 215 if config.ErrorProneJar == "" { 216 ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?") 217 } 218 219 if len(flags.errorProneExtraJavacFlags) > 0 { 220 if len(flags.javacFlags) > 0 { 221 flags.javacFlags = flags.errorProneExtraJavacFlags + " " + flags.javacFlags 222 } else { 223 flags.javacFlags = flags.errorProneExtraJavacFlags 224 } 225 } 226 227 transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil, 228 "errorprone", "errorprone", errorprone) 229 } 230 231 func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath, 232 srcFiles, srcJars android.Paths, flags javaBuilderFlags) { 233 234 var deps android.Paths 235 deps = append(deps, srcJars...) 236 deps = append(deps, flags.bootClasspath...) 237 deps = append(deps, flags.classpath...) 238 239 var bootClasspath string 240 if len(flags.bootClasspath) == 0 && ctx.Device() { 241 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 242 // ensure java does not fall back to the default bootclasspath. 243 bootClasspath = `--bootclasspath ""` 244 } else { 245 bootClasspath = flags.bootClasspath.FormJavaClassPath("--bootclasspath") 246 } 247 248 ctx.Build(pctx, android.BuildParams{ 249 Rule: turbine, 250 Description: "turbine", 251 Output: outputFile, 252 Inputs: srcFiles, 253 Implicits: deps, 254 Args: map[string]string{ 255 "javacFlags": flags.javacFlags, 256 "bootClasspath": bootClasspath, 257 "srcJars": strings.Join(srcJars.Strings(), " "), 258 "classpath": flags.classpath.FormJavaClassPath("--classpath"), 259 "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(), 260 "javaVersion": flags.javaVersion, 261 }, 262 }) 263 } 264 265 // transformJavaToClasses takes source files and converts them to a jar containing .class files. 266 // srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain 267 // sources. flags contains various command line flags to be passed to the compiler. 268 // 269 // This method may be used for different compilers, including javac and Error Prone. The rule 270 // argument specifies which command line to use and desc sets the description of the rule that will 271 // be printed at build time. The stem argument provides the file name of the output jar, and 272 // suffix will be appended to various intermediate files and directories to avoid collisions when 273 // this function is called twice in the same module directory. 274 func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, 275 shardIdx int, srcFiles, srcJars android.Paths, 276 flags javaBuilderFlags, deps android.Paths, 277 intermediatesDir, desc string, rule blueprint.Rule) { 278 279 deps = append(deps, srcJars...) 280 281 var bootClasspath string 282 if flags.javaVersion == "1.9" { 283 deps = append(deps, flags.systemModules...) 284 bootClasspath = flags.systemModules.FormJavaSystemModulesPath("--system=", ctx.Device()) 285 } else { 286 deps = append(deps, flags.bootClasspath...) 287 if len(flags.bootClasspath) == 0 && ctx.Device() { 288 // explicitly specify -bootclasspath "" if the bootclasspath is empty to 289 // ensure java does not fall back to the default bootclasspath. 290 bootClasspath = `-bootclasspath ""` 291 } else { 292 bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") 293 } 294 } 295 296 deps = append(deps, flags.classpath...) 297 298 srcJarDir := "srcjars" 299 outDir := "classes" 300 annoDir := "anno" 301 if shardIdx >= 0 { 302 shardDir := "shard" + strconv.Itoa(shardIdx) 303 srcJarDir = filepath.Join(shardDir, srcJarDir) 304 outDir = filepath.Join(shardDir, outDir) 305 annoDir = filepath.Join(shardDir, annoDir) 306 } 307 ctx.Build(pctx, android.BuildParams{ 308 Rule: rule, 309 Description: desc, 310 Output: outputFile, 311 Inputs: srcFiles, 312 Implicits: deps, 313 Args: map[string]string{ 314 "javacFlags": flags.javacFlags, 315 "bootClasspath": bootClasspath, 316 "classpath": flags.classpath.FormJavaClassPath("-classpath"), 317 "srcJars": strings.Join(srcJars.Strings(), " "), 318 "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(), 319 "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(), 320 "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(), 321 "javaVersion": flags.javaVersion, 322 }, 323 }) 324 } 325 326 func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath, 327 jarArgs []string, deps android.Paths) { 328 329 ctx.Build(pctx, android.BuildParams{ 330 Rule: jar, 331 Description: "jar", 332 Output: outputFile, 333 Implicits: deps, 334 Args: map[string]string{ 335 "jarArgs": strings.Join(jarArgs, " "), 336 }, 337 }) 338 } 339 340 func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePath, desc string, 341 jars android.Paths, manifest android.OptionalPath, stripDirs bool, dirsToStrip []string) { 342 343 var deps android.Paths 344 345 var jarArgs []string 346 if manifest.Valid() { 347 jarArgs = append(jarArgs, "-m ", manifest.String()) 348 deps = append(deps, manifest.Path()) 349 } 350 351 if dirsToStrip != nil { 352 for _, dir := range dirsToStrip { 353 jarArgs = append(jarArgs, "-stripDir ", dir) 354 } 355 } 356 357 // Remove any module-info.class files that may have come from prebuilt jars, they cause problems 358 // for downstream tools like desugar. 359 jarArgs = append(jarArgs, "-stripFile module-info.class") 360 361 if stripDirs { 362 jarArgs = append(jarArgs, "-D") 363 } 364 365 ctx.Build(pctx, android.BuildParams{ 366 Rule: combineJar, 367 Description: desc, 368 Output: outputFile, 369 Inputs: jars, 370 Implicits: deps, 371 Args: map[string]string{ 372 "jarArgs": strings.Join(jarArgs, " "), 373 }, 374 }) 375 } 376 377 func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, 378 classesJar android.Path, rulesFile android.Path) { 379 ctx.Build(pctx, android.BuildParams{ 380 Rule: jarjar, 381 Description: "jarjar", 382 Output: outputFile, 383 Input: classesJar, 384 Implicit: rulesFile, 385 Args: map[string]string{ 386 "rulesFile": rulesFile.String(), 387 }, 388 }) 389 } 390 391 type classpath []android.Path 392 393 func (x *classpath) FormJavaClassPath(optName string) string { 394 if len(*x) > 0 { 395 return optName + " " + strings.Join(x.Strings(), ":") 396 } else { 397 return "" 398 } 399 } 400 401 // Returns a --system argument in the form javac expects with -source 1.9. If forceEmpty is true, 402 // returns --system=none if the list is empty to ensure javac does not fall back to the default 403 // system modules. 404 func (x *classpath) FormJavaSystemModulesPath(optName string, forceEmpty bool) string { 405 if len(*x) > 1 { 406 panic("more than one system module") 407 } else if len(*x) == 1 { 408 return optName + strings.TrimSuffix((*x)[0].String(), "lib/modules") 409 } else if forceEmpty { 410 return optName + "none" 411 } else { 412 return "" 413 } 414 } 415 416 func (x *classpath) FormDesugarClasspath(optName string) []string { 417 if x == nil || *x == nil { 418 return nil 419 } 420 flags := make([]string, len(*x)) 421 for i, v := range *x { 422 flags[i] = optName + " " + v.String() 423 } 424 425 return flags 426 } 427 428 // Convert a classpath to an android.Paths 429 func (x *classpath) Paths() android.Paths { 430 return append(android.Paths(nil), (*x)...) 431 } 432 433 func (x *classpath) Strings() []string { 434 if x == nil { 435 return nil 436 } 437 ret := make([]string, len(*x)) 438 for i, path := range *x { 439 ret[i] = path.String() 440 } 441 return ret 442 }