blob: 2a04f701d8d7b0e0403b544604d1754f2054d057 [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:
Colin Cross2fe66872015-03-30 17:20:39 -070034// Proto
35// Renderscript
36// Post-jar passes:
37// Proguard
38// Emma
39// Jarjar
40// Dex
41// Rmtypedefs
42// Jack
43// DroidDoc
44// Findbugs
45
46// javaBase contains the properties and members used by all java module types, and implements
47// the blueprint.Module interface.
48type javaBase struct {
49 common.AndroidModuleBase
50 module JavaModuleType
51
52 properties struct {
53 // srcs: list of source files used to compile the Java module. May be .java, .logtags, .proto,
54 // or .aidl files.
55 Srcs []string `android:"arch_variant,arch_subtract"`
56
Colin Cross276284f2015-04-20 13:51:48 -070057 // java_resource_dirs: list of directories containing Java resources
58 Java_resource_dirs []string `android:"arch_variant"`
Colin Cross2fe66872015-03-30 17:20:39 -070059
60 // no_standard_libraries: don't build against the default libraries (core-libart, core-junit,
61 // ext, and framework for device targets)
62 No_standard_libraries bool
63
64 // javacflags: list of module-specific flags that will be used for javac compiles
65 Javacflags []string `android:"arch_variant"`
66
67 // dxflags: list of module-specific flags that will be used for dex compiles
68 Dxflags []string `android:"arch_variant"`
69
70 // java_libs: list of of java libraries that will be in the classpath
71 Java_libs []string `android:"arch_variant"`
72
73 // java_static_libs: list of java libraries that will be compiled into the resulting jar
74 Java_static_libs []string `android:"arch_variant"`
75
76 // manifest: manifest file to be included in resulting jar
77 Manifest string
78
79 // sdk_version: if not blank, set to the version of the sdk to compile against
80 Sdk_version string
81
82 // Set for device java libraries, and for host versions of device java libraries
83 // built for testing
84 Dex bool `blueprint:"mutated"`
Colin Cross65bf4f22015-04-03 16:54:17 -070085
86 // jarjar_rules: if not blank, run jarjar using the specified rules file
87 Jarjar_rules string
Colin Crossc0b06f12015-04-08 13:03:43 -070088
89 // aidl_includes: directories to pass to aidl tool
90 Aidl_includes []string
91
92 // aidl_export_include_dirs: directories that should be added as include directories
93 // for any aidl sources of modules that depend on this module
94 Export_aidl_include_dirs []string
Colin Cross2fe66872015-03-30 17:20:39 -070095 }
96
97 // output file suitable for inserting into the classpath of another compile
98 classpathFile string
99
100 // jarSpecs suitable for inserting classes from a static library into another jar
101 classJarSpecs []jarSpec
102
103 // jarSpecs suitable for inserting resources from a static library into another jar
104 resourceJarSpecs []jarSpec
105
Colin Crossc0b06f12015-04-08 13:03:43 -0700106 exportAidlIncludeDirs []string
107
Colin Crossf05fe972015-04-10 17:45:20 -0700108 logtagsSrcs []string
109
Colin Cross2fe66872015-03-30 17:20:39 -0700110 // installed file for binary dependency
111 installFile string
112}
113
114type JavaModuleType interface {
115 GenerateJavaBuildActions(ctx common.AndroidModuleContext)
116}
117
118type JavaDependency interface {
119 ClasspathFile() string
120 ClassJarSpecs() []jarSpec
121 ResourceJarSpecs() []jarSpec
Colin Crossc0b06f12015-04-08 13:03:43 -0700122 AidlIncludeDirs() []string
Colin Cross2fe66872015-03-30 17:20:39 -0700123}
124
125func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
126 props ...interface{}) (blueprint.Module, []interface{}) {
127
128 base.module = module
129
130 props = append(props, &base.properties)
131
132 return common.InitAndroidArchModule(base, hod, common.MultilibCommon, props...)
133}
134
135func (j *javaBase) BootClasspath(ctx common.AndroidBaseContext) string {
136 if ctx.Device() {
137 if j.properties.Sdk_version == "" {
138 return "core-libart"
139 } else if j.properties.Sdk_version == "current" {
140 // TODO: !TARGET_BUILD_APPS
Colin Crossc0b06f12015-04-08 13:03:43 -0700141 // TODO: export preprocessed framework.aidl from android_stubs_current
Colin Cross2fe66872015-03-30 17:20:39 -0700142 return "android_stubs_current"
143 } else if j.properties.Sdk_version == "system_current" {
144 return "android_system_stubs_current"
145 } else {
146 return "sdk_v" + j.properties.Sdk_version
147 }
148 } else {
149 if j.properties.Dex {
150 return "core-libart"
151 } else {
152 return ""
153 }
154 }
155}
156
157func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
158 var deps []string
159
160 if !j.properties.No_standard_libraries {
161 bootClasspath := j.BootClasspath(ctx)
162 if bootClasspath != "" {
163 deps = append(deps, bootClasspath)
164 }
165 }
166 deps = append(deps, j.properties.Java_libs...)
167 deps = append(deps, j.properties.Java_static_libs...)
168
169 return deps
170}
171
Colin Crossc0b06f12015-04-08 13:03:43 -0700172func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess string,
Colin Crossf03c82b2015-04-13 13:53:40 -0700173 aidlIncludeDirs []string) []string {
Colin Crossc0b06f12015-04-08 13:03:43 -0700174
175 localAidlIncludes := pathtools.PrefixPaths(j.properties.Aidl_includes, common.ModuleSrcDir(ctx))
176
177 var flags []string
178 if aidlPreprocess != "" {
179 flags = append(flags, "-p"+aidlPreprocess)
180 } else {
181 flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs, "-I"))
182 }
183
184 flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs, "-I"))
185 flags = append(flags, common.JoinWithPrefix(localAidlIncludes, "-I"))
186 flags = append(flags, "-I"+common.ModuleSrcDir(ctx))
187 flags = append(flags, "-I"+filepath.Join(common.ModuleSrcDir(ctx), "src"))
188
Colin Crossf03c82b2015-04-13 13:53:40 -0700189 return flags
Colin Crossc0b06f12015-04-08 13:03:43 -0700190}
191
Colin Cross2fe66872015-03-30 17:20:39 -0700192func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string,
Colin Crossc0b06f12015-04-08 13:03:43 -0700193 bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess string,
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700194 aidlIncludeDirs []string, srcFileLists []string) {
Colin Cross2fe66872015-03-30 17:20:39 -0700195
196 ctx.VisitDirectDeps(func(module blueprint.Module) {
197 otherName := ctx.OtherModuleName(module)
198 if javaDep, ok := module.(JavaDependency); ok {
Colin Cross6cbb1272015-04-08 11:23:01 -0700199 if otherName == j.BootClasspath(ctx) {
200 bootClasspath = javaDep.ClasspathFile()
201 } else if inList(otherName, j.properties.Java_libs) {
Colin Cross2fe66872015-03-30 17:20:39 -0700202 classpath = append(classpath, javaDep.ClasspathFile())
203 } else if inList(otherName, j.properties.Java_static_libs) {
204 classpath = append(classpath, javaDep.ClasspathFile())
205 classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...)
206 resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...)
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700207 } else if ctx.ModuleName() == "framework" && otherName == "framework-res" {
208 // framework.jar has a one-off dependency on the R.java and Manifest.java files
209 // generated by framework-res.apk
210 srcFileLists = append(srcFileLists, module.(*javaBase).module.(*AndroidApp).rJarSpec.fileList)
Colin Cross2fe66872015-03-30 17:20:39 -0700211 } else {
212 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
213 }
Colin Crossaa8630b2015-04-13 13:52:22 -0700214 aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...)
215 if sdkDep, ok := module.(sdkDependency); ok {
216 if sdkDep.AidlPreprocessed() != "" {
217 if aidlPreprocess != "" {
218 ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
219 aidlPreprocess, sdkDep.AidlPreprocessed())
220 } else {
221 aidlPreprocess = sdkDep.AidlPreprocessed()
222 }
Colin Crossc0b06f12015-04-08 13:03:43 -0700223 }
224 }
Colin Cross2fe66872015-03-30 17:20:39 -0700225 } else {
226 ctx.ModuleErrorf("unknown dependency module type for %q", otherName)
227 }
228 })
229
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700230 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
231 aidlIncludeDirs, srcFileLists
Colin Cross2fe66872015-03-30 17:20:39 -0700232}
233
234func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
235 j.module.GenerateJavaBuildActions(ctx)
236}
237
238func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
Colin Crossc0b06f12015-04-08 13:03:43 -0700239
240 j.exportAidlIncludeDirs = pathtools.PrefixPaths(j.properties.Export_aidl_include_dirs,
241 common.ModuleSrcDir(ctx))
242
243 classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700244 aidlIncludeDirs, srcFileLists := j.collectDeps(ctx)
Colin Crossc0b06f12015-04-08 13:03:43 -0700245
Colin Crossf03c82b2015-04-13 13:53:40 -0700246 var flags javaBuilderFlags
247
248 javacFlags := j.properties.Javacflags
249 if len(javacFlags) > 0 {
250 ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
251 flags.javacFlags = "$javacFlags"
252 }
253
254 aidlFlags := j.aidlFlags(ctx, aidlPreprocess, aidlIncludeDirs)
255 if len(aidlFlags) > 0 {
256 ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
257 flags.aidlFlags = "$aidlFlags"
Colin Cross2fe66872015-03-30 17:20:39 -0700258 }
259
260 var javacDeps []string
261
Colin Cross2fe66872015-03-30 17:20:39 -0700262 if bootClasspath != "" {
263 flags.bootClasspath = "-bootclasspath " + bootClasspath
264 javacDeps = append(javacDeps, bootClasspath)
265 }
266
267 if len(classpath) > 0 {
268 flags.classpath = "-classpath " + strings.Join(classpath, ":")
269 javacDeps = append(javacDeps, classpath...)
270 }
271
Colin Crossc0b06f12015-04-08 13:03:43 -0700272 srcFiles := common.ExpandSources(ctx, j.properties.Srcs)
273
Colin Crossf05fe972015-04-10 17:45:20 -0700274 srcFiles = j.genSources(ctx, srcFiles, flags)
Colin Crossc0b06f12015-04-08 13:03:43 -0700275
Colin Cross8cf13342015-04-10 15:41:49 -0700276 if len(srcFiles) > 0 {
277 // Compile java sources into .class files
Colin Crosse7a9f3f2015-04-13 14:02:52 -0700278 classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, javacDeps)
Colin Cross8cf13342015-04-10 15:41:49 -0700279 if ctx.Failed() {
280 return
281 }
282
283 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700284 }
285
Colin Cross276284f2015-04-20 13:51:48 -0700286 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs),
287 resourceJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700288
289 manifest := j.properties.Manifest
290 if manifest != "" {
291 manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
292 }
293
294 allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
295 allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
296
297 // Combine classes + resources into classes-full-debug.jar
298 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest)
299 if ctx.Failed() {
300 return
301 }
Colin Cross65bf4f22015-04-03 16:54:17 -0700302
Colin Cross65bf4f22015-04-03 16:54:17 -0700303 if j.properties.Jarjar_rules != "" {
304 jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
305 // Transform classes-full-debug.jar into classes-jarjar.jar
306 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
307 if ctx.Failed() {
308 return
309 }
Colin Cross20978302015-04-10 17:05:07 -0700310
311 classes, _ := TransformPrebuiltJarToClasses(ctx, outputFile)
312 classJarSpecs = []jarSpec{classes}
Colin Cross65bf4f22015-04-03 16:54:17 -0700313 }
314
Colin Cross20978302015-04-10 17:05:07 -0700315 j.resourceJarSpecs = resourceJarSpecs
316 j.classJarSpecs = classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700317 j.classpathFile = outputFile
318
Colin Cross8cf13342015-04-10 15:41:49 -0700319 if j.properties.Dex && len(srcFiles) > 0 {
Colin Cross2fe66872015-03-30 17:20:39 -0700320 dxFlags := j.properties.Dxflags
321 if false /* emma enabled */ {
322 // If you instrument class files that have local variable debug information in
323 // them emma does not correctly maintain the local variable table.
324 // This will cause an error when you try to convert the class files for Android.
325 // The workaround here is to build different dex file here based on emma switch
326 // then later copy into classes.dex. When emma is on, dx is run with --no-locals
327 // option to remove local variable information
328 dxFlags = append(dxFlags, "--no-locals")
329 }
330
Colin Cross1332b002015-04-07 17:11:30 -0700331 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700332 dxFlags = append(dxFlags, "--no-optimize")
333 }
334
Colin Cross1332b002015-04-07 17:11:30 -0700335 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700336 dxFlags = append(dxFlags,
337 "--debug",
338 "--verbose",
339 "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
340 "--dump-width=1000")
341 }
342
343 flags.dxFlags = strings.Join(dxFlags, " ")
344
345 // Compile classes.jar into classes.dex
Colin Cross6d1e72d2015-04-10 17:44:24 -0700346 dexJarSpec := TransformClassesJarToDex(ctx, outputFile, flags)
Colin Cross2fe66872015-03-30 17:20:39 -0700347 if ctx.Failed() {
348 return
349 }
350
351 // Combine classes.dex + resources into javalib.jar
Colin Cross6d1e72d2015-04-10 17:44:24 -0700352 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexJarSpec)
Colin Cross2fe66872015-03-30 17:20:39 -0700353 }
354
355 j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile)
356}
357
358var _ JavaDependency = (*JavaLibrary)(nil)
359
360func (j *javaBase) ClasspathFile() string {
361 return j.classpathFile
362}
363
364func (j *javaBase) ClassJarSpecs() []jarSpec {
365 return j.classJarSpecs
366}
367
368func (j *javaBase) ResourceJarSpecs() []jarSpec {
369 return j.resourceJarSpecs
370}
371
Colin Crossc0b06f12015-04-08 13:03:43 -0700372func (j *javaBase) AidlIncludeDirs() []string {
373 return j.exportAidlIncludeDirs
374}
375
Colin Crossf05fe972015-04-10 17:45:20 -0700376var _ logtagsProducer = (*javaBase)(nil)
377
378func (j *javaBase) logtags() []string {
379 return j.logtagsSrcs
380}
381
Colin Cross2fe66872015-03-30 17:20:39 -0700382//
383// Java libraries (.jar file)
384//
385
386type JavaLibrary struct {
387 javaBase
388}
389
390func JavaLibraryFactory() (blueprint.Module, []interface{}) {
391 module := &JavaLibrary{}
392
393 module.properties.Dex = true
394
395 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported)
396}
397
398func JavaLibraryHostFactory() (blueprint.Module, []interface{}) {
399 module := &JavaLibrary{}
400
401 return NewJavaBase(&module.javaBase, module, common.HostSupported)
402}
403
404//
405// Java Binaries (.jar file plus wrapper script)
406//
407
408type JavaBinary struct {
409 JavaLibrary
410
411 binaryProperties struct {
412 // wrapper: installable script to execute the resulting jar
413 Wrapper string
414 }
415}
416
417func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
418 j.JavaLibrary.GenerateJavaBuildActions(ctx)
419
420 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
421 // another build rule before the jar has been installed.
422 ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
423 j.installFile)
424}
425
426func JavaBinaryFactory() (blueprint.Module, []interface{}) {
427 module := &JavaBinary{}
428
429 module.properties.Dex = true
430
431 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties)
432}
433
434func JavaBinaryHostFactory() (blueprint.Module, []interface{}) {
435 module := &JavaBinary{}
436
437 return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties)
438}
439
440//
441// Java prebuilts
442//
443
444type JavaPrebuilt struct {
445 common.AndroidModuleBase
446
447 properties struct {
Colin Crossaa8630b2015-04-13 13:52:22 -0700448 Srcs []string
Colin Cross2fe66872015-03-30 17:20:39 -0700449 }
450
Colin Crosse1d62a82015-04-03 16:53:05 -0700451 classpathFile string
452 classJarSpecs, resourceJarSpecs []jarSpec
Colin Cross2fe66872015-03-30 17:20:39 -0700453}
454
455func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
456 if len(j.properties.Srcs) != 1 {
457 ctx.ModuleErrorf("expected exactly one jar in srcs")
458 return
459 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700460 prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
461
462 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
463
464 j.classpathFile = prebuilt
465 j.classJarSpecs = []jarSpec{classJarSpec}
466 j.resourceJarSpecs = []jarSpec{resourceJarSpec}
Colin Crosse1d62a82015-04-03 16:53:05 -0700467 ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
Colin Cross2fe66872015-03-30 17:20:39 -0700468}
469
470var _ JavaDependency = (*JavaPrebuilt)(nil)
471
472func (j *JavaPrebuilt) ClasspathFile() string {
473 return j.classpathFile
474}
475
476func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700477 return j.classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700478}
479
480func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700481 return j.resourceJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700482}
483
Colin Crossc0b06f12015-04-08 13:03:43 -0700484func (j *JavaPrebuilt) AidlIncludeDirs() []string {
485 return nil
486}
487
Colin Cross2fe66872015-03-30 17:20:39 -0700488func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
489 module := &JavaPrebuilt{}
490
491 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
492 common.MultilibCommon, &module.properties)
493}
494
Colin Crossaa8630b2015-04-13 13:52:22 -0700495//
496// SDK java prebuilts (.jar containing resources plus framework.aidl)
497//
498
499type sdkDependency interface {
500 JavaDependency
501 AidlPreprocessed() string
502}
503
504var _ sdkDependency = (*sdkPrebuilt)(nil)
505
506type sdkPrebuilt struct {
507 JavaPrebuilt
508
509 sdkProperties struct {
510 Aidl_preprocessed string
511 }
512
513 aidlPreprocessed string
514}
515
516func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
517 j.JavaPrebuilt.GenerateAndroidBuildActions(ctx)
518
519 if j.sdkProperties.Aidl_preprocessed != "" {
520 j.aidlPreprocessed = filepath.Join(common.ModuleSrcDir(ctx), j.sdkProperties.Aidl_preprocessed)
521 }
522}
523
524func (j *sdkPrebuilt) AidlPreprocessed() string {
525 return j.aidlPreprocessed
526}
527
528func SdkPrebuiltFactory() (blueprint.Module, []interface{}) {
529 module := &sdkPrebuilt{}
530
531 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
532 common.MultilibCommon, &module.properties, &module.sdkProperties)
533}
534
Colin Cross2fe66872015-03-30 17:20:39 -0700535func inList(s string, l []string) bool {
536 for _, e := range l {
537 if e == s {
538 return true
539 }
540 }
541 return false
542}