Home | History | Annotate | Download | only in java
      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/common"
     26 
     27 	"github.com/google/blueprint"
     28 	_ "github.com/google/blueprint/bootstrap"
     29 )
     30 
     31 var (
     32 	pctx = common.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.StaticRule("javac",
     41 		blueprint.RuleParams{
     42 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
     43 				`$javacCmd -encoding UTF-8 $javacFlags $bootClasspath $classpath ` +
     44 				`-extdirs "" -d $outDir @$out.rsp || ( rm -rf "$outDir"; exit 41 ) && ` +
     45 				`find $outDir -name "*.class" > $out`,
     46 			Rspfile:        "$out.rsp",
     47 			RspfileContent: "$in",
     48 			Description:    "javac $outDir",
     49 		},
     50 		"javacCmd", "javacFlags", "bootClasspath", "classpath", "outDir")
     51 
     52 	jar = pctx.StaticRule("jar",
     53 		blueprint.RuleParams{
     54 			Command:     `$jarCmd -o $out $jarArgs`,
     55 			CommandDeps: []string{"$jarCmd"},
     56 			Description: "jar $out",
     57 		},
     58 		"jarCmd", "jarArgs")
     59 
     60 	dx = pctx.StaticRule("dx",
     61 		blueprint.RuleParams{
     62 			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
     63 				`$dxCmd --dex --output=$outDir $dxFlags $in || ( rm -rf "$outDir"; exit 41 ) && ` +
     64 				`find "$outDir" -name "classes*.dex" > $out`,
     65 			CommandDeps: []string{"$dxCmd"},
     66 			Description: "dex $out",
     67 		},
     68 		"outDir", "dxFlags")
     69 
     70 	jarjar = pctx.StaticRule("jarjar",
     71 		blueprint.RuleParams{
     72 			Command:     "java -jar $jarjarCmd process $rulesFile $in $out",
     73 			CommandDeps: []string{"$jarjarCmd", "$rulesFile"},
     74 			Description: "jarjar $out",
     75 		},
     76 		"rulesFile")
     77 
     78 	extractPrebuilt = pctx.StaticRule("extractPrebuilt",
     79 		blueprint.RuleParams{
     80 			Command: `rm -rf $outDir && unzip -qo $in -d $outDir && ` +
     81 				`find $outDir -name "*.class" > $classFile && ` +
     82 				`find $outDir -type f -a \! -name "*.class" -a \! -name "MANIFEST.MF" > $resourceFile || ` +
     83 				`(rm -rf $outDir; exit 42)`,
     84 			Description: "extract java prebuilt $outDir",
     85 		},
     86 		"outDir", "classFile", "resourceFile")
     87 )
     88 
     89 func init() {
     90 	pctx.Import("github.com/google/blueprint/bootstrap")
     91 	pctx.StaticVariable("commonJdkFlags", "-source 1.7 -target 1.7 -Xmaxerrs 9999999")
     92 	pctx.StaticVariable("javacCmd", "javac -J-Xmx1024M $commonJdkFlags")
     93 	pctx.StaticVariable("jarCmd", filepath.Join("${bootstrap.BinDir}", "soong_jar"))
     94 	pctx.HostBinToolVariable("dxCmd", "dx")
     95 	pctx.HostJavaToolVariable("jarjarCmd", "jarjar.jar")
     96 }
     97 
     98 type javaBuilderFlags struct {
     99 	javacFlags    string
    100 	dxFlags       string
    101 	bootClasspath string
    102 	classpath     string
    103 	aidlFlags     string
    104 }
    105 
    106 type jarSpec struct {
    107 	fileList, dir common.Path
    108 }
    109 
    110 func (j jarSpec) soongJarArgs() string {
    111 	return "-C " + j.dir.String() + " -l " + j.fileList.String()
    112 }
    113 
    114 func TransformJavaToClasses(ctx common.AndroidModuleContext, srcFiles common.Paths, srcFileLists common.Paths,
    115 	flags javaBuilderFlags, deps common.Paths) jarSpec {
    116 
    117 	classDir := common.PathForModuleOut(ctx, "classes")
    118 	classFileList := common.PathForModuleOut(ctx, "classes.list")
    119 
    120 	javacFlags := flags.javacFlags + common.JoinWithPrefix(srcFileLists.Strings(), "@")
    121 
    122 	deps = append(deps, srcFileLists...)
    123 
    124 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    125 		Rule:      javac,
    126 		Output:    classFileList,
    127 		Inputs:    srcFiles,
    128 		Implicits: deps,
    129 		Args: map[string]string{
    130 			"javacFlags":    javacFlags,
    131 			"bootClasspath": flags.bootClasspath,
    132 			"classpath":     flags.classpath,
    133 			"outDir":        classDir.String(),
    134 		},
    135 	})
    136 
    137 	return jarSpec{classFileList, classDir}
    138 }
    139 
    140 func TransformClassesToJar(ctx common.AndroidModuleContext, classes []jarSpec,
    141 	manifest common.OptionalPath) common.Path {
    142 
    143 	outputFile := common.PathForModuleOut(ctx, "classes-full-debug.jar")
    144 
    145 	deps := common.Paths{}
    146 	jarArgs := []string{}
    147 
    148 	for _, j := range classes {
    149 		deps = append(deps, j.fileList)
    150 		jarArgs = append(jarArgs, j.soongJarArgs())
    151 	}
    152 
    153 	if manifest.Valid() {
    154 		deps = append(deps, manifest.Path())
    155 		jarArgs = append(jarArgs, "-m "+manifest.String())
    156 	}
    157 
    158 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    159 		Rule:      jar,
    160 		Output:    outputFile,
    161 		Implicits: deps,
    162 		Args: map[string]string{
    163 			"jarArgs": strings.Join(jarArgs, " "),
    164 		},
    165 	})
    166 
    167 	return outputFile
    168 }
    169 
    170 func TransformClassesJarToDex(ctx common.AndroidModuleContext, classesJar common.Path,
    171 	flags javaBuilderFlags) jarSpec {
    172 
    173 	outDir := common.PathForModuleOut(ctx, "dex")
    174 	outputFile := common.PathForModuleOut(ctx, "dex.filelist")
    175 
    176 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    177 		Rule:   dx,
    178 		Output: outputFile,
    179 		Input:  classesJar,
    180 		Args: map[string]string{
    181 			"dxFlags": flags.dxFlags,
    182 			"outDir":  outDir.String(),
    183 		},
    184 	})
    185 
    186 	return jarSpec{outputFile, outDir}
    187 }
    188 
    189 func TransformDexToJavaLib(ctx common.AndroidModuleContext, resources []jarSpec,
    190 	dexJarSpec jarSpec) common.Path {
    191 
    192 	outputFile := common.PathForModuleOut(ctx, "javalib.jar")
    193 	var deps common.Paths
    194 	var jarArgs []string
    195 
    196 	for _, j := range resources {
    197 		deps = append(deps, j.fileList)
    198 		jarArgs = append(jarArgs, j.soongJarArgs())
    199 	}
    200 
    201 	deps = append(deps, dexJarSpec.fileList)
    202 	jarArgs = append(jarArgs, dexJarSpec.soongJarArgs())
    203 
    204 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    205 		Rule:      jar,
    206 		Output:    outputFile,
    207 		Implicits: deps,
    208 		Args: map[string]string{
    209 			"jarArgs": strings.Join(jarArgs, " "),
    210 		},
    211 	})
    212 
    213 	return outputFile
    214 }
    215 
    216 func TransformJarJar(ctx common.AndroidModuleContext, classesJar common.Path, rulesFile common.Path) common.Path {
    217 	outputFile := common.PathForModuleOut(ctx, "classes-jarjar.jar")
    218 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    219 		Rule:     jarjar,
    220 		Output:   outputFile,
    221 		Input:    classesJar,
    222 		Implicit: rulesFile,
    223 		Args: map[string]string{
    224 			"rulesFile": rulesFile.String(),
    225 		},
    226 	})
    227 
    228 	return outputFile
    229 }
    230 
    231 func TransformPrebuiltJarToClasses(ctx common.AndroidModuleContext,
    232 	prebuilt common.Path) (classJarSpec, resourceJarSpec jarSpec) {
    233 
    234 	classDir := common.PathForModuleOut(ctx, "extracted/classes")
    235 	classFileList := common.PathForModuleOut(ctx, "extracted/classes.list")
    236 	resourceFileList := common.PathForModuleOut(ctx, "extracted/resources.list")
    237 
    238 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    239 		Rule:    extractPrebuilt,
    240 		Outputs: common.WritablePaths{classFileList, resourceFileList},
    241 		Input:   prebuilt,
    242 		Args: map[string]string{
    243 			"outDir":       classDir.String(),
    244 			"classFile":    classFileList.String(),
    245 			"resourceFile": resourceFileList.String(),
    246 		},
    247 	})
    248 
    249 	return jarSpec{classFileList, classDir}, jarSpec{resourceFileList, classDir}
    250 }
    251