blob: 8750dbf87e829c5ace12d64c73fa6635c88760af [file] [log] [blame]
Colin Cross2fe66872015-03-30 17:20:39 -07001// 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 contains the module types for compiling Java for Android, and converts the properties
18// into the flags and filenames necessary to pass to the compiler. The final creation of the rules
19// is handled in builder.go
20
21import (
22 "fmt"
23 "path/filepath"
24 "strings"
25
26 "github.com/google/blueprint"
27 "github.com/google/blueprint/pathtools"
28
29 "android/soong/common"
30)
31
Colin Cross2fe66872015-03-30 17:20:39 -070032// TODO:
33// Autogenerated files:
34// AIDL
35// Proto
36// Renderscript
37// Post-jar passes:
38// Proguard
39// Emma
40// Jarjar
41// Dex
42// Rmtypedefs
43// Jack
44// DroidDoc
45// Findbugs
46
47// javaBase contains the properties and members used by all java module types, and implements
48// the blueprint.Module interface.
49type javaBase struct {
50 common.AndroidModuleBase
51 module JavaModuleType
52
53 properties struct {
54 // srcs: list of source files used to compile the Java module. May be .java, .logtags, .proto,
55 // or .aidl files.
56 Srcs []string `android:"arch_variant,arch_subtract"`
57
58 // resource_dirs: list of directories containing resources
59 Resource_dirs []string `android:"arch_variant"`
60
61 // no_standard_libraries: don't build against the default libraries (core-libart, core-junit,
62 // ext, and framework for device targets)
63 No_standard_libraries bool
64
65 // javacflags: list of module-specific flags that will be used for javac compiles
66 Javacflags []string `android:"arch_variant"`
67
68 // dxflags: list of module-specific flags that will be used for dex compiles
69 Dxflags []string `android:"arch_variant"`
70
71 // java_libs: list of of java libraries that will be in the classpath
72 Java_libs []string `android:"arch_variant"`
73
74 // java_static_libs: list of java libraries that will be compiled into the resulting jar
75 Java_static_libs []string `android:"arch_variant"`
76
77 // manifest: manifest file to be included in resulting jar
78 Manifest string
79
80 // sdk_version: if not blank, set to the version of the sdk to compile against
81 Sdk_version string
82
83 // Set for device java libraries, and for host versions of device java libraries
84 // built for testing
85 Dex bool `blueprint:"mutated"`
Colin Cross65bf4f22015-04-03 16:54:17 -070086
87 // jarjar_rules: if not blank, run jarjar using the specified rules file
88 Jarjar_rules string
Colin Cross2fe66872015-03-30 17:20:39 -070089 }
90
91 // output file suitable for inserting into the classpath of another compile
92 classpathFile string
93
94 // jarSpecs suitable for inserting classes from a static library into another jar
95 classJarSpecs []jarSpec
96
97 // jarSpecs suitable for inserting resources from a static library into another jar
98 resourceJarSpecs []jarSpec
99
100 // installed file for binary dependency
101 installFile string
102}
103
104type JavaModuleType interface {
105 GenerateJavaBuildActions(ctx common.AndroidModuleContext)
106}
107
108type JavaDependency interface {
109 ClasspathFile() string
110 ClassJarSpecs() []jarSpec
111 ResourceJarSpecs() []jarSpec
112}
113
114func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
115 props ...interface{}) (blueprint.Module, []interface{}) {
116
117 base.module = module
118
119 props = append(props, &base.properties)
120
121 return common.InitAndroidArchModule(base, hod, common.MultilibCommon, props...)
122}
123
124func (j *javaBase) BootClasspath(ctx common.AndroidBaseContext) string {
125 if ctx.Device() {
126 if j.properties.Sdk_version == "" {
127 return "core-libart"
128 } else if j.properties.Sdk_version == "current" {
129 // TODO: !TARGET_BUILD_APPS
130 return "android_stubs_current"
131 } else if j.properties.Sdk_version == "system_current" {
132 return "android_system_stubs_current"
133 } else {
134 return "sdk_v" + j.properties.Sdk_version
135 }
136 } else {
137 if j.properties.Dex {
138 return "core-libart"
139 } else {
140 return ""
141 }
142 }
143}
144
145func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
146 var deps []string
147
148 if !j.properties.No_standard_libraries {
149 bootClasspath := j.BootClasspath(ctx)
150 if bootClasspath != "" {
151 deps = append(deps, bootClasspath)
152 }
153 }
154 deps = append(deps, j.properties.Java_libs...)
155 deps = append(deps, j.properties.Java_static_libs...)
156
157 return deps
158}
159
160func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string,
161 bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec) {
162
163 ctx.VisitDirectDeps(func(module blueprint.Module) {
164 otherName := ctx.OtherModuleName(module)
165 if javaDep, ok := module.(JavaDependency); ok {
166 if inList(otherName, j.properties.Java_libs) {
167 classpath = append(classpath, javaDep.ClasspathFile())
168 } else if inList(otherName, j.properties.Java_static_libs) {
169 classpath = append(classpath, javaDep.ClasspathFile())
170 classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...)
171 resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...)
172 } else if otherName == j.BootClasspath(ctx) {
173 bootClasspath = javaDep.ClasspathFile()
174 } else {
175 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
176 }
177 } else {
178 ctx.ModuleErrorf("unknown dependency module type for %q", otherName)
179 }
180 })
181
182 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs
183}
184
185func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
186 j.module.GenerateJavaBuildActions(ctx)
187}
188
189func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
190 flags := javaBuilderFlags{
191 javacFlags: strings.Join(j.properties.Javacflags, " "),
192 }
193
194 var javacDeps []string
195
196 srcFiles := j.properties.Srcs
197 srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx))
198 srcFiles = common.ExpandGlobs(ctx, srcFiles)
199
200 classpath, bootClasspath, classJarSpecs, resourceJarSpecs := j.collectDeps(ctx)
201
202 if bootClasspath != "" {
203 flags.bootClasspath = "-bootclasspath " + bootClasspath
204 javacDeps = append(javacDeps, bootClasspath)
205 }
206
207 if len(classpath) > 0 {
208 flags.classpath = "-classpath " + strings.Join(classpath, ":")
209 javacDeps = append(javacDeps, classpath...)
210 }
211
212 // Compile java sources into .class files
213 classes := TransformJavaToClasses(ctx, srcFiles, flags, javacDeps)
214 if ctx.Failed() {
215 return
216 }
217
218 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs), resourceJarSpecs...)
219 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
220
221 manifest := j.properties.Manifest
222 if manifest != "" {
223 manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
224 }
225
226 allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
227 allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
228
229 // Combine classes + resources into classes-full-debug.jar
230 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest)
231 if ctx.Failed() {
232 return
233 }
Colin Cross65bf4f22015-04-03 16:54:17 -0700234
Colin Cross2fe66872015-03-30 17:20:39 -0700235 j.classJarSpecs = classJarSpecs
236 j.resourceJarSpecs = resourceJarSpecs
Colin Cross65bf4f22015-04-03 16:54:17 -0700237
238 if j.properties.Jarjar_rules != "" {
239 jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
240 // Transform classes-full-debug.jar into classes-jarjar.jar
241 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
242 if ctx.Failed() {
243 return
244 }
245 }
246
Colin Cross2fe66872015-03-30 17:20:39 -0700247 j.classpathFile = outputFile
248
249 if j.properties.Dex {
250 dxFlags := j.properties.Dxflags
251 if false /* emma enabled */ {
252 // If you instrument class files that have local variable debug information in
253 // them emma does not correctly maintain the local variable table.
254 // This will cause an error when you try to convert the class files for Android.
255 // The workaround here is to build different dex file here based on emma switch
256 // then later copy into classes.dex. When emma is on, dx is run with --no-locals
257 // option to remove local variable information
258 dxFlags = append(dxFlags, "--no-locals")
259 }
260
Colin Cross1332b002015-04-07 17:11:30 -0700261 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700262 dxFlags = append(dxFlags, "--no-optimize")
263 }
264
Colin Cross1332b002015-04-07 17:11:30 -0700265 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700266 dxFlags = append(dxFlags,
267 "--debug",
268 "--verbose",
269 "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
270 "--dump-width=1000")
271 }
272
273 flags.dxFlags = strings.Join(dxFlags, " ")
274
275 // Compile classes.jar into classes.dex
276 dexFile := TransformClassesJarToDex(ctx, outputFile, flags)
277 if ctx.Failed() {
278 return
279 }
280
281 // Combine classes.dex + resources into javalib.jar
282 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexFile)
283 }
284
285 j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile)
286}
287
288var _ JavaDependency = (*JavaLibrary)(nil)
289
290func (j *javaBase) ClasspathFile() string {
291 return j.classpathFile
292}
293
294func (j *javaBase) ClassJarSpecs() []jarSpec {
295 return j.classJarSpecs
296}
297
298func (j *javaBase) ResourceJarSpecs() []jarSpec {
299 return j.resourceJarSpecs
300}
301
302//
303// Java libraries (.jar file)
304//
305
306type JavaLibrary struct {
307 javaBase
308}
309
310func JavaLibraryFactory() (blueprint.Module, []interface{}) {
311 module := &JavaLibrary{}
312
313 module.properties.Dex = true
314
315 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported)
316}
317
318func JavaLibraryHostFactory() (blueprint.Module, []interface{}) {
319 module := &JavaLibrary{}
320
321 return NewJavaBase(&module.javaBase, module, common.HostSupported)
322}
323
324//
325// Java Binaries (.jar file plus wrapper script)
326//
327
328type JavaBinary struct {
329 JavaLibrary
330
331 binaryProperties struct {
332 // wrapper: installable script to execute the resulting jar
333 Wrapper string
334 }
335}
336
337func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
338 j.JavaLibrary.GenerateJavaBuildActions(ctx)
339
340 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
341 // another build rule before the jar has been installed.
342 ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
343 j.installFile)
344}
345
346func JavaBinaryFactory() (blueprint.Module, []interface{}) {
347 module := &JavaBinary{}
348
349 module.properties.Dex = true
350
351 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties)
352}
353
354func JavaBinaryHostFactory() (blueprint.Module, []interface{}) {
355 module := &JavaBinary{}
356
357 return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties)
358}
359
360//
361// Java prebuilts
362//
363
364type JavaPrebuilt struct {
365 common.AndroidModuleBase
366
367 properties struct {
368 Srcs []string
369 }
370
Colin Crosse1d62a82015-04-03 16:53:05 -0700371 classpathFile string
372 classJarSpecs, resourceJarSpecs []jarSpec
Colin Cross2fe66872015-03-30 17:20:39 -0700373}
374
375func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
376 if len(j.properties.Srcs) != 1 {
377 ctx.ModuleErrorf("expected exactly one jar in srcs")
378 return
379 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700380 prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
381
382 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
383
384 j.classpathFile = prebuilt
385 j.classJarSpecs = []jarSpec{classJarSpec}
386 j.resourceJarSpecs = []jarSpec{resourceJarSpec}
387
388 ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
Colin Cross2fe66872015-03-30 17:20:39 -0700389}
390
391var _ JavaDependency = (*JavaPrebuilt)(nil)
392
393func (j *JavaPrebuilt) ClasspathFile() string {
394 return j.classpathFile
395}
396
397func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700398 return j.classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700399}
400
401func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700402 return j.resourceJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700403}
404
405func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
406 module := &JavaPrebuilt{}
407
408 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
409 common.MultilibCommon, &module.properties)
410}
411
412func inList(s string, l []string) bool {
413 for _, e := range l {
414 if e == s {
415 return true
416 }
417 }
418 return false
419}