|  | // Copyright 2015 Google Inc. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | package java | 
|  |  | 
|  | // This file generates the final rules for compiling all Java.  All properties related to | 
|  | // compiling should have been translated into javaBuilderFlags or another argument to the Transform* | 
|  | // functions. | 
|  |  | 
|  | import ( | 
|  | "path/filepath" | 
|  | "strings" | 
|  |  | 
|  | "android/soong/android" | 
|  |  | 
|  | "github.com/google/blueprint" | 
|  | _ "github.com/google/blueprint/bootstrap" | 
|  | ) | 
|  |  | 
|  | var ( | 
|  | pctx = android.NewPackageContext("android/soong/java") | 
|  |  | 
|  | // Compiling java is not conducive to proper dependency tracking.  The path-matches-class-name | 
|  | // requirement leads to unpredictable generated source file names, and a single .java file | 
|  | // will get compiled into multiple .class files if it contains inner classes.  To work around | 
|  | // this, all java rules write into separate directories and then a post-processing step lists | 
|  | // the files in the the directory into a list file that later rules depend on (and sometimes | 
|  | // read from directly using @<listfile>) | 
|  | javac = pctx.StaticRule("javac", | 
|  | blueprint.RuleParams{ | 
|  | Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + | 
|  | `$javacCmd -encoding UTF-8 $javacFlags $bootClasspath $classpath ` + | 
|  | `-extdirs "" -d $outDir @$out.rsp || ( rm -rf "$outDir"; exit 41 ) && ` + | 
|  | `find $outDir -name "*.class" > $out`, | 
|  | Rspfile:        "$out.rsp", | 
|  | RspfileContent: "$in", | 
|  | Description:    "javac $outDir", | 
|  | }, | 
|  | "javacCmd", "javacFlags", "bootClasspath", "classpath", "outDir") | 
|  |  | 
|  | jar = pctx.StaticRule("jar", | 
|  | blueprint.RuleParams{ | 
|  | Command:     `$jarCmd -o $out $jarArgs`, | 
|  | CommandDeps: []string{"$jarCmd"}, | 
|  | Description: "jar $out", | 
|  | }, | 
|  | "jarCmd", "jarArgs") | 
|  |  | 
|  | dx = pctx.StaticRule("dx", | 
|  | blueprint.RuleParams{ | 
|  | Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + | 
|  | `$dxCmd --dex --output=$outDir $dxFlags $in || ( rm -rf "$outDir"; exit 41 ) && ` + | 
|  | `find "$outDir" -name "classes*.dex" > $out`, | 
|  | CommandDeps: []string{"$dxCmd"}, | 
|  | Description: "dex $out", | 
|  | }, | 
|  | "outDir", "dxFlags") | 
|  |  | 
|  | jarjar = pctx.StaticRule("jarjar", | 
|  | blueprint.RuleParams{ | 
|  | Command:     "java -jar $jarjarCmd process $rulesFile $in $out", | 
|  | CommandDeps: []string{"$jarjarCmd", "$rulesFile"}, | 
|  | Description: "jarjar $out", | 
|  | }, | 
|  | "rulesFile") | 
|  |  | 
|  | extractPrebuilt = pctx.StaticRule("extractPrebuilt", | 
|  | blueprint.RuleParams{ | 
|  | Command: `rm -rf $outDir && unzip -qo $in -d $outDir && ` + | 
|  | `find $outDir -name "*.class" > $classFile && ` + | 
|  | `find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" > $resourceFile || ` + | 
|  | `(rm -rf $outDir; exit 42)`, | 
|  | Description: "extract java prebuilt $outDir", | 
|  | }, | 
|  | "outDir", "classFile", "resourceFile") | 
|  | ) | 
|  |  | 
|  | func init() { | 
|  | pctx.Import("github.com/google/blueprint/bootstrap") | 
|  | pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999") | 
|  | pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags") | 
|  | pctx.StaticVariable("jarCmd", filepath.Join("${bootstrap.ToolDir}", "soong_zip")) | 
|  | pctx.HostBinToolVariable("dxCmd", "dx") | 
|  | pctx.HostJavaToolVariable("jarjarCmd", "jarjar.jar") | 
|  | } | 
|  |  | 
|  | type javaBuilderFlags struct { | 
|  | javacFlags    string | 
|  | dxFlags       string | 
|  | bootClasspath string | 
|  | classpath     string | 
|  | aidlFlags     string | 
|  | } | 
|  |  | 
|  | type jarSpec struct { | 
|  | fileList, dir android.Path | 
|  | } | 
|  |  | 
|  | func (j jarSpec) soongJarArgs() string { | 
|  | return "-C " + j.dir.String() + " -l " + j.fileList.String() | 
|  | } | 
|  |  | 
|  | func TransformJavaToClasses(ctx android.ModuleContext, srcFiles android.Paths, srcFileLists android.Paths, | 
|  | flags javaBuilderFlags, deps android.Paths) jarSpec { | 
|  |  | 
|  | classDir := android.PathForModuleOut(ctx, "classes") | 
|  | classFileList := android.PathForModuleOut(ctx, "classes.list") | 
|  |  | 
|  | javacFlags := flags.javacFlags + android.JoinWithPrefix(srcFileLists.Strings(), "@") | 
|  |  | 
|  | deps = append(deps, srcFileLists...) | 
|  |  | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:      javac, | 
|  | Output:    classFileList, | 
|  | Inputs:    srcFiles, | 
|  | Implicits: deps, | 
|  | Args: map[string]string{ | 
|  | "javacFlags":    javacFlags, | 
|  | "bootClasspath": flags.bootClasspath, | 
|  | "classpath":     flags.classpath, | 
|  | "outDir":        classDir.String(), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return jarSpec{classFileList, classDir} | 
|  | } | 
|  |  | 
|  | func TransformClassesToJar(ctx android.ModuleContext, classes []jarSpec, | 
|  | manifest android.OptionalPath) android.Path { | 
|  |  | 
|  | outputFile := android.PathForModuleOut(ctx, "classes-full-debug.jar") | 
|  |  | 
|  | deps := android.Paths{} | 
|  | jarArgs := []string{} | 
|  |  | 
|  | for _, j := range classes { | 
|  | deps = append(deps, j.fileList) | 
|  | jarArgs = append(jarArgs, j.soongJarArgs()) | 
|  | } | 
|  |  | 
|  | if manifest.Valid() { | 
|  | deps = append(deps, manifest.Path()) | 
|  | jarArgs = append(jarArgs, "-m "+manifest.String()) | 
|  | } | 
|  |  | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:      jar, | 
|  | Output:    outputFile, | 
|  | Implicits: deps, | 
|  | Args: map[string]string{ | 
|  | "jarArgs": strings.Join(jarArgs, " "), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return outputFile | 
|  | } | 
|  |  | 
|  | func TransformClassesJarToDex(ctx android.ModuleContext, classesJar android.Path, | 
|  | flags javaBuilderFlags) jarSpec { | 
|  |  | 
|  | outDir := android.PathForModuleOut(ctx, "dex") | 
|  | outputFile := android.PathForModuleOut(ctx, "dex.filelist") | 
|  |  | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:   dx, | 
|  | Output: outputFile, | 
|  | Input:  classesJar, | 
|  | Args: map[string]string{ | 
|  | "dxFlags": flags.dxFlags, | 
|  | "outDir":  outDir.String(), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return jarSpec{outputFile, outDir} | 
|  | } | 
|  |  | 
|  | func TransformDexToJavaLib(ctx android.ModuleContext, resources []jarSpec, | 
|  | dexJarSpec jarSpec) android.Path { | 
|  |  | 
|  | outputFile := android.PathForModuleOut(ctx, "javalib.jar") | 
|  | var deps android.Paths | 
|  | var jarArgs []string | 
|  |  | 
|  | for _, j := range resources { | 
|  | deps = append(deps, j.fileList) | 
|  | jarArgs = append(jarArgs, j.soongJarArgs()) | 
|  | } | 
|  |  | 
|  | deps = append(deps, dexJarSpec.fileList) | 
|  | jarArgs = append(jarArgs, dexJarSpec.soongJarArgs()) | 
|  |  | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:      jar, | 
|  | Output:    outputFile, | 
|  | Implicits: deps, | 
|  | Args: map[string]string{ | 
|  | "jarArgs": strings.Join(jarArgs, " "), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return outputFile | 
|  | } | 
|  |  | 
|  | func TransformJarJar(ctx android.ModuleContext, classesJar android.Path, rulesFile android.Path) android.Path { | 
|  | outputFile := android.PathForModuleOut(ctx, "classes-jarjar.jar") | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:     jarjar, | 
|  | Output:   outputFile, | 
|  | Input:    classesJar, | 
|  | Implicit: rulesFile, | 
|  | Args: map[string]string{ | 
|  | "rulesFile": rulesFile.String(), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return outputFile | 
|  | } | 
|  |  | 
|  | func TransformPrebuiltJarToClasses(ctx android.ModuleContext, | 
|  | prebuilt android.Path) (classJarSpec, resourceJarSpec jarSpec) { | 
|  |  | 
|  | classDir := android.PathForModuleOut(ctx, "extracted/classes") | 
|  | classFileList := android.PathForModuleOut(ctx, "extracted/classes.list") | 
|  | resourceFileList := android.PathForModuleOut(ctx, "extracted/resources.list") | 
|  |  | 
|  | ctx.ModuleBuild(pctx, android.ModuleBuildParams{ | 
|  | Rule:    extractPrebuilt, | 
|  | Outputs: android.WritablePaths{classFileList, resourceFileList}, | 
|  | Input:   prebuilt, | 
|  | Args: map[string]string{ | 
|  | "outDir":       classDir.String(), | 
|  | "classFile":    classFileList.String(), | 
|  | "resourceFile": resourceFileList.String(), | 
|  | }, | 
|  | }) | 
|  |  | 
|  | return jarSpec{classFileList, classDir}, jarSpec{resourceFileList, classDir} | 
|  | } |