blob: 448580ec478fc4620b61d5bb2e21f8a276409cd8 [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 Cross2fe66872015-03-30 17:20:39 -070027
28 "android/soong/common"
29)
30
Colin Cross2fe66872015-03-30 17:20:39 -070031// TODO:
32// Autogenerated files:
33// AIDL
34// 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
57 // resource_dirs: list of directories containing resources
58 Resource_dirs []string `android:"arch_variant"`
59
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 Cross2fe66872015-03-30 17:20:39 -070088 }
89
90 // output file suitable for inserting into the classpath of another compile
91 classpathFile string
92
93 // jarSpecs suitable for inserting classes from a static library into another jar
94 classJarSpecs []jarSpec
95
96 // jarSpecs suitable for inserting resources from a static library into another jar
97 resourceJarSpecs []jarSpec
98
99 // installed file for binary dependency
100 installFile string
101}
102
103type JavaModuleType interface {
104 GenerateJavaBuildActions(ctx common.AndroidModuleContext)
105}
106
107type JavaDependency interface {
108 ClasspathFile() string
109 ClassJarSpecs() []jarSpec
110 ResourceJarSpecs() []jarSpec
111}
112
113func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
114 props ...interface{}) (blueprint.Module, []interface{}) {
115
116 base.module = module
117
118 props = append(props, &base.properties)
119
120 return common.InitAndroidArchModule(base, hod, common.MultilibCommon, props...)
121}
122
123func (j *javaBase) BootClasspath(ctx common.AndroidBaseContext) string {
124 if ctx.Device() {
125 if j.properties.Sdk_version == "" {
126 return "core-libart"
127 } else if j.properties.Sdk_version == "current" {
128 // TODO: !TARGET_BUILD_APPS
129 return "android_stubs_current"
130 } else if j.properties.Sdk_version == "system_current" {
131 return "android_system_stubs_current"
132 } else {
133 return "sdk_v" + j.properties.Sdk_version
134 }
135 } else {
136 if j.properties.Dex {
137 return "core-libart"
138 } else {
139 return ""
140 }
141 }
142}
143
144func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
145 var deps []string
146
147 if !j.properties.No_standard_libraries {
148 bootClasspath := j.BootClasspath(ctx)
149 if bootClasspath != "" {
150 deps = append(deps, bootClasspath)
151 }
152 }
153 deps = append(deps, j.properties.Java_libs...)
154 deps = append(deps, j.properties.Java_static_libs...)
155
156 return deps
157}
158
159func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string,
160 bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec) {
161
162 ctx.VisitDirectDeps(func(module blueprint.Module) {
163 otherName := ctx.OtherModuleName(module)
164 if javaDep, ok := module.(JavaDependency); ok {
Colin Cross6cbb1272015-04-08 11:23:01 -0700165 if otherName == j.BootClasspath(ctx) {
166 bootClasspath = javaDep.ClasspathFile()
167 } else if inList(otherName, j.properties.Java_libs) {
Colin Cross2fe66872015-03-30 17:20:39 -0700168 classpath = append(classpath, javaDep.ClasspathFile())
169 } else if inList(otherName, j.properties.Java_static_libs) {
170 classpath = append(classpath, javaDep.ClasspathFile())
171 classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...)
172 resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...)
Colin Cross2fe66872015-03-30 17:20:39 -0700173 } else {
174 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
175 }
176 } else {
177 ctx.ModuleErrorf("unknown dependency module type for %q", otherName)
178 }
179 })
180
181 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs
182}
183
184func (j *javaBase) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
185 j.module.GenerateJavaBuildActions(ctx)
186}
187
188func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
189 flags := javaBuilderFlags{
190 javacFlags: strings.Join(j.properties.Javacflags, " "),
191 }
192
193 var javacDeps []string
194
Colin Crossfce53272015-04-08 11:21:40 -0700195 srcFiles := common.ExpandSources(ctx, j.properties.Srcs)
Colin Cross2fe66872015-03-30 17:20:39 -0700196
197 classpath, bootClasspath, classJarSpecs, resourceJarSpecs := j.collectDeps(ctx)
198
199 if bootClasspath != "" {
200 flags.bootClasspath = "-bootclasspath " + bootClasspath
201 javacDeps = append(javacDeps, bootClasspath)
202 }
203
204 if len(classpath) > 0 {
205 flags.classpath = "-classpath " + strings.Join(classpath, ":")
206 javacDeps = append(javacDeps, classpath...)
207 }
208
209 // Compile java sources into .class files
210 classes := TransformJavaToClasses(ctx, srcFiles, flags, javacDeps)
211 if ctx.Failed() {
212 return
213 }
214
215 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs), resourceJarSpecs...)
216 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
217
218 manifest := j.properties.Manifest
219 if manifest != "" {
220 manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
221 }
222
223 allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
224 allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
225
226 // Combine classes + resources into classes-full-debug.jar
227 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest)
228 if ctx.Failed() {
229 return
230 }
Colin Cross65bf4f22015-04-03 16:54:17 -0700231
Colin Cross2fe66872015-03-30 17:20:39 -0700232 j.classJarSpecs = classJarSpecs
233 j.resourceJarSpecs = resourceJarSpecs
Colin Cross65bf4f22015-04-03 16:54:17 -0700234
235 if j.properties.Jarjar_rules != "" {
236 jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
237 // Transform classes-full-debug.jar into classes-jarjar.jar
238 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
239 if ctx.Failed() {
240 return
241 }
242 }
243
Colin Cross2fe66872015-03-30 17:20:39 -0700244 j.classpathFile = outputFile
245
246 if j.properties.Dex {
247 dxFlags := j.properties.Dxflags
248 if false /* emma enabled */ {
249 // If you instrument class files that have local variable debug information in
250 // them emma does not correctly maintain the local variable table.
251 // This will cause an error when you try to convert the class files for Android.
252 // The workaround here is to build different dex file here based on emma switch
253 // then later copy into classes.dex. When emma is on, dx is run with --no-locals
254 // option to remove local variable information
255 dxFlags = append(dxFlags, "--no-locals")
256 }
257
Colin Cross1332b002015-04-07 17:11:30 -0700258 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700259 dxFlags = append(dxFlags, "--no-optimize")
260 }
261
Colin Cross1332b002015-04-07 17:11:30 -0700262 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" {
Colin Cross2fe66872015-03-30 17:20:39 -0700263 dxFlags = append(dxFlags,
264 "--debug",
265 "--verbose",
266 "--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
267 "--dump-width=1000")
268 }
269
270 flags.dxFlags = strings.Join(dxFlags, " ")
271
272 // Compile classes.jar into classes.dex
273 dexFile := TransformClassesJarToDex(ctx, outputFile, flags)
274 if ctx.Failed() {
275 return
276 }
277
278 // Combine classes.dex + resources into javalib.jar
279 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexFile)
280 }
281
282 j.installFile = ctx.InstallFileName("framework", ctx.ModuleName()+".jar", outputFile)
283}
284
285var _ JavaDependency = (*JavaLibrary)(nil)
286
287func (j *javaBase) ClasspathFile() string {
288 return j.classpathFile
289}
290
291func (j *javaBase) ClassJarSpecs() []jarSpec {
292 return j.classJarSpecs
293}
294
295func (j *javaBase) ResourceJarSpecs() []jarSpec {
296 return j.resourceJarSpecs
297}
298
299//
300// Java libraries (.jar file)
301//
302
303type JavaLibrary struct {
304 javaBase
305}
306
307func JavaLibraryFactory() (blueprint.Module, []interface{}) {
308 module := &JavaLibrary{}
309
310 module.properties.Dex = true
311
312 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported)
313}
314
315func JavaLibraryHostFactory() (blueprint.Module, []interface{}) {
316 module := &JavaLibrary{}
317
318 return NewJavaBase(&module.javaBase, module, common.HostSupported)
319}
320
321//
322// Java Binaries (.jar file plus wrapper script)
323//
324
325type JavaBinary struct {
326 JavaLibrary
327
328 binaryProperties struct {
329 // wrapper: installable script to execute the resulting jar
330 Wrapper string
331 }
332}
333
334func (j *JavaBinary) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
335 j.JavaLibrary.GenerateJavaBuildActions(ctx)
336
337 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
338 // another build rule before the jar has been installed.
339 ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
340 j.installFile)
341}
342
343func JavaBinaryFactory() (blueprint.Module, []interface{}) {
344 module := &JavaBinary{}
345
346 module.properties.Dex = true
347
348 return NewJavaBase(&module.javaBase, module, common.HostAndDeviceSupported, &module.binaryProperties)
349}
350
351func JavaBinaryHostFactory() (blueprint.Module, []interface{}) {
352 module := &JavaBinary{}
353
354 return NewJavaBase(&module.javaBase, module, common.HostSupported, &module.binaryProperties)
355}
356
357//
358// Java prebuilts
359//
360
361type JavaPrebuilt struct {
362 common.AndroidModuleBase
363
364 properties struct {
365 Srcs []string
366 }
367
Colin Crosse1d62a82015-04-03 16:53:05 -0700368 classpathFile string
369 classJarSpecs, resourceJarSpecs []jarSpec
Colin Cross2fe66872015-03-30 17:20:39 -0700370}
371
372func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
373 if len(j.properties.Srcs) != 1 {
374 ctx.ModuleErrorf("expected exactly one jar in srcs")
375 return
376 }
Colin Crosse1d62a82015-04-03 16:53:05 -0700377 prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
378
379 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
380
381 j.classpathFile = prebuilt
382 j.classJarSpecs = []jarSpec{classJarSpec}
383 j.resourceJarSpecs = []jarSpec{resourceJarSpec}
384
385 ctx.InstallFileName("framework", ctx.ModuleName()+".jar", j.classpathFile)
Colin Cross2fe66872015-03-30 17:20:39 -0700386}
387
388var _ JavaDependency = (*JavaPrebuilt)(nil)
389
390func (j *JavaPrebuilt) ClasspathFile() string {
391 return j.classpathFile
392}
393
394func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700395 return j.classJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700396}
397
398func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec {
Colin Crosse1d62a82015-04-03 16:53:05 -0700399 return j.resourceJarSpecs
Colin Cross2fe66872015-03-30 17:20:39 -0700400}
401
402func JavaPrebuiltFactory() (blueprint.Module, []interface{}) {
403 module := &JavaPrebuilt{}
404
405 return common.InitAndroidArchModule(module, common.HostAndDeviceSupported,
406 common.MultilibCommon, &module.properties)
407}
408
409func inList(s string, l []string) bool {
410 for _, e := range l {
411 if e == s {
412 return true
413 }
414 }
415 return false
416}