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/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