1// 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 Module. The final creation of the rules 19// is handled in builder.go 20 21import ( 22 "fmt" 23 "strings" 24 25 "github.com/google/blueprint" 26 27 "android/soong/android" 28 "android/soong/genrule" 29 "android/soong/java/config" 30) 31 32func init() { 33 android.RegisterModuleType("java_library", JavaLibraryFactory) 34 android.RegisterModuleType("java_library_static", JavaLibraryFactory) 35 android.RegisterModuleType("java_library_host", JavaLibraryHostFactory) 36 android.RegisterModuleType("java_binary", JavaBinaryFactory) 37 android.RegisterModuleType("java_binary_host", JavaBinaryHostFactory) 38 android.RegisterModuleType("java_prebuilt_library", JavaPrebuiltFactory) 39 android.RegisterModuleType("android_prebuilt_sdk", SdkPrebuiltFactory) 40 android.RegisterModuleType("android_app", AndroidAppFactory) 41 42 android.RegisterSingletonType("logtags", LogtagsSingleton) 43} 44 45// TODO: 46// Autogenerated files: 47// Proto 48// Renderscript 49// Post-jar passes: 50// Proguard 51// Jacoco 52// Jarjar 53// Dex 54// Rmtypedefs 55// DroidDoc 56// Findbugs 57 58type compilerProperties struct { 59 // list of source files used to compile the Java module. May be .java, .logtags, .proto, 60 // or .aidl files. 61 Srcs []string `android:"arch_variant"` 62 63 // list of source files that should not be used to build the Java module. 64 // This is most useful in the arch/multilib variants to remove non-common files 65 Exclude_srcs []string `android:"arch_variant"` 66 67 // list of directories containing Java resources 68 Resource_dirs []string `android:"arch_variant"` 69 70 // list of directories that should be excluded from resource_dirs 71 Exclude_resource_dirs []string `android:"arch_variant"` 72 73 // don't build against the default libraries (legacy-test, core-junit, 74 // ext, and framework for device targets) 75 No_standard_libraries bool 76 77 // list of module-specific flags that will be used for javac compiles 78 Javacflags []string `android:"arch_variant"` 79 80 // list of of java libraries that will be in the classpath 81 Libs []string `android:"arch_variant"` 82 83 // list of java libraries that will be compiled into the resulting jar 84 Static_libs []string `android:"arch_variant"` 85 86 // manifest file to be included in resulting jar 87 Manifest *string 88 89 // if not blank, run jarjar using the specified rules file 90 Jarjar_rules *string 91} 92 93type compilerDeviceProperties struct { 94 // list of module-specific flags that will be used for dex compiles 95 Dxflags []string `android:"arch_variant"` 96 97 // if not blank, set to the version of the sdk to compile against 98 Sdk_version string 99 100 // Set for device java libraries, and for host versions of device java libraries 101 // built for testing 102 Dex bool `blueprint:"mutated"` 103 104 // directories to pass to aidl tool 105 Aidl_includes []string 106 107 // directories that should be added as include directories 108 // for any aidl sources of modules that depend on this module 109 Export_aidl_include_dirs []string 110} 111 112// Module contains the properties and members used by all java module types 113type Module struct { 114 android.ModuleBase 115 116 properties compilerProperties 117 deviceProperties compilerDeviceProperties 118 119 // output file suitable for inserting into the classpath of another compile 120 classpathFile android.Path 121 122 // output file suitable for installing or running 123 outputFile android.Path 124 125 // jarSpecs suitable for inserting classes from a static library into another jar 126 classJarSpecs []jarSpec 127 128 // jarSpecs suitable for inserting resources from a static library into another jar 129 resourceJarSpecs []jarSpec 130 131 exportAidlIncludeDirs android.Paths 132 133 logtagsSrcs android.Paths 134 135 // filelists of extra source files that should be included in the javac command line, 136 // for example R.java generated by aapt for android apps 137 ExtraSrcLists android.Paths 138 139 // installed file for binary dependency 140 installFile android.Path 141} 142 143type JavaDependency interface { 144 ClasspathFile() android.Path 145 ClassJarSpecs() []jarSpec 146 ResourceJarSpecs() []jarSpec 147 AidlIncludeDirs() android.Paths 148} 149 150type dependencyTag struct { 151 blueprint.BaseDependencyTag 152 name string 153} 154 155var ( 156 javaStaticLibTag = dependencyTag{name: "staticlib"} 157 javaLibTag = dependencyTag{name: "javalib"} 158 bootClasspathTag = dependencyTag{name: "bootclasspath"} 159 frameworkResTag = dependencyTag{name: "framework-res"} 160 sdkDependencyTag = dependencyTag{name: "sdk"} 161) 162 163func (j *Module) deps(ctx android.BottomUpMutatorContext) { 164 if !j.properties.No_standard_libraries { 165 if ctx.Device() { 166 switch j.deviceProperties.Sdk_version { 167 case "": 168 ctx.AddDependency(ctx.Module(), bootClasspathTag, "core-libart") 169 case "current": 170 // TODO: !TARGET_BUILD_APPS 171 // TODO: export preprocessed framework.aidl from android_stubs_current 172 ctx.AddDependency(ctx.Module(), bootClasspathTag, "android_stubs_current") 173 case "system_current": 174 ctx.AddDependency(ctx.Module(), bootClasspathTag, "android_system_stubs_current") 175 default: 176 ctx.AddDependency(ctx.Module(), sdkDependencyTag, "sdk_v"+j.deviceProperties.Sdk_version) 177 } 178 } else { 179 if j.deviceProperties.Dex { 180 ctx.AddDependency(ctx.Module(), bootClasspathTag, "core-libart") 181 } 182 } 183 184 if ctx.Device() && j.deviceProperties.Sdk_version == "" { 185 ctx.AddDependency(ctx.Module(), javaLibTag, config.DefaultLibraries...) 186 } 187 } 188 ctx.AddDependency(ctx.Module(), javaLibTag, j.properties.Libs...) 189 ctx.AddDependency(ctx.Module(), javaStaticLibTag, j.properties.Static_libs...) 190} 191 192func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, 193 aidlIncludeDirs android.Paths) []string { 194 195 localAidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl_includes) 196 197 var flags []string 198 if aidlPreprocess.Valid() { 199 flags = append(flags, "-p"+aidlPreprocess.String()) 200 } else { 201 flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I")) 202 } 203 204 flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I")) 205 flags = append(flags, android.JoinWithPrefix(localAidlIncludes.Strings(), "-I")) 206 flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String()) 207 if src := android.ExistentPathForSource(ctx, "", "src"); src.Valid() { 208 flags = append(flags, "-I"+src.String()) 209 } 210 211 return flags 212} 213 214func (j *Module) collectDeps(ctx android.ModuleContext) (classpath android.Paths, 215 bootClasspath android.OptionalPath, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess android.OptionalPath, 216 aidlIncludeDirs android.Paths, srcFileLists android.Paths) { 217 218 ctx.VisitDirectDeps(func(module blueprint.Module) { 219 otherName := ctx.OtherModuleName(module) 220 tag := ctx.OtherModuleDependencyTag(module) 221 222 javaDep, _ := module.(JavaDependency) 223 if javaDep == nil { 224 switch tag { 225 case android.DefaultsDepTag, android.SourceDepTag: 226 default: 227 ctx.ModuleErrorf("depends on non-java module %q", otherName) 228 } 229 return 230 } 231 232 switch tag { 233 case bootClasspathTag: 234 bootClasspath = android.OptionalPathForPath(javaDep.ClasspathFile()) 235 case javaLibTag: 236 classpath = append(classpath, javaDep.ClasspathFile()) 237 case javaStaticLibTag: 238 classpath = append(classpath, javaDep.ClasspathFile()) 239 classJarSpecs = append(classJarSpecs, javaDep.ClassJarSpecs()...) 240 resourceJarSpecs = append(resourceJarSpecs, javaDep.ResourceJarSpecs()...) 241 case frameworkResTag: 242 if ctx.ModuleName() == "framework" { 243 // framework.jar has a one-off dependency on the R.java and Manifest.java files 244 // generated by framework-res.apk 245 srcFileLists = append(srcFileLists, module.(*AndroidApp).aaptJavaFileList) 246 } 247 case sdkDependencyTag: 248 sdkDep := module.(sdkDependency) 249 if sdkDep.AidlPreprocessed().Valid() { 250 if aidlPreprocess.Valid() { 251 ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q", 252 aidlPreprocess, sdkDep.AidlPreprocessed()) 253 } else { 254 aidlPreprocess = sdkDep.AidlPreprocessed() 255 } 256 } 257 default: 258 panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) 259 } 260 261 aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...) 262 }) 263 264 return classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess, 265 aidlIncludeDirs, srcFileLists 266} 267 268func (j *Module) compile(ctx android.ModuleContext) { 269 270 j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs) 271 272 classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess, 273 aidlIncludeDirs, srcFileLists := j.collectDeps(ctx) 274 275 var flags javaBuilderFlags 276 277 javacFlags := j.properties.Javacflags 278 if len(javacFlags) > 0 { 279 ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " ")) 280 flags.javacFlags = "$javacFlags" 281 } 282 283 aidlFlags := j.aidlFlags(ctx, aidlPreprocess, aidlIncludeDirs) 284 if len(aidlFlags) > 0 { 285 ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " ")) 286 flags.aidlFlags = "$aidlFlags" 287 } 288 289 var javacDeps android.Paths 290 291 if bootClasspath.Valid() { 292 flags.bootClasspath = "-bootclasspath " + bootClasspath.String() 293 javacDeps = append(javacDeps, bootClasspath.Path()) 294 } 295 296 if len(classpath) > 0 { 297 flags.classpath = "-classpath " + strings.Join(classpath.Strings(), ":") 298 javacDeps = append(javacDeps, classpath...) 299 } 300 301 srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs) 302 303 srcFiles = j.genSources(ctx, srcFiles, flags) 304 305 ctx.VisitDirectDeps(func(module blueprint.Module) { 306 if gen, ok := module.(genrule.SourceFileGenerator); ok { 307 srcFiles = append(srcFiles, gen.GeneratedSourceFiles()...) 308 } 309 }) 310 311 srcFileLists = append(srcFileLists, j.ExtraSrcLists...) 312 313 if len(srcFiles) > 0 { 314 // Compile java sources into .class files 315 classes := TransformJavaToClasses(ctx, srcFiles, srcFileLists, flags, javacDeps) 316 if ctx.Failed() { 317 return 318 } 319 320 classJarSpecs = append([]jarSpec{classes}, classJarSpecs...) 321 } 322 323 resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Resource_dirs, j.properties.Exclude_resource_dirs), 324 resourceJarSpecs...) 325 326 manifest := android.OptionalPathForModuleSrc(ctx, j.properties.Manifest) 327 328 allJarSpecs := append([]jarSpec(nil), classJarSpecs...) 329 allJarSpecs = append(allJarSpecs, resourceJarSpecs...) 330 331 // Combine classes + resources into classes-full-debug.jar 332 outputFile := TransformClassesToJar(ctx, allJarSpecs, manifest) 333 if ctx.Failed() { 334 return 335 } 336 337 if j.properties.Jarjar_rules != nil { 338 jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) 339 // Transform classes-full-debug.jar into classes-jarjar.jar 340 outputFile = TransformJarJar(ctx, outputFile, jarjar_rules) 341 if ctx.Failed() { 342 return 343 } 344 345 classes, _ := TransformPrebuiltJarToClasses(ctx, outputFile) 346 classJarSpecs = []jarSpec{classes} 347 } 348 349 j.resourceJarSpecs = resourceJarSpecs 350 j.classJarSpecs = classJarSpecs 351 j.classpathFile = outputFile 352 353 if j.deviceProperties.Dex && len(srcFiles) > 0 { 354 dxFlags := j.deviceProperties.Dxflags 355 if false /* emma enabled */ { 356 // If you instrument class files that have local variable debug information in 357 // them emma does not correctly maintain the local variable table. 358 // This will cause an error when you try to convert the class files for Android. 359 // The workaround here is to build different dex file here based on emma switch 360 // then later copy into classes.dex. When emma is on, dx is run with --no-locals 361 // option to remove local variable information 362 dxFlags = append(dxFlags, "--no-locals") 363 } 364 365 if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" { 366 dxFlags = append(dxFlags, "--no-optimize") 367 } 368 369 if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" { 370 dxFlags = append(dxFlags, 371 "--debug", 372 "--verbose", 373 "--dump-to="+android.PathForModuleOut(ctx, "classes.lst").String(), 374 "--dump-width=1000") 375 } 376 377 flags.dxFlags = strings.Join(dxFlags, " ") 378 379 // Compile classes.jar into classes.dex 380 dexJarSpec := TransformClassesJarToDex(ctx, outputFile, flags) 381 if ctx.Failed() { 382 return 383 } 384 385 // Combine classes.dex + resources into javalib.jar 386 outputFile = TransformDexToJavaLib(ctx, resourceJarSpecs, dexJarSpec) 387 } 388 ctx.CheckbuildFile(outputFile) 389 j.outputFile = outputFile 390} 391 392var _ JavaDependency = (*JavaLibrary)(nil) 393 394func (j *Module) ClasspathFile() android.Path { 395 return j.classpathFile 396} 397 398func (j *Module) ClassJarSpecs() []jarSpec { 399 return j.classJarSpecs 400} 401 402func (j *Module) ResourceJarSpecs() []jarSpec { 403 return j.resourceJarSpecs 404} 405 406func (j *Module) AidlIncludeDirs() android.Paths { 407 return j.exportAidlIncludeDirs 408} 409 410var _ logtagsProducer = (*Module)(nil) 411 412func (j *Module) logtags() android.Paths { 413 return j.logtagsSrcs 414} 415 416// 417// Java libraries (.jar file) 418// 419 420type JavaLibrary struct { 421 Module 422} 423 424func (j *JavaLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 425 j.compile(ctx) 426 427 j.installFile = ctx.InstallFileName(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile) 428} 429 430func (j *JavaLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { 431 j.deps(ctx) 432} 433 434func JavaLibraryFactory() android.Module { 435 module := &JavaLibrary{} 436 437 module.deviceProperties.Dex = true 438 439 module.AddProperties( 440 &module.Module.properties, 441 &module.Module.deviceProperties) 442 443 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 444 return module 445} 446 447func JavaLibraryHostFactory() android.Module { 448 module := &JavaLibrary{} 449 450 module.AddProperties(&module.Module.properties) 451 452 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) 453 return module 454} 455 456// 457// Java Binaries (.jar file plus wrapper script) 458// 459 460type javaBinaryProperties struct { 461 // installable script to execute the resulting jar 462 Wrapper string 463} 464 465type JavaBinary struct { 466 JavaLibrary 467 468 binaryProperties javaBinaryProperties 469} 470 471func (j *JavaBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) { 472 j.JavaLibrary.GenerateAndroidBuildActions(ctx) 473 474 // Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by 475 // another build rule before the jar has been installed. 476 ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), android.PathForModuleSrc(ctx, j.binaryProperties.Wrapper), 477 j.installFile) 478} 479 480func (j *JavaBinary) DepsMutator(ctx android.BottomUpMutatorContext) { 481 j.deps(ctx) 482} 483 484func JavaBinaryFactory() android.Module { 485 module := &JavaBinary{} 486 487 module.deviceProperties.Dex = true 488 489 module.AddProperties( 490 &module.Module.properties, 491 &module.Module.deviceProperties, 492 &module.binaryProperties) 493 494 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 495 return module 496} 497 498func JavaBinaryHostFactory() android.Module { 499 module := &JavaBinary{} 500 501 module.AddProperties( 502 &module.Module.properties, 503 &module.Module.deviceProperties, 504 &module.binaryProperties) 505 506 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) 507 return module 508} 509 510// 511// Java prebuilts 512// 513 514type JavaPrebuilt struct { 515 android.ModuleBase 516 prebuilt android.Prebuilt 517 518 classpathFile android.Path 519 classJarSpecs, resourceJarSpecs []jarSpec 520} 521 522func (j *JavaPrebuilt) Prebuilt() *android.Prebuilt { 523 return &j.prebuilt 524} 525 526func (j *JavaPrebuilt) DepsMutator(ctx android.BottomUpMutatorContext) { 527} 528 529func (j *JavaPrebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 530 prebuilt := j.prebuilt.Path(ctx) 531 532 classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt) 533 534 j.classpathFile = prebuilt 535 j.classJarSpecs = []jarSpec{classJarSpec} 536 j.resourceJarSpecs = []jarSpec{resourceJarSpec} 537 ctx.InstallFileName(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.classpathFile) 538} 539 540var _ JavaDependency = (*JavaPrebuilt)(nil) 541 542func (j *JavaPrebuilt) ClasspathFile() android.Path { 543 return j.classpathFile 544} 545 546func (j *JavaPrebuilt) ClassJarSpecs() []jarSpec { 547 return j.classJarSpecs 548} 549 550func (j *JavaPrebuilt) ResourceJarSpecs() []jarSpec { 551 return j.resourceJarSpecs 552} 553 554func (j *JavaPrebuilt) AidlIncludeDirs() android.Paths { 555 return nil 556} 557 558func JavaPrebuiltFactory() android.Module { 559 module := &JavaPrebuilt{} 560 561 module.AddProperties(&module.prebuilt.Properties) 562 563 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 564 return module 565} 566 567// 568// SDK java prebuilts (.jar containing resources plus framework.aidl) 569// 570 571type sdkDependency interface { 572 JavaDependency 573 AidlPreprocessed() android.OptionalPath 574} 575 576var _ sdkDependency = (*sdkPrebuilt)(nil) 577 578type sdkPrebuiltProperties struct { 579 Aidl_preprocessed *string 580} 581 582type sdkPrebuilt struct { 583 JavaPrebuilt 584 585 sdkProperties sdkPrebuiltProperties 586 587 aidlPreprocessed android.OptionalPath 588} 589 590func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { 591 j.JavaPrebuilt.GenerateAndroidBuildActions(ctx) 592 593 j.aidlPreprocessed = android.OptionalPathForModuleSrc(ctx, j.sdkProperties.Aidl_preprocessed) 594} 595 596func (j *sdkPrebuilt) AidlPreprocessed() android.OptionalPath { 597 return j.aidlPreprocessed 598} 599 600func SdkPrebuiltFactory() android.Module { 601 module := &sdkPrebuilt{} 602 603 module.AddProperties( 604 &module.prebuilt.Properties, 605 &module.sdkProperties) 606 607 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 608 return module 609} 610 611func inList(s string, l []string) bool { 612 for _, e := range l { 613 if e == s { 614 return true 615 } 616 } 617 return false 618} 619