• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
15package 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
21import (
22	"path/filepath"
23	"strings"
24
25	"android/soong/android"
26
27	"github.com/google/blueprint"
28	_ "github.com/google/blueprint/bootstrap"
29)
30
31var (
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
85func 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
101type javaBuilderFlags struct {
102	javacFlags    string
103	dxFlags       string
104	bootClasspath string
105	classpath     string
106	aidlFlags     string
107}
108
109type jarSpec struct {
110	fileList, dir android.Path
111}
112
113func (j jarSpec) soongJarArgs() string {
114	return "-C " + j.dir.String() + " -l " + j.fileList.String()
115}
116
117func 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
144func 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
175func 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
195func 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
223func 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
239func 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