1// Copyright 2021 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 17import ( 18 "fmt" 19 "path/filepath" 20 "reflect" 21 "slices" 22 "strconv" 23 "strings" 24 25 "github.com/google/blueprint" 26 "github.com/google/blueprint/pathtools" 27 "github.com/google/blueprint/proptools" 28 29 "android/soong/android" 30 "android/soong/dexpreopt" 31 "android/soong/java/config" 32) 33 34// This file contains the definition and the implementation of the base module that most 35// source-based Java module structs embed. 36 37// TODO: 38// Autogenerated files: 39// Renderscript 40// Post-jar passes: 41// Proguard 42// Rmtypedefs 43// DroidDoc 44// Findbugs 45 46// Properties that are common to most Java modules, i.e. whether it's a host or device module. 47type CommonProperties struct { 48 // list of source files used to compile the Java module. May be .java, .kt, .logtags, .proto, 49 // or .aidl files. 50 Srcs []string `android:"path,arch_variant"` 51 52 // list Kotlin of source files containing Kotlin code that should be treated as common code in 53 // a codebase that supports Kotlin multiplatform. See 54 // https://kotlinlang.org/docs/reference/multiplatform.html. May be only be .kt files. 55 Common_srcs []string `android:"path,arch_variant"` 56 57 // list of source files that should not be used to build the Java module. 58 // This is most useful in the arch/multilib variants to remove non-common files 59 Exclude_srcs []string `android:"path,arch_variant"` 60 61 // list of directories containing Java resources 62 Java_resource_dirs []string `android:"arch_variant"` 63 64 // list of directories that should be excluded from java_resource_dirs 65 Exclude_java_resource_dirs []string `android:"arch_variant"` 66 67 // list of files to use as Java resources 68 Java_resources []string `android:"path,arch_variant"` 69 70 // list of files that should be excluded from java_resources and java_resource_dirs 71 Exclude_java_resources []string `android:"path,arch_variant"` 72 73 // list of module-specific flags that will be used for javac compiles 74 Javacflags []string `android:"arch_variant"` 75 76 // list of module-specific flags that will be used for kotlinc compiles 77 Kotlincflags []string `android:"arch_variant"` 78 79 // list of java libraries that will be in the classpath 80 Libs []string `android:"arch_variant"` 81 82 // list of java libraries that will be compiled into the resulting jar 83 Static_libs []string `android:"arch_variant"` 84 85 // list of java libraries that should not be used to build this module 86 Exclude_static_libs []string `android:"arch_variant"` 87 88 // manifest file to be included in resulting jar 89 Manifest *string `android:"path"` 90 91 // if not blank, run jarjar using the specified rules file 92 Jarjar_rules *string `android:"path,arch_variant"` 93 94 // if not blank, used as prefix to generate repackage rule 95 Jarjar_prefix *string 96 97 // If not blank, set the java version passed to javac as -source and -target 98 Java_version *string 99 100 // If set to true, allow this module to be dexed and installed on devices. Has no 101 // effect on host modules, which are always considered installable. 102 Installable *bool 103 104 // If set to true, include sources used to compile the module in to the final jar 105 Include_srcs *bool 106 107 // If not empty, classes are restricted to the specified packages and their sub-packages. 108 // This restriction is checked after applying jarjar rules and including static libs. 109 Permitted_packages []string 110 111 // List of modules to use as annotation processors 112 Plugins []string 113 114 // List of modules to export to libraries that directly depend on this library as annotation 115 // processors. Note that if the plugins set generates_api: true this will disable the turbine 116 // optimization on modules that depend on this module, which will reduce parallelism and cause 117 // more recompilation. 118 Exported_plugins []string 119 120 // The number of Java source entries each Javac instance can process 121 Javac_shard_size *int64 122 123 // Add host jdk tools.jar to bootclasspath 124 Use_tools_jar *bool 125 126 Openjdk9 struct { 127 // List of source files that should only be used when passing -source 1.9 or higher 128 Srcs []string `android:"path"` 129 130 // List of javac flags that should only be used when passing -source 1.9 or higher 131 Javacflags []string 132 } 133 134 // When compiling language level 9+ .java code in packages that are part of 135 // a system module, patch_module names the module that your sources and 136 // dependencies should be patched into. The Android runtime currently 137 // doesn't implement the JEP 261 module system so this option is only 138 // supported at compile time. It should only be needed to compile tests in 139 // packages that exist in libcore and which are inconvenient to move 140 // elsewhere. 141 Patch_module *string 142 143 Jacoco struct { 144 // List of classes to include for instrumentation with jacoco to collect coverage 145 // information at runtime when building with coverage enabled. If unset defaults to all 146 // classes. 147 // Supports '*' as the last character of an entry in the list as a wildcard match. 148 // If preceded by '.' it matches all classes in the package and subpackages, otherwise 149 // it matches classes in the package that have the class name as a prefix. 150 Include_filter []string 151 152 // List of classes to exclude from instrumentation with jacoco to collect coverage 153 // information at runtime when building with coverage enabled. Overrides classes selected 154 // by the include_filter property. 155 // Supports '*' as the last character of an entry in the list as a wildcard match. 156 // If preceded by '.' it matches all classes in the package and subpackages, otherwise 157 // it matches classes in the package that have the class name as a prefix. 158 Exclude_filter []string 159 } 160 161 Errorprone struct { 162 // List of javac flags that should only be used when running errorprone. 163 Javacflags []string 164 165 // List of java_plugin modules that provide extra errorprone checks. 166 Extra_check_modules []string 167 168 // This property can be in 3 states. When set to true, errorprone will 169 // be run during the regular build. When set to false, errorprone will 170 // never be run. When unset, errorprone will be run when the RUN_ERROR_PRONE 171 // environment variable is true. Setting this to false will improve build 172 // performance more than adding -XepDisableAllChecks in javacflags. 173 Enabled *bool 174 } 175 176 Proto struct { 177 // List of extra options that will be passed to the proto generator. 178 Output_params []string 179 } 180 181 // If true, then jacocoagent is automatically added as a libs dependency so that 182 // r8 will not strip instrumentation classes out of dexed libraries. 183 Instrument bool `blueprint:"mutated"` 184 // If true, then the module supports statically including the jacocoagent 185 // into the library. 186 Supports_static_instrumentation bool `blueprint:"mutated"` 187 188 // List of files to include in the META-INF/services folder of the resulting jar. 189 Services []string `android:"path,arch_variant"` 190 191 // If true, package the kotlin stdlib into the jar. Defaults to true. 192 Static_kotlin_stdlib *bool `android:"arch_variant"` 193 194 // A list of java_library instances that provide additional hiddenapi annotations for the library. 195 Hiddenapi_additional_annotations []string 196 197 // Additional srcJars tacked in by GeneratedJavaLibraryModule 198 Generated_srcjars []android.Path `android:"mutated"` 199 200 // intermediate aconfig cache file tacked in by GeneratedJavaLibraryModule 201 Aconfig_Cache_files []android.Path `android:"mutated"` 202 203 // If true, then only the headers are built and not the implementation jar. 204 Headers_only *bool 205 206 // A list of files or dependencies to make available to the build sandbox. This is 207 // useful if source files are symlinks, the targets of the symlinks must be listed here. 208 // Note that currently not all actions implemented by android_apps are sandboxed, so you 209 // may only see this being necessary in lint builds. 210 Compile_data []string `android:"path"` 211 212 // Property signifying whether the module compiles stubs or not. 213 // Should be set to true when srcs of this module are stub files. 214 // This property does not need to be set to true when the module depends on 215 // the stubs via libs, but should be set to true when the module depends on 216 // the stubs via static libs. 217 Is_stubs_module *bool 218} 219 220// Properties that are specific to device modules. Host module factories should not add these when 221// constructing a new module. 222type DeviceProperties struct { 223 // If not blank, set to the version of the sdk to compile against. 224 // Defaults to an empty string, which compiles the module against the private platform APIs. 225 // Values are of one of the following forms: 226 // 1) numerical API level, "current", "none", or "core_platform" 227 // 2) An SDK kind with an API level: "<sdk kind>_<API level>" 228 // See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds. 229 // If the SDK kind is empty, it will be set to public. 230 Sdk_version *string 231 232 // if not blank, set the maximum version of the sdk that the compiled artifacts will run against. 233 // Defaults to empty string "". See sdk_version for possible values. 234 Max_sdk_version *string 235 236 // if not blank, set the maxSdkVersion properties of permission and uses-permission tags. 237 // Defaults to empty string "". See sdk_version for possible values. 238 Replace_max_sdk_version_placeholder *string 239 240 // if not blank, set the targetSdkVersion in the AndroidManifest.xml. 241 // Defaults to sdk_version if not set. See sdk_version for possible values. 242 Target_sdk_version *string 243 244 // Whether to compile against the platform APIs instead of an SDK. 245 // If true, then sdk_version must be empty. The value of this field 246 // is ignored when module's type isn't android_app, android_test, or android_test_helper_app. 247 Platform_apis *bool 248 249 Aidl struct { 250 // Top level directories to pass to aidl tool 251 Include_dirs []string 252 253 // Directories rooted at the Android.bp file to pass to aidl tool 254 Local_include_dirs []string 255 256 // directories that should be added as include directories for any aidl sources of modules 257 // that depend on this module, as well as to aidl for this module. 258 Export_include_dirs []string 259 260 // whether to generate traces (for systrace) for this interface 261 Generate_traces *bool 262 263 // whether to generate Binder#GetTransaction name method. 264 Generate_get_transaction_name *bool 265 266 // whether all interfaces should be annotated with required permissions. 267 Enforce_permissions *bool 268 269 // allowlist for interfaces that (temporarily) do not require annotation for permissions. 270 Enforce_permissions_exceptions []string `android:"path"` 271 272 // list of flags that will be passed to the AIDL compiler 273 Flags []string 274 } 275 276 // If true, export a copy of the module as a -hostdex module for host testing. 277 Hostdex *bool 278 279 Target struct { 280 Hostdex struct { 281 // Additional required dependencies to add to -hostdex modules. 282 Required []string 283 } 284 } 285 286 // When targeting 1.9 and above, override the modules to use with --system, 287 // otherwise provides defaults libraries to add to the bootclasspath. 288 System_modules *string 289 290 IsSDKLibrary bool `blueprint:"mutated"` 291 292 // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file. 293 // Defaults to false. 294 V4_signature *bool 295 296 // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the 297 // public stubs library. 298 SyspropPublicStub string `blueprint:"mutated"` 299 300 HiddenAPIPackageProperties 301 HiddenAPIFlagFileProperties 302} 303 304// Properties that can be overridden by overriding module (e.g. override_android_app) 305type OverridableProperties struct { 306 // set the name of the output. If not set, `name` is used. 307 // To override a module with this property set, overriding module might need to set this as well. 308 // Otherwise, both the overridden and the overriding modules will have the same output name, which 309 // can cause the duplicate output error. 310 Stem *string 311 312 // if not blank, set the minimum version of the sdk that the compiled artifacts will run against. 313 // Defaults to sdk_version if not set. See sdk_version for possible values. 314 Min_sdk_version *string 315} 316 317// Functionality common to Module and Import 318// 319// It is embedded in Module so its functionality can be used by methods in Module 320// but it is currently only initialized by Import and Library. 321type embeddableInModuleAndImport struct { 322 323 // Functionality related to this being used as a component of a java_sdk_library. 324 EmbeddableSdkLibraryComponent 325} 326 327func (e *embeddableInModuleAndImport) initModuleAndImport(module android.Module) { 328 e.initSdkLibraryComponent(module) 329} 330 331// Module/Import's DepIsInSameApex(...) delegates to this method. 332// 333// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with 334// the one provided by ApexModuleBase. 335func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 336 // dependencies other than the static linkage are all considered crossing APEX boundary 337 if staticLibTag == ctx.OtherModuleDependencyTag(dep) { 338 return true 339 } 340 return false 341} 342 343// OptionalDexJarPath can be either unset, hold a valid path to a dex jar file, 344// or an invalid path describing the reason it is invalid. 345// 346// It is unset if a dex jar isn't applicable, i.e. no build rule has been 347// requested to create one. 348// 349// If a dex jar has been requested to be built then it is set, and it may be 350// either a valid android.Path, or invalid with a reason message. The latter 351// happens if the source that should produce the dex file isn't able to. 352// 353// E.g. it is invalid with a reason message if there is a prebuilt APEX that 354// could produce the dex jar through a deapexer module, but the APEX isn't 355// installable so doing so wouldn't be safe. 356type OptionalDexJarPath struct { 357 isSet bool 358 path android.OptionalPath 359} 360 361// IsSet returns true if a path has been set, either invalid or valid. 362func (o OptionalDexJarPath) IsSet() bool { 363 return o.isSet 364} 365 366// Valid returns true if there is a path that is valid. 367func (o OptionalDexJarPath) Valid() bool { 368 return o.isSet && o.path.Valid() 369} 370 371// Path returns the valid path, or panics if it's either not set or is invalid. 372func (o OptionalDexJarPath) Path() android.Path { 373 if !o.isSet { 374 panic("path isn't set") 375 } 376 return o.path.Path() 377} 378 379// PathOrNil returns the path if it's set and valid, or else nil. 380func (o OptionalDexJarPath) PathOrNil() android.Path { 381 if o.Valid() { 382 return o.Path() 383 } 384 return nil 385} 386 387// InvalidReason returns the reason for an invalid path, which is never "". It 388// returns "" for an unset or valid path. 389func (o OptionalDexJarPath) InvalidReason() string { 390 if !o.isSet { 391 return "" 392 } 393 return o.path.InvalidReason() 394} 395 396func (o OptionalDexJarPath) String() string { 397 if !o.isSet { 398 return "<unset>" 399 } 400 return o.path.String() 401} 402 403// makeUnsetDexJarPath returns an unset OptionalDexJarPath. 404func makeUnsetDexJarPath() OptionalDexJarPath { 405 return OptionalDexJarPath{isSet: false} 406} 407 408// makeDexJarPathFromOptionalPath returns an OptionalDexJarPath that is set with 409// the given OptionalPath, which may be valid or invalid. 410func makeDexJarPathFromOptionalPath(path android.OptionalPath) OptionalDexJarPath { 411 return OptionalDexJarPath{isSet: true, path: path} 412} 413 414// makeDexJarPathFromPath returns an OptionalDexJarPath that is set with the 415// valid given path. It returns an unset OptionalDexJarPath if the given path is 416// nil. 417func makeDexJarPathFromPath(path android.Path) OptionalDexJarPath { 418 if path == nil { 419 return makeUnsetDexJarPath() 420 } 421 return makeDexJarPathFromOptionalPath(android.OptionalPathForPath(path)) 422} 423 424// Module contains the properties and members used by all java module types 425type Module struct { 426 android.ModuleBase 427 android.DefaultableModuleBase 428 android.ApexModuleBase 429 430 // Functionality common to Module and Import. 431 embeddableInModuleAndImport 432 433 properties CommonProperties 434 protoProperties android.ProtoProperties 435 deviceProperties DeviceProperties 436 437 overridableProperties OverridableProperties 438 sourceProperties android.SourceProperties 439 440 // jar file containing header classes including static library dependencies, suitable for 441 // inserting into the bootclasspath/classpath of another compile 442 headerJarFile android.Path 443 444 repackagedHeaderJarFile android.Path 445 446 // jar file containing implementation classes including static library dependencies but no 447 // resources 448 implementationJarFile android.Path 449 450 // jar file containing only resources including from static library dependencies 451 resourceJar android.Path 452 453 // args and dependencies to package source files into a srcjar 454 srcJarArgs []string 455 srcJarDeps android.Paths 456 457 // the source files of this module and all its static dependencies 458 transitiveSrcFiles *android.DepSet[android.Path] 459 460 // jar file containing implementation classes and resources including static library 461 // dependencies 462 implementationAndResourcesJar android.Path 463 464 // output file containing classes.dex and resources 465 dexJarFile OptionalDexJarPath 466 467 // output file containing uninstrumented classes that will be instrumented by jacoco 468 jacocoReportClassesFile android.Path 469 470 // output file of the module, which may be a classes jar or a dex jar 471 outputFile android.Path 472 extraOutputFiles android.Paths 473 474 exportAidlIncludeDirs android.Paths 475 ignoredAidlPermissionList android.Paths 476 477 logtagsSrcs android.Paths 478 479 // installed file for binary dependency 480 installFile android.Path 481 482 // installed file for hostdex copy 483 hostdexInstallFile android.InstallPath 484 485 // list of unique .java and .kt source files 486 uniqueSrcFiles android.Paths 487 488 // list of srcjars that was passed to javac 489 compiledSrcJars android.Paths 490 491 // manifest file to use instead of properties.Manifest 492 overrideManifest android.OptionalPath 493 494 // list of plugins that this java module is exporting 495 exportedPluginJars android.Paths 496 497 // list of plugins that this java module is exporting 498 exportedPluginClasses []string 499 500 // if true, the exported plugins generate API and require disabling turbine. 501 exportedDisableTurbine bool 502 503 // list of source files, collected from srcFiles with unique java and all kt files, 504 // will be used by android.IDEInfo struct 505 expandIDEInfoCompiledSrcs []string 506 507 // expanded Jarjar_rules 508 expandJarjarRules android.Path 509 510 // jarjar rule for inherited jarjar rules 511 repackageJarjarRules android.Path 512 513 // Extra files generated by the module type to be added as java resources. 514 extraResources android.Paths 515 516 hiddenAPI 517 dexer 518 dexpreopter 519 usesLibrary 520 linter 521 522 // list of the xref extraction files 523 kytheFiles android.Paths 524 525 hideApexVariantFromMake bool 526 527 sdkVersion android.SdkSpec 528 minSdkVersion android.ApiLevel 529 maxSdkVersion android.ApiLevel 530 531 sourceExtensions []string 532 533 annoSrcJars android.Paths 534 535 // output file name based on Stem property. 536 // This should be set in every ModuleWithStem's GenerateAndroidBuildActions 537 // or the module should override Stem(). 538 stem string 539 540 // Values that will be set in the JarJarProvider data for jarjar repackaging, 541 // and merged with our dependencies' rules. 542 jarjarRenameRules map[string]string 543 544 stubsLinkType StubsLinkType 545 546 // Paths to the aconfig intermediate cache files that are provided by the 547 // java_aconfig_library or java_library modules that are statically linked 548 // to this module. Does not contain cache files from all transitive dependencies. 549 aconfigCacheFiles android.Paths 550} 551 552func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { 553 sdkVersion := j.SdkVersion(ctx) 554 if sdkVersion.Stable() { 555 return nil 556 } 557 if sdkVersion.Kind == android.SdkCorePlatform { 558 if useLegacyCorePlatformApi(ctx, j.BaseModuleName()) { 559 return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion) 560 } else { 561 // Treat stable core platform as stable. 562 return nil 563 } 564 } else { 565 return fmt.Errorf("non stable SDK %v", sdkVersion) 566 } 567} 568 569// checkSdkVersions enforces restrictions around SDK dependencies. 570func (j *Module) checkSdkVersions(ctx android.ModuleContext) { 571 if j.RequiresStableAPIs(ctx) { 572 if sc, ok := ctx.Module().(android.SdkContext); ok { 573 if !sc.SdkVersion(ctx).Specified() { 574 ctx.PropertyErrorf("sdk_version", 575 "sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).") 576 } 577 } 578 } 579 580 // Make sure this module doesn't statically link to modules with lower-ranked SDK link type. 581 // See rank() for details. 582 ctx.VisitDirectDeps(func(module android.Module) { 583 tag := ctx.OtherModuleDependencyTag(module) 584 switch module.(type) { 585 // TODO(satayev): cover other types as well, e.g. imports 586 case *Library, *AndroidLibrary: 587 switch tag { 588 case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag: 589 j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag)) 590 } 591 } 592 }) 593} 594 595func (j *Module) checkPlatformAPI(ctx android.ModuleContext) { 596 if sc, ok := ctx.Module().(android.SdkContext); ok { 597 usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis) 598 sdkVersionSpecified := sc.SdkVersion(ctx).Specified() 599 if usePlatformAPI && sdkVersionSpecified { 600 ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.") 601 } else if !usePlatformAPI && !sdkVersionSpecified { 602 ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true") 603 } 604 605 } 606} 607 608func (j *Module) checkHeadersOnly(ctx android.ModuleContext) { 609 if _, ok := ctx.Module().(android.SdkContext); ok { 610 headersOnly := proptools.Bool(j.properties.Headers_only) 611 installable := proptools.Bool(j.properties.Installable) 612 613 if headersOnly && installable { 614 ctx.PropertyErrorf("headers_only", "This module has conflicting settings. headers_only is true which, which means this module doesn't generate an implementation jar. However installable is set to true.") 615 } 616 } 617} 618 619func (j *Module) addHostProperties() { 620 j.AddProperties( 621 &j.properties, 622 &j.overridableProperties, 623 &j.protoProperties, 624 &j.usesLibraryProperties, 625 ) 626} 627 628func (j *Module) addHostAndDeviceProperties() { 629 j.addHostProperties() 630 j.AddProperties( 631 &j.deviceProperties, 632 &j.dexer.dexProperties, 633 &j.dexpreoptProperties, 634 &j.linter.properties, 635 ) 636} 637 638// provideHiddenAPIPropertyInfo populates a HiddenAPIPropertyInfo from hidden API properties and 639// makes it available through the hiddenAPIPropertyInfoProvider. 640func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) { 641 hiddenAPIInfo := newHiddenAPIPropertyInfo() 642 643 // Populate with flag file paths from the properties. 644 hiddenAPIInfo.extractFlagFilesFromProperties(ctx, &j.deviceProperties.HiddenAPIFlagFileProperties) 645 646 // Populate with package rules from the properties. 647 hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties) 648 649 android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo) 650} 651 652func (j *Module) OutputFiles(tag string) (android.Paths, error) { 653 switch tag { 654 case "": 655 return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil 656 case android.DefaultDistTag: 657 return android.Paths{j.outputFile}, nil 658 case ".jar": 659 return android.Paths{j.implementationAndResourcesJar}, nil 660 case ".hjar": 661 return android.Paths{j.headerJarFile}, nil 662 case ".proguard_map": 663 if j.dexer.proguardDictionary.Valid() { 664 return android.Paths{j.dexer.proguardDictionary.Path()}, nil 665 } 666 return nil, fmt.Errorf("%q was requested, but no output file was found.", tag) 667 case ".generated_srcjars": 668 return j.properties.Generated_srcjars, nil 669 case ".lint": 670 if j.linter.outputs.xml != nil { 671 return android.Paths{j.linter.outputs.xml}, nil 672 } 673 return nil, fmt.Errorf("%q was requested, but no output file was found.", tag) 674 default: 675 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 676 } 677} 678 679var _ android.OutputFileProducer = (*Module)(nil) 680 681func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) { 682 initJavaModule(module, hod, false) 683} 684 685func InitJavaModuleMultiTargets(module android.DefaultableModule, hod android.HostOrDeviceSupported) { 686 initJavaModule(module, hod, true) 687} 688 689func initJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported, multiTargets bool) { 690 multilib := android.MultilibCommon 691 if multiTargets { 692 android.InitAndroidMultiTargetsArchModule(module, hod, multilib) 693 } else { 694 android.InitAndroidArchModule(module, hod, multilib) 695 } 696 android.InitDefaultableModule(module) 697} 698 699func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool { 700 return j.properties.Instrument && 701 ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") && 702 ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir()) 703} 704 705func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool { 706 return j.properties.Supports_static_instrumentation && 707 j.shouldInstrument(ctx) && 708 (ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_STATIC") || 709 ctx.Config().UnbundledBuild()) 710} 711 712func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { 713 // Force enable the instrumentation for java code that is built for APEXes ... 714 // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent 715 // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true. 716 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 717 isJacocoAgent := ctx.ModuleName() == "jacocoagent" 718 719 if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() { 720 if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) { 721 return true 722 } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { 723 return true 724 } 725 } 726 return false 727} 728 729func (j *Module) setInstrument(value bool) { 730 j.properties.Instrument = value 731} 732 733func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { 734 return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version)) 735} 736 737func (j *Module) SystemModules() string { 738 return proptools.String(j.deviceProperties.System_modules) 739} 740 741func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 742 if j.overridableProperties.Min_sdk_version != nil { 743 return android.ApiLevelFrom(ctx, *j.overridableProperties.Min_sdk_version) 744 } 745 return j.SdkVersion(ctx).ApiLevel 746} 747 748func (j *Module) GetDeviceProperties() *DeviceProperties { 749 return &j.deviceProperties 750} 751 752func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 753 if j.deviceProperties.Max_sdk_version != nil { 754 return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version) 755 } 756 // Default is PrivateApiLevel 757 return android.SdkSpecPrivate.ApiLevel 758} 759 760func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel { 761 if j.deviceProperties.Replace_max_sdk_version_placeholder != nil { 762 return android.ApiLevelFrom(ctx, *j.deviceProperties.Replace_max_sdk_version_placeholder) 763 } 764 // Default is PrivateApiLevel 765 return android.SdkSpecPrivate.ApiLevel 766} 767 768func (j *Module) MinSdkVersionString() string { 769 return j.minSdkVersion.String() 770} 771 772func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel { 773 if j.deviceProperties.Target_sdk_version != nil { 774 return android.ApiLevelFrom(ctx, *j.deviceProperties.Target_sdk_version) 775 } 776 return j.SdkVersion(ctx).ApiLevel 777} 778 779func (j *Module) AvailableFor(what string) bool { 780 if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) { 781 // Exception: for hostdex: true libraries, the platform variant is created 782 // even if it's not marked as available to platform. In that case, the platform 783 // variant is used only for the hostdex and not installed to the device. 784 return true 785 } 786 return j.ApexModuleBase.AvailableFor(what) 787} 788 789func (j *Module) deps(ctx android.BottomUpMutatorContext) { 790 if ctx.Device() { 791 j.linter.deps(ctx) 792 793 sdkDeps(ctx, android.SdkContext(j), j.dexer) 794 795 if j.deviceProperties.SyspropPublicStub != "" { 796 // This is a sysprop implementation library that has a corresponding sysprop public 797 // stubs library, and a dependency on it so that dependencies on the implementation can 798 // be forwarded to the public stubs library when necessary. 799 ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub) 800 } 801 } 802 803 libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) 804 805 j.properties.Static_libs = android.RemoveListFromList(j.properties.Static_libs, j.properties.Exclude_static_libs) 806 ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...) 807 808 // Add dependency on libraries that provide additional hidden api annotations. 809 ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...) 810 811 if ctx.Config().EnforceInterPartitionJavaSdkLibrary() { 812 // Require java_sdk_library at inter-partition java dependency to ensure stable 813 // interface between partitions. If inter-partition java_library dependency is detected, 814 // raise build error because java_library doesn't have a stable interface. 815 // 816 // Inputs: 817 // PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY 818 // if true, enable enforcement 819 // PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST 820 // exception list of java_library names to allow inter-partition dependency 821 for idx := range j.properties.Libs { 822 if libDeps[idx] == nil { 823 continue 824 } 825 826 if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok { 827 // java_sdk_library is always allowed at inter-partition dependency. 828 // So, skip check. 829 if _, ok := javaDep.(*SdkLibrary); ok { 830 continue 831 } 832 833 j.checkPartitionsForJavaDependency(ctx, "libs", javaDep) 834 } 835 } 836 } 837 838 // For library dependencies that are component libraries (like stubs), add the implementation 839 // as a dependency (dexpreopt needs to be against the implementation library, not stubs). 840 for _, dep := range libDeps { 841 if dep != nil { 842 if component, ok := dep.(SdkLibraryComponentDependency); ok { 843 if lib := component.OptionalSdkLibraryImplementation(); lib != nil { 844 // Add library as optional if it's one of the optional compatibility libs or it's 845 // explicitly listed in the optional_uses_libs property. 846 tag := usesLibReqTag 847 if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) || 848 android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) { 849 tag = usesLibOptTag 850 } 851 ctx.AddVariationDependencies(nil, tag, *lib) 852 } 853 } 854 } 855 } 856 857 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...) 858 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...) 859 ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...) 860 861 android.ProtoDeps(ctx, &j.protoProperties) 862 if j.hasSrcExt(".proto") { 863 protoDeps(ctx, &j.protoProperties) 864 } 865 866 if j.hasSrcExt(".kt") { 867 // TODO(ccross): move this to a mutator pass that can tell if generated sources contain 868 // Kotlin files 869 ctx.AddVariationDependencies(nil, kotlinStdlibTag, 870 "kotlin-stdlib", "kotlin-stdlib-jdk7", "kotlin-stdlib-jdk8") 871 ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations") 872 } 873 874 // Framework libraries need special handling in static coverage builds: they should not have 875 // static dependency on jacoco, otherwise there would be multiple conflicting definitions of 876 // the same jacoco classes coming from different bootclasspath jars. 877 if inList(ctx.ModuleName(), config.InstrumentFrameworkModules) { 878 if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") { 879 j.properties.Instrument = true 880 } 881 } else if j.shouldInstrumentStatic(ctx) { 882 ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent") 883 } 884 885 if j.useCompose() { 886 ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, 887 "androidx.compose.compiler_compiler-hosted") 888 } 889} 890 891func hasSrcExt(srcs []string, ext string) bool { 892 for _, src := range srcs { 893 if filepath.Ext(src) == ext { 894 return true 895 } 896 } 897 898 return false 899} 900 901func (j *Module) hasSrcExt(ext string) bool { 902 return hasSrcExt(j.properties.Srcs, ext) 903} 904 905func (j *Module) individualAidlFlags(ctx android.ModuleContext, aidlFile android.Path) string { 906 var flags string 907 908 if Bool(j.deviceProperties.Aidl.Enforce_permissions) { 909 if !android.InList(aidlFile.String(), j.ignoredAidlPermissionList.Strings()) { 910 flags = "-Wmissing-permission-annotation -Werror" 911 } 912 } 913 return flags 914} 915 916func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, 917 aidlIncludeDirs android.Paths, aidlSrcs android.Paths) (string, android.Paths) { 918 919 aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs) 920 aidlIncludes = append(aidlIncludes, 921 android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)...) 922 aidlIncludes = append(aidlIncludes, 923 android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...) 924 925 var flags []string 926 var deps android.Paths 927 var includeDirs android.Paths 928 929 flags = append(flags, j.deviceProperties.Aidl.Flags...) 930 931 if aidlPreprocess.Valid() { 932 flags = append(flags, "-p"+aidlPreprocess.String()) 933 deps = append(deps, aidlPreprocess.Path()) 934 } else if len(aidlIncludeDirs) > 0 { 935 includeDirs = append(includeDirs, aidlIncludeDirs...) 936 } 937 938 if len(j.exportAidlIncludeDirs) > 0 { 939 includeDirs = append(includeDirs, j.exportAidlIncludeDirs...) 940 } 941 942 if len(aidlIncludes) > 0 { 943 includeDirs = append(includeDirs, aidlIncludes...) 944 } 945 946 includeDirs = append(includeDirs, android.PathForModuleSrc(ctx)) 947 if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() { 948 includeDirs = append(includeDirs, src.Path()) 949 } 950 flags = append(flags, android.JoinWithPrefix(includeDirs.Strings(), "-I")) 951 // add flags for dirs containing AIDL srcs that haven't been specified yet 952 flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs)) 953 954 sdkVersion := (j.SdkVersion(ctx)).Kind 955 defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform) || (sdkVersion == android.SdkModule) || (sdkVersion == android.SdkSystem)) 956 if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) { 957 flags = append(flags, "-t") 958 } 959 960 if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) { 961 flags = append(flags, "--transaction_names") 962 } 963 964 if Bool(j.deviceProperties.Aidl.Enforce_permissions) { 965 exceptions := j.deviceProperties.Aidl.Enforce_permissions_exceptions 966 j.ignoredAidlPermissionList = android.PathsForModuleSrcExcludes(ctx, exceptions, nil) 967 } 968 969 aidlMinSdkVersion := j.MinSdkVersion(ctx).String() 970 flags = append(flags, "--min_sdk_version="+aidlMinSdkVersion) 971 972 return strings.Join(flags, " "), deps 973} 974 975func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags { 976 977 var flags javaBuilderFlags 978 979 // javaVersion flag. 980 flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j)) 981 982 epEnabled := j.properties.Errorprone.Enabled 983 if (ctx.Config().RunErrorProne() && epEnabled == nil) || Bool(epEnabled) { 984 if config.ErrorProneClasspath == nil && !ctx.Config().RunningInsideUnitTest() { 985 ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?") 986 } 987 988 errorProneFlags := []string{ 989 "-Xplugin:ErrorProne", 990 "${config.ErrorProneChecks}", 991 } 992 errorProneFlags = append(errorProneFlags, j.properties.Errorprone.Javacflags...) 993 994 flags.errorProneExtraJavacFlags = "${config.ErrorProneHeapFlags} ${config.ErrorProneFlags} " + 995 "'" + strings.Join(errorProneFlags, " ") + "'" 996 flags.errorProneProcessorPath = classpath(android.PathsForSource(ctx, config.ErrorProneClasspath)) 997 } 998 999 // classpath 1000 flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...) 1001 flags.classpath = append(flags.classpath, deps.classpath...) 1002 flags.dexClasspath = append(flags.dexClasspath, deps.dexClasspath...) 1003 flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...) 1004 flags.processorPath = append(flags.processorPath, deps.processorPath...) 1005 flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...) 1006 1007 flags.processors = append(flags.processors, deps.processorClasses...) 1008 flags.processors = android.FirstUniqueStrings(flags.processors) 1009 1010 if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() && 1011 decodeSdkDep(ctx, android.SdkContext(j)).hasStandardLibs() { 1012 // Give host-side tools a version of OpenJDK's standard libraries 1013 // close to what they're targeting. As of Dec 2017, AOSP is only 1014 // bundling OpenJDK 8 and 9, so nothing < 8 is available. 1015 // 1016 // When building with OpenJDK 8, the following should have no 1017 // effect since those jars would be available by default. 1018 // 1019 // When building with OpenJDK 9 but targeting a version < 1.8, 1020 // putting them on the bootclasspath means that: 1021 // a) code can't (accidentally) refer to OpenJDK 9 specific APIs 1022 // b) references to existing APIs are not reinterpreted in an 1023 // OpenJDK 9-specific way, eg. calls to subclasses of 1024 // java.nio.Buffer as in http://b/70862583 1025 java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME") 1026 flags.bootClasspath = append(flags.bootClasspath, 1027 android.PathForSource(ctx, java8Home, "jre/lib/jce.jar"), 1028 android.PathForSource(ctx, java8Home, "jre/lib/rt.jar")) 1029 if Bool(j.properties.Use_tools_jar) { 1030 flags.bootClasspath = append(flags.bootClasspath, 1031 android.PathForSource(ctx, java8Home, "lib/tools.jar")) 1032 } 1033 } 1034 1035 // systemModules 1036 flags.systemModules = deps.systemModules 1037 1038 return flags 1039} 1040 1041func (j *Module) collectJavacFlags( 1042 ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags { 1043 // javac flags. 1044 javacFlags := j.properties.Javacflags 1045 var needsDebugInfo bool 1046 1047 needsDebugInfo = false 1048 for _, flag := range javacFlags { 1049 if strings.HasPrefix(flag, "-g") { 1050 needsDebugInfo = true 1051 } 1052 } 1053 1054 if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() && !needsDebugInfo { 1055 // For non-host binaries, override the -g flag passed globally to remove 1056 // local variable debug info to reduce disk and memory usage. 1057 javacFlags = append(javacFlags, "-g:source,lines") 1058 } 1059 javacFlags = append(javacFlags, "-Xlint:-dep-ann") 1060 1061 if flags.javaVersion.usesJavaModules() { 1062 javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...) 1063 } else if len(j.properties.Openjdk9.Javacflags) > 0 { 1064 // java version defaults higher than openjdk 9, these conditionals should no longer be necessary 1065 ctx.PropertyErrorf("openjdk9.javacflags", "JDK version defaults to higher than 9") 1066 } 1067 1068 if flags.javaVersion.usesJavaModules() { 1069 if j.properties.Patch_module != nil { 1070 // Manually specify build directory in case it is not under the repo root. 1071 // (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so 1072 // just adding a symlink under the root doesn't help.) 1073 patchPaths := []string{".", ctx.Config().SoongOutDir()} 1074 1075 classPath := flags.classpath.FormJavaClassPath("") 1076 if classPath != "" { 1077 patchPaths = append(patchPaths, classPath) 1078 } 1079 javacFlags = append( 1080 javacFlags, 1081 "--patch-module="+String(j.properties.Patch_module)+"="+strings.Join(patchPaths, ":")) 1082 } 1083 } 1084 1085 if len(javacFlags) > 0 { 1086 // optimization. 1087 ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " ")) 1088 flags.javacFlags = "$javacFlags" 1089 } 1090 1091 return flags 1092} 1093 1094func (j *Module) AddJSONData(d *map[string]interface{}) { 1095 (&j.ModuleBase).AddJSONData(d) 1096 (*d)["Java"] = map[string]interface{}{ 1097 "SourceExtensions": j.sourceExtensions, 1098 } 1099 1100} 1101 1102func (j *Module) addGeneratedSrcJars(path android.Path) { 1103 j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path) 1104} 1105 1106func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) { 1107 1108 // Auto-propagating jarjar rules 1109 jarjarProviderData := j.collectJarJarRules(ctx) 1110 if jarjarProviderData != nil { 1111 android.SetProvider(ctx, JarJarProvider, *jarjarProviderData) 1112 text := getJarJarRuleText(jarjarProviderData) 1113 if text != "" { 1114 ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt") 1115 android.WriteFileRule(ctx, ruleTextFile, text) 1116 j.repackageJarjarRules = ruleTextFile 1117 } 1118 } 1119 1120 j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs) 1121 1122 deps := j.collectDeps(ctx) 1123 flags := j.collectBuilderFlags(ctx, deps) 1124 1125 if flags.javaVersion.usesJavaModules() { 1126 j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...) 1127 } else if len(j.properties.Openjdk9.Javacflags) > 0 { 1128 // java version defaults higher than openjdk 9, these conditionals should no longer be necessary 1129 ctx.PropertyErrorf("openjdk9.srcs", "JDK version defaults to higher than 9") 1130 } 1131 1132 srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) 1133 j.sourceExtensions = []string{} 1134 for _, ext := range []string{".kt", ".proto", ".aidl", ".java", ".logtags"} { 1135 if hasSrcExt(srcFiles.Strings(), ext) { 1136 j.sourceExtensions = append(j.sourceExtensions, ext) 1137 } 1138 } 1139 if hasSrcExt(srcFiles.Strings(), ".proto") { 1140 flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags) 1141 } 1142 1143 kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil) 1144 if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 { 1145 ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files") 1146 } 1147 1148 aidlSrcs := srcFiles.FilterByExt(".aidl") 1149 flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs, aidlSrcs) 1150 1151 nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar") 1152 srcFiles = j.genSources(ctx, srcFiles, flags) 1153 1154 // Collect javac flags only after computing the full set of srcFiles to 1155 // ensure that the --patch-module lookup paths are complete. 1156 flags = j.collectJavacFlags(ctx, flags, srcFiles) 1157 1158 srcJars := srcFiles.FilterByExt(".srcjar") 1159 srcJars = append(srcJars, deps.srcJars...) 1160 srcJars = append(srcJars, extraSrcJars...) 1161 srcJars = append(srcJars, j.properties.Generated_srcjars...) 1162 srcFiles = srcFiles.FilterOutByExt(".srcjar") 1163 1164 if j.properties.Jarjar_rules != nil { 1165 j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) 1166 } 1167 1168 jarName := j.Stem() + ".jar" 1169 1170 var uniqueJavaFiles android.Paths 1171 set := make(map[string]bool) 1172 for _, v := range srcFiles.FilterByExt(".java") { 1173 if _, found := set[v.String()]; !found { 1174 set[v.String()] = true 1175 uniqueJavaFiles = append(uniqueJavaFiles, v) 1176 } 1177 } 1178 var uniqueKtFiles android.Paths 1179 for _, v := range srcFiles.FilterByExt(".kt") { 1180 if _, found := set[v.String()]; !found { 1181 set[v.String()] = true 1182 uniqueKtFiles = append(uniqueKtFiles, v) 1183 } 1184 } 1185 1186 var uniqueSrcFiles android.Paths 1187 uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...) 1188 uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...) 1189 j.uniqueSrcFiles = uniqueSrcFiles 1190 android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()}) 1191 1192 // We don't currently run annotation processors in turbine, which means we can't use turbine 1193 // generated header jars when an annotation processor that generates API is enabled. One 1194 // exception (handled further below) is when kotlin sources are enabled, in which case turbine 1195 // is used to run all of the annotation processors. 1196 disableTurbine := deps.disableTurbine 1197 1198 // Collect .java and .kt files for AIDEGen 1199 j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...) 1200 1201 var kotlinJars android.Paths 1202 var kotlinHeaderJars android.Paths 1203 1204 // Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before 1205 // any dependencies so that it can override any non-final R classes from dependencies with the 1206 // final R classes from the app. 1207 flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...) 1208 1209 j.aconfigCacheFiles = append(deps.aconfigProtoFiles, j.properties.Aconfig_Cache_files...) 1210 1211 // If compiling headers then compile them and skip the rest 1212 if proptools.Bool(j.properties.Headers_only) { 1213 if srcFiles.HasExt(".kt") { 1214 ctx.ModuleErrorf("Compiling headers_only with .kt not supported") 1215 } 1216 if ctx.Config().IsEnvFalse("TURBINE_ENABLED") || disableTurbine { 1217 ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.") 1218 } 1219 1220 _, j.headerJarFile, _ = 1221 j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, 1222 extraCombinedJars) 1223 if ctx.Failed() { 1224 return 1225 } 1226 1227 android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ 1228 HeaderJars: android.PathsIfNonNil(j.headerJarFile), 1229 TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars, 1230 TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars, 1231 AidlIncludeDirs: j.exportAidlIncludeDirs, 1232 ExportedPlugins: j.exportedPluginJars, 1233 ExportedPluginClasses: j.exportedPluginClasses, 1234 ExportedPluginDisableTurbine: j.exportedDisableTurbine, 1235 StubsLinkType: j.stubsLinkType, 1236 AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles, 1237 }) 1238 1239 j.outputFile = j.headerJarFile 1240 return 1241 } 1242 1243 if srcFiles.HasExt(".kt") { 1244 // When using kotlin sources turbine is used to generate annotation processor sources, 1245 // including for annotation processors that generate API, so we can use turbine for 1246 // java sources too. 1247 disableTurbine = false 1248 1249 // user defined kotlin flags. 1250 kotlincFlags := j.properties.Kotlincflags 1251 CheckKotlincFlags(ctx, kotlincFlags) 1252 1253 // Workaround for KT-46512 1254 kotlincFlags = append(kotlincFlags, "-Xsam-conversions=class") 1255 1256 // If there are kotlin files, compile them first but pass all the kotlin and java files 1257 // kotlinc will use the java files to resolve types referenced by the kotlin files, but 1258 // won't emit any classes for them. 1259 kotlincFlags = append(kotlincFlags, "-no-stdlib") 1260 if ctx.Device() { 1261 kotlincFlags = append(kotlincFlags, "-no-jdk") 1262 } 1263 1264 for _, plugin := range deps.kotlinPlugins { 1265 kotlincFlags = append(kotlincFlags, "-Xplugin="+plugin.String()) 1266 } 1267 flags.kotlincDeps = append(flags.kotlincDeps, deps.kotlinPlugins...) 1268 1269 if len(kotlincFlags) > 0 { 1270 // optimization. 1271 ctx.Variable(pctx, "kotlincFlags", strings.Join(kotlincFlags, " ")) 1272 flags.kotlincFlags += "$kotlincFlags" 1273 } 1274 1275 // Collect common .kt files for AIDEGen 1276 j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...) 1277 1278 flags.classpath = append(flags.classpath, deps.kotlinStdlib...) 1279 flags.classpath = append(flags.classpath, deps.kotlinAnnotations...) 1280 1281 flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...) 1282 flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...) 1283 1284 if len(flags.processorPath) > 0 { 1285 // Use kapt for annotation processing 1286 kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar") 1287 kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar") 1288 kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) 1289 srcJars = append(srcJars, kaptSrcJar) 1290 kotlinJars = append(kotlinJars, kaptResJar) 1291 // Disable annotation processing in javac, it's already been handled by kapt 1292 flags.processorPath = nil 1293 flags.processors = nil 1294 } 1295 1296 kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) 1297 kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName) 1298 kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags) 1299 if ctx.Failed() { 1300 return 1301 } 1302 1303 kotlinJarPath := j.repackageFlagsIfNecessary(ctx, kotlinJar.OutputPath, jarName, "kotlinc") 1304 1305 // Make javac rule depend on the kotlinc rule 1306 flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...) 1307 1308 kotlinJars = append(kotlinJars, kotlinJarPath) 1309 kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar) 1310 1311 // Jar kotlin classes into the final jar after javac 1312 if BoolDefault(j.properties.Static_kotlin_stdlib, true) { 1313 kotlinJars = append(kotlinJars, deps.kotlinStdlib...) 1314 kotlinJars = append(kotlinJars, deps.kotlinAnnotations...) 1315 kotlinHeaderJars = append(kotlinHeaderJars, deps.kotlinStdlib...) 1316 kotlinHeaderJars = append(kotlinHeaderJars, deps.kotlinAnnotations...) 1317 } else { 1318 flags.dexClasspath = append(flags.dexClasspath, deps.kotlinStdlib...) 1319 flags.dexClasspath = append(flags.dexClasspath, deps.kotlinAnnotations...) 1320 } 1321 } 1322 1323 jars := slices.Clone(kotlinJars) 1324 1325 j.compiledSrcJars = srcJars 1326 1327 enableSharding := false 1328 var headerJarFileWithoutDepsOrJarjar android.Path 1329 if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !disableTurbine { 1330 if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 { 1331 enableSharding = true 1332 // Formerly, there was a check here that prevented annotation processors 1333 // from being used when sharding was enabled, as some annotation processors 1334 // do not function correctly in sharded environments. It was removed to 1335 // allow for the use of annotation processors that do function correctly 1336 // with sharding enabled. See: b/77284273. 1337 } 1338 extraJars := append(slices.Clone(kotlinHeaderJars), extraCombinedJars...) 1339 headerJarFileWithoutDepsOrJarjar, j.headerJarFile, j.repackagedHeaderJarFile = 1340 j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars) 1341 if ctx.Failed() { 1342 return 1343 } 1344 } 1345 if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 { 1346 hasErrorproneableFiles := false 1347 for _, ext := range j.sourceExtensions { 1348 if ext != ".proto" && ext != ".aidl" { 1349 // Skip running errorprone on pure proto or pure aidl modules. Some modules take a long time to 1350 // compile, and it's not useful to have warnings on these generated sources. 1351 hasErrorproneableFiles = true 1352 break 1353 } 1354 } 1355 var extraJarDeps android.Paths 1356 if Bool(j.properties.Errorprone.Enabled) { 1357 // If error-prone is enabled, enable errorprone flags on the regular 1358 // build. 1359 flags = enableErrorproneFlags(flags) 1360 } else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil { 1361 // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create 1362 // a new jar file just for compiling with the errorprone compiler to. 1363 // This is because we don't want to cause the java files to get completely 1364 // rebuilt every time the state of the RUN_ERROR_PRONE variable changes. 1365 // We also don't want to run this if errorprone is enabled by default for 1366 // this module, or else we could have duplicated errorprone messages. 1367 errorproneFlags := enableErrorproneFlags(flags) 1368 errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) 1369 errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar") 1370 1371 transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil, 1372 "errorprone", "errorprone") 1373 1374 extraJarDeps = append(extraJarDeps, errorprone) 1375 } 1376 1377 if enableSharding { 1378 if headerJarFileWithoutDepsOrJarjar != nil { 1379 flags.classpath = append(classpath{headerJarFileWithoutDepsOrJarjar}, flags.classpath...) 1380 } 1381 shardSize := int(*(j.properties.Javac_shard_size)) 1382 var shardSrcs []android.Paths 1383 if len(uniqueJavaFiles) > 0 { 1384 shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize) 1385 for idx, shardSrc := range shardSrcs { 1386 classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc, 1387 nil, flags, extraJarDeps) 1388 classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx)) 1389 jars = append(jars, classes) 1390 } 1391 } 1392 // Assume approximately 5 sources per srcjar. 1393 // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean 1394 // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files. 1395 if len(srcJars) > 0 { 1396 startIdx := len(shardSrcs) 1397 shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5) 1398 for idx, shardSrcJars := range shardSrcJarsList { 1399 classes := j.compileJavaClasses(ctx, jarName, startIdx+idx, 1400 nil, shardSrcJars, flags, extraJarDeps) 1401 classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx)) 1402 jars = append(jars, classes) 1403 } 1404 } 1405 } else { 1406 classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps) 1407 classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac") 1408 jars = append(jars, classes) 1409 } 1410 if ctx.Failed() { 1411 return 1412 } 1413 } 1414 1415 jars = append(jars, extraCombinedJars...) 1416 1417 j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles 1418 1419 var includeSrcJar android.WritablePath 1420 if Bool(j.properties.Include_srcs) { 1421 includeSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+".srcjar") 1422 TransformResourcesToJar(ctx, includeSrcJar, j.srcJarArgs, j.srcJarDeps) 1423 } 1424 1425 dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, 1426 j.properties.Exclude_java_resource_dirs, j.properties.Exclude_java_resources) 1427 fileArgs, fileDeps := ResourceFilesToJarArgs(ctx, j.properties.Java_resources, j.properties.Exclude_java_resources) 1428 extraArgs, extraDeps := resourcePathsToJarArgs(j.extraResources), j.extraResources 1429 1430 var resArgs []string 1431 var resDeps android.Paths 1432 1433 resArgs = append(resArgs, dirArgs...) 1434 resDeps = append(resDeps, dirDeps...) 1435 1436 resArgs = append(resArgs, fileArgs...) 1437 resDeps = append(resDeps, fileDeps...) 1438 1439 resArgs = append(resArgs, extraArgs...) 1440 resDeps = append(resDeps, extraDeps...) 1441 1442 if len(resArgs) > 0 { 1443 resourceJar := android.PathForModuleOut(ctx, "res", jarName) 1444 TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps) 1445 j.resourceJar = resourceJar 1446 if ctx.Failed() { 1447 return 1448 } 1449 } 1450 1451 var resourceJars android.Paths 1452 if j.resourceJar != nil { 1453 resourceJars = append(resourceJars, j.resourceJar) 1454 } 1455 if Bool(j.properties.Include_srcs) { 1456 resourceJars = append(resourceJars, includeSrcJar) 1457 } 1458 resourceJars = append(resourceJars, deps.staticResourceJars...) 1459 1460 if len(resourceJars) > 1 { 1461 combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName) 1462 TransformJarsToJar(ctx, combinedJar, "for resources", resourceJars, android.OptionalPath{}, 1463 false, nil, nil) 1464 j.resourceJar = combinedJar 1465 } else if len(resourceJars) == 1 { 1466 j.resourceJar = resourceJars[0] 1467 } 1468 1469 if len(deps.staticJars) > 0 { 1470 jars = append(jars, deps.staticJars...) 1471 } 1472 1473 manifest := j.overrideManifest 1474 if !manifest.Valid() && j.properties.Manifest != nil { 1475 manifest = android.OptionalPathForPath(android.PathForModuleSrc(ctx, *j.properties.Manifest)) 1476 } 1477 1478 services := android.PathsForModuleSrc(ctx, j.properties.Services) 1479 if len(services) > 0 { 1480 servicesJar := android.PathForModuleOut(ctx, "services", jarName) 1481 var zipargs []string 1482 for _, file := range services { 1483 serviceFile := file.String() 1484 zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile) 1485 } 1486 rule := zip 1487 args := map[string]string{ 1488 "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "), 1489 } 1490 if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ZIP") { 1491 rule = zipRE 1492 args["implicits"] = strings.Join(services.Strings(), ",") 1493 } 1494 ctx.Build(pctx, android.BuildParams{ 1495 Rule: rule, 1496 Output: servicesJar, 1497 Implicits: services, 1498 Args: args, 1499 }) 1500 jars = append(jars, servicesJar) 1501 } 1502 1503 // Combine the classes built from sources, any manifests, and any static libraries into 1504 // classes.jar. If there is only one input jar this step will be skipped. 1505 var outputFile android.OutputPath 1506 1507 if len(jars) == 1 && !manifest.Valid() { 1508 // Optimization: skip the combine step as there is nothing to do 1509 // TODO(ccross): this leaves any module-info.class files, but those should only come from 1510 // prebuilt dependencies until we support modules in the platform build, so there shouldn't be 1511 // any if len(jars) == 1. 1512 1513 // moduleStubLinkType determines if the module is the TopLevelStubLibrary generated 1514 // from sdk_library. The TopLevelStubLibrary contains only one static lib, 1515 // either with .from-source or .from-text suffix. 1516 // outputFile should be agnostic to the build configuration, 1517 // thus "combine" the single static lib in order to prevent the static lib from being exposed 1518 // to the copy rules. 1519 stub, _ := moduleStubLinkType(ctx.ModuleName()) 1520 1521 // Transform the single path to the jar into an OutputPath as that is required by the following 1522 // code. 1523 if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok && !stub { 1524 // The path contains an embedded OutputPath so reuse that. 1525 outputFile = moduleOutPath.OutputPath 1526 } else if outputPath, ok := jars[0].(android.OutputPath); ok && !stub { 1527 // The path is an OutputPath so reuse it directly. 1528 outputFile = outputPath 1529 } else { 1530 // The file is not in the out directory so create an OutputPath into which it can be copied 1531 // and which the following code can use to refer to it. 1532 combinedJar := android.PathForModuleOut(ctx, "combined", jarName) 1533 ctx.Build(pctx, android.BuildParams{ 1534 Rule: android.Cp, 1535 Input: jars[0], 1536 Output: combinedJar, 1537 }) 1538 outputFile = combinedJar.OutputPath 1539 } 1540 } else { 1541 combinedJar := android.PathForModuleOut(ctx, "combined", jarName) 1542 TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest, 1543 false, nil, nil) 1544 outputFile = combinedJar.OutputPath 1545 } 1546 1547 // jarjar implementation jar if necessary 1548 if j.expandJarjarRules != nil { 1549 // Transform classes.jar into classes-jarjar.jar 1550 jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName).OutputPath 1551 TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules) 1552 outputFile = jarjarFile 1553 1554 // jarjar resource jar if necessary 1555 if j.resourceJar != nil { 1556 resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName) 1557 TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules) 1558 j.resourceJar = resourceJarJarFile 1559 } 1560 1561 if ctx.Failed() { 1562 return 1563 } 1564 } 1565 1566 // Check package restrictions if necessary. 1567 if len(j.properties.Permitted_packages) > 0 { 1568 // Time stamp file created by the package check rule. 1569 pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp") 1570 1571 // Create a rule to copy the output jar to another path and add a validate dependency that 1572 // will check that the jar only contains the permitted packages. The new location will become 1573 // the output file of this module. 1574 inputFile := outputFile 1575 outputFile = android.PathForModuleOut(ctx, "package-check", jarName).OutputPath 1576 ctx.Build(pctx, android.BuildParams{ 1577 Rule: android.Cp, 1578 Input: inputFile, 1579 Output: outputFile, 1580 // Make sure that any dependency on the output file will cause ninja to run the package check 1581 // rule. 1582 Validation: pkgckFile, 1583 }) 1584 1585 // Check packages and create a timestamp file when complete. 1586 CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages) 1587 1588 if ctx.Failed() { 1589 return 1590 } 1591 } 1592 1593 j.implementationJarFile = outputFile 1594 if j.headerJarFile == nil { 1595 // If this module couldn't generate a header jar (for example due to api generating annotation processors) 1596 // then use the implementation jar. Run it through zip2zip first to remove any files in META-INF/services 1597 // so that javac on modules that depend on this module don't pick up annotation processors (which may be 1598 // missing their implementations) from META-INF/services/javax.annotation.processing.Processor. 1599 headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName) 1600 convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile) 1601 j.headerJarFile = headerJarFile 1602 } 1603 1604 // enforce syntax check to jacoco filters for any build (http://b/183622051) 1605 specs := j.jacocoModuleToZipCommand(ctx) 1606 if ctx.Failed() { 1607 return 1608 } 1609 1610 if j.shouldInstrument(ctx) { 1611 outputFile = j.instrument(ctx, flags, outputFile, jarName, specs) 1612 } 1613 1614 // merge implementation jar with resources if necessary 1615 implementationAndResourcesJar := outputFile 1616 if j.resourceJar != nil { 1617 jars := android.Paths{j.resourceJar, implementationAndResourcesJar} 1618 combinedJar := android.PathForModuleOut(ctx, "withres", jarName).OutputPath 1619 TransformJarsToJar(ctx, combinedJar, "for resources", jars, manifest, 1620 false, nil, nil) 1621 implementationAndResourcesJar = combinedJar 1622 } 1623 1624 j.implementationAndResourcesJar = implementationAndResourcesJar 1625 1626 // Enable dex compilation for the APEX variants, unless it is disabled explicitly 1627 compileDex := j.dexProperties.Compile_dex 1628 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) 1629 if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() { 1630 if compileDex == nil { 1631 compileDex = proptools.BoolPtr(true) 1632 } 1633 if j.deviceProperties.Hostdex == nil { 1634 j.deviceProperties.Hostdex = proptools.BoolPtr(true) 1635 } 1636 } 1637 1638 if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) { 1639 if j.hasCode(ctx) { 1640 if j.shouldInstrumentStatic(ctx) { 1641 j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles, 1642 android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags")) 1643 } 1644 // Dex compilation 1645 var dexOutputFile android.OutputPath 1646 params := &compileDexParams{ 1647 flags: flags, 1648 sdkVersion: j.SdkVersion(ctx), 1649 minSdkVersion: j.MinSdkVersion(ctx), 1650 classesJar: implementationAndResourcesJar, 1651 jarName: jarName, 1652 } 1653 if j.GetProfileGuided() && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting() { 1654 ctx.PropertyErrorf("enable_profile_rewriting", 1655 "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.", 1656 ) 1657 } 1658 if j.EnableProfileRewriting() { 1659 profile := j.GetProfile() 1660 if profile == "" || !j.GetProfileGuided() { 1661 ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true") 1662 } 1663 params.artProfileInput = &profile 1664 } 1665 dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params) 1666 if ctx.Failed() { 1667 return 1668 } 1669 1670 // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt. 1671 if dexArtProfileOutput != nil { 1672 j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput) 1673 } 1674 1675 // merge dex jar with resources if necessary 1676 if j.resourceJar != nil { 1677 jars := android.Paths{dexOutputFile, j.resourceJar} 1678 combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath 1679 TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, 1680 false, nil, nil) 1681 if *j.dexProperties.Uncompress_dex { 1682 combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath 1683 TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil) 1684 dexOutputFile = combinedAlignedJar 1685 } else { 1686 dexOutputFile = combinedJar 1687 } 1688 } 1689 1690 // Initialize the hiddenapi structure. 1691 1692 j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), j.implementationJarFile, j.dexProperties.Uncompress_dex) 1693 1694 // Encode hidden API flags in dex file, if needed. 1695 dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile) 1696 1697 j.dexJarFile = makeDexJarPathFromPath(dexOutputFile) 1698 1699 // Dexpreopting 1700 libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()) 1701 if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") { 1702 libName = strings.TrimSuffix(libName, ".impl") 1703 } 1704 j.dexpreopt(ctx, libName, dexOutputFile) 1705 1706 outputFile = dexOutputFile 1707 } else { 1708 // There is no code to compile into a dex jar, make sure the resources are propagated 1709 // to the APK if this is an app. 1710 outputFile = implementationAndResourcesJar 1711 j.dexJarFile = makeDexJarPathFromPath(j.resourceJar) 1712 } 1713 1714 if ctx.Failed() { 1715 return 1716 } 1717 } else { 1718 outputFile = implementationAndResourcesJar 1719 } 1720 1721 if ctx.Device() { 1722 lintSDKVersion := func(apiLevel android.ApiLevel) android.ApiLevel { 1723 if !apiLevel.IsPreview() { 1724 return apiLevel 1725 } else { 1726 return ctx.Config().DefaultAppTargetSdk(ctx) 1727 } 1728 } 1729 1730 j.linter.name = ctx.ModuleName() 1731 j.linter.srcs = append(srcFiles, nonGeneratedSrcJars...) 1732 j.linter.srcJars, _ = android.FilterPathList(srcJars, nonGeneratedSrcJars) 1733 j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...) 1734 j.linter.classes = j.implementationJarFile 1735 j.linter.minSdkVersion = lintSDKVersion(j.MinSdkVersion(ctx)) 1736 j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx)) 1737 j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx).ApiLevel) 1738 j.linter.compileSdkKind = j.SdkVersion(ctx).Kind 1739 j.linter.javaLanguageLevel = flags.javaVersion.String() 1740 j.linter.kotlinLanguageLevel = "1.3" 1741 j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data) 1742 if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() { 1743 j.linter.buildModuleReportZip = true 1744 } 1745 j.linter.lint(ctx) 1746 } 1747 1748 j.collectTransitiveSrcFiles(ctx, srcFiles) 1749 1750 ctx.CheckbuildFile(outputFile) 1751 1752 android.SetProvider(ctx, JavaInfoProvider, JavaInfo{ 1753 HeaderJars: android.PathsIfNonNil(j.headerJarFile), 1754 RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile), 1755 TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars, 1756 TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars, 1757 ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar), 1758 ImplementationJars: android.PathsIfNonNil(j.implementationJarFile), 1759 ResourceJars: android.PathsIfNonNil(j.resourceJar), 1760 AidlIncludeDirs: j.exportAidlIncludeDirs, 1761 SrcJarArgs: j.srcJarArgs, 1762 SrcJarDeps: j.srcJarDeps, 1763 TransitiveSrcFiles: j.transitiveSrcFiles, 1764 ExportedPlugins: j.exportedPluginJars, 1765 ExportedPluginClasses: j.exportedPluginClasses, 1766 ExportedPluginDisableTurbine: j.exportedDisableTurbine, 1767 JacocoReportClassesFile: j.jacocoReportClassesFile, 1768 StubsLinkType: j.stubsLinkType, 1769 AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles, 1770 }) 1771 1772 // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource 1773 j.outputFile = outputFile.WithoutRel() 1774} 1775 1776func (j *Module) useCompose() bool { 1777 return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs) 1778} 1779 1780func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) { 1781 ctx.VisitDirectDeps(func(m android.Module) { 1782 depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider) 1783 depTag := ctx.OtherModuleDependencyTag(m) 1784 1785 if depProguardInfo.UnconditionallyExportedProguardFlags != nil { 1786 transitiveUnconditionalExportedFlags = append(transitiveUnconditionalExportedFlags, depProguardInfo.UnconditionallyExportedProguardFlags) 1787 transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.UnconditionallyExportedProguardFlags) 1788 } 1789 1790 if depTag == staticLibTag && depProguardInfo.ProguardFlagsFiles != nil { 1791 transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.ProguardFlagsFiles) 1792 } 1793 }) 1794 1795 return transitiveProguardFlags, transitiveUnconditionalExportedFlags 1796} 1797 1798func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo { 1799 transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx) 1800 1801 directUnconditionalExportedFlags := android.Paths{} 1802 proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files) 1803 exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files) 1804 if exportUnconditionally { 1805 // if we explicitly export, then our unconditional exports are the same as our transitive flags 1806 transitiveUnconditionalExportedFlags = transitiveProguardFlags 1807 directUnconditionalExportedFlags = proguardFlagsForThisModule 1808 } 1809 1810 return ProguardSpecInfo{ 1811 Export_proguard_flags_files: exportUnconditionally, 1812 ProguardFlagsFiles: android.NewDepSet[android.Path]( 1813 android.POSTORDER, 1814 proguardFlagsForThisModule, 1815 transitiveProguardFlags, 1816 ), 1817 UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path]( 1818 android.POSTORDER, 1819 directUnconditionalExportedFlags, 1820 transitiveUnconditionalExportedFlags, 1821 ), 1822 } 1823 1824} 1825 1826// Returns a copy of the supplied flags, but with all the errorprone-related 1827// fields copied to the regular build's fields. 1828func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags { 1829 flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...) 1830 1831 if len(flags.errorProneExtraJavacFlags) > 0 { 1832 if len(flags.javacFlags) > 0 { 1833 flags.javacFlags += " " + flags.errorProneExtraJavacFlags 1834 } else { 1835 flags.javacFlags = flags.errorProneExtraJavacFlags 1836 } 1837 } 1838 return flags 1839} 1840 1841func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int, 1842 srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath { 1843 1844 kzipName := pathtools.ReplaceExtension(jarName, "kzip") 1845 annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar") 1846 if idx >= 0 { 1847 kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip" 1848 annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar") 1849 jarName += strconv.Itoa(idx) 1850 } 1851 1852 classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath 1853 TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps) 1854 1855 if ctx.Config().EmitXrefRules() && ctx.Module() == ctx.PrimaryModule() { 1856 extractionFile := android.PathForModuleOut(ctx, kzipName) 1857 emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps) 1858 j.kytheFiles = append(j.kytheFiles, extractionFile) 1859 } 1860 1861 if len(flags.processorPath) > 0 { 1862 j.annoSrcJars = append(j.annoSrcJars, annoSrcJar) 1863 } 1864 1865 return classes 1866} 1867 1868// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user, 1869// since some of these flags may be used internally. 1870func CheckKotlincFlags(ctx android.ModuleContext, flags []string) { 1871 for _, flag := range flags { 1872 flag = strings.TrimSpace(flag) 1873 1874 if !strings.HasPrefix(flag, "-") { 1875 ctx.PropertyErrorf("kotlincflags", "Flag `%s` must start with `-`", flag) 1876 } else if strings.HasPrefix(flag, "-Xintellij-plugin-root") { 1877 ctx.PropertyErrorf("kotlincflags", 1878 "Bad flag: `%s`, only use internal compiler for consistency.", flag) 1879 } else if inList(flag, config.KotlincIllegalFlags) { 1880 ctx.PropertyErrorf("kotlincflags", "Flag `%s` already used by build system", flag) 1881 } else if flag == "-include-runtime" { 1882 ctx.PropertyErrorf("kotlincflags", "Bad flag: `%s`, do not include runtime.", flag) 1883 } else { 1884 args := strings.Split(flag, " ") 1885 if args[0] == "-kotlin-home" { 1886 ctx.PropertyErrorf("kotlincflags", 1887 "Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo).", flag) 1888 } 1889 } 1890 } 1891} 1892 1893func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths, 1894 deps deps, flags javaBuilderFlags, jarName string, 1895 extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar android.Path) { 1896 1897 var jars android.Paths 1898 if len(srcFiles) > 0 || len(srcJars) > 0 { 1899 // Compile java sources into turbine.jar. 1900 turbineJar := android.PathForModuleOut(ctx, "turbine", jarName) 1901 TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags) 1902 if ctx.Failed() { 1903 return nil, nil, nil 1904 } 1905 jars = append(jars, turbineJar) 1906 headerJar = turbineJar 1907 } 1908 1909 jars = append(jars, extraJars...) 1910 1911 // Combine any static header libraries into classes-header.jar. If there is only 1912 // one input jar this step will be skipped. 1913 jars = append(jars, deps.staticHeaderJars...) 1914 1915 // we cannot skip the combine step for now if there is only one jar 1916 // since we have to strip META-INF/TRANSITIVE dir from turbine.jar 1917 combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName) 1918 TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{}, 1919 false, nil, []string{"META-INF/TRANSITIVE"}) 1920 jarjarAndDepsHeaderJar = combinedJar 1921 1922 if j.expandJarjarRules != nil { 1923 // Transform classes.jar into classes-jarjar.jar 1924 jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName) 1925 TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules) 1926 jarjarAndDepsHeaderJar = jarjarFile 1927 if ctx.Failed() { 1928 return nil, nil, nil 1929 } 1930 } 1931 1932 if j.repackageJarjarRules != nil { 1933 repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-turbine-jarjar", jarName) 1934 TransformJarJar(ctx, repackagedJarjarFile, jarjarAndDepsHeaderJar, j.repackageJarjarRules) 1935 jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile 1936 if ctx.Failed() { 1937 return nil, nil, nil 1938 } 1939 } else { 1940 jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar 1941 } 1942 1943 return headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar 1944} 1945 1946func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags, 1947 classesJar android.Path, jarName string, specs string) android.OutputPath { 1948 1949 jacocoReportClassesFile := android.PathForModuleOut(ctx, "jacoco-report-classes", jarName) 1950 instrumentedJar := android.PathForModuleOut(ctx, "jacoco", jarName).OutputPath 1951 1952 jacocoInstrumentJar(ctx, instrumentedJar, jacocoReportClassesFile, classesJar, specs) 1953 1954 j.jacocoReportClassesFile = jacocoReportClassesFile 1955 1956 return instrumentedJar 1957} 1958 1959type providesTransitiveHeaderJars struct { 1960 // set of header jars for all transitive libs deps 1961 transitiveLibsHeaderJars *android.DepSet[android.Path] 1962 // set of header jars for all transitive static libs deps 1963 transitiveStaticLibsHeaderJars *android.DepSet[android.Path] 1964} 1965 1966func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet[android.Path] { 1967 return j.transitiveLibsHeaderJars 1968} 1969 1970func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet[android.Path] { 1971 return j.transitiveStaticLibsHeaderJars 1972} 1973 1974func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) { 1975 directLibs := android.Paths{} 1976 directStaticLibs := android.Paths{} 1977 transitiveLibs := []*android.DepSet[android.Path]{} 1978 transitiveStaticLibs := []*android.DepSet[android.Path]{} 1979 ctx.VisitDirectDeps(func(module android.Module) { 1980 // don't add deps of the prebuilt version of the same library 1981 if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) { 1982 return 1983 } 1984 1985 dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider) 1986 tag := ctx.OtherModuleDependencyTag(module) 1987 _, isUsesLibDep := tag.(usesLibraryDependencyTag) 1988 if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep { 1989 directLibs = append(directLibs, dep.HeaderJars...) 1990 } else if tag == staticLibTag { 1991 directStaticLibs = append(directStaticLibs, dep.HeaderJars...) 1992 } else { 1993 // Don't propagate transitive libs for other kinds of dependencies. 1994 return 1995 } 1996 1997 if dep.TransitiveLibsHeaderJars != nil { 1998 transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars) 1999 } 2000 if dep.TransitiveStaticLibsHeaderJars != nil { 2001 transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars) 2002 } 2003 }) 2004 j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs) 2005 j.transitiveStaticLibsHeaderJars = android.NewDepSet(android.POSTORDER, directStaticLibs, transitiveStaticLibs) 2006} 2007 2008func (j *Module) HeaderJars() android.Paths { 2009 if j.headerJarFile == nil { 2010 return nil 2011 } 2012 return android.Paths{j.headerJarFile} 2013} 2014 2015func (j *Module) ImplementationJars() android.Paths { 2016 if j.implementationJarFile == nil { 2017 return nil 2018 } 2019 return android.Paths{j.implementationJarFile} 2020} 2021 2022func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { 2023 return j.dexJarFile 2024} 2025 2026func (j *Module) DexJarInstallPath() android.Path { 2027 return j.installFile 2028} 2029 2030func (j *Module) ImplementationAndResourcesJars() android.Paths { 2031 if j.implementationAndResourcesJar == nil { 2032 return nil 2033 } 2034 return android.Paths{j.implementationAndResourcesJar} 2035} 2036 2037func (j *Module) AidlIncludeDirs() android.Paths { 2038 // exportAidlIncludeDirs is type android.Paths already 2039 return j.exportAidlIncludeDirs 2040} 2041 2042func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap { 2043 return j.classLoaderContexts 2044} 2045 2046// Collect information for opening IDE project files in java/jdeps.go. 2047func (j *Module) IDEInfo(dpInfo *android.IdeInfo) { 2048 dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...) 2049 dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...) 2050 dpInfo.SrcJars = append(dpInfo.SrcJars, j.compiledSrcJars.Strings()...) 2051 dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...) 2052 if j.expandJarjarRules != nil { 2053 dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String()) 2054 } 2055 dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...) 2056 dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...) 2057 dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...) 2058} 2059 2060func (j *Module) CompilerDeps() []string { 2061 jdeps := []string{} 2062 jdeps = append(jdeps, j.properties.Libs...) 2063 jdeps = append(jdeps, j.properties.Static_libs...) 2064 return jdeps 2065} 2066 2067func (j *Module) hasCode(ctx android.ModuleContext) bool { 2068 srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs) 2069 return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0 2070} 2071 2072// Implements android.ApexModule 2073func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { 2074 return j.depIsInSameApex(ctx, dep) 2075} 2076 2077// Implements android.ApexModule 2078func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { 2079 sdkVersionSpec := j.SdkVersion(ctx) 2080 minSdkVersion := j.MinSdkVersion(ctx) 2081 if !minSdkVersion.Specified() { 2082 return fmt.Errorf("min_sdk_version is not specified") 2083 } 2084 // If the module is compiling against core (via sdk_version), skip comparison check. 2085 if sdkVersionSpec.Kind == android.SdkCore { 2086 return nil 2087 } 2088 if minSdkVersion.GreaterThan(sdkVersion) { 2089 return fmt.Errorf("newer SDK(%v)", minSdkVersion) 2090 } 2091 return nil 2092} 2093 2094func (j *Module) Stem() string { 2095 if j.stem == "" { 2096 panic("Stem() called before stem property was set") 2097 } 2098 return j.stem 2099} 2100 2101func (j *Module) JacocoReportClassesFile() android.Path { 2102 return j.jacocoReportClassesFile 2103} 2104 2105func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) { 2106 var fromDeps []*android.DepSet[android.Path] 2107 ctx.VisitDirectDeps(func(module android.Module) { 2108 tag := ctx.OtherModuleDependencyTag(module) 2109 if tag == staticLibTag { 2110 depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider) 2111 if depInfo.TransitiveSrcFiles != nil { 2112 fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles) 2113 } 2114 } 2115 }) 2116 2117 j.transitiveSrcFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps) 2118} 2119 2120func (j *Module) IsInstallable() bool { 2121 return Bool(j.properties.Installable) 2122} 2123 2124type sdkLinkType int 2125 2126const ( 2127 // TODO(jiyong) rename these for better readability. Make the allowed 2128 // and disallowed link types explicit 2129 // order is important here. See rank() 2130 javaCore sdkLinkType = iota 2131 javaSdk 2132 javaSystem 2133 javaModule 2134 javaSystemServer 2135 javaPlatform 2136) 2137 2138func (lt sdkLinkType) String() string { 2139 switch lt { 2140 case javaCore: 2141 return "core Java API" 2142 case javaSdk: 2143 return "Android API" 2144 case javaSystem: 2145 return "system API" 2146 case javaModule: 2147 return "module API" 2148 case javaSystemServer: 2149 return "system server API" 2150 case javaPlatform: 2151 return "private API" 2152 default: 2153 panic(fmt.Errorf("unrecognized linktype: %d", lt)) 2154 } 2155} 2156 2157// rank determines the total order among sdkLinkType. An SDK link type of rank A can link to 2158// another SDK link type of rank B only when B <= A. For example, a module linking to Android SDK 2159// can't statically depend on modules that use Platform API. 2160func (lt sdkLinkType) rank() int { 2161 return int(lt) 2162} 2163 2164type moduleWithSdkDep interface { 2165 android.Module 2166 getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) 2167} 2168 2169func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) { 2170 switch name { 2171 case android.SdkCore.DefaultJavaLibraryName(), 2172 "legacy.core.platform.api.stubs", 2173 "stable.core.platform.api.stubs", 2174 "stub-annotations", "private-stub-annotations-jar", 2175 "core-lambda-stubs", 2176 "core-generated-annotation-stubs": 2177 return javaCore, true 2178 case android.SdkPublic.DefaultJavaLibraryName(): 2179 return javaSdk, true 2180 case android.SdkSystem.DefaultJavaLibraryName(): 2181 return javaSystem, true 2182 case android.SdkModule.DefaultJavaLibraryName(): 2183 return javaModule, true 2184 case android.SdkSystemServer.DefaultJavaLibraryName(): 2185 return javaSystemServer, true 2186 case android.SdkTest.DefaultJavaLibraryName(): 2187 return javaSystem, true 2188 } 2189 2190 if stub, linkType := moduleStubLinkType(name); stub { 2191 return linkType, true 2192 } 2193 2194 ver := m.SdkVersion(ctx) 2195 switch ver.Kind { 2196 case android.SdkCore: 2197 return javaCore, false 2198 case android.SdkSystem: 2199 return javaSystem, false 2200 case android.SdkPublic: 2201 return javaSdk, false 2202 case android.SdkModule: 2203 return javaModule, false 2204 case android.SdkSystemServer: 2205 return javaSystemServer, false 2206 case android.SdkPrivate, android.SdkNone, android.SdkCorePlatform, android.SdkTest: 2207 return javaPlatform, false 2208 } 2209 2210 if !ver.Valid() { 2211 panic(fmt.Errorf("sdk_version is invalid. got %q", ver.Raw)) 2212 } 2213 return javaSdk, false 2214} 2215 2216// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than 2217// this module's. See the comment on rank() for details and an example. 2218func (j *Module) checkSdkLinkType( 2219 ctx android.ModuleContext, dep moduleWithSdkDep, tag dependencyTag) { 2220 if ctx.Host() { 2221 return 2222 } 2223 2224 myLinkType, stubs := j.getSdkLinkType(ctx, ctx.ModuleName()) 2225 if stubs { 2226 return 2227 } 2228 depLinkType, _ := dep.getSdkLinkType(ctx, ctx.OtherModuleName(dep)) 2229 2230 if myLinkType.rank() < depLinkType.rank() { 2231 ctx.ModuleErrorf("compiles against %v, but dependency %q is compiling against %v. "+ 2232 "In order to fix this, consider adjusting sdk_version: OR platform_apis: "+ 2233 "property of the source or target module so that target module is built "+ 2234 "with the same or smaller API set when compared to the source.", 2235 myLinkType, ctx.OtherModuleName(dep), depLinkType) 2236 } 2237} 2238 2239func (j *Module) collectDeps(ctx android.ModuleContext) deps { 2240 var deps deps 2241 2242 if ctx.Device() { 2243 sdkDep := decodeSdkDep(ctx, android.SdkContext(j)) 2244 if sdkDep.invalidVersion { 2245 ctx.AddMissingDependencies(sdkDep.bootclasspath) 2246 ctx.AddMissingDependencies(sdkDep.java9Classpath) 2247 } else if sdkDep.useFiles { 2248 // sdkDep.jar is actually equivalent to turbine header.jar. 2249 deps.classpath = append(deps.classpath, sdkDep.jars...) 2250 deps.dexClasspath = append(deps.dexClasspath, sdkDep.jars...) 2251 deps.aidlPreprocess = sdkDep.aidl 2252 } else { 2253 deps.aidlPreprocess = sdkDep.aidl 2254 } 2255 } 2256 2257 sdkLinkType, _ := j.getSdkLinkType(ctx, ctx.ModuleName()) 2258 2259 j.collectTransitiveHeaderJars(ctx) 2260 ctx.VisitDirectDeps(func(module android.Module) { 2261 otherName := ctx.OtherModuleName(module) 2262 tag := ctx.OtherModuleDependencyTag(module) 2263 2264 if IsJniDepTag(tag) { 2265 // Handled by AndroidApp.collectAppDeps 2266 return 2267 } 2268 if tag == certificateTag { 2269 // Handled by AndroidApp.collectAppDeps 2270 return 2271 } 2272 2273 if dep, ok := module.(SdkLibraryDependency); ok { 2274 switch tag { 2275 case sdkLibTag, libTag: 2276 depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx)) 2277 deps.classpath = append(deps.classpath, depHeaderJars...) 2278 deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...) 2279 case staticLibTag: 2280 ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) 2281 } 2282 } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok { 2283 if sdkLinkType != javaPlatform { 2284 if syspropDep, ok := android.OtherModuleProvider(ctx, module, SyspropPublicStubInfoProvider); ok { 2285 // dep is a sysprop implementation library, but this module is not linking against 2286 // the platform, so it gets the sysprop public stubs library instead. Replace 2287 // dep with the JavaInfo from the SyspropPublicStubInfoProvider. 2288 dep = syspropDep.JavaInfo 2289 } 2290 } 2291 switch tag { 2292 case bootClasspathTag: 2293 deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...) 2294 case sdkLibTag, libTag, instrumentationForTag: 2295 if _, ok := module.(*Plugin); ok { 2296 ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName) 2297 } 2298 deps.classpath = append(deps.classpath, dep.HeaderJars...) 2299 deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...) 2300 if len(dep.RepackagedHeaderJars) == 1 && !slices.Contains(dep.HeaderJars, dep.RepackagedHeaderJars[0]) { 2301 deps.classpath = append(deps.classpath, dep.RepackagedHeaderJars...) 2302 deps.dexClasspath = append(deps.dexClasspath, dep.RepackagedHeaderJars...) 2303 } 2304 deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...) 2305 addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...) 2306 deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine 2307 case java9LibTag: 2308 deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...) 2309 case staticLibTag: 2310 if _, ok := module.(*Plugin); ok { 2311 ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName) 2312 } 2313 deps.classpath = append(deps.classpath, dep.HeaderJars...) 2314 deps.staticJars = append(deps.staticJars, dep.ImplementationJars...) 2315 deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars...) 2316 deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars...) 2317 deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...) 2318 addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...) 2319 // Turbine doesn't run annotation processors, so any module that uses an 2320 // annotation processor that generates API is incompatible with the turbine 2321 // optimization. 2322 deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine 2323 deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...) 2324 case pluginTag: 2325 if plugin, ok := module.(*Plugin); ok { 2326 if plugin.pluginProperties.Processor_class != nil { 2327 addPlugins(&deps, dep.ImplementationAndResourcesJars, *plugin.pluginProperties.Processor_class) 2328 } else { 2329 addPlugins(&deps, dep.ImplementationAndResourcesJars) 2330 } 2331 // Turbine doesn't run annotation processors, so any module that uses an 2332 // annotation processor that generates API is incompatible with the turbine 2333 // optimization. 2334 deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api) 2335 } else { 2336 ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName) 2337 } 2338 case errorpronePluginTag: 2339 if _, ok := module.(*Plugin); ok { 2340 deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, dep.ImplementationAndResourcesJars...) 2341 } else { 2342 ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName) 2343 } 2344 case exportedPluginTag: 2345 if plugin, ok := module.(*Plugin); ok { 2346 j.exportedPluginJars = append(j.exportedPluginJars, dep.ImplementationAndResourcesJars...) 2347 if plugin.pluginProperties.Processor_class != nil { 2348 j.exportedPluginClasses = append(j.exportedPluginClasses, *plugin.pluginProperties.Processor_class) 2349 } 2350 // Turbine doesn't run annotation processors, so any module that uses an 2351 // annotation processor that generates API is incompatible with the turbine 2352 // optimization. 2353 j.exportedDisableTurbine = Bool(plugin.pluginProperties.Generates_api) 2354 } else { 2355 ctx.PropertyErrorf("exported_plugins", "%q is not a java_plugin module", otherName) 2356 } 2357 case kotlinStdlibTag: 2358 deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...) 2359 case kotlinAnnotationsTag: 2360 deps.kotlinAnnotations = dep.HeaderJars 2361 case kotlinPluginTag: 2362 deps.kotlinPlugins = append(deps.kotlinPlugins, dep.ImplementationAndResourcesJars...) 2363 case syspropPublicStubDepTag: 2364 // This is a sysprop implementation library, forward the JavaInfoProvider from 2365 // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider. 2366 android.SetProvider(ctx, SyspropPublicStubInfoProvider, SyspropPublicStubInfo{ 2367 JavaInfo: dep, 2368 }) 2369 } 2370 } else if dep, ok := module.(android.SourceFileProducer); ok { 2371 switch tag { 2372 case sdkLibTag, libTag: 2373 checkProducesJars(ctx, dep) 2374 deps.classpath = append(deps.classpath, dep.Srcs()...) 2375 deps.dexClasspath = append(deps.classpath, dep.Srcs()...) 2376 case staticLibTag: 2377 checkProducesJars(ctx, dep) 2378 deps.classpath = append(deps.classpath, dep.Srcs()...) 2379 deps.staticJars = append(deps.staticJars, dep.Srcs()...) 2380 deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...) 2381 } 2382 } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok { 2383 switch tag { 2384 case staticLibTag: 2385 deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...) 2386 } 2387 } else { 2388 switch tag { 2389 case bootClasspathTag: 2390 // If a system modules dependency has been added to the bootclasspath 2391 // then add its libs to the bootclasspath. 2392 sm := module.(SystemModulesProvider) 2393 deps.bootClasspath = append(deps.bootClasspath, sm.HeaderJars()...) 2394 2395 case systemModulesTag: 2396 if deps.systemModules != nil { 2397 panic("Found two system module dependencies") 2398 } 2399 sm := module.(SystemModulesProvider) 2400 outputDir, outputDeps := sm.OutputDirAndDeps() 2401 deps.systemModules = &systemModules{outputDir, outputDeps} 2402 2403 case instrumentationForTag: 2404 ctx.PropertyErrorf("instrumentation_for", "dependency %q of type %q does not provide JavaInfo so is unsuitable for use with this property", ctx.OtherModuleName(module), ctx.OtherModuleType(module)) 2405 } 2406 } 2407 2408 addCLCFromDep(ctx, module, j.classLoaderContexts) 2409 addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary) 2410 }) 2411 2412 return deps 2413} 2414 2415// Provider for jarjar renaming rules. 2416// 2417// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be 2418// passed to all rdeps. The typical way that these renamings will NOT be inherited is when a module 2419// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on 2420// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then 2421// be renamed from that module. 2422// TODO: Add another property to suppress the forwarding of 2423type DependencyUse int 2424 2425const ( 2426 RenameUseInvalid DependencyUse = iota 2427 RenameUseInclude 2428 RenameUseExclude 2429) 2430 2431type RenameUseElement struct { 2432 DepName string 2433 RenameUse DependencyUse 2434 Why string // token for determining where in the logic the decision was made. 2435} 2436 2437type JarJarProviderData struct { 2438 // Mapping of class names: original --> renamed. If the value is "", the class will be 2439 // renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has 2440 // attribute). Rdeps of that module will inherit the renaming. 2441 Rename map[string]string 2442 RenameUse []RenameUseElement 2443} 2444 2445func (this JarJarProviderData) GetDebugString() string { 2446 result := "" 2447 for _, k := range android.SortedKeys(this.Rename) { 2448 v := this.Rename[k] 2449 if strings.Contains(k, "android.companion.virtual.flags.FakeFeatureFlagsImpl") { 2450 result += k + "-->" + v + ";" 2451 } 2452 } 2453 return result 2454} 2455 2456var JarJarProvider = blueprint.NewProvider[JarJarProviderData]() 2457 2458var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath" 2459 2460func init() { 2461 android.SetJarJarPrefixHandler(mergeJarJarPrefixes) 2462} 2463 2464// BaseJarJarProviderData contains information that will propagate across dependencies regardless of 2465// whether they are java modules or not. 2466type BaseJarJarProviderData struct { 2467 JarJarProviderData JarJarProviderData 2468} 2469 2470func (this BaseJarJarProviderData) GetDebugString() string { 2471 return this.JarJarProviderData.GetDebugString() 2472} 2473 2474var BaseJarJarProvider = blueprint.NewProvider[BaseJarJarProviderData]() 2475 2476// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called. 2477// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have 2478// either JarJarProvider or BaseJarJarProvider. 2479func mergeJarJarPrefixes(ctx android.ModuleContext) { 2480 mod := ctx.Module() 2481 // Explicitly avoid propagating into some module types. 2482 switch reflect.TypeOf(mod).String() { 2483 case "*java.Droidstubs": 2484 return 2485 } 2486 jarJarData := collectDirectDepsProviders(ctx) 2487 if jarJarData != nil { 2488 providerData := BaseJarJarProviderData{ 2489 JarJarProviderData: *jarJarData, 2490 } 2491 android.SetProvider(ctx, BaseJarJarProvider, providerData) 2492 } 2493 2494} 2495 2496// Add a jarjar renaming rule to this module, to be inherited to all dependent modules. 2497func (module *Module) addJarJarRenameRule(original string, renamed string) { 2498 if module.jarjarRenameRules == nil { 2499 module.jarjarRenameRules = make(map[string]string) 2500 } 2501 module.jarjarRenameRules[original] = renamed 2502} 2503 2504func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) { 2505 // Gather repackage information from deps 2506 // If the dep jas a JarJarProvider, it is used. Otherwise, any BaseJarJarProvider is used. 2507 2508 module := ctx.Module() 2509 moduleName := module.Name() 2510 2511 ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) { 2512 tag := ctx.OtherModuleDependencyTag(m) 2513 // This logic mirrors that in (*Module).collectDeps above. There are several places 2514 // where we explicitly return RenameUseExclude, even though it is the default, to 2515 // indicate that it has been verified to be the case. 2516 // 2517 // Note well: there are probably cases that are getting to the unconditional return 2518 // and are therefore wrong. 2519 shouldIncludeRenames := func() (DependencyUse, string) { 2520 if moduleName == m.Name() { 2521 return RenameUseInclude, "name" // If we have the same module name, include the renames. 2522 } 2523 if sc, ok := module.(android.SdkContext); ok { 2524 if ctx.Device() { 2525 sdkDep := decodeSdkDep(ctx, sc) 2526 if !sdkDep.invalidVersion && sdkDep.useFiles { 2527 return RenameUseExclude, "useFiles" 2528 } 2529 } 2530 } 2531 if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag { 2532 return RenameUseExclude, "tags" 2533 } 2534 if _, ok := m.(SdkLibraryDependency); ok { 2535 switch tag { 2536 case sdkLibTag, libTag: 2537 return RenameUseExclude, "sdklibdep" // matches collectDeps() 2538 } 2539 return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps() 2540 } else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok { 2541 switch ji.StubsLinkType { 2542 case Stubs: 2543 return RenameUseExclude, "info" 2544 case Implementation: 2545 return RenameUseInclude, "info" 2546 default: 2547 //fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m) 2548 // Fall through to the heuristic logic. 2549 } 2550 switch reflect.TypeOf(m).String() { 2551 case "*java.GeneratedJavaLibraryModule": 2552 // Probably a java_aconfig_library module. 2553 // TODO: make this check better. 2554 return RenameUseInclude, "reflect" 2555 } 2556 switch tag { 2557 case bootClasspathTag: 2558 return RenameUseExclude, "tagswitch" 2559 case sdkLibTag, libTag, instrumentationForTag: 2560 return RenameUseInclude, "tagswitch" 2561 case java9LibTag: 2562 return RenameUseExclude, "tagswitch" 2563 case staticLibTag: 2564 return RenameUseInclude, "tagswitch" 2565 case pluginTag: 2566 return RenameUseInclude, "tagswitch" 2567 case errorpronePluginTag: 2568 return RenameUseInclude, "tagswitch" 2569 case exportedPluginTag: 2570 return RenameUseInclude, "tagswitch" 2571 case kotlinStdlibTag, kotlinAnnotationsTag: 2572 return RenameUseExclude, "tagswitch" 2573 case kotlinPluginTag: 2574 return RenameUseInclude, "tagswitch" 2575 default: 2576 return RenameUseExclude, "tagswitch" 2577 } 2578 } else if _, ok := m.(android.SourceFileProducer); ok { 2579 switch tag { 2580 case sdkLibTag, libTag, staticLibTag: 2581 return RenameUseInclude, "srcfile" 2582 default: 2583 return RenameUseExclude, "srcfile" 2584 } 2585 } else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok { 2586 return RenameUseInclude, "aconfig_declarations_group" 2587 } else { 2588 switch tag { 2589 case bootClasspathTag: 2590 return RenameUseExclude, "else" 2591 case systemModulesTag: 2592 return RenameUseInclude, "else" 2593 } 2594 } 2595 // If we got here, choose the safer option, which may lead to a build failure, rather 2596 // than runtime failures on the device. 2597 return RenameUseExclude, "end" 2598 } 2599 2600 if result == nil { 2601 result = &JarJarProviderData{ 2602 Rename: make(map[string]string), 2603 RenameUse: make([]RenameUseElement, 0), 2604 } 2605 } 2606 how, why := shouldIncludeRenames() 2607 result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why}) 2608 if how != RenameUseInclude { 2609 // Nothing to merge. 2610 return 2611 } 2612 2613 merge := func(theirs *JarJarProviderData) { 2614 for orig, renamed := range theirs.Rename { 2615 if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" { 2616 result.Rename[orig] = renamed 2617 } else if preexisting != "" && renamed != "" && preexisting != renamed { 2618 if strings.HasPrefix(preexisting, overridableJarJarPrefix) { 2619 result.Rename[orig] = renamed 2620 } else if !strings.HasPrefix(renamed, overridableJarJarPrefix) { 2621 ctx.ModuleErrorf("1. Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting, ctx.ModuleName(), m.Name()) 2622 continue 2623 } 2624 } 2625 } 2626 } 2627 if theirs, ok := android.OtherModuleProvider(ctx, m, JarJarProvider); ok { 2628 merge(&theirs) 2629 } else if theirs, ok := android.OtherModuleProvider(ctx, m, BaseJarJarProvider); ok { 2630 // TODO: if every java.Module should have a JarJarProvider, and we find only the 2631 // BaseJarJarProvider, then there is a bug. Consider seeing if m can be cast 2632 // to java.Module. 2633 merge(&theirs.JarJarProviderData) 2634 } 2635 }) 2636 return 2637} 2638 2639func (this Module) GetDebugString() string { 2640 return "sdk_version=" + proptools.String(this.deviceProperties.Sdk_version) 2641} 2642 2643// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to 2644// us, and if it's been set, apply the jarjar_prefix property to rename them. 2645func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData { 2646 // Gather repackage information from deps 2647 result := collectDirectDepsProviders(ctx) 2648 2649 // Update that with entries we've stored for ourself 2650 for orig, renamed := range module.jarjarRenameRules { 2651 if result == nil { 2652 result = &JarJarProviderData{ 2653 Rename: make(map[string]string), 2654 } 2655 } 2656 if renamed != "" { 2657 if preexisting, exists := (*result).Rename[orig]; exists && preexisting != renamed { 2658 ctx.ModuleErrorf("Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting) 2659 continue 2660 } 2661 } 2662 (*result).Rename[orig] = renamed 2663 } 2664 2665 // If there are no renamings, then jarjar_prefix does nothing, so skip the extra work. 2666 if result == nil { 2667 return nil 2668 } 2669 2670 // If they've given us a jarjar_prefix property, then we will use that to rename any classes 2671 // that have not yet been renamed. 2672 prefix := proptools.String(module.properties.Jarjar_prefix) 2673 if prefix != "" { 2674 if prefix[0] == '.' { 2675 ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not start with '.'") 2676 return nil 2677 } 2678 if prefix[len(prefix)-1] == '.' { 2679 ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not end with '.'") 2680 return nil 2681 } 2682 2683 var updated map[string]string 2684 for orig, renamed := range (*result).Rename { 2685 if renamed == "" { 2686 if updated == nil { 2687 updated = make(map[string]string) 2688 } 2689 updated[orig] = prefix + "." + orig 2690 } 2691 } 2692 for orig, renamed := range updated { 2693 (*result).Rename[orig] = renamed 2694 } 2695 } 2696 2697 return result 2698} 2699 2700// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map 2701// to "" won't be in this list because they shouldn't be renamed yet. 2702func getJarJarRuleText(provider *JarJarProviderData) string { 2703 result := "" 2704 for _, orig := range android.SortedKeys(provider.Rename) { 2705 renamed := provider.Rename[orig] 2706 if renamed != "" { 2707 result += "rule " + orig + " " + renamed + "\n" 2708 } 2709 } 2710 return result 2711} 2712 2713// Repackage the flags if the jarjar rule txt for the flags is generated 2714func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.WritablePath, jarName, info string) android.WritablePath { 2715 if j.repackageJarjarRules == nil { 2716 return infile 2717 } 2718 repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info+jarName) 2719 TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules) 2720 return repackagedJarjarFile 2721} 2722 2723func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) { 2724 deps.processorPath = append(deps.processorPath, pluginJars...) 2725 deps.processorClasses = append(deps.processorClasses, pluginClasses...) 2726} 2727 2728// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with 2729// this interface. 2730type ProvidesUsesLib interface { 2731 ProvidesUsesLib() *string 2732} 2733 2734func (j *Module) ProvidesUsesLib() *string { 2735 return j.usesLibraryProperties.Provides_uses_lib 2736} 2737 2738type ModuleWithStem interface { 2739 Stem() string 2740} 2741 2742var _ ModuleWithStem = (*Module)(nil) 2743 2744type ModuleWithUsesLibrary interface { 2745 UsesLibrary() *usesLibrary 2746} 2747 2748func (j *Module) UsesLibrary() *usesLibrary { 2749 return &j.usesLibrary 2750} 2751 2752var _ ModuleWithUsesLibrary = (*Module)(nil) 2753