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 "strings" 24 25 "android/soong/android" 26 27 "github.com/google/blueprint" 28 _ "github.com/google/blueprint/bootstrap" 29 ) 30 31 var ( 32 pctx = android.NewPackageContext("android/soong/java") 33 34 // Compiling java is not conducive to proper dependency tracking. The path-matches-class-name 35 // requirement leads to unpredictable generated source file names, and a single .java file 36 // will get compiled into multiple .class files if it contains inner classes. To work around 37 // this, all java rules write into separate directories and then a post-processing step lists 38 // the files in the the directory into a list file that later rules depend on (and sometimes 39 // read from directly using @<listfile>) 40 javac = pctx.AndroidGomaStaticRule("javac", 41 blueprint.RuleParams{ 42 Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + 43 `${JavacWrapper}$javacCmd ` + 44 `-encoding UTF-8 $javacFlags $bootClasspath $classpath ` + 45 `-extdirs "" -d $outDir @$out.rsp || ( rm -rf "$outDir"; exit 41 ) && ` + 46 `find $outDir -name "*.class" > $out`, 47 Rspfile: "$out.rsp", 48 RspfileContent: "$in", 49 }, 50 "javacCmd", "javacFlags", "bootClasspath", "classpath", "outDir") 51 52 jar = pctx.AndroidStaticRule("jar", 53 blueprint.RuleParams{ 54 Command: `$jarCmd -o $out $jarArgs`, 55 CommandDeps: []string{"$jarCmd"}, 56 }, 57 "jarCmd", "jarArgs") 58 59 dx = pctx.AndroidStaticRule("dx", 60 blueprint.RuleParams{ 61 Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + 62 `$dxCmd --dex --output=$outDir $dxFlags $in || ( rm -rf "$outDir"; exit 41 ) && ` + 63 `find "$outDir" -name "classes*.dex" > $out`, 64 CommandDeps: []string{"$dxCmd"}, 65 }, 66 "outDir", "dxFlags") 67 68 jarjar = pctx.AndroidStaticRule("jarjar", 69 blueprint.RuleParams{ 70 Command: "java -jar $jarjarCmd process $rulesFile $in $out", 71 CommandDeps: []string{"$jarjarCmd", "$rulesFile"}, 72 }, 73 "rulesFile") 74 75 extractPrebuilt = pctx.AndroidStaticRule("extractPrebuilt", 76 blueprint.RuleParams{ 77 Command: `rm -rf $outDir && unzip -qo $in -d $outDir && ` + 78 `find $outDir -name "*.class" > $classFile && ` + 79 `find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" > $resourceFile || ` + 80 `(rm -rf $outDir; exit 42)`, 81 }, 82 "outDir", "classFile", "resourceFile") 83 ) 84 85 func init() { 86 pctx.Import("github.com/google/blueprint/bootstrap") 87 pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999") 88 pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags") 89 pctx.StaticVariable("jarCmd", filepath.Join("${bootstrap.ToolDir}", "soong_zip")) 90 pctx.HostBinToolVariable("dxCmd", "dx") 91 pctx.HostJavaToolVariable("jarjarCmd", "jarjar.jar") 92 93 pctx.VariableFunc("JavacWrapper", func(config interface{}) (string, error) { 94 if override := config.(android.Config).Getenv("JAVAC_WRAPPER"); override != "" { 95 return override + " ", nil 96 } 97 return "", nil 98 }) 99 } 100 101 type javaBuilderFlags struct { 102 javacFlags string 103 dxFlags string 104 bootClasspath string 105 classpath string 106 aidlFlags string 107 } 108 109 type jarSpec struct { 110 fileList, dir android.Path 111 } 112 113 func (j jarSpec) soongJarArgs() string { 114 return "-C " + j.dir.String() + " -l " + j.fileList.String() 115 } 116 117 func TransformJavaToClasses(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths, 118 flags javaBuilderFlags, deps android.Paths) jarSpec { 119 120 classDir := android.PathForModuleOut(ctx, "classes") 121 classFileList := android.PathForModuleOut(ctx, "classes.list") 122 123 javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@") 124 125 deps = append(deps, srcFileLists...) 126 127 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 128 Rule: javac, 129 Description: "javac", 130 Output: classFileList, 131 Inputs: srcFiles, 132 Implicits: deps, 133 Args: map[string]string{ 134 "javacFlags": javacFlags, 135 "bootClasspath": flags.bootClasspath, 136 "classpath": flags.classpath, 137 "outDir": classDir.String(), 138 }, 139 }) 140 141 return jarSpec{classFileList, classDir} 142 } 143 144 func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec, 145 manifest android.OptionalPath) android.Path { 146 147 outputFile := android.PathForModuleOut(ctx, "classes-full-debug.jar") 148 149 deps := android.Paths{} 150 jarArgs := []string{} 151 152 for _, j := range classes { 153 deps = append(deps, j.fileList) 154 jarArgs = append(jarArgs, j.soongJarArgs()) 155 } 156 157 if manifest.Valid() { 158 deps = append(deps, manifest.Path()) 159 jarArgs = append(jarArgs, "-m "+manifest.String()) 160 } 161 162 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 163 Rule: jar, 164 Description: "jar", 165 Output: outputFile, 166 Implicits: deps, 167 Args: map[string]string{ 168 "jarArgs": strings.Join(jarArgs, " "), 169 }, 170 }) 171 172 return outputFile 173 } 174 175 func TransformClassesJarToDex(ctx android.ModuleContext, classesJar android.Path, 176 flags javaBuilderFlags) jarSpec { 177 178 outDir := android.PathForModuleOut(ctx, "dex") 179 outputFile := android.PathForModuleOut(ctx, "dex.filelist") 180 181 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 182 Rule: dx, 183 Description: "dx", 184 Output: outputFile, 185 Input: classesJar, 186 Args: map[string]string{ 187 "dxFlags": flags.dxFlags, 188 "outDir": outDir.String(), 189 }, 190 }) 191 192 return jarSpec{outputFile, outDir} 193 } 194 195 func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec, 196 dexJarSpec jarSpec) android.Path { 197 198 outputFile := android.PathForModuleOut(ctx, "javalib.jar") 199 var deps android.Paths 200 var jarArgs []string 201 202 for _, j := range resources { 203 deps = append(deps, j.fileList) 204 jarArgs = append(jarArgs, j.soongJarArgs()) 205 } 206 207 deps = append(deps, dexJarSpec.fileList) 208 jarArgs = append(jarArgs, dexJarSpec.soongJarArgs()) 209 210 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 211 Rule: jar, 212 Description: "jar", 213 Output: outputFile, 214 Implicits: deps, 215 Args: map[string]string{ 216 "jarArgs": strings.Join(jarArgs, " "), 217 }, 218 }) 219 220 return outputFile 221 } 222 223 func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.Path { 224 outputFile := android.PathForModuleOut(ctx, "classes-jarjar.jar") 225 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 226 Rule: jarjar, 227 Description: "jarjar", 228 Output: outputFile, 229 Input: classesJar, 230 Implicit: rulesFile, 231 Args: map[string]string{ 232 "rulesFile": rulesFile.String(), 233 }, 234 }) 235 236 return outputFile 237 } 238 239 func TransformPrebuiltJarToClasses(ctx android.ModuleContext, 240 prebuilt android.Path) (classJarSpec, resourceJarSpec jarSpec) { 241 242 classDir := android.PathForModuleOut(ctx, "extracted/classes") 243 classFileList := android.PathForModuleOut(ctx, "extracted/classes.list") 244 resourceFileList := android.PathForModuleOut(ctx, "extracted/resources.list") 245 246 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 247 Rule: extractPrebuilt, 248 Description: "extract classes", 249 Outputs: android.WritablePaths{classFileList, resourceFileList}, 250 Input: prebuilt, 251 Args: map[string]string{ 252 "outDir": classDir.String(), 253 "classFile": classFileList.String(), 254 "resourceFile": resourceFileList.String(), 255 }, 256 }) 257 258 return jarSpec{classFileList, classDir}, jarSpec{resourceFileList, classDir} 259 } 260