builder.go 27 KB

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