blob: 215924bbd0ea013315add459f79b05066a6b1a75 [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"
Colin Crossc0b06f12015-04-08 13:03:43 -070027 "github.com/google/blueprint/pathtools"
Colin Cross2fe66872015-03-30 17:20:39 -070028
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
Colin Cross276284f2015-04-20 13:51:48 -070058 // java_resource_dirs: list of directories containing Java resources
59 Java_resource_dirs []string `android:"arch_variant"`
Colin Cross2fe66872015-03-30 17:20:39 -070060
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 Crossc0b06f12015-04-08 13:03:43 -070089
90 // aidl_includes: directories to pass to aidl tool
91 Aidl_includes []string
92
93 // aidl_export_include_dirs: directories that should be added as include directories
94 // for any aidl sources of modules that depend on this module
95 Export_aidl_include_dirs []string
Colin Cross2fe66872015-03-30 17:20:39 -070096 }
97
98 // output file suitable for inserting into the classpath of another compile
99 classpathFile string
100
101 // jarSpecs suitable for inserting classes from a static library into another jar
102 classJarSpecs []jarSpec
103
104 // jarSpecs suitable for inserting resources from a static library into another jar
105 resourceJarSpecs []jarSpec
106
Colin Crossc0b06f12015-04-08 13:03:43 -0700107 exportAidlIncludeDirs []string
108
Colin Crossf05fe972015-04-10 17:45:20 -0700109 logtagsSrcs []string
110
Colin Cross2fe66872015-03-30 17:20:39 -0700111 // installed file for binary dependency
112 installFile string
113}
114
115type JavaModuleType interface {
116 GenerateJavaBuildActions(ctx common.AndroidModuleContext)
117}
118
119type JavaDependency interface {
120 ClasspathFile() string
121 ClassJarSpecs() []jarSpec
122 ResourceJarSpecs() []jarSpec
Colin Crossc0b06f12015-04-08 13:03:43 -0700123 AidlIncludeDirs() []string
Colin Cross2fe66872015-03-30 17:20:39 -0700124}
125
126func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
127 props ...interface{}) (blueprint.Module, []interface{}) {
128
129 base.module = module
130
131 props = append(props, &base.properties)
132
133 return common.InitAndroidArchModule(base, hod, common.MultilibCommon, props...)
134}
135
136func (j *javaBase) BootClasspath(ctx common.AndroidBaseContext) string {
137 if ctx.Device() {
138 if j.properties.Sdk_version == "" {
139 return "core-libart"
140 } else if j.properties.Sdk_version == "current" {
141 // TODO: !TARGET_BUILD_APPS
Colin Crossc0b06f12015-04-08 13:03:43 -0700142 // TODO: export preprocessed framework.aidl from android_stubs_current
Colin Cross2fe66872015-03-30 17:20:39 -0700143 return "android_stubs_current"
144 } else if j.properties.Sdk_version == "system_current" {
145 return "android_system_stubs_current"
146 } else {
147 return "sdk_v" + j.properties.Sdk_version
148 }
149 } else {
150 if j.properties.Dex {
151 return "core-libart"
152 } else {
153 return ""
154 }
155 }
156}
157
158func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
159 var deps []string
160
161 if !j.properties.No_standard_libraries {
162 bootClasspath := j.BootClasspath(ctx)
163 if bootClasspath != "" {
164 deps = append(deps, bootClasspath)
165 }
166 }
167 deps = append(deps, j.properties.Java_libs...)
168 deps = append(deps, j.properties.Java_static_libs...)
169
170 return deps
171}
172
Colin Crossc0b06f12015-04-08 13:03:43 -0700173func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess string,
Colin Crossf03c82b2015-04-13 13:53:40 -0700174 aidlIncludeDirs []string) []string {
Colin Crossc0b06f12015-04-08 13:03:43 -0700175
176 localAidlIncludes := pathtools.PrefixPaths(j.properties.Aidl_includes, common.ModuleSrcDir(ctx))
177
178 var flags []string
179 if aidlPreprocess != "" {
180 flags = append(flags, "-p"+aidlPreprocess)
181 } else {
182 flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs, "-I"))
183 }
184
185 flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs, "-I"))
186 flags = append(flags, common.JoinWithPrefix(localAidlIncludes, "-I"))
187 flags = append(flags, "-I"+common.ModuleSrcDir(ctx))
188 flags = append(flags, "-I"+filepath.Join(common.ModuleSrcDir(ctx), "src"))
189
Colin Crossf03c82b2015-04-13 13:53:40 -0700190 return flags
Colin Crossc0b06f12015-04-08 13:03:43 -0700191}
192
Colin Cross2fe66872015-03-30 17:20:39 -0700193func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string,
Colin Crossc0b06f12015-04-08 13:03:43 -0700194 bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess string,
195 aidlIncludeDirs []string) {
Colin Cross2fe66872015-03-30 17:20:39 -0700196
197 ctx.VisitDirectDeps(func(module blueprint.Module) {
198 otherName := ctx.OtherModuleName(module)
199 if javaDep, ok := module.(JavaDependency); ok {
Colin Cross6cbb1272015-04-08 11:23:01 -0700200 if otherName == j.BootClasspath(ctx) {
201 bootClasspath = javaDep.ClasspathFile()
202 } else if inList(otherName, j.properties.Java_libs) {
Colin Cross2fe66872015-03-30 17:20:39 -0700203 classpath = append(classpath, javaDep.ClasspathFile())
204 } else if inList(otherName, j.properties.Java_static_libs) {
205 classpath = append(classpath, javaDep.ClasspathFile())
206 classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...)
207 resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...)
Colin Cross2fe66872015-03-30 17:20:39 -0700208 } else {
209 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
210 }
Colin Crossaa8630b2015-04-13 13:52:22 -0700211 aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...)
212 if sdkDep, ok := module.(sdkDependency); ok {
213 if sdkDep.AidlPreprocessed() != "" {
214 if aidlPreprocess != "" {
215 ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
216 aidlPreprocess, sdkDep.AidlPreprocessed())
217 } else {
218 aidlPreprocess = sdkDep.AidlPreprocessed()
219 }
Colin Crossc0b06f12015-04-08 13:03:43 -0700220 }
221 }
Colin Cross2fe66872015-03-30 17:20:39 -0700222 } else {
223 ctx.ModuleErrorf("unknown dependency module type for %q", otherName)
224 }
225 })
226
Colin Crossc0b06f12015-04-08 13:03:43 -0700227 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess, aidlIncludeDirs
Colin Cross2fe66872015-03-30 17:20:39 -0700228}
229
230func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
231 j.module.GenerateJavaBuildActions(ctx)
232}
233
234func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
Colin Crossc0b06f12015-04-08 13:03:43 -0700235
236 j.exportAidlIncludeDirs = pathtools.PrefixPaths(j.properties.Export_aidl_include_dirs,
237 common.ModuleSrcDir(ctx))
238
239 classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
240 aidlIncludeDirs := j.collectDeps(ctx)
241
Colin Crossf03c82b2015-04-13 13:53:40 -0700242 var flags javaBuilderFlags
243
244 javacFlags := j.properties.Javacflags
245 if len(javacFlags) > 0 {
246 ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
247 flags.javacFlags = "$javacFlags"
248 }
249
250 aidlFlags := j.aidlFlags(ctx, aidlPreprocess, aidlIncludeDirs)
251 if len(aidlFlags) > 0 {
252 ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
253 flags.aidlFlags = "$aidlFlags"
Colin Cross2fe66872015-03-30 17:20:39 -0700254 }
255
256 var javacDeps []string
257
Colin Cross2fe66872015-03-30 17:20:39 -0700258 if bootClasspath != "" {
259 flags.bootClasspath = "-bootclasspath " + bootClasspath
260 javacDeps = append(javacDeps, bootClasspath)
261 }
262
263 if len(classpath) > 0 {
264 flags.classpath = "-classpath " + strings.Join(classpath, ":")
265 javacDeps = append(javacDeps, classpath...)
266 }
267
Colin Crossc0b06f12015-04-08 13:03:43 -0700268 srcFiles := common.ExpandSources(ctx, j.properties.Srcs)
269
Colin Crossf05fe972015-04-10 17:45:20 -0700270 srcFiles = j.genSources(ctx, srcFiles, flags)
Colin Crossc0b06f12015-04-08 13:03:43 -0700271
Colin Cross8cf13342015-04-10 15:41:49 -0700272 if len(srcFiles) > 0 {
273 // Compile java sources into .class files
274 classes := TransformJavaToClasses(ctx, srcFiles, flags, javacDeps)
275 if ctx.Failed() {
276 return
277 }
278
279 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700280 }
281
Colin Cross276284f2015-04-20 13:51:48 -0700282 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs),
283 resourceJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700284
285 manifest := j.properties.Manifest
286 if manifest != "" {
287 manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
288 }
289
290 allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
291 allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
292
293 // Combine classes + resources into classes-full-debug.jar
294 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest)
295 if ctx.Failed() {
296 return
297 }
Colin Cross65bf4f22015-04-03 16:54:17 -0700298
Colin Cross65bf4f22015-04-03 16:54:17 -0700299 if j.properties.Jarjar_rules != "" {
300 jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
301 // Transform classes-full-debug.jar into classes-jarjar.jar
302 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
303 if ctx.Failed() {
304 return
305 }
Colin Cross20978302015-04-10 17:05:07 -0700306
307 classes, _ := TransformPrebuiltJarToClasses(ctx, outputFile)
308 classJarSpecs = []jarSpec{classes}
Colin Cross65bf4f22015-04-03 16:54:17 -0700309 }
310
Colin Cross20978302015-04-10 17:05:07 -0700311 j.resourceJarSpecs = resourceJarSpecs
312 j.classJarSpecs = classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700313 j.classpathFile = outputFile
314
Colin Cross8cf13342015-04-10 15:41:49 -0700315 if j.properties.Dex && len(srcFiles) > 0 {
Colin Cross2fe66872015-03-30 17:20:39 -0700316 dxFlags := j.properties.Dxflags
317 if false /* emma enabled */ {
318 // If you instrument class files that have local variable debug information in
319 // them emma does not correctly maintain the local variable table.
320 // This will cause an error when you try to convert the class files for Android.
321 // The workaround here is to build different dex file here based on emma switch
322 // then later copy into classes.dex. When emma is on, dx is run with --no-locals
323 // option to remove local variable information
324 dxFlags = append(dxFlags, "--no-locals")
325 }
326
Colin Cross1332b002015-04-07 17:11:30 -0700327 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700328 dxFlags = append(dxFlags, "--no-optimize")
329 }
330
Colin Cross1332b002015-04-07 17:11:30 -0700331 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700332 dxFlags = append(dxFlags,
333 "--debug",
334 "--verbose",
335 "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
336 "--dump-width=1000")
337 }
338
339 flags.dxFlags = strings.Join(dxFlags, " ")
340
341 // Compile classes.jar into classes.dex
Colin Cross6d1e72d2015-04-10 17:44:24 -0700342 dexJarSpec := TransformClassesJarToDex(ctx, outputFile, flags)
Colin Cross2fe66872015-03-30 17:20:39 -0700343 if ctx.Failed() {
344 return
345 }
346
347 // Combine classes.dex + resources into javalib.jar
Colin Cross6d1e72d2015-04-10 17:44:24 -0700348 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexJarSpec)
Colin Cross2fe66872015-03-30 17:20:39 -0700349 }
350
351 j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile)
352}
353
354var _ JavaDependency = (*JavaLibrary)(nil)
355
356func (j *javaBase) ClasspathFile() string {
357 return j.classpathFile
358}
359
360func (j *javaBase) ClassJarSpecs() []jarSpec {
361 return j.classJarSpecs
362}
363
364func (j *javaBase) ResourceJarSpecs() []jarSpec {
365 return j.resourceJarSpecs
366}
367
Colin Crossc0b06f12015-04-08 13:03:43 -0700368func (j *javaBase) AidlIncludeDirs() []string {
369 return j.exportAidlIncludeDirs
370}
371
Colin Crossf05fe972015-04-10 17:45:20 -0700372var _ logtagsProducer = (*javaBase)(nil)
373
374func (j *javaBase) logtags() []string {
375 return j.logtagsSrcs
376}
377
Colin Cross2fe66872015-03-30 17:20:39 -0700378//
379// Java libraries (.jar file)
380//
381
382type JavaLibrary struct {
383 javaBase
384}
385
386func JavaLibraryFactory() (blueprint.Module, []interface{}) {
387 module := &JavaLibrary{}
388
389 module.properties.Dex = true
390
391 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported)
392}
393
394func JavaLibraryHostFactory() (blueprint.Module, []interface{}) {
395 module := &JavaLibrary{}
396
397 return NewJavaBase(&module.javaBase, module, common.HostSupported)
398}
399
400//
401// Java Binaries (.jar file plus wrapper script)
402//
403
404type JavaBinary struct {
405 JavaLibrary
406
407 binaryProperties struct {
408 // wrapper: installable script to execute the resulting jar
409 Wrapper string
410 }
411}
412
413func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
414 j.JavaLibrary.GenerateJavaBuildActions(ctx)
415
416 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
417 // another build rule before the jar has been installed.
418 ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
419 j.installFile)
420}
421
422func JavaBinaryFactory() (blueprint.Module, []interface{}) {
423 module := &JavaBinary{}
424
425 module.properties.Dex = true
426
427 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties)
428}
429
430func JavaBinaryHostFactory() (blueprint.Module, []interface{}) {
431 module := &JavaBinary{}
432
433 return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties)
434}
435
436//
437// Java prebuilts
438//
439
440type JavaPrebuilt struct {
441 common.AndroidModuleBase
442
443 properties struct {
Colin Crossaa8630b2015-04-13 13:52:22 -0700444 Srcs []string
Colin Cross2fe66872015-03-30 17:20:39 -0700445 }
446
Colin Crosse1d62a82015-04-03 16:53:05 -0700447 classpathFile string
448 classJarSpecs, resourceJarSpecs []jarSpec
Colin Cross2fe66872015-03-30 17:20:39 -0700449}
450
451func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
452 if len(j.properties.Srcs) != 1 {
453 ctx.ModuleErrorf("expected exactly one jar in srcs")
454 return
455 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700456 prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
457
458 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
459
460 j.classpathFile = prebuilt
461 j.classJarSpecs = []jarSpec{classJarSpec}
462 j.resourceJarSpecs = []jarSpec{resourceJarSpec}
Colin Crosse1d62a82015-04-03 16:53:05 -0700463 ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
Colin Cross2fe66872015-03-30 17:20:39 -0700464}
465
466var _ JavaDependency = (*JavaPrebuilt)(nil)
467
468func (j *JavaPrebuilt) ClasspathFile() string {
469 return j.classpathFile
470}
471
472func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700473 return j.classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700474}
475
476func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700477 return j.resourceJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700478}
479
Colin Crossc0b06f12015-04-08 13:03:43 -0700480func (j *JavaPrebuilt) AidlIncludeDirs() []string {
481 return nil
482}
483
Colin Cross2fe66872015-03-30 17:20:39 -0700484func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
485 module := &JavaPrebuilt{}
486
487 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
488 common.MultilibCommon, &module.properties)
489}
490
Colin Crossaa8630b2015-04-13 13:52:22 -0700491//
492// SDK java prebuilts (.jar containing resources plus framework.aidl)
493//
494
495type sdkDependency interface {
496 JavaDependency
497 AidlPreprocessed() string
498}
499
500var _ sdkDependency = (*sdkPrebuilt)(nil)
501
502type sdkPrebuilt struct {
503 JavaPrebuilt
504
505 sdkProperties struct {
506 Aidl_preprocessed string
507 }
508
509 aidlPreprocessed string
510}
511
512func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
513 j.JavaPrebuilt.GenerateAndroidBuildActions(ctx)
514
515 if j.sdkProperties.Aidl_preprocessed != "" {
516 j.aidlPreprocessed = filepath.Join(common.ModuleSrcDir(ctx), j.sdkProperties.Aidl_preprocessed)
517 }
518}
519
520func (j *sdkPrebuilt) AidlPreprocessed() string {
521 return j.aidlPreprocessed
522}
523
524func SdkPrebuiltFactory() (blueprint.Module, []interface{}) {
525 module := &sdkPrebuilt{}
526
527 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
528 common.MultilibCommon, &module.properties, &module.sdkProperties)
529}
530
Colin Cross2fe66872015-03-30 17:20:39 -0700531func inList(s string, l []string) bool {
532 for _, e := range l {
533 if e == s {
534 return true
535 }
536 }
537 return false
538}