blob: 7f6b134634bc3d3496cfea3389102f716937b460 [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
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 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 Cross2fe66872015-03-30 17:20:39 -0700109 // installed file for binary dependency
110 installFile string
111}
112
113type JavaModuleType interface {
114 GenerateJavaBuildActions(ctx common.AndroidModuleContext)
115}
116
117type JavaDependency interface {
118 ClasspathFile() string
119 ClassJarSpecs() []jarSpec
120 ResourceJarSpecs() []jarSpec
Colin Crossc0b06f12015-04-08 13:03:43 -0700121 AidlIncludeDirs() []string
122 AidlPreprocessed() 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,
173 aidlIncludeDirs []string) string {
174
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
189 return strings.Join(flags, " ")
190}
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,
194 aidlIncludeDirs []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 Cross2fe66872015-03-30 17:20:39 -0700207 } else {
208 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
209 }
Colin Crossc0b06f12015-04-08 13:03:43 -0700210 aidlIncludeDirs = append(aidlIncludeDirs, j.AidlIncludeDirs()...)
211 if j.AidlPreprocessed() != "" {
212 if aidlPreprocess != "" {
213 ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
214 aidlPreprocess, j.AidlPreprocessed())
215 } else {
216 aidlPreprocess = j.AidlPreprocessed()
217 }
218 }
Colin Cross2fe66872015-03-30 17:20:39 -0700219 } else {
220 ctx.ModuleErrorf("unknown dependency module type for %q", otherName)
221 }
222 })
223
Colin Crossc0b06f12015-04-08 13:03:43 -0700224 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess, aidlIncludeDirs
Colin Cross2fe66872015-03-30 17:20:39 -0700225}
226
227func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
228 j.module.GenerateJavaBuildActions(ctx)
229}
230
231func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
Colin Crossc0b06f12015-04-08 13:03:43 -0700232
233 j.exportAidlIncludeDirs = pathtools.PrefixPaths(j.properties.Export_aidl_include_dirs,
234 common.ModuleSrcDir(ctx))
235
236 classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
237 aidlIncludeDirs := j.collectDeps(ctx)
238
Colin Cross2fe66872015-03-30 17:20:39 -0700239 flags := javaBuilderFlags{
240 javacFlags: strings.Join(j.properties.Javacflags, " "),
Colin Crossc0b06f12015-04-08 13:03:43 -0700241 aidlFlags: j.aidlFlags(ctx, aidlPreprocess, aidlIncludeDirs),
Colin Cross2fe66872015-03-30 17:20:39 -0700242 }
243
244 var javacDeps []string
245
Colin Cross2fe66872015-03-30 17:20:39 -0700246 if bootClasspath != "" {
247 flags.bootClasspath = "-bootclasspath " + bootClasspath
248 javacDeps = append(javacDeps, bootClasspath)
249 }
250
251 if len(classpath) > 0 {
252 flags.classpath = "-classpath " + strings.Join(classpath, ":")
253 javacDeps = append(javacDeps, classpath...)
254 }
255
Colin Crossc0b06f12015-04-08 13:03:43 -0700256 srcFiles := common.ExpandSources(ctx, j.properties.Srcs)
257
258 srcFiles = genSources(ctx, srcFiles, flags)
259
Colin Cross8cf13342015-04-10 15:41:49 -0700260 if len(srcFiles) > 0 {
261 // Compile java sources into .class files
262 classes := TransformJavaToClasses(ctx, srcFiles, flags, javacDeps)
263 if ctx.Failed() {
264 return
265 }
266
267 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700268 }
269
270 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs), resourceJarSpecs...)
Colin Cross2fe66872015-03-30 17:20:39 -0700271
272 manifest := j.properties.Manifest
273 if manifest != "" {
274 manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
275 }
276
277 allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
278 allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
279
280 // Combine classes + resources into classes-full-debug.jar
281 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest)
282 if ctx.Failed() {
283 return
284 }
Colin Cross65bf4f22015-04-03 16:54:17 -0700285
Colin Cross65bf4f22015-04-03 16:54:17 -0700286 if j.properties.Jarjar_rules != "" {
287 jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
288 // Transform classes-full-debug.jar into classes-jarjar.jar
289 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
290 if ctx.Failed() {
291 return
292 }
Colin Cross20978302015-04-10 17:05:07 -0700293
294 classes, _ := TransformPrebuiltJarToClasses(ctx, outputFile)
295 classJarSpecs = []jarSpec{classes}
Colin Cross65bf4f22015-04-03 16:54:17 -0700296 }
297
Colin Cross20978302015-04-10 17:05:07 -0700298 j.resourceJarSpecs = resourceJarSpecs
299 j.classJarSpecs = classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700300 j.classpathFile = outputFile
301
Colin Cross8cf13342015-04-10 15:41:49 -0700302 if j.properties.Dex && len(srcFiles) > 0 {
Colin Cross2fe66872015-03-30 17:20:39 -0700303 dxFlags := j.properties.Dxflags
304 if false /* emma enabled */ {
305 // If you instrument class files that have local variable debug information in
306 // them emma does not correctly maintain the local variable table.
307 // This will cause an error when you try to convert the class files for Android.
308 // The workaround here is to build different dex file here based on emma switch
309 // then later copy into classes.dex. When emma is on, dx is run with --no-locals
310 // option to remove local variable information
311 dxFlags = append(dxFlags, "--no-locals")
312 }
313
Colin Cross1332b002015-04-07 17:11:30 -0700314 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700315 dxFlags = append(dxFlags, "--no-optimize")
316 }
317
Colin Cross1332b002015-04-07 17:11:30 -0700318 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700319 dxFlags = append(dxFlags,
320 "--debug",
321 "--verbose",
322 "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
323 "--dump-width=1000")
324 }
325
326 flags.dxFlags = strings.Join(dxFlags, " ")
327
328 // Compile classes.jar into classes.dex
Colin Cross6d1e72d2015-04-10 17:44:24 -0700329 dexJarSpec := TransformClassesJarToDex(ctx, outputFile, flags)
Colin Cross2fe66872015-03-30 17:20:39 -0700330 if ctx.Failed() {
331 return
332 }
333
334 // Combine classes.dex + resources into javalib.jar
Colin Cross6d1e72d2015-04-10 17:44:24 -0700335 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexJarSpec)
Colin Cross2fe66872015-03-30 17:20:39 -0700336 }
337
338 j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile)
339}
340
341var _ JavaDependency = (*JavaLibrary)(nil)
342
343func (j *javaBase) ClasspathFile() string {
344 return j.classpathFile
345}
346
347func (j *javaBase) ClassJarSpecs() []jarSpec {
348 return j.classJarSpecs
349}
350
351func (j *javaBase) ResourceJarSpecs() []jarSpec {
352 return j.resourceJarSpecs
353}
354
Colin Crossc0b06f12015-04-08 13:03:43 -0700355func (j *javaBase) AidlIncludeDirs() []string {
356 return j.exportAidlIncludeDirs
357}
358
359func (j *javaBase) AidlPreprocessed() string {
360 return ""
361}
362
Colin Cross2fe66872015-03-30 17:20:39 -0700363//
364// Java libraries (.jar file)
365//
366
367type JavaLibrary struct {
368 javaBase
369}
370
371func JavaLibraryFactory() (blueprint.Module, []interface{}) {
372 module := &JavaLibrary{}
373
374 module.properties.Dex = true
375
376 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported)
377}
378
379func JavaLibraryHostFactory() (blueprint.Module, []interface{}) {
380 module := &JavaLibrary{}
381
382 return NewJavaBase(&module.javaBase, module, common.HostSupported)
383}
384
385//
386// Java Binaries (.jar file plus wrapper script)
387//
388
389type JavaBinary struct {
390 JavaLibrary
391
392 binaryProperties struct {
393 // wrapper: installable script to execute the resulting jar
394 Wrapper string
395 }
396}
397
398func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
399 j.JavaLibrary.GenerateJavaBuildActions(ctx)
400
401 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
402 // another build rule before the jar has been installed.
403 ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
404 j.installFile)
405}
406
407func JavaBinaryFactory() (blueprint.Module, []interface{}) {
408 module := &JavaBinary{}
409
410 module.properties.Dex = true
411
412 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties)
413}
414
415func JavaBinaryHostFactory() (blueprint.Module, []interface{}) {
416 module := &JavaBinary{}
417
418 return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties)
419}
420
421//
422// Java prebuilts
423//
424
425type JavaPrebuilt struct {
426 common.AndroidModuleBase
427
428 properties struct {
Colin Crossc0b06f12015-04-08 13:03:43 -0700429 Srcs []string
430 Aidl_preprocessed string
Colin Cross2fe66872015-03-30 17:20:39 -0700431 }
432
Colin Crossc0b06f12015-04-08 13:03:43 -0700433 aidlPreprocessed string
Colin Crosse1d62a82015-04-03 16:53:05 -0700434 classpathFile string
435 classJarSpecs, resourceJarSpecs []jarSpec
Colin Cross2fe66872015-03-30 17:20:39 -0700436}
437
438func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
439 if len(j.properties.Srcs) != 1 {
440 ctx.ModuleErrorf("expected exactly one jar in srcs")
441 return
442 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700443 prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
444
445 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
446
447 j.classpathFile = prebuilt
448 j.classJarSpecs = []jarSpec{classJarSpec}
449 j.resourceJarSpecs = []jarSpec{resourceJarSpec}
Colin Crossc0b06f12015-04-08 13:03:43 -0700450 if j.properties.Aidl_preprocessed != "" {
451 j.aidlPreprocessed = filepath.Join(common.ModuleSrcDir(ctx), j.properties.Aidl_preprocessed)
452 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700453 ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
Colin Cross2fe66872015-03-30 17:20:39 -0700454}
455
456var _ JavaDependency = (*JavaPrebuilt)(nil)
457
458func (j *JavaPrebuilt) ClasspathFile() string {
459 return j.classpathFile
460}
461
462func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700463 return j.classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700464}
465
466func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700467 return j.resourceJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700468}
469
Colin Crossc0b06f12015-04-08 13:03:43 -0700470func (j *JavaPrebuilt) AidlIncludeDirs() []string {
471 return nil
472}
473
474func (j *JavaPrebuilt) AidlPreprocessed() string {
475 return j.aidlPreprocessed
476}
477
Colin Cross2fe66872015-03-30 17:20:39 -0700478func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
479 module := &JavaPrebuilt{}
480
481 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
482 common.MultilibCommon, &module.properties)
483}
484
485func inList(s string, l []string) bool {
486 for _, e := range l {
487 if e == s {
488 return true
489 }
490 }
491 return false
492}