2021-03-17 23:56:23 +01:00
// Copyright 2021 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package java
import (
"fmt"
"path/filepath"
2024-02-05 23:46:00 +01:00
"reflect"
"slices"
2021-03-17 23:56:23 +01:00
"strconv"
"strings"
2023-11-28 22:14:56 +01:00
"github.com/google/blueprint"
2021-03-17 23:56:23 +01:00
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/dexpreopt"
"android/soong/java/config"
)
// This file contains the definition and the implementation of the base module that most
// source-based Java module structs embed.
// TODO:
// Autogenerated files:
// Renderscript
// Post-jar passes:
// Proguard
// Rmtypedefs
// DroidDoc
// Findbugs
// Properties that are common to most Java modules, i.e. whether it's a host or device module.
type CommonProperties struct {
// list of source files used to compile the Java module. May be .java, .kt, .logtags, .proto,
// or .aidl files.
Srcs [ ] string ` android:"path,arch_variant" `
// list Kotlin of source files containing Kotlin code that should be treated as common code in
// a codebase that supports Kotlin multiplatform. See
// https://kotlinlang.org/docs/reference/multiplatform.html. May be only be .kt files.
Common_srcs [ ] string ` android:"path,arch_variant" `
// list of source files that should not be used to build the Java module.
// This is most useful in the arch/multilib variants to remove non-common files
Exclude_srcs [ ] string ` android:"path,arch_variant" `
// list of directories containing Java resources
Java_resource_dirs [ ] string ` android:"arch_variant" `
// list of directories that should be excluded from java_resource_dirs
Exclude_java_resource_dirs [ ] string ` android:"arch_variant" `
// list of files to use as Java resources
Java_resources [ ] string ` android:"path,arch_variant" `
// list of files that should be excluded from java_resources and java_resource_dirs
Exclude_java_resources [ ] string ` android:"path,arch_variant" `
// list of module-specific flags that will be used for javac compiles
Javacflags [ ] string ` android:"arch_variant" `
// list of module-specific flags that will be used for kotlinc compiles
Kotlincflags [ ] string ` android:"arch_variant" `
// list of java libraries that will be in the classpath
Libs [ ] string ` android:"arch_variant" `
// list of java libraries that will be compiled into the resulting jar
Static_libs [ ] string ` android:"arch_variant" `
2023-06-02 00:17:32 +02:00
// list of java libraries that should not be used to build this module
Exclude_static_libs [ ] string ` android:"arch_variant" `
2021-03-17 23:56:23 +01:00
// manifest file to be included in resulting jar
Manifest * string ` android:"path" `
// if not blank, run jarjar using the specified rules file
Jarjar_rules * string ` android:"path,arch_variant" `
2024-02-05 23:46:00 +01:00
// if not blank, used as prefix to generate repackage rule
Jarjar_prefix * string
2024-03-06 19:58:05 +01:00
// if set to true, skip the jarjar repackaging
Skip_jarjar_repackage * bool
2021-03-17 23:56:23 +01:00
// If not blank, set the java version passed to javac as -source and -target
Java_version * string
// If set to true, allow this module to be dexed and installed on devices. Has no
// effect on host modules, which are always considered installable.
Installable * bool
// If set to true, include sources used to compile the module in to the final jar
Include_srcs * bool
// If not empty, classes are restricted to the specified packages and their sub-packages.
// This restriction is checked after applying jarjar rules and including static libs.
Permitted_packages [ ] string
// List of modules to use as annotation processors
Plugins [ ] string
// List of modules to export to libraries that directly depend on this library as annotation
// processors. Note that if the plugins set generates_api: true this will disable the turbine
// optimization on modules that depend on this module, which will reduce parallelism and cause
// more recompilation.
Exported_plugins [ ] string
// The number of Java source entries each Javac instance can process
Javac_shard_size * int64
// Add host jdk tools.jar to bootclasspath
Use_tools_jar * bool
Openjdk9 struct {
// List of source files that should only be used when passing -source 1.9 or higher
Srcs [ ] string ` android:"path" `
// List of javac flags that should only be used when passing -source 1.9 or higher
Javacflags [ ] string
}
// When compiling language level 9+ .java code in packages that are part of
// a system module, patch_module names the module that your sources and
// dependencies should be patched into. The Android runtime currently
// doesn't implement the JEP 261 module system so this option is only
// supported at compile time. It should only be needed to compile tests in
// packages that exist in libcore and which are inconvenient to move
// elsewhere.
2023-10-05 23:02:00 +02:00
Patch_module * string
2021-03-17 23:56:23 +01:00
Jacoco struct {
// List of classes to include for instrumentation with jacoco to collect coverage
// information at runtime when building with coverage enabled. If unset defaults to all
// classes.
// Supports '*' as the last character of an entry in the list as a wildcard match.
// If preceded by '.' it matches all classes in the package and subpackages, otherwise
// it matches classes in the package that have the class name as a prefix.
Include_filter [ ] string
// List of classes to exclude from instrumentation with jacoco to collect coverage
// information at runtime when building with coverage enabled. Overrides classes selected
// by the include_filter property.
// Supports '*' as the last character of an entry in the list as a wildcard match.
// If preceded by '.' it matches all classes in the package and subpackages, otherwise
// it matches classes in the package that have the class name as a prefix.
Exclude_filter [ ] string
}
Errorprone struct {
// List of javac flags that should only be used when running errorprone.
Javacflags [ ] string
// List of java_plugin modules that provide extra errorprone checks.
Extra_check_modules [ ] string
2021-06-14 00:23:16 +02:00
2021-06-18 21:25:54 +02:00
// This property can be in 3 states. When set to true, errorprone will
// be run during the regular build. When set to false, errorprone will
// never be run. When unset, errorprone will be run when the RUN_ERROR_PRONE
// environment variable is true. Setting this to false will improve build
// performance more than adding -XepDisableAllChecks in javacflags.
2021-06-14 00:23:16 +02:00
Enabled * bool
2021-03-17 23:56:23 +01:00
}
Proto struct {
// List of extra options that will be passed to the proto generator.
Output_params [ ] string
}
2022-08-31 21:57:52 +02:00
// If true, then jacocoagent is automatically added as a libs dependency so that
// r8 will not strip instrumentation classes out of dexed libraries.
2021-03-17 23:56:23 +01:00
Instrument bool ` blueprint:"mutated" `
2022-05-03 02:28:40 +02:00
// If true, then the module supports statically including the jacocoagent
// into the library.
Supports_static_instrumentation bool ` blueprint:"mutated" `
2021-03-17 23:56:23 +01:00
// List of files to include in the META-INF/services folder of the resulting jar.
Services [ ] string ` android:"path,arch_variant" `
// If true, package the kotlin stdlib into the jar. Defaults to true.
Static_kotlin_stdlib * bool ` android:"arch_variant" `
// A list of java_library instances that provide additional hiddenapi annotations for the library.
Hiddenapi_additional_annotations [ ] string
2023-06-01 23:42:59 +02:00
// Additional srcJars tacked in by GeneratedJavaLibraryModule
Generated_srcjars [ ] android . Path ` android:"mutated" `
2023-08-22 23:28:11 +02:00
// If true, then only the headers are built and not the implementation jar.
2023-10-05 23:18:44 +02:00
Headers_only * bool
2023-12-14 03:22:18 +01:00
// A list of files or dependencies to make available to the build sandbox. This is
// useful if source files are symlinks, the targets of the symlinks must be listed here.
// Note that currently not all actions implemented by android_apps are sandboxed, so you
// may only see this being necessary in lint builds.
Compile_data [ ] string ` android:"path" `
2024-02-12 23:49:21 +01:00
// Property signifying whether the module compiles stubs or not.
// Should be set to true when srcs of this module are stub files.
// This property does not need to be set to true when the module depends on
// the stubs via libs, but should be set to true when the module depends on
// the stubs via static libs.
Is_stubs_module * bool
2021-03-17 23:56:23 +01:00
}
// Properties that are specific to device modules. Host module factories should not add these when
// constructing a new module.
type DeviceProperties struct {
2021-11-05 20:30:24 +01:00
// If not blank, set to the version of the sdk to compile against.
2022-10-14 18:51:23 +02:00
// Defaults to an empty string, which compiles the module against the private platform APIs.
2021-11-05 20:30:24 +01:00
// Values are of one of the following forms:
2022-04-14 22:18:47 +02:00
// 1) numerical API level, "current", "none", or "core_platform"
// 2) An SDK kind with an API level: "<sdk kind>_<API level>"
// See build/soong/android/sdk_version.go for the complete and up to date list of SDK kinds.
// If the SDK kind is empty, it will be set to public.
2021-03-17 23:56:23 +01:00
Sdk_version * string
// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
2021-11-05 20:30:24 +01:00
// Defaults to sdk_version if not set. See sdk_version for possible values.
2021-03-17 23:56:23 +01:00
Min_sdk_version * string
2021-11-29 18:25:52 +01:00
// if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
// Defaults to empty string "". See sdk_version for possible values.
Max_sdk_version * string
2022-05-17 22:21:50 +02:00
// if not blank, set the maxSdkVersion properties of permission and uses-permission tags.
// Defaults to empty string "". See sdk_version for possible values.
Replace_max_sdk_version_placeholder * string
2021-03-17 23:56:23 +01:00
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
2021-11-05 20:30:24 +01:00
// Defaults to sdk_version if not set. See sdk_version for possible values.
2021-03-17 23:56:23 +01:00
Target_sdk_version * string
// Whether to compile against the platform APIs instead of an SDK.
// If true, then sdk_version must be empty. The value of this field
2022-04-18 21:27:17 +02:00
// is ignored when module's type isn't android_app, android_test, or android_test_helper_app.
2021-03-17 23:56:23 +01:00
Platform_apis * bool
Aidl struct {
// Top level directories to pass to aidl tool
Include_dirs [ ] string
// Directories rooted at the Android.bp file to pass to aidl tool
Local_include_dirs [ ] string
// directories that should be added as include directories for any aidl sources of modules
// that depend on this module, as well as to aidl for this module.
Export_include_dirs [ ] string
// whether to generate traces (for systrace) for this interface
Generate_traces * bool
// whether to generate Binder#GetTransaction name method.
Generate_get_transaction_name * bool
2022-02-10 05:41:46 +01:00
// whether all interfaces should be annotated with required permissions.
Enforce_permissions * bool
// allowlist for interfaces that (temporarily) do not require annotation for permissions.
Enforce_permissions_exceptions [ ] string ` android:"path" `
2021-03-17 23:56:23 +01:00
// list of flags that will be passed to the AIDL compiler
Flags [ ] string
}
// If true, export a copy of the module as a -hostdex module for host testing.
Hostdex * bool
Target struct {
Hostdex struct {
// Additional required dependencies to add to -hostdex modules.
Required [ ] string
}
}
// When targeting 1.9 and above, override the modules to use with --system,
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules * string
IsSDKLibrary bool ` blueprint:"mutated" `
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
// Defaults to false.
V4_signature * bool
// Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
// public stubs library.
SyspropPublicStub string ` blueprint:"mutated" `
2022-07-27 18:27:42 +02:00
HiddenAPIPackageProperties
HiddenAPIFlagFileProperties
2021-03-17 23:56:23 +01:00
}
2024-03-15 10:29:29 +01:00
// Properties that can be overridden by overriding module (e.g. override_android_app)
type OverridableProperties struct {
2022-01-08 04:16:32 +01:00
// set the name of the output. If not set, `name` is used.
// To override a module with this property set, overriding module might need to set this as well.
// Otherwise, both the overridden and the overriding modules will have the same output name, which
// can cause the duplicate output error.
Stem * string
}
2021-03-17 23:56:23 +01:00
// Functionality common to Module and Import
//
// It is embedded in Module so its functionality can be used by methods in Module
// but it is currently only initialized by Import and Library.
type embeddableInModuleAndImport struct {
// Functionality related to this being used as a component of a java_sdk_library.
EmbeddableSdkLibraryComponent
}
2021-06-23 12:39:47 +02:00
func ( e * embeddableInModuleAndImport ) initModuleAndImport ( module android . Module ) {
e . initSdkLibraryComponent ( module )
2021-03-17 23:56:23 +01:00
}
// Module/Import's DepIsInSameApex(...) delegates to this method.
//
// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with
// the one provided by ApexModuleBase.
func ( e * embeddableInModuleAndImport ) depIsInSameApex ( ctx android . BaseModuleContext , dep android . Module ) bool {
// dependencies other than the static linkage are all considered crossing APEX boundary
if staticLibTag == ctx . OtherModuleDependencyTag ( dep ) {
return true
}
return false
}
2021-09-15 04:34:04 +02:00
// OptionalDexJarPath can be either unset, hold a valid path to a dex jar file,
// or an invalid path describing the reason it is invalid.
//
// It is unset if a dex jar isn't applicable, i.e. no build rule has been
// requested to create one.
//
// If a dex jar has been requested to be built then it is set, and it may be
// either a valid android.Path, or invalid with a reason message. The latter
// happens if the source that should produce the dex file isn't able to.
//
// E.g. it is invalid with a reason message if there is a prebuilt APEX that
// could produce the dex jar through a deapexer module, but the APEX isn't
// installable so doing so wouldn't be safe.
type OptionalDexJarPath struct {
isSet bool
path android . OptionalPath
}
// IsSet returns true if a path has been set, either invalid or valid.
func ( o OptionalDexJarPath ) IsSet ( ) bool {
return o . isSet
}
// Valid returns true if there is a path that is valid.
func ( o OptionalDexJarPath ) Valid ( ) bool {
return o . isSet && o . path . Valid ( )
}
// Path returns the valid path, or panics if it's either not set or is invalid.
func ( o OptionalDexJarPath ) Path ( ) android . Path {
if ! o . isSet {
panic ( "path isn't set" )
}
return o . path . Path ( )
}
// PathOrNil returns the path if it's set and valid, or else nil.
func ( o OptionalDexJarPath ) PathOrNil ( ) android . Path {
if o . Valid ( ) {
return o . Path ( )
}
return nil
}
// InvalidReason returns the reason for an invalid path, which is never "". It
// returns "" for an unset or valid path.
func ( o OptionalDexJarPath ) InvalidReason ( ) string {
if ! o . isSet {
return ""
}
return o . path . InvalidReason ( )
}
func ( o OptionalDexJarPath ) String ( ) string {
if ! o . isSet {
return "<unset>"
}
return o . path . String ( )
}
// makeUnsetDexJarPath returns an unset OptionalDexJarPath.
func makeUnsetDexJarPath ( ) OptionalDexJarPath {
return OptionalDexJarPath { isSet : false }
}
// makeDexJarPathFromOptionalPath returns an OptionalDexJarPath that is set with
// the given OptionalPath, which may be valid or invalid.
func makeDexJarPathFromOptionalPath ( path android . OptionalPath ) OptionalDexJarPath {
return OptionalDexJarPath { isSet : true , path : path }
}
// makeDexJarPathFromPath returns an OptionalDexJarPath that is set with the
// valid given path. It returns an unset OptionalDexJarPath if the given path is
// nil.
func makeDexJarPathFromPath ( path android . Path ) OptionalDexJarPath {
if path == nil {
return makeUnsetDexJarPath ( )
}
return makeDexJarPathFromOptionalPath ( android . OptionalPathForPath ( path ) )
}
2021-03-17 23:56:23 +01:00
// Module contains the properties and members used by all java module types
type Module struct {
android . ModuleBase
android . DefaultableModuleBase
android . ApexModuleBase
// Functionality common to Module and Import.
embeddableInModuleAndImport
properties CommonProperties
protoProperties android . ProtoProperties
deviceProperties DeviceProperties
2024-03-15 10:29:29 +01:00
overridableProperties OverridableProperties
2022-01-08 04:16:32 +01:00
2021-03-17 23:56:23 +01:00
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
headerJarFile android . Path
2024-02-05 23:46:00 +01:00
repackagedHeaderJarFile android . Path
2021-03-17 23:56:23 +01:00
// jar file containing implementation classes including static library dependencies but no
// resources
implementationJarFile android . Path
// jar file containing only resources including from static library dependencies
resourceJar android . Path
// args and dependencies to package source files into a srcjar
srcJarArgs [ ] string
srcJarDeps android . Paths
2023-09-20 15:39:57 +02:00
// the source files of this module and all its static dependencies
transitiveSrcFiles * android . DepSet [ android . Path ]
2021-03-17 23:56:23 +01:00
// jar file containing implementation classes and resources including static library
// dependencies
implementationAndResourcesJar android . Path
// output file containing classes.dex and resources
2021-09-15 04:34:04 +02:00
dexJarFile OptionalDexJarPath
2021-03-17 23:56:23 +01:00
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android . Path
// output file of the module, which may be a classes jar or a dex jar
outputFile android . Path
extraOutputFiles android . Paths
2022-02-10 05:41:46 +01:00
exportAidlIncludeDirs android . Paths
ignoredAidlPermissionList android . Paths
2021-03-17 23:56:23 +01:00
logtagsSrcs android . Paths
// installed file for binary dependency
installFile android . Path
2021-11-10 23:38:50 +01:00
// installed file for hostdex copy
hostdexInstallFile android . InstallPath
2022-10-11 05:13:30 +02:00
// list of unique .java and .kt source files
uniqueSrcFiles android . Paths
// list of srcjars that was passed to javac
compiledSrcJars android . Paths
2021-03-17 23:56:23 +01:00
// manifest file to use instead of properties.Manifest
overrideManifest android . OptionalPath
// list of plugins that this java module is exporting
exportedPluginJars android . Paths
// list of plugins that this java module is exporting
exportedPluginClasses [ ] string
// if true, the exported plugins generate API and require disabling turbine.
exportedDisableTurbine bool
// list of source files, collected from srcFiles with unique java and all kt files,
// will be used by android.IDEInfo struct
expandIDEInfoCompiledSrcs [ ] string
// expanded Jarjar_rules
expandJarjarRules android . Path
2024-02-05 23:46:00 +01:00
// jarjar rule for inherited jarjar rules
repackageJarjarRules android . Path
2021-03-17 23:56:23 +01:00
// Extra files generated by the module type to be added as java resources.
extraResources android . Paths
hiddenAPI
dexer
dexpreopter
usesLibrary
linter
// list of the xref extraction files
kytheFiles android . Paths
hideApexVariantFromMake bool
2021-04-02 01:45:46 +02:00
sdkVersion android . SdkSpec
2023-03-03 22:20:36 +01:00
minSdkVersion android . ApiLevel
2023-03-02 01:56:06 +01:00
maxSdkVersion android . ApiLevel
2021-10-29 19:08:48 +02:00
sourceExtensions [ ] string
2023-06-08 08:14:59 +02:00
annoSrcJars android . Paths
2023-07-01 02:13:47 +02:00
// output file name based on Stem property.
// This should be set in every ModuleWithStem's GenerateAndroidBuildActions
// or the module should override Stem().
stem string
2023-07-16 22:20:33 +02:00
2023-11-28 22:14:56 +01:00
// Single aconfig "cache file" merged from this module and all dependencies.
mergedAconfigFiles map [ string ] android . Paths
2024-02-05 23:46:00 +01:00
// Values that will be set in the JarJarProvider data for jarjar repackaging,
// and merged with our dependencies' rules.
jarjarRenameRules map [ string ] string
2024-02-12 23:49:21 +01:00
stubsLinkType StubsLinkType
2021-03-17 23:56:23 +01:00
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) CheckStableSdkVersion ( ctx android . BaseModuleContext ) error {
sdkVersion := j . SdkVersion ( ctx )
2021-03-29 13:11:58 +02:00
if sdkVersion . Stable ( ) {
2021-03-17 23:56:23 +01:00
return nil
}
2021-03-29 13:11:58 +02:00
if sdkVersion . Kind == android . SdkCorePlatform {
2021-03-15 10:39:13 +01:00
if useLegacyCorePlatformApi ( ctx , j . BaseModuleName ( ) ) {
2021-03-17 23:56:23 +01:00
return fmt . Errorf ( "non stable SDK %v - uses legacy core platform" , sdkVersion )
} else {
// Treat stable core platform as stable.
return nil
}
} else {
return fmt . Errorf ( "non stable SDK %v" , sdkVersion )
}
}
// checkSdkVersions enforces restrictions around SDK dependencies.
func ( j * Module ) checkSdkVersions ( ctx android . ModuleContext ) {
if j . RequiresStableAPIs ( ctx ) {
2021-03-29 13:11:58 +02:00
if sc , ok := ctx . Module ( ) . ( android . SdkContext ) ; ok {
2021-04-02 01:45:46 +02:00
if ! sc . SdkVersion ( ctx ) . Specified ( ) {
2021-03-17 23:56:23 +01:00
ctx . PropertyErrorf ( "sdk_version" ,
"sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set)." )
}
}
}
// Make sure this module doesn't statically link to modules with lower-ranked SDK link type.
// See rank() for details.
ctx . VisitDirectDeps ( func ( module android . Module ) {
tag := ctx . OtherModuleDependencyTag ( module )
switch module . ( type ) {
// TODO(satayev): cover other types as well, e.g. imports
case * Library , * AndroidLibrary :
switch tag {
2022-09-23 22:50:56 +02:00
case bootClasspathTag , sdkLibTag , libTag , staticLibTag , java9LibTag :
2021-03-17 23:56:23 +01:00
j . checkSdkLinkType ( ctx , module . ( moduleWithSdkDep ) , tag . ( dependencyTag ) )
}
}
} )
}
func ( j * Module ) checkPlatformAPI ( ctx android . ModuleContext ) {
2021-03-29 13:11:58 +02:00
if sc , ok := ctx . Module ( ) . ( android . SdkContext ) ; ok {
2021-03-17 23:56:23 +01:00
usePlatformAPI := proptools . Bool ( j . deviceProperties . Platform_apis )
2021-04-02 01:45:46 +02:00
sdkVersionSpecified := sc . SdkVersion ( ctx ) . Specified ( )
2021-03-17 23:56:23 +01:00
if usePlatformAPI && sdkVersionSpecified {
2021-11-16 05:15:33 +01:00
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." )
2021-03-17 23:56:23 +01:00
} else if ! usePlatformAPI && ! sdkVersionSpecified {
2021-11-16 05:15:33 +01:00
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" )
2021-03-17 23:56:23 +01:00
}
}
}
2023-08-22 23:28:11 +02:00
func ( j * Module ) checkHeadersOnly ( ctx android . ModuleContext ) {
if _ , ok := ctx . Module ( ) . ( android . SdkContext ) ; ok {
2023-10-05 23:18:44 +02:00
headersOnly := proptools . Bool ( j . properties . Headers_only )
2023-08-22 23:28:11 +02:00
installable := proptools . Bool ( j . properties . Installable )
if headersOnly && installable {
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." )
}
}
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) addHostProperties ( ) {
j . AddProperties (
& j . properties ,
2024-03-15 10:29:29 +01:00
& j . overridableProperties ,
2021-03-17 23:56:23 +01:00
& j . protoProperties ,
& j . usesLibraryProperties ,
)
}
func ( j * Module ) addHostAndDeviceProperties ( ) {
j . addHostProperties ( )
j . AddProperties (
& j . deviceProperties ,
& j . dexer . dexProperties ,
& j . dexpreoptProperties ,
& j . linter . properties ,
)
}
2022-07-27 18:27:42 +02:00
// provideHiddenAPIPropertyInfo populates a HiddenAPIPropertyInfo from hidden API properties and
// makes it available through the hiddenAPIPropertyInfoProvider.
func ( j * Module ) provideHiddenAPIPropertyInfo ( ctx android . ModuleContext ) {
hiddenAPIInfo := newHiddenAPIPropertyInfo ( )
// Populate with flag file paths from the properties.
hiddenAPIInfo . extractFlagFilesFromProperties ( ctx , & j . deviceProperties . HiddenAPIFlagFileProperties )
// Populate with package rules from the properties.
hiddenAPIInfo . extractPackageRulesFromProperties ( & j . deviceProperties . HiddenAPIPackageProperties )
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , hiddenAPIPropertyInfoProvider , hiddenAPIInfo )
2022-07-27 18:27:42 +02:00
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) OutputFiles ( tag string ) ( android . Paths , error ) {
switch tag {
case "" :
return append ( android . Paths { j . outputFile } , j . extraOutputFiles ... ) , nil
case android . DefaultDistTag :
return android . Paths { j . outputFile } , nil
case ".jar" :
return android . Paths { j . implementationAndResourcesJar } , nil
2022-10-14 20:45:44 +02:00
case ".hjar" :
return android . Paths { j . headerJarFile } , nil
2021-03-17 23:56:23 +01:00
case ".proguard_map" :
if j . dexer . proguardDictionary . Valid ( ) {
return android . Paths { j . dexer . proguardDictionary . Path ( ) } , nil
}
return nil , fmt . Errorf ( "%q was requested, but no output file was found." , tag )
2023-08-20 04:48:34 +02:00
case ".generated_srcjars" :
return j . properties . Generated_srcjars , nil
2023-09-29 02:26:43 +02:00
case ".lint" :
if j . linter . outputs . xml != nil {
return android . Paths { j . linter . outputs . xml } , nil
}
return nil , fmt . Errorf ( "%q was requested, but no output file was found." , tag )
2021-03-17 23:56:23 +01:00
default :
return nil , fmt . Errorf ( "unsupported module reference tag %q" , tag )
}
}
var _ android . OutputFileProducer = ( * Module ) ( nil )
func InitJavaModule ( module android . DefaultableModule , hod android . HostOrDeviceSupported ) {
initJavaModule ( module , hod , false )
}
func InitJavaModuleMultiTargets ( module android . DefaultableModule , hod android . HostOrDeviceSupported ) {
initJavaModule ( module , hod , true )
}
func initJavaModule ( module android . DefaultableModule , hod android . HostOrDeviceSupported , multiTargets bool ) {
multilib := android . MultilibCommon
if multiTargets {
android . InitAndroidMultiTargetsArchModule ( module , hod , multilib )
} else {
android . InitAndroidArchModule ( module , hod , multilib )
}
android . InitDefaultableModule ( module )
}
func ( j * Module ) shouldInstrument ( ctx android . BaseModuleContext ) bool {
return j . properties . Instrument &&
ctx . Config ( ) . IsEnvTrue ( "EMMA_INSTRUMENT" ) &&
ctx . DeviceConfig ( ) . JavaCoverageEnabledForPath ( ctx . ModuleDir ( ) )
}
func ( j * Module ) shouldInstrumentStatic ( ctx android . BaseModuleContext ) bool {
2022-05-03 02:28:40 +02:00
return j . properties . Supports_static_instrumentation &&
j . shouldInstrument ( ctx ) &&
2021-03-17 23:56:23 +01:00
( ctx . Config ( ) . IsEnvTrue ( "EMMA_INSTRUMENT_STATIC" ) ||
ctx . Config ( ) . UnbundledBuild ( ) )
}
func ( j * Module ) shouldInstrumentInApex ( ctx android . BaseModuleContext ) bool {
// Force enable the instrumentation for java code that is built for APEXes ...
// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
// doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
2023-12-14 00:54:49 +01:00
apexInfo , _ := android . ModuleProvider ( ctx , android . ApexInfoProvider )
2021-03-17 23:56:23 +01:00
isJacocoAgent := ctx . ModuleName ( ) == "jacocoagent"
if j . DirectlyInAnyApex ( ) && ! isJacocoAgent && ! apexInfo . IsForPlatform ( ) {
if ! inList ( ctx . ModuleName ( ) , config . InstrumentFrameworkModules ) {
return true
} else if ctx . Config ( ) . IsEnvTrue ( "EMMA_INSTRUMENT_FRAMEWORK" ) {
return true
}
}
return false
}
2022-09-07 18:07:07 +02:00
func ( j * Module ) setInstrument ( value bool ) {
j . properties . Instrument = value
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) SdkVersion ( ctx android . EarlyModuleContext ) android . SdkSpec {
return android . SdkSpecFrom ( ctx , String ( j . deviceProperties . Sdk_version ) )
2021-03-17 23:56:23 +01:00
}
2021-03-29 13:11:58 +02:00
func ( j * Module ) SystemModules ( ) string {
2021-03-17 23:56:23 +01:00
return proptools . String ( j . deviceProperties . System_modules )
}
2023-03-03 22:20:36 +01:00
func ( j * Module ) MinSdkVersion ( ctx android . EarlyModuleContext ) android . ApiLevel {
2021-03-17 23:56:23 +01:00
if j . deviceProperties . Min_sdk_version != nil {
2023-03-03 22:20:36 +01:00
return android . ApiLevelFrom ( ctx , * j . deviceProperties . Min_sdk_version )
2021-03-17 23:56:23 +01:00
}
2023-03-03 22:20:36 +01:00
return j . SdkVersion ( ctx ) . ApiLevel
2021-03-17 23:56:23 +01:00
}
2023-09-20 00:09:10 +02:00
func ( j * Module ) GetDeviceProperties ( ) * DeviceProperties {
return & j . deviceProperties
}
2023-03-02 01:56:06 +01:00
func ( j * Module ) MaxSdkVersion ( ctx android . EarlyModuleContext ) android . ApiLevel {
if j . deviceProperties . Max_sdk_version != nil {
return android . ApiLevelFrom ( ctx , * j . deviceProperties . Max_sdk_version )
}
// Default is PrivateApiLevel
return android . SdkSpecPrivate . ApiLevel
2021-11-29 18:25:52 +01:00
}
2023-03-02 01:56:06 +01:00
func ( j * Module ) ReplaceMaxSdkVersionPlaceholder ( ctx android . EarlyModuleContext ) android . ApiLevel {
if j . deviceProperties . Replace_max_sdk_version_placeholder != nil {
return android . ApiLevelFrom ( ctx , * j . deviceProperties . Replace_max_sdk_version_placeholder )
}
// Default is PrivateApiLevel
return android . SdkSpecPrivate . ApiLevel
2022-05-17 22:21:50 +02:00
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) MinSdkVersionString ( ) string {
2023-03-03 22:20:36 +01:00
return j . minSdkVersion . String ( )
2021-03-17 23:56:23 +01:00
}
2023-03-02 00:38:49 +01:00
func ( j * Module ) TargetSdkVersion ( ctx android . EarlyModuleContext ) android . ApiLevel {
2021-04-02 01:45:46 +02:00
if j . deviceProperties . Target_sdk_version != nil {
2023-03-02 00:38:49 +01:00
return android . ApiLevelFrom ( ctx , * j . deviceProperties . Target_sdk_version )
2021-04-02 01:45:46 +02:00
}
2023-03-02 00:38:49 +01:00
return j . SdkVersion ( ctx ) . ApiLevel
2021-03-17 23:56:23 +01:00
}
func ( j * Module ) AvailableFor ( what string ) bool {
if what == android . AvailableToPlatform && Bool ( j . deviceProperties . Hostdex ) {
// Exception: for hostdex: true libraries, the platform variant is created
// even if it's not marked as available to platform. In that case, the platform
// variant is used only for the hostdex and not installed to the device.
return true
}
return j . ApexModuleBase . AvailableFor ( what )
}
func ( j * Module ) deps ( ctx android . BottomUpMutatorContext ) {
if ctx . Device ( ) {
j . linter . deps ( ctx )
2021-03-29 13:11:58 +02:00
sdkDeps ( ctx , android . SdkContext ( j ) , j . dexer )
2021-03-17 23:56:23 +01:00
if j . deviceProperties . SyspropPublicStub != "" {
// This is a sysprop implementation library that has a corresponding sysprop public
// stubs library, and a dependency on it so that dependencies on the implementation can
// be forwarded to the public stubs library when necessary.
ctx . AddVariationDependencies ( nil , syspropPublicStubDepTag , j . deviceProperties . SyspropPublicStub )
}
}
libDeps := ctx . AddVariationDependencies ( nil , libTag , j . properties . Libs ... )
2023-06-02 00:17:32 +02:00
j . properties . Static_libs = android . RemoveListFromList ( j . properties . Static_libs , j . properties . Exclude_static_libs )
2021-03-17 23:56:23 +01:00
ctx . AddVariationDependencies ( nil , staticLibTag , j . properties . Static_libs ... )
// Add dependency on libraries that provide additional hidden api annotations.
ctx . AddVariationDependencies ( nil , hiddenApiAnnotationsTag , j . properties . Hiddenapi_additional_annotations ... )
if ctx . DeviceConfig ( ) . VndkVersion ( ) != "" && ctx . Config ( ) . EnforceInterPartitionJavaSdkLibrary ( ) {
// Require java_sdk_library at inter-partition java dependency to ensure stable
// interface between partitions. If inter-partition java_library dependency is detected,
// raise build error because java_library doesn't have a stable interface.
//
// Inputs:
// PRODUCT_ENFORCE_INTER_PARTITION_JAVA_SDK_LIBRARY
// if true, enable enforcement
// PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
// exception list of java_library names to allow inter-partition dependency
for idx := range j . properties . Libs {
if libDeps [ idx ] == nil {
continue
}
if javaDep , ok := libDeps [ idx ] . ( javaSdkLibraryEnforceContext ) ; ok {
// java_sdk_library is always allowed at inter-partition dependency.
// So, skip check.
if _ , ok := javaDep . ( * SdkLibrary ) ; ok {
continue
}
j . checkPartitionsForJavaDependency ( ctx , "libs" , javaDep )
}
}
}
// For library dependencies that are component libraries (like stubs), add the implementation
// as a dependency (dexpreopt needs to be against the implementation library, not stubs).
for _ , dep := range libDeps {
if dep != nil {
if component , ok := dep . ( SdkLibraryComponentDependency ) ; ok {
if lib := component . OptionalSdkLibraryImplementation ( ) ; lib != nil {
2021-08-12 17:16:11 +02:00
// Add library as optional if it's one of the optional compatibility libs.
2022-05-04 13:00:02 +02:00
tag := usesLibReqTag
if android . InList ( * lib , dexpreopt . OptionalCompatUsesLibs ) {
tag = usesLibOptTag
}
2021-08-12 17:16:11 +02:00
ctx . AddVariationDependencies ( nil , tag , * lib )
2021-03-17 23:56:23 +01:00
}
}
}
}
ctx . AddFarVariationDependencies ( ctx . Config ( ) . BuildOSCommonTarget . Variations ( ) , pluginTag , j . properties . Plugins ... )
ctx . AddFarVariationDependencies ( ctx . Config ( ) . BuildOSCommonTarget . Variations ( ) , errorpronePluginTag , j . properties . Errorprone . Extra_check_modules ... )
ctx . AddFarVariationDependencies ( ctx . Config ( ) . BuildOSCommonTarget . Variations ( ) , exportedPluginTag , j . properties . Exported_plugins ... )
android . ProtoDeps ( ctx , & j . protoProperties )
if j . hasSrcExt ( ".proto" ) {
protoDeps ( ctx , & j . protoProperties )
}
if j . hasSrcExt ( ".kt" ) {
// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
// Kotlin files
ctx . AddVariationDependencies ( nil , kotlinStdlibTag ,
"kotlin-stdlib" , "kotlin-stdlib-jdk7" , "kotlin-stdlib-jdk8" )
2022-05-03 23:20:24 +02:00
ctx . AddVariationDependencies ( nil , kotlinAnnotationsTag , "kotlin-annotations" )
2021-03-17 23:56:23 +01:00
}
// Framework libraries need special handling in static coverage builds: they should not have
// static dependency on jacoco, otherwise there would be multiple conflicting definitions of
// the same jacoco classes coming from different bootclasspath jars.
if inList ( ctx . ModuleName ( ) , config . InstrumentFrameworkModules ) {
if ctx . Config ( ) . IsEnvTrue ( "EMMA_INSTRUMENT_FRAMEWORK" ) {
j . properties . Instrument = true
}
} else if j . shouldInstrumentStatic ( ctx ) {
ctx . AddVariationDependencies ( nil , staticLibTag , "jacocoagent" )
}
2021-09-17 23:11:52 +02:00
if j . useCompose ( ) {
ctx . AddVariationDependencies ( ctx . Config ( ) . BuildOSCommonTarget . Variations ( ) , kotlinPluginTag ,
"androidx.compose.compiler_compiler-hosted" )
}
2021-03-17 23:56:23 +01:00
}
func hasSrcExt ( srcs [ ] string , ext string ) bool {
for _ , src := range srcs {
if filepath . Ext ( src ) == ext {
return true
}
}
return false
}
func ( j * Module ) hasSrcExt ( ext string ) bool {
return hasSrcExt ( j . properties . Srcs , ext )
}
2022-02-10 05:41:46 +01:00
func ( j * Module ) individualAidlFlags ( ctx android . ModuleContext , aidlFile android . Path ) string {
var flags string
if Bool ( j . deviceProperties . Aidl . Enforce_permissions ) {
if ! android . InList ( aidlFile . String ( ) , j . ignoredAidlPermissionList . Strings ( ) ) {
flags = "-Wmissing-permission-annotation -Werror"
}
}
return flags
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) aidlFlags ( ctx android . ModuleContext , aidlPreprocess android . OptionalPath ,
2022-05-24 19:10:02 +02:00
aidlIncludeDirs android . Paths , aidlSrcs android . Paths ) ( string , android . Paths ) {
2021-03-17 23:56:23 +01:00
aidlIncludes := android . PathsForModuleSrc ( ctx , j . deviceProperties . Aidl . Local_include_dirs )
aidlIncludes = append ( aidlIncludes ,
android . PathsForModuleSrc ( ctx , j . deviceProperties . Aidl . Export_include_dirs ) ... )
aidlIncludes = append ( aidlIncludes ,
android . PathsForSource ( ctx , j . deviceProperties . Aidl . Include_dirs ) ... )
var flags [ ] string
var deps android . Paths
2022-05-24 19:10:02 +02:00
var includeDirs android . Paths
2021-03-17 23:56:23 +01:00
flags = append ( flags , j . deviceProperties . Aidl . Flags ... )
if aidlPreprocess . Valid ( ) {
flags = append ( flags , "-p" + aidlPreprocess . String ( ) )
deps = append ( deps , aidlPreprocess . Path ( ) )
} else if len ( aidlIncludeDirs ) > 0 {
2022-05-24 19:10:02 +02:00
includeDirs = append ( includeDirs , aidlIncludeDirs ... )
2021-03-17 23:56:23 +01:00
}
if len ( j . exportAidlIncludeDirs ) > 0 {
2022-05-24 19:10:02 +02:00
includeDirs = append ( includeDirs , j . exportAidlIncludeDirs ... )
2021-03-17 23:56:23 +01:00
}
if len ( aidlIncludes ) > 0 {
2022-05-24 19:10:02 +02:00
includeDirs = append ( includeDirs , aidlIncludes ... )
2021-03-17 23:56:23 +01:00
}
2022-05-24 19:10:02 +02:00
includeDirs = append ( includeDirs , android . PathForModuleSrc ( ctx ) )
2021-03-17 23:56:23 +01:00
if src := android . ExistentPathForSource ( ctx , ctx . ModuleDir ( ) , "src" ) ; src . Valid ( ) {
2022-05-24 19:10:02 +02:00
includeDirs = append ( includeDirs , src . Path ( ) )
2021-03-17 23:56:23 +01:00
}
2022-05-24 19:10:02 +02:00
flags = append ( flags , android . JoinWithPrefix ( includeDirs . Strings ( ) , "-I" ) )
// add flags for dirs containing AIDL srcs that haven't been specified yet
flags = append ( flags , genAidlIncludeFlags ( ctx , aidlSrcs , includeDirs ) )
2021-03-17 23:56:23 +01:00
2022-08-17 12:46:34 +02:00
sdkVersion := ( j . SdkVersion ( ctx ) ) . Kind
2022-11-22 14:01:22 +01:00
defaultTrace := ( ( sdkVersion == android . SdkSystemServer ) || ( sdkVersion == android . SdkCore ) || ( sdkVersion == android . SdkCorePlatform ) || ( sdkVersion == android . SdkModule ) || ( sdkVersion == android . SdkSystem ) )
2022-08-17 12:46:34 +02:00
if proptools . BoolDefault ( j . deviceProperties . Aidl . Generate_traces , defaultTrace ) {
2021-03-17 23:56:23 +01:00
flags = append ( flags , "-t" )
}
if Bool ( j . deviceProperties . Aidl . Generate_get_transaction_name ) {
flags = append ( flags , "--transaction_names" )
}
2022-02-10 05:41:46 +01:00
if Bool ( j . deviceProperties . Aidl . Enforce_permissions ) {
exceptions := j . deviceProperties . Aidl . Enforce_permissions_exceptions
j . ignoredAidlPermissionList = android . PathsForModuleSrcExcludes ( ctx , exceptions , nil )
}
2023-03-03 22:20:36 +01:00
aidlMinSdkVersion := j . MinSdkVersion ( ctx ) . String ( )
2021-11-05 23:08:45 +01:00
flags = append ( flags , "--min_sdk_version=" + aidlMinSdkVersion )
2021-03-17 23:56:23 +01:00
return strings . Join ( flags , " " ) , deps
}
func ( j * Module ) collectBuilderFlags ( ctx android . ModuleContext , deps deps ) javaBuilderFlags {
var flags javaBuilderFlags
// javaVersion flag.
2021-03-29 13:11:58 +02:00
flags . javaVersion = getJavaVersion ( ctx , String ( j . properties . Java_version ) , android . SdkContext ( j ) )
2021-03-17 23:56:23 +01:00
2021-06-18 21:25:54 +02:00
epEnabled := j . properties . Errorprone . Enabled
if ( ctx . Config ( ) . RunErrorProne ( ) && epEnabled == nil ) || Bool ( epEnabled ) {
2022-10-06 12:01:59 +02:00
if config . ErrorProneClasspath == nil && ! ctx . Config ( ) . RunningInsideUnitTest ( ) {
2021-03-17 23:56:23 +01:00
ctx . ModuleErrorf ( "cannot build with Error Prone, missing external/error_prone?" )
}
errorProneFlags := [ ] string {
"-Xplugin:ErrorProne" ,
"${config.ErrorProneChecks}" ,
}
errorProneFlags = append ( errorProneFlags , j . properties . Errorprone . Javacflags ... )
2022-02-28 22:07:03 +01:00
flags . errorProneExtraJavacFlags = "${config.ErrorProneHeapFlags} ${config.ErrorProneFlags} " +
2021-03-17 23:56:23 +01:00
"'" + strings . Join ( errorProneFlags , " " ) + "'"
flags . errorProneProcessorPath = classpath ( android . PathsForSource ( ctx , config . ErrorProneClasspath ) )
}
// classpath
flags . bootClasspath = append ( flags . bootClasspath , deps . bootClasspath ... )
flags . classpath = append ( flags . classpath , deps . classpath ... )
2022-03-17 19:12:32 +01:00
flags . dexClasspath = append ( flags . dexClasspath , deps . dexClasspath ... )
2021-03-17 23:56:23 +01:00
flags . java9Classpath = append ( flags . java9Classpath , deps . java9Classpath ... )
flags . processorPath = append ( flags . processorPath , deps . processorPath ... )
flags . errorProneProcessorPath = append ( flags . errorProneProcessorPath , deps . errorProneProcessorPath ... )
flags . processors = append ( flags . processors , deps . processorClasses ... )
flags . processors = android . FirstUniqueStrings ( flags . processors )
if len ( flags . bootClasspath ) == 0 && ctx . Host ( ) && ! flags . javaVersion . usesJavaModules ( ) &&
2021-03-29 13:11:58 +02:00
decodeSdkDep ( ctx , android . SdkContext ( j ) ) . hasStandardLibs ( ) {
2021-03-17 23:56:23 +01:00
// Give host-side tools a version of OpenJDK's standard libraries
// close to what they're targeting. As of Dec 2017, AOSP is only
// bundling OpenJDK 8 and 9, so nothing < 8 is available.
//
// When building with OpenJDK 8, the following should have no
// effect since those jars would be available by default.
//
// When building with OpenJDK 9 but targeting a version < 1.8,
// putting them on the bootclasspath means that:
// a) code can't (accidentally) refer to OpenJDK 9 specific APIs
// b) references to existing APIs are not reinterpreted in an
// OpenJDK 9-specific way, eg. calls to subclasses of
// java.nio.Buffer as in http://b/70862583
java8Home := ctx . Config ( ) . Getenv ( "ANDROID_JAVA8_HOME" )
flags . bootClasspath = append ( flags . bootClasspath ,
android . PathForSource ( ctx , java8Home , "jre/lib/jce.jar" ) ,
android . PathForSource ( ctx , java8Home , "jre/lib/rt.jar" ) )
if Bool ( j . properties . Use_tools_jar ) {
flags . bootClasspath = append ( flags . bootClasspath ,
android . PathForSource ( ctx , java8Home , "lib/tools.jar" ) )
}
}
// systemModules
flags . systemModules = deps . systemModules
return flags
}
func ( j * Module ) collectJavacFlags (
ctx android . ModuleContext , flags javaBuilderFlags , srcFiles android . Paths ) javaBuilderFlags {
// javac flags.
javacFlags := j . properties . Javacflags
2023-10-25 17:17:11 +02:00
var needsDebugInfo bool
2021-03-17 23:56:23 +01:00
2023-10-25 17:17:11 +02:00
needsDebugInfo = false
for _ , flag := range javacFlags {
if strings . HasPrefix ( flag , "-g" ) {
needsDebugInfo = true
}
}
if ctx . Config ( ) . MinimizeJavaDebugInfo ( ) && ! ctx . Host ( ) && ! needsDebugInfo {
2021-03-17 23:56:23 +01:00
// For non-host binaries, override the -g flag passed globally to remove
// local variable debug info to reduce disk and memory usage.
javacFlags = append ( javacFlags , "-g:source,lines" )
}
javacFlags = append ( javacFlags , "-Xlint:-dep-ann" )
if flags . javaVersion . usesJavaModules ( ) {
javacFlags = append ( javacFlags , j . properties . Openjdk9 . Javacflags ... )
2023-10-06 22:47:00 +02:00
} else if len ( j . properties . Openjdk9 . Javacflags ) > 0 {
// java version defaults higher than openjdk 9, these conditionals should no longer be necessary
ctx . PropertyErrorf ( "openjdk9.javacflags" , "JDK version defaults to higher than 9" )
}
2021-03-17 23:56:23 +01:00
2023-10-06 22:47:00 +02:00
if flags . javaVersion . usesJavaModules ( ) {
2021-03-17 23:56:23 +01:00
if j . properties . Patch_module != nil {
// Manually specify build directory in case it is not under the repo root.
// (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
// just adding a symlink under the root doesn't help.)
2021-08-26 15:07:24 +02:00
patchPaths := [ ] string { "." , ctx . Config ( ) . SoongOutDir ( ) }
2021-03-17 23:56:23 +01:00
classPath := flags . classpath . FormJavaClassPath ( "" )
if classPath != "" {
patchPaths = append ( patchPaths , classPath )
}
javacFlags = append (
javacFlags ,
"--patch-module=" + String ( j . properties . Patch_module ) + "=" + strings . Join ( patchPaths , ":" ) )
}
}
if len ( javacFlags ) > 0 {
// optimization.
ctx . Variable ( pctx , "javacFlags" , strings . Join ( javacFlags , " " ) )
flags . javacFlags = "$javacFlags"
}
return flags
}
2021-10-29 19:08:48 +02:00
func ( j * Module ) AddJSONData ( d * map [ string ] interface { } ) {
( & j . ModuleBase ) . AddJSONData ( d )
( * d ) [ "Java" ] = map [ string ] interface { } {
"SourceExtensions" : j . sourceExtensions ,
}
}
2023-09-19 21:51:59 +02:00
func ( j * Module ) addGeneratedSrcJars ( path android . Path ) {
j . properties . Generated_srcjars = append ( j . properties . Generated_srcjars , path )
2023-06-01 23:42:59 +02:00
}
2023-06-21 07:40:02 +02:00
func ( j * Module ) compile ( ctx android . ModuleContext , extraSrcJars , extraClasspathJars , extraCombinedJars android . Paths ) {
2024-02-05 23:46:00 +01:00
// Auto-propagating jarjar rules
jarjarProviderData := j . collectJarJarRules ( ctx )
if jarjarProviderData != nil {
android . SetProvider ( ctx , JarJarProvider , * jarjarProviderData )
2024-03-06 19:58:05 +01:00
if ! proptools . Bool ( j . properties . Skip_jarjar_repackage ) {
text := getJarJarRuleText ( jarjarProviderData )
if text != "" {
ruleTextFile := android . PathForModuleOut ( ctx , "repackaged-jarjar" , "repackaging.txt" )
android . WriteFileRule ( ctx , ruleTextFile , text )
j . repackageJarjarRules = ruleTextFile
}
2024-02-05 23:46:00 +01:00
}
}
2021-03-17 23:56:23 +01:00
j . exportAidlIncludeDirs = android . PathsForModuleSrc ( ctx , j . deviceProperties . Aidl . Export_include_dirs )
deps := j . collectDeps ( ctx )
flags := j . collectBuilderFlags ( ctx , deps )
if flags . javaVersion . usesJavaModules ( ) {
j . properties . Srcs = append ( j . properties . Srcs , j . properties . Openjdk9 . Srcs ... )
2023-10-06 22:47:00 +02:00
} else if len ( j . properties . Openjdk9 . Javacflags ) > 0 {
// java version defaults higher than openjdk 9, these conditionals should no longer be necessary
ctx . PropertyErrorf ( "openjdk9.srcs" , "JDK version defaults to higher than 9" )
2021-03-17 23:56:23 +01:00
}
2021-12-20 12:51:24 +01:00
2021-03-17 23:56:23 +01:00
srcFiles := android . PathsForModuleSrcExcludes ( ctx , j . properties . Srcs , j . properties . Exclude_srcs )
2021-10-29 19:08:48 +02:00
j . sourceExtensions = [ ] string { }
for _ , ext := range [ ] string { ".kt" , ".proto" , ".aidl" , ".java" , ".logtags" } {
if hasSrcExt ( srcFiles . Strings ( ) , ext ) {
j . sourceExtensions = append ( j . sourceExtensions , ext )
}
}
2021-03-17 23:56:23 +01:00
if hasSrcExt ( srcFiles . Strings ( ) , ".proto" ) {
flags = protoFlags ( ctx , & j . properties , & j . protoProperties , flags )
}
kotlinCommonSrcFiles := android . PathsForModuleSrcExcludes ( ctx , j . properties . Common_srcs , nil )
if len ( kotlinCommonSrcFiles . FilterOutByExt ( ".kt" ) ) > 0 {
ctx . PropertyErrorf ( "common_srcs" , "common_srcs must be .kt files" )
}
2022-05-24 19:10:02 +02:00
aidlSrcs := srcFiles . FilterByExt ( ".aidl" )
flags . aidlFlags , flags . aidlDeps = j . aidlFlags ( ctx , deps . aidlPreprocess , deps . aidlIncludeDirs , aidlSrcs )
2022-05-05 06:49:02 +02:00
nonGeneratedSrcJars := srcFiles . FilterByExt ( ".srcjar" )
2021-03-17 23:56:23 +01:00
srcFiles = j . genSources ( ctx , srcFiles , flags )
// Collect javac flags only after computing the full set of srcFiles to
// ensure that the --patch-module lookup paths are complete.
flags = j . collectJavacFlags ( ctx , flags , srcFiles )
srcJars := srcFiles . FilterByExt ( ".srcjar" )
srcJars = append ( srcJars , deps . srcJars ... )
2023-06-21 07:40:02 +02:00
srcJars = append ( srcJars , extraSrcJars ... )
2023-06-01 23:42:59 +02:00
srcJars = append ( srcJars , j . properties . Generated_srcjars ... )
2021-06-29 19:42:00 +02:00
srcFiles = srcFiles . FilterOutByExt ( ".srcjar" )
2021-03-17 23:56:23 +01:00
if j . properties . Jarjar_rules != nil {
j . expandJarjarRules = android . PathForModuleSrc ( ctx , * j . properties . Jarjar_rules )
}
2023-07-01 02:13:47 +02:00
jarName := j . Stem ( ) + ".jar"
2021-03-17 23:56:23 +01:00
2022-10-11 05:13:30 +02:00
var uniqueJavaFiles android . Paths
2021-03-17 23:56:23 +01:00
set := make ( map [ string ] bool )
2022-10-11 05:13:30 +02:00
for _ , v := range srcFiles . FilterByExt ( ".java" ) {
2021-03-17 23:56:23 +01:00
if _ , found := set [ v . String ( ) ] ; ! found {
set [ v . String ( ) ] = true
2022-10-11 05:13:30 +02:00
uniqueJavaFiles = append ( uniqueJavaFiles , v )
2021-03-17 23:56:23 +01:00
}
}
2022-10-11 05:13:30 +02:00
var uniqueKtFiles android . Paths
for _ , v := range srcFiles . FilterByExt ( ".kt" ) {
if _ , found := set [ v . String ( ) ] ; ! found {
set [ v . String ( ) ] = true
uniqueKtFiles = append ( uniqueKtFiles , v )
}
}
var uniqueSrcFiles android . Paths
uniqueSrcFiles = append ( uniqueSrcFiles , uniqueJavaFiles ... )
uniqueSrcFiles = append ( uniqueSrcFiles , uniqueKtFiles ... )
j . uniqueSrcFiles = uniqueSrcFiles
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , blueprint . SrcsFileProviderKey , blueprint . SrcsFileProviderData { SrcPaths : uniqueSrcFiles . Strings ( ) } )
2021-03-17 23:56:23 +01:00
2022-03-29 02:12:39 +02:00
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
// exception (handled further below) is when kotlin sources are enabled, in which case turbine
// is used to run all of the annotation processors.
disableTurbine := deps . disableTurbine
2022-10-11 05:13:30 +02:00
// Collect .java and .kt files for AIDEGen
2021-03-17 23:56:23 +01:00
j . expandIDEInfoCompiledSrcs = append ( j . expandIDEInfoCompiledSrcs , uniqueSrcFiles . Strings ( ) ... )
var kotlinJars android . Paths
2022-03-29 02:08:01 +02:00
var kotlinHeaderJars android . Paths
2021-03-17 23:56:23 +01:00
2023-06-21 07:40:02 +02:00
// Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
// any dependencies so that it can override any non-final R classes from dependencies with the
// final R classes from the app.
flags . classpath = append ( android . CopyOf ( extraClasspathJars ) , flags . classpath ... )
2023-08-22 23:28:11 +02:00
// If compiling headers then compile them and skip the rest
2023-10-05 23:18:44 +02:00
if proptools . Bool ( j . properties . Headers_only ) {
2023-08-22 23:28:11 +02:00
if srcFiles . HasExt ( ".kt" ) {
ctx . ModuleErrorf ( "Compiling headers_only with .kt not supported" )
}
if ctx . Config ( ) . IsEnvFalse ( "TURBINE_ENABLED" ) || disableTurbine {
ctx . ModuleErrorf ( "headers_only is enabled but Turbine is disabled." )
}
2024-02-05 23:46:00 +01:00
_ , j . headerJarFile , _ =
2023-08-22 23:28:11 +02:00
j . compileJavaHeader ( ctx , uniqueJavaFiles , srcJars , deps , flags , jarName ,
extraCombinedJars )
if ctx . Failed ( ) {
return
}
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , JavaInfoProvider , JavaInfo {
2024-03-13 02:21:16 +01:00
HeaderJars : android . PathsIfNonNil ( j . headerJarFile ) ,
TransitiveLibsHeaderJars : j . transitiveLibsHeaderJars ,
TransitiveStaticLibsHeaderJars : j . transitiveStaticLibsHeaderJars ,
AidlIncludeDirs : j . exportAidlIncludeDirs ,
ExportedPlugins : j . exportedPluginJars ,
ExportedPluginClasses : j . exportedPluginClasses ,
ExportedPluginDisableTurbine : j . exportedDisableTurbine ,
StubsLinkType : j . stubsLinkType ,
AconfigIntermediateCacheOutputPaths : deps . aconfigProtoFiles ,
2023-08-22 23:28:11 +02:00
} )
j . outputFile = j . headerJarFile
return
}
2021-03-17 23:56:23 +01:00
if srcFiles . HasExt ( ".kt" ) {
2022-03-29 02:12:39 +02:00
// When using kotlin sources turbine is used to generate annotation processor sources,
// including for annotation processors that generate API, so we can use turbine for
// java sources too.
disableTurbine = false
2021-03-17 23:56:23 +01:00
// user defined kotlin flags.
kotlincFlags := j . properties . Kotlincflags
CheckKotlincFlags ( ctx , kotlincFlags )
2021-05-17 19:47:10 +02:00
// Workaround for KT-46512
kotlincFlags = append ( kotlincFlags , "-Xsam-conversions=class" )
2021-03-17 23:56:23 +01:00
// If there are kotlin files, compile them first but pass all the kotlin and java files
// kotlinc will use the java files to resolve types referenced by the kotlin files, but
// won't emit any classes for them.
kotlincFlags = append ( kotlincFlags , "-no-stdlib" )
if ctx . Device ( ) {
kotlincFlags = append ( kotlincFlags , "-no-jdk" )
}
2021-09-17 23:11:52 +02:00
for _ , plugin := range deps . kotlinPlugins {
kotlincFlags = append ( kotlincFlags , "-Xplugin=" + plugin . String ( ) )
}
flags . kotlincDeps = append ( flags . kotlincDeps , deps . kotlinPlugins ... )
2021-03-17 23:56:23 +01:00
if len ( kotlincFlags ) > 0 {
// optimization.
ctx . Variable ( pctx , "kotlincFlags" , strings . Join ( kotlincFlags , " " ) )
flags . kotlincFlags += "$kotlincFlags"
}
2022-10-11 05:13:30 +02:00
// Collect common .kt files for AIDEGen
2021-03-17 23:56:23 +01:00
j . expandIDEInfoCompiledSrcs = append ( j . expandIDEInfoCompiledSrcs , kotlinCommonSrcFiles . Strings ( ) ... )
flags . classpath = append ( flags . classpath , deps . kotlinStdlib ... )
flags . classpath = append ( flags . classpath , deps . kotlinAnnotations ... )
flags . kotlincClasspath = append ( flags . kotlincClasspath , flags . bootClasspath ... )
flags . kotlincClasspath = append ( flags . kotlincClasspath , flags . classpath ... )
2022-04-06 08:14:38 +02:00
if len ( flags . processorPath ) > 0 {
2021-03-17 23:56:23 +01:00
// Use kapt for annotation processing
2022-04-06 08:14:38 +02:00
kaptSrcJar := android . PathForModuleOut ( ctx , "kapt" , "kapt-sources.jar" )
kaptResJar := android . PathForModuleOut ( ctx , "kapt" , "kapt-res.jar" )
2022-10-11 05:13:30 +02:00
kotlinKapt ( ctx , kaptSrcJar , kaptResJar , uniqueSrcFiles , kotlinCommonSrcFiles , srcJars , flags )
2022-04-06 08:14:38 +02:00
srcJars = append ( srcJars , kaptSrcJar )
kotlinJars = append ( kotlinJars , kaptResJar )
2021-03-17 23:56:23 +01:00
// Disable annotation processing in javac, it's already been handled by kapt
flags . processorPath = nil
flags . processors = nil
}
kotlinJar := android . PathForModuleOut ( ctx , "kotlin" , jarName )
2022-03-29 02:08:01 +02:00
kotlinHeaderJar := android . PathForModuleOut ( ctx , "kotlin_headers" , jarName )
2022-10-11 05:13:30 +02:00
kotlinCompile ( ctx , kotlinJar , kotlinHeaderJar , uniqueSrcFiles , kotlinCommonSrcFiles , srcJars , flags )
2021-03-17 23:56:23 +01:00
if ctx . Failed ( ) {
return
}
2022-04-06 08:14:38 +02:00
// Make javac rule depend on the kotlinc rule
flags . classpath = append ( classpath { kotlinHeaderJar } , flags . classpath ... )
2021-03-17 23:56:23 +01:00
kotlinJars = append ( kotlinJars , kotlinJar )
2022-03-29 02:08:01 +02:00
kotlinHeaderJars = append ( kotlinHeaderJars , kotlinHeaderJar )
2021-03-17 23:56:23 +01:00
// Jar kotlin classes into the final jar after javac
if BoolDefault ( j . properties . Static_kotlin_stdlib , true ) {
kotlinJars = append ( kotlinJars , deps . kotlinStdlib ... )
2022-05-03 23:20:24 +02:00
kotlinJars = append ( kotlinJars , deps . kotlinAnnotations ... )
2022-03-29 02:08:01 +02:00
kotlinHeaderJars = append ( kotlinHeaderJars , deps . kotlinStdlib ... )
2022-05-03 23:20:24 +02:00
kotlinHeaderJars = append ( kotlinHeaderJars , deps . kotlinAnnotations ... )
2022-03-17 19:12:32 +01:00
} else {
flags . dexClasspath = append ( flags . dexClasspath , deps . kotlinStdlib ... )
2022-05-03 23:20:24 +02:00
flags . dexClasspath = append ( flags . dexClasspath , deps . kotlinAnnotations ... )
2021-03-17 23:56:23 +01:00
}
}
2024-02-23 19:05:21 +01:00
jars := slices . Clone ( kotlinJars )
2021-03-17 23:56:23 +01:00
j . compiledSrcJars = srcJars
enableSharding := false
2021-11-19 07:23:12 +01:00
var headerJarFileWithoutDepsOrJarjar android . Path
2022-03-29 02:12:39 +02:00
if ctx . Device ( ) && ! ctx . Config ( ) . IsEnvFalse ( "TURBINE_ENABLED" ) && ! disableTurbine {
2021-03-17 23:56:23 +01:00
if j . properties . Javac_shard_size != nil && * ( j . properties . Javac_shard_size ) > 0 {
enableSharding = true
// Formerly, there was a check here that prevented annotation processors
// from being used when sharding was enabled, as some annotation processors
// do not function correctly in sharded environments. It was removed to
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
2024-02-23 19:05:21 +01:00
extraJars := append ( slices . Clone ( kotlinHeaderJars ) , extraCombinedJars ... )
2024-02-05 23:46:00 +01:00
headerJarFileWithoutDepsOrJarjar , j . headerJarFile , j . repackagedHeaderJarFile =
2023-06-21 07:40:02 +02:00
j . compileJavaHeader ( ctx , uniqueJavaFiles , srcJars , deps , flags , jarName , extraJars )
2021-03-17 23:56:23 +01:00
if ctx . Failed ( ) {
return
}
}
2022-10-11 05:13:30 +02:00
if len ( uniqueJavaFiles ) > 0 || len ( srcJars ) > 0 {
2022-08-24 20:22:52 +02:00
hasErrorproneableFiles := false
for _ , ext := range j . sourceExtensions {
if ext != ".proto" && ext != ".aidl" {
// Skip running errorprone on pure proto or pure aidl modules. Some modules take a long time to
// compile, and it's not useful to have warnings on these generated sources.
hasErrorproneableFiles = true
break
}
}
2021-03-17 23:56:23 +01:00
var extraJarDeps android . Paths
2021-06-14 00:23:16 +02:00
if Bool ( j . properties . Errorprone . Enabled ) {
// If error-prone is enabled, enable errorprone flags on the regular
// build.
flags = enableErrorproneFlags ( flags )
2022-08-24 20:22:52 +02:00
} else if hasErrorproneableFiles && ctx . Config ( ) . RunErrorProne ( ) && j . properties . Errorprone . Enabled == nil {
2021-06-14 00:23:16 +02:00
// Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
// a new jar file just for compiling with the errorprone compiler to.
// This is because we don't want to cause the java files to get completely
// rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
// We also don't want to run this if errorprone is enabled by default for
// this module, or else we could have duplicated errorprone messages.
errorproneFlags := enableErrorproneFlags ( flags )
2021-03-17 23:56:23 +01:00
errorprone := android . PathForModuleOut ( ctx , "errorprone" , jarName )
2023-06-08 08:14:59 +02:00
errorproneAnnoSrcJar := android . PathForModuleOut ( ctx , "errorprone" , "anno.srcjar" )
2021-06-14 00:23:16 +02:00
2023-06-08 08:14:59 +02:00
transformJavaToClasses ( ctx , errorprone , - 1 , uniqueJavaFiles , srcJars , errorproneAnnoSrcJar , errorproneFlags , nil ,
2021-06-14 00:23:16 +02:00
"errorprone" , "errorprone" )
2021-03-17 23:56:23 +01:00
extraJarDeps = append ( extraJarDeps , errorprone )
}
if enableSharding {
2021-11-19 07:23:12 +01:00
if headerJarFileWithoutDepsOrJarjar != nil {
flags . classpath = append ( classpath { headerJarFileWithoutDepsOrJarjar } , flags . classpath ... )
}
2021-03-17 23:56:23 +01:00
shardSize := int ( * ( j . properties . Javac_shard_size ) )
var shardSrcs [ ] android . Paths
2022-10-11 05:13:30 +02:00
if len ( uniqueJavaFiles ) > 0 {
shardSrcs = android . ShardPaths ( uniqueJavaFiles , shardSize )
2021-03-17 23:56:23 +01:00
for idx , shardSrc := range shardSrcs {
classes := j . compileJavaClasses ( ctx , jarName , idx , shardSrc ,
nil , flags , extraJarDeps )
jars = append ( jars , classes )
}
}
2023-09-26 06:46:58 +02:00
// Assume approximately 5 sources per srcjar.
// For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean
// of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files.
2021-03-17 23:56:23 +01:00
if len ( srcJars ) > 0 {
2023-09-26 06:46:58 +02:00
startIdx := len ( shardSrcs )
shardSrcJarsList := android . ShardPaths ( srcJars , shardSize / 5 )
for idx , shardSrcJars := range shardSrcJarsList {
classes := j . compileJavaClasses ( ctx , jarName , startIdx + idx ,
nil , shardSrcJars , flags , extraJarDeps )
jars = append ( jars , classes )
}
2021-03-17 23:56:23 +01:00
}
} else {
2022-10-11 05:13:30 +02:00
classes := j . compileJavaClasses ( ctx , jarName , - 1 , uniqueJavaFiles , srcJars , flags , extraJarDeps )
2021-03-17 23:56:23 +01:00
jars = append ( jars , classes )
}
if ctx . Failed ( ) {
return
}
}
2024-02-23 19:05:21 +01:00
jars = append ( jars , extraCombinedJars ... )
2021-03-17 23:56:23 +01:00
j . srcJarArgs , j . srcJarDeps = resourcePathsToJarArgs ( srcFiles ) , srcFiles
var includeSrcJar android . WritablePath
if Bool ( j . properties . Include_srcs ) {
includeSrcJar = android . PathForModuleOut ( ctx , ctx . ModuleName ( ) + ".srcjar" )
TransformResourcesToJar ( ctx , includeSrcJar , j . srcJarArgs , j . srcJarDeps )
}
dirArgs , dirDeps := ResourceDirsToJarArgs ( ctx , j . properties . Java_resource_dirs ,
j . properties . Exclude_java_resource_dirs , j . properties . Exclude_java_resources )
fileArgs , fileDeps := ResourceFilesToJarArgs ( ctx , j . properties . Java_resources , j . properties . Exclude_java_resources )
extraArgs , extraDeps := resourcePathsToJarArgs ( j . extraResources ) , j . extraResources
var resArgs [ ] string
var resDeps android . Paths
resArgs = append ( resArgs , dirArgs ... )
resDeps = append ( resDeps , dirDeps ... )
resArgs = append ( resArgs , fileArgs ... )
resDeps = append ( resDeps , fileDeps ... )
resArgs = append ( resArgs , extraArgs ... )
resDeps = append ( resDeps , extraDeps ... )
if len ( resArgs ) > 0 {
resourceJar := android . PathForModuleOut ( ctx , "res" , jarName )
TransformResourcesToJar ( ctx , resourceJar , resArgs , resDeps )
j . resourceJar = resourceJar
if ctx . Failed ( ) {
return
}
}
var resourceJars android . Paths
if j . resourceJar != nil {
resourceJars = append ( resourceJars , j . resourceJar )
}
if Bool ( j . properties . Include_srcs ) {
resourceJars = append ( resourceJars , includeSrcJar )
}
resourceJars = append ( resourceJars , deps . staticResourceJars ... )
if len ( resourceJars ) > 1 {
combinedJar := android . PathForModuleOut ( ctx , "res-combined" , jarName )
TransformJarsToJar ( ctx , combinedJar , "for resources" , resourceJars , android . OptionalPath { } ,
false , nil , nil )
j . resourceJar = combinedJar
} else if len ( resourceJars ) == 1 {
j . resourceJar = resourceJars [ 0 ]
}
if len ( deps . staticJars ) > 0 {
jars = append ( jars , deps . staticJars ... )
}
manifest := j . overrideManifest
if ! manifest . Valid ( ) && j . properties . Manifest != nil {
manifest = android . OptionalPathForPath ( android . PathForModuleSrc ( ctx , * j . properties . Manifest ) )
}
services := android . PathsForModuleSrc ( ctx , j . properties . Services )
if len ( services ) > 0 {
servicesJar := android . PathForModuleOut ( ctx , "services" , jarName )
var zipargs [ ] string
for _ , file := range services {
serviceFile := file . String ( )
zipargs = append ( zipargs , "-C" , filepath . Dir ( serviceFile ) , "-f" , serviceFile )
}
rule := zip
args := map [ string ] string {
"jarArgs" : "-P META-INF/services/ " + strings . Join ( proptools . NinjaAndShellEscapeList ( zipargs ) , " " ) ,
}
if ctx . Config ( ) . UseRBE ( ) && ctx . Config ( ) . IsEnvTrue ( "RBE_ZIP" ) {
rule = zipRE
args [ "implicits" ] = strings . Join ( services . Strings ( ) , "," )
}
ctx . Build ( pctx , android . BuildParams {
Rule : rule ,
Output : servicesJar ,
Implicits : services ,
Args : args ,
} )
jars = append ( jars , servicesJar )
}
// Combine the classes built from sources, any manifests, and any static libraries into
// classes.jar. If there is only one input jar this step will be skipped.
var outputFile android . OutputPath
if len ( jars ) == 1 && ! manifest . Valid ( ) {
// Optimization: skip the combine step as there is nothing to do
// TODO(ccross): this leaves any module-info.class files, but those should only come from
// prebuilt dependencies until we support modules in the platform build, so there shouldn't be
// any if len(jars) == 1.
2023-06-09 01:25:57 +02:00
// moduleStubLinkType determines if the module is the TopLevelStubLibrary generated
// from sdk_library. The TopLevelStubLibrary contains only one static lib,
// either with .from-source or .from-text suffix.
// outputFile should be agnostic to the build configuration,
// thus "combine" the single static lib in order to prevent the static lib from being exposed
// to the copy rules.
stub , _ := moduleStubLinkType ( ctx . ModuleName ( ) )
2021-03-17 23:56:23 +01:00
// Transform the single path to the jar into an OutputPath as that is required by the following
// code.
2023-06-09 01:25:57 +02:00
if moduleOutPath , ok := jars [ 0 ] . ( android . ModuleOutPath ) ; ok && ! stub {
2021-03-17 23:56:23 +01:00
// The path contains an embedded OutputPath so reuse that.
outputFile = moduleOutPath . OutputPath
2023-06-09 01:25:57 +02:00
} else if outputPath , ok := jars [ 0 ] . ( android . OutputPath ) ; ok && ! stub {
2021-03-17 23:56:23 +01:00
// The path is an OutputPath so reuse it directly.
outputFile = outputPath
} else {
// The file is not in the out directory so create an OutputPath into which it can be copied
// and which the following code can use to refer to it.
combinedJar := android . PathForModuleOut ( ctx , "combined" , jarName )
ctx . Build ( pctx , android . BuildParams {
Rule : android . Cp ,
Input : jars [ 0 ] ,
Output : combinedJar ,
} )
outputFile = combinedJar . OutputPath
}
} else {
combinedJar := android . PathForModuleOut ( ctx , "combined" , jarName )
TransformJarsToJar ( ctx , combinedJar , "for javac" , jars , manifest ,
false , nil , nil )
outputFile = combinedJar . OutputPath
}
// jarjar implementation jar if necessary
if j . expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android . PathForModuleOut ( ctx , "jarjar" , jarName ) . OutputPath
TransformJarJar ( ctx , jarjarFile , outputFile , j . expandJarjarRules )
outputFile = jarjarFile
// jarjar resource jar if necessary
if j . resourceJar != nil {
resourceJarJarFile := android . PathForModuleOut ( ctx , "res-jarjar" , jarName )
TransformJarJar ( ctx , resourceJarJarFile , j . resourceJar , j . expandJarjarRules )
j . resourceJar = resourceJarJarFile
}
if ctx . Failed ( ) {
return
}
}
2024-02-05 23:46:00 +01:00
// Automatic jarjar rules propagation
if j . repackageJarjarRules != nil {
repackagedJarjarFile := android . PathForModuleOut ( ctx , "repackaged-jarjar" , jarName ) . OutputPath
TransformJarJar ( ctx , repackagedJarjarFile , outputFile , j . repackageJarjarRules )
outputFile = repackagedJarjarFile
if ctx . Failed ( ) {
return
}
}
2021-03-17 23:56:23 +01:00
// Check package restrictions if necessary.
if len ( j . properties . Permitted_packages ) > 0 {
2021-10-01 14:19:58 +02:00
// Time stamp file created by the package check rule.
2021-03-17 23:56:23 +01:00
pkgckFile := android . PathForModuleOut ( ctx , "package-check.stamp" )
2021-10-01 14:19:58 +02:00
// Create a rule to copy the output jar to another path and add a validate dependency that
// will check that the jar only contains the permitted packages. The new location will become
// the output file of this module.
inputFile := outputFile
outputFile = android . PathForModuleOut ( ctx , "package-check" , jarName ) . OutputPath
ctx . Build ( pctx , android . BuildParams {
Rule : android . Cp ,
Input : inputFile ,
Output : outputFile ,
// Make sure that any dependency on the output file will cause ninja to run the package check
// rule.
Validation : pkgckFile ,
} )
// Check packages and create a timestamp file when complete.
2021-03-17 23:56:23 +01:00
CheckJarPackages ( ctx , pkgckFile , outputFile , j . properties . Permitted_packages )
if ctx . Failed ( ) {
return
}
}
j . implementationJarFile = outputFile
if j . headerJarFile == nil {
2023-07-19 07:11:07 +02:00
// If this module couldn't generate a header jar (for example due to api generating annotation processors)
// then use the implementation jar. Run it through zip2zip first to remove any files in META-INF/services
// so that javac on modules that depend on this module don't pick up annotation processors (which may be
// missing their implementations) from META-INF/services/javax.annotation.processing.Processor.
headerJarFile := android . PathForModuleOut ( ctx , "javac-header" , jarName )
convertImplementationJarToHeaderJar ( ctx , j . implementationJarFile , headerJarFile )
j . headerJarFile = headerJarFile
2021-03-17 23:56:23 +01:00
}
2021-05-13 21:42:24 +02:00
// enforce syntax check to jacoco filters for any build (http://b/183622051)
specs := j . jacocoModuleToZipCommand ( ctx )
if ctx . Failed ( ) {
return
}
2021-03-17 23:56:23 +01:00
if j . shouldInstrument ( ctx ) {
2021-05-13 21:42:24 +02:00
outputFile = j . instrument ( ctx , flags , outputFile , jarName , specs )
2021-03-17 23:56:23 +01:00
}
// merge implementation jar with resources if necessary
implementationAndResourcesJar := outputFile
if j . resourceJar != nil {
jars := android . Paths { j . resourceJar , implementationAndResourcesJar }
combinedJar := android . PathForModuleOut ( ctx , "withres" , jarName ) . OutputPath
TransformJarsToJar ( ctx , combinedJar , "for resources" , jars , manifest ,
false , nil , nil )
implementationAndResourcesJar = combinedJar
}
j . implementationAndResourcesJar = implementationAndResourcesJar
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
2022-06-29 12:15:52 +02:00
compileDex := j . dexProperties . Compile_dex
2023-12-14 00:54:49 +01:00
apexInfo , _ := android . ModuleProvider ( ctx , android . ApexInfoProvider )
2021-03-17 23:56:23 +01:00
if j . DirectlyInAnyApex ( ) && ! apexInfo . IsForPlatform ( ) {
2022-06-29 12:15:52 +02:00
if compileDex == nil {
compileDex = proptools . BoolPtr ( true )
2021-03-17 23:56:23 +01:00
}
if j . deviceProperties . Hostdex == nil {
j . deviceProperties . Hostdex = proptools . BoolPtr ( true )
}
}
2022-06-29 12:15:52 +02:00
if ctx . Device ( ) && ( Bool ( j . properties . Installable ) || Bool ( compileDex ) ) {
2021-03-17 23:56:23 +01:00
if j . hasCode ( ctx ) {
if j . shouldInstrumentStatic ( ctx ) {
2023-11-22 00:13:56 +01:00
j . dexer . extraProguardFlagsFiles = append ( j . dexer . extraProguardFlagsFiles ,
2021-03-17 23:56:23 +01:00
android . PathForSource ( ctx , "build/make/core/proguard.jacoco.flags" ) )
}
// Dex compilation
var dexOutputFile android . OutputPath
2023-02-23 19:05:05 +01:00
params := & compileDexParams {
flags : flags ,
sdkVersion : j . SdkVersion ( ctx ) ,
minSdkVersion : j . MinSdkVersion ( ctx ) ,
classesJar : implementationAndResourcesJar ,
jarName : jarName ,
}
dexOutputFile = j . dexer . compileDex ( ctx , params )
2021-03-17 23:56:23 +01:00
if ctx . Failed ( ) {
return
}
// merge dex jar with resources if necessary
if j . resourceJar != nil {
jars := android . Paths { dexOutputFile , j . resourceJar }
combinedJar := android . PathForModuleOut ( ctx , "dex-withres" , jarName ) . OutputPath
TransformJarsToJar ( ctx , combinedJar , "for dex resources" , jars , android . OptionalPath { } ,
false , nil , nil )
if * j . dexProperties . Uncompress_dex {
combinedAlignedJar := android . PathForModuleOut ( ctx , "dex-withres-aligned" , jarName ) . OutputPath
2023-09-07 07:31:32 +02:00
TransformZipAlign ( ctx , combinedAlignedJar , combinedJar , nil )
2021-03-17 23:56:23 +01:00
dexOutputFile = combinedAlignedJar
} else {
dexOutputFile = combinedJar
}
}
2021-05-16 06:21:16 +02:00
// Initialize the hiddenapi structure.
2021-09-15 04:34:04 +02:00
j . initHiddenAPI ( ctx , makeDexJarPathFromPath ( dexOutputFile ) , j . implementationJarFile , j . dexProperties . Uncompress_dex )
2021-05-16 06:21:16 +02:00
// Encode hidden API flags in dex file, if needed.
dexOutputFile = j . hiddenAPIEncodeDex ( ctx , dexOutputFile )
2021-09-15 04:34:04 +02:00
j . dexJarFile = makeDexJarPathFromPath ( dexOutputFile )
2021-03-17 23:56:23 +01:00
// Dexpreopting
2024-01-24 00:56:29 +01:00
j . dexpreopt ( ctx , android . RemoveOptionalPrebuiltPrefix ( ctx . ModuleName ( ) ) , dexOutputFile )
2021-03-17 23:56:23 +01:00
outputFile = dexOutputFile
} else {
// There is no code to compile into a dex jar, make sure the resources are propagated
// to the APK if this is an app.
outputFile = implementationAndResourcesJar
2021-09-15 04:34:04 +02:00
j . dexJarFile = makeDexJarPathFromPath ( j . resourceJar )
2021-03-17 23:56:23 +01:00
}
if ctx . Failed ( ) {
return
}
} else {
outputFile = implementationAndResourcesJar
}
if ctx . Device ( ) {
2023-11-06 20:43:17 +01:00
lintSDKVersion := func ( apiLevel android . ApiLevel ) android . ApiLevel {
2023-03-03 22:20:36 +01:00
if ! apiLevel . IsPreview ( ) {
2023-11-06 20:43:17 +01:00
return apiLevel
2021-03-17 23:56:23 +01:00
} else {
2023-11-06 20:43:17 +01:00
return ctx . Config ( ) . DefaultAppTargetSdk ( ctx )
2021-03-17 23:56:23 +01:00
}
}
j . linter . name = ctx . ModuleName ( )
2022-05-05 06:49:02 +02:00
j . linter . srcs = append ( srcFiles , nonGeneratedSrcJars ... )
j . linter . srcJars , _ = android . FilterPathList ( srcJars , nonGeneratedSrcJars )
2021-03-17 23:56:23 +01:00
j . linter . classpath = append ( append ( android . Paths ( nil ) , flags . bootClasspath ... ) , flags . classpath ... )
j . linter . classes = j . implementationJarFile
2022-04-22 19:28:25 +02:00
j . linter . minSdkVersion = lintSDKVersion ( j . MinSdkVersion ( ctx ) )
2023-03-02 00:38:49 +01:00
j . linter . targetSdkVersion = lintSDKVersion ( j . TargetSdkVersion ( ctx ) )
2023-03-03 22:20:36 +01:00
j . linter . compileSdkVersion = lintSDKVersion ( j . SdkVersion ( ctx ) . ApiLevel )
2021-06-08 20:11:21 +02:00
j . linter . compileSdkKind = j . SdkVersion ( ctx ) . Kind
2021-03-17 23:56:23 +01:00
j . linter . javaLanguageLevel = flags . javaVersion . String ( )
j . linter . kotlinLanguageLevel = "1.3"
2023-12-14 03:22:18 +01:00
j . linter . compile_data = android . PathsForModuleSrc ( ctx , j . properties . Compile_data )
2021-03-17 23:56:23 +01:00
if ! apexInfo . IsForPlatform ( ) && ctx . Config ( ) . UnbundledBuildApps ( ) {
j . linter . buildModuleReportZip = true
}
j . linter . lint ( ctx )
}
2023-09-20 15:39:57 +02:00
j . collectTransitiveSrcFiles ( ctx , srcFiles )
2021-03-17 23:56:23 +01:00
ctx . CheckbuildFile ( outputFile )
2023-12-19 20:01:57 +01:00
android . CollectDependencyAconfigFiles ( ctx , & j . mergedAconfigFiles )
2023-07-16 22:20:33 +02:00
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , JavaInfoProvider , JavaInfo {
2024-03-13 02:21:16 +01:00
HeaderJars : android . PathsIfNonNil ( j . headerJarFile ) ,
RepackagedHeaderJars : android . PathsIfNonNil ( j . repackagedHeaderJarFile ) ,
TransitiveLibsHeaderJars : j . transitiveLibsHeaderJars ,
TransitiveStaticLibsHeaderJars : j . transitiveStaticLibsHeaderJars ,
ImplementationAndResourcesJars : android . PathsIfNonNil ( j . implementationAndResourcesJar ) ,
ImplementationJars : android . PathsIfNonNil ( j . implementationJarFile ) ,
ResourceJars : android . PathsIfNonNil ( j . resourceJar ) ,
AidlIncludeDirs : j . exportAidlIncludeDirs ,
SrcJarArgs : j . srcJarArgs ,
SrcJarDeps : j . srcJarDeps ,
TransitiveSrcFiles : j . transitiveSrcFiles ,
ExportedPlugins : j . exportedPluginJars ,
ExportedPluginClasses : j . exportedPluginClasses ,
ExportedPluginDisableTurbine : j . exportedDisableTurbine ,
JacocoReportClassesFile : j . jacocoReportClassesFile ,
StubsLinkType : j . stubsLinkType ,
AconfigIntermediateCacheOutputPaths : deps . aconfigProtoFiles ,
2021-03-17 23:56:23 +01:00
} )
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
j . outputFile = outputFile . WithoutRel ( )
}
2021-09-17 23:11:52 +02:00
func ( j * Module ) useCompose ( ) bool {
return android . InList ( "androidx.compose.runtime_runtime" , j . properties . Static_libs )
}
2024-03-27 22:11:51 +01:00
func collectDepProguardSpecInfo ( ctx android . ModuleContext ) ( transitiveProguardFlags , transitiveUnconditionalExportedFlags [ ] * android . DepSet [ android . Path ] ) {
2023-08-03 00:00:35 +02:00
ctx . VisitDirectDeps ( func ( m android . Module ) {
2023-12-13 22:47:44 +01:00
depProguardInfo , _ := android . OtherModuleProvider ( ctx , m , ProguardSpecInfoProvider )
2023-08-03 00:00:35 +02:00
depTag := ctx . OtherModuleDependencyTag ( m )
if depProguardInfo . UnconditionallyExportedProguardFlags != nil {
transitiveUnconditionalExportedFlags = append ( transitiveUnconditionalExportedFlags , depProguardInfo . UnconditionallyExportedProguardFlags )
transitiveProguardFlags = append ( transitiveProguardFlags , depProguardInfo . UnconditionallyExportedProguardFlags )
}
if depTag == staticLibTag && depProguardInfo . ProguardFlagsFiles != nil {
transitiveProguardFlags = append ( transitiveProguardFlags , depProguardInfo . ProguardFlagsFiles )
}
} )
2024-03-27 22:11:51 +01:00
return transitiveProguardFlags , transitiveUnconditionalExportedFlags
}
func ( j * Module ) collectProguardSpecInfo ( ctx android . ModuleContext ) ProguardSpecInfo {
transitiveProguardFlags , transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo ( ctx )
2023-08-03 00:00:35 +02:00
directUnconditionalExportedFlags := android . Paths { }
proguardFlagsForThisModule := android . PathsForModuleSrc ( ctx , j . dexProperties . Optimize . Proguard_flags_files )
exportUnconditionally := proptools . Bool ( j . dexProperties . Optimize . Export_proguard_flags_files )
if exportUnconditionally {
// if we explicitly export, then our unconditional exports are the same as our transitive flags
transitiveUnconditionalExportedFlags = transitiveProguardFlags
directUnconditionalExportedFlags = proguardFlagsForThisModule
}
return ProguardSpecInfo {
Export_proguard_flags_files : exportUnconditionally ,
ProguardFlagsFiles : android . NewDepSet [ android . Path ] (
android . POSTORDER ,
proguardFlagsForThisModule ,
transitiveProguardFlags ,
) ,
UnconditionallyExportedProguardFlags : android . NewDepSet [ android . Path ] (
android . POSTORDER ,
directUnconditionalExportedFlags ,
transitiveUnconditionalExportedFlags ,
) ,
}
}
2021-06-14 00:23:16 +02:00
// Returns a copy of the supplied flags, but with all the errorprone-related
// fields copied to the regular build's fields.
func enableErrorproneFlags ( flags javaBuilderFlags ) javaBuilderFlags {
flags . processorPath = append ( flags . errorProneProcessorPath , flags . processorPath ... )
if len ( flags . errorProneExtraJavacFlags ) > 0 {
if len ( flags . javacFlags ) > 0 {
flags . javacFlags += " " + flags . errorProneExtraJavacFlags
} else {
flags . javacFlags = flags . errorProneExtraJavacFlags
}
}
return flags
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) compileJavaClasses ( ctx android . ModuleContext , jarName string , idx int ,
srcFiles , srcJars android . Paths , flags javaBuilderFlags , extraJarDeps android . Paths ) android . WritablePath {
kzipName := pathtools . ReplaceExtension ( jarName , "kzip" )
2023-06-08 08:14:59 +02:00
annoSrcJar := android . PathForModuleOut ( ctx , "javac" , "anno.srcjar" )
2021-03-17 23:56:23 +01:00
if idx >= 0 {
kzipName = strings . TrimSuffix ( jarName , filepath . Ext ( jarName ) ) + strconv . Itoa ( idx ) + ".kzip"
2023-06-08 08:14:59 +02:00
annoSrcJar = android . PathForModuleOut ( ctx , "javac" , "anno-" + strconv . Itoa ( idx ) + ".srcjar" )
2021-03-17 23:56:23 +01:00
jarName += strconv . Itoa ( idx )
}
classes := android . PathForModuleOut ( ctx , "javac" , jarName ) . OutputPath
2023-06-08 08:14:59 +02:00
TransformJavaToClasses ( ctx , classes , idx , srcFiles , srcJars , annoSrcJar , flags , extraJarDeps )
2021-03-17 23:56:23 +01:00
if ctx . Config ( ) . EmitXrefRules ( ) {
extractionFile := android . PathForModuleOut ( ctx , kzipName )
emitXrefRule ( ctx , extractionFile , idx , srcFiles , srcJars , flags , extraJarDeps )
j . kytheFiles = append ( j . kytheFiles , extractionFile )
}
2023-06-08 08:14:59 +02:00
if len ( flags . processorPath ) > 0 {
j . annoSrcJars = append ( j . annoSrcJars , annoSrcJar )
}
2021-03-17 23:56:23 +01:00
return classes
}
// Check for invalid kotlinc flags. Only use this for flags explicitly passed by the user,
// since some of these flags may be used internally.
func CheckKotlincFlags ( ctx android . ModuleContext , flags [ ] string ) {
for _ , flag := range flags {
flag = strings . TrimSpace ( flag )
if ! strings . HasPrefix ( flag , "-" ) {
ctx . PropertyErrorf ( "kotlincflags" , "Flag `%s` must start with `-`" , flag )
} else if strings . HasPrefix ( flag , "-Xintellij-plugin-root" ) {
ctx . PropertyErrorf ( "kotlincflags" ,
"Bad flag: `%s`, only use internal compiler for consistency." , flag )
} else if inList ( flag , config . KotlincIllegalFlags ) {
ctx . PropertyErrorf ( "kotlincflags" , "Flag `%s` already used by build system" , flag )
} else if flag == "-include-runtime" {
ctx . PropertyErrorf ( "kotlincflags" , "Bad flag: `%s`, do not include runtime." , flag )
} else {
args := strings . Split ( flag , " " )
if args [ 0 ] == "-kotlin-home" {
ctx . PropertyErrorf ( "kotlincflags" ,
"Bad flag: `%s`, kotlin home already set to default (path to kotlinc in the repo)." , flag )
}
}
}
}
func ( j * Module ) compileJavaHeader ( ctx android . ModuleContext , srcFiles , srcJars android . Paths ,
deps deps , flags javaBuilderFlags , jarName string ,
2024-02-05 23:46:00 +01:00
extraJars android . Paths ) ( headerJar , jarjarAndDepsHeaderJar , jarjarAndDepsRepackagedHeaderJar android . Path ) {
2021-03-17 23:56:23 +01:00
var jars android . Paths
if len ( srcFiles ) > 0 || len ( srcJars ) > 0 {
// Compile java sources into turbine.jar.
turbineJar := android . PathForModuleOut ( ctx , "turbine" , jarName )
TransformJavaToHeaderClasses ( ctx , turbineJar , srcFiles , srcJars , flags )
if ctx . Failed ( ) {
2024-02-05 23:46:00 +01:00
return nil , nil , nil
2021-03-17 23:56:23 +01:00
}
jars = append ( jars , turbineJar )
2021-11-19 07:23:12 +01:00
headerJar = turbineJar
2021-03-17 23:56:23 +01:00
}
jars = append ( jars , extraJars ... )
// Combine any static header libraries into classes-header.jar. If there is only
// one input jar this step will be skipped.
jars = append ( jars , deps . staticHeaderJars ... )
// we cannot skip the combine step for now if there is only one jar
// since we have to strip META-INF/TRANSITIVE dir from turbine.jar
combinedJar := android . PathForModuleOut ( ctx , "turbine-combined" , jarName )
TransformJarsToJar ( ctx , combinedJar , "for turbine" , jars , android . OptionalPath { } ,
false , nil , [ ] string { "META-INF/TRANSITIVE" } )
2021-11-19 07:23:12 +01:00
jarjarAndDepsHeaderJar = combinedJar
2021-03-17 23:56:23 +01:00
if j . expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android . PathForModuleOut ( ctx , "turbine-jarjar" , jarName )
2021-11-19 07:23:12 +01:00
TransformJarJar ( ctx , jarjarFile , jarjarAndDepsHeaderJar , j . expandJarjarRules )
jarjarAndDepsHeaderJar = jarjarFile
2021-03-17 23:56:23 +01:00
if ctx . Failed ( ) {
2024-02-05 23:46:00 +01:00
return nil , nil , nil
2021-03-17 23:56:23 +01:00
}
}
2024-02-05 23:46:00 +01:00
if j . repackageJarjarRules != nil {
repackagedJarjarFile := android . PathForModuleOut ( ctx , "repackaged-turbine-jarjar" , jarName )
TransformJarJar ( ctx , repackagedJarjarFile , jarjarAndDepsHeaderJar , j . repackageJarjarRules )
jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile
if ctx . Failed ( ) {
return nil , nil , nil
}
} else {
jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar
}
return headerJar , jarjarAndDepsHeaderJar , jarjarAndDepsRepackagedHeaderJar
2021-03-17 23:56:23 +01:00
}
func ( j * Module ) instrument ( ctx android . ModuleContext , flags javaBuilderFlags ,
2021-05-13 21:42:24 +02:00
classesJar android . Path , jarName string , specs string ) android . OutputPath {
2021-03-17 23:56:23 +01:00
jacocoReportClassesFile := android . PathForModuleOut ( ctx , "jacoco-report-classes" , jarName )
instrumentedJar := android . PathForModuleOut ( ctx , "jacoco" , jarName ) . OutputPath
jacocoInstrumentJar ( ctx , instrumentedJar , jacocoReportClassesFile , classesJar , specs )
j . jacocoReportClassesFile = jacocoReportClassesFile
return instrumentedJar
}
2022-11-29 17:19:37 +01:00
type providesTransitiveHeaderJars struct {
// set of header jars for all transitive libs deps
2022-04-21 21:50:51 +02:00
transitiveLibsHeaderJars * android . DepSet [ android . Path ]
2022-11-29 17:19:37 +01:00
// set of header jars for all transitive static libs deps
2022-04-21 21:50:51 +02:00
transitiveStaticLibsHeaderJars * android . DepSet [ android . Path ]
2022-11-29 17:19:37 +01:00
}
2022-04-21 21:50:51 +02:00
func ( j * providesTransitiveHeaderJars ) TransitiveLibsHeaderJars ( ) * android . DepSet [ android . Path ] {
2022-11-29 17:19:37 +01:00
return j . transitiveLibsHeaderJars
}
2022-04-21 21:50:51 +02:00
func ( j * providesTransitiveHeaderJars ) TransitiveStaticLibsHeaderJars ( ) * android . DepSet [ android . Path ] {
2022-11-29 17:19:37 +01:00
return j . transitiveStaticLibsHeaderJars
}
func ( j * providesTransitiveHeaderJars ) collectTransitiveHeaderJars ( ctx android . ModuleContext ) {
directLibs := android . Paths { }
directStaticLibs := android . Paths { }
2022-04-21 21:50:51 +02:00
transitiveLibs := [ ] * android . DepSet [ android . Path ] { }
transitiveStaticLibs := [ ] * android . DepSet [ android . Path ] { }
2022-11-29 17:19:37 +01:00
ctx . VisitDirectDeps ( func ( module android . Module ) {
// don't add deps of the prebuilt version of the same library
if ctx . ModuleName ( ) == android . RemoveOptionalPrebuiltPrefix ( module . Name ( ) ) {
return
}
2023-12-13 22:47:44 +01:00
dep , _ := android . OtherModuleProvider ( ctx , module , JavaInfoProvider )
2022-11-29 17:19:37 +01:00
tag := ctx . OtherModuleDependencyTag ( module )
_ , isUsesLibDep := tag . ( usesLibraryDependencyTag )
if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
directLibs = append ( directLibs , dep . HeaderJars ... )
} else if tag == staticLibTag {
directStaticLibs = append ( directStaticLibs , dep . HeaderJars ... )
2023-10-27 20:47:10 +02:00
} else {
// Don't propagate transitive libs for other kinds of dependencies.
return
}
if dep . TransitiveLibsHeaderJars != nil {
transitiveLibs = append ( transitiveLibs , dep . TransitiveLibsHeaderJars )
}
if dep . TransitiveStaticLibsHeaderJars != nil {
transitiveStaticLibs = append ( transitiveStaticLibs , dep . TransitiveStaticLibsHeaderJars )
2022-11-29 17:19:37 +01:00
}
} )
j . transitiveLibsHeaderJars = android . NewDepSet ( android . POSTORDER , directLibs , transitiveLibs )
j . transitiveStaticLibsHeaderJars = android . NewDepSet ( android . POSTORDER , directStaticLibs , transitiveStaticLibs )
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) HeaderJars ( ) android . Paths {
if j . headerJarFile == nil {
return nil
}
return android . Paths { j . headerJarFile }
}
func ( j * Module ) ImplementationJars ( ) android . Paths {
if j . implementationJarFile == nil {
return nil
}
return android . Paths { j . implementationJarFile }
}
2024-01-09 22:35:56 +01:00
func ( j * Module ) DexJarBuildPath ( ctx android . ModuleErrorfContext ) OptionalDexJarPath {
2021-03-17 23:56:23 +01:00
return j . dexJarFile
}
func ( j * Module ) DexJarInstallPath ( ) android . Path {
return j . installFile
}
func ( j * Module ) ImplementationAndResourcesJars ( ) android . Paths {
if j . implementationAndResourcesJar == nil {
return nil
}
return android . Paths { j . implementationAndResourcesJar }
}
func ( j * Module ) AidlIncludeDirs ( ) android . Paths {
// exportAidlIncludeDirs is type android.Paths already
return j . exportAidlIncludeDirs
}
func ( j * Module ) ClassLoaderContexts ( ) dexpreopt . ClassLoaderContextMap {
return j . classLoaderContexts
}
// Collect information for opening IDE project files in java/jdeps.go.
func ( j * Module ) IDEInfo ( dpInfo * android . IdeInfo ) {
dpInfo . Deps = append ( dpInfo . Deps , j . CompilerDeps ( ) ... )
dpInfo . Srcs = append ( dpInfo . Srcs , j . expandIDEInfoCompiledSrcs ... )
dpInfo . SrcJars = append ( dpInfo . SrcJars , j . compiledSrcJars . Strings ( ) ... )
dpInfo . Aidl_include_dirs = append ( dpInfo . Aidl_include_dirs , j . deviceProperties . Aidl . Include_dirs ... )
if j . expandJarjarRules != nil {
dpInfo . Jarjar_rules = append ( dpInfo . Jarjar_rules , j . expandJarjarRules . String ( ) )
}
2022-04-13 14:41:01 +02:00
dpInfo . Static_libs = append ( dpInfo . Static_libs , j . properties . Static_libs ... )
dpInfo . Libs = append ( dpInfo . Libs , j . properties . Libs ... )
2023-06-08 08:14:59 +02:00
dpInfo . SrcJars = append ( dpInfo . SrcJars , j . annoSrcJars . Strings ( ) ... )
2021-03-17 23:56:23 +01:00
}
func ( j * Module ) CompilerDeps ( ) [ ] string {
jdeps := [ ] string { }
jdeps = append ( jdeps , j . properties . Libs ... )
jdeps = append ( jdeps , j . properties . Static_libs ... )
return jdeps
}
func ( j * Module ) hasCode ( ctx android . ModuleContext ) bool {
srcFiles := android . PathsForModuleSrcExcludes ( ctx , j . properties . Srcs , j . properties . Exclude_srcs )
return len ( srcFiles ) > 0 || len ( ctx . GetDirectDepsWithTag ( staticLibTag ) ) > 0
}
// Implements android.ApexModule
func ( j * Module ) DepIsInSameApex ( ctx android . BaseModuleContext , dep android . Module ) bool {
return j . depIsInSameApex ( ctx , dep )
}
// Implements android.ApexModule
2021-12-06 12:42:40 +01:00
func ( j * Module ) ShouldSupportSdkVersion ( ctx android . BaseModuleContext , sdkVersion android . ApiLevel ) error {
2023-02-24 19:38:56 +01:00
sdkVersionSpec := j . SdkVersion ( ctx )
2023-03-03 22:20:36 +01:00
minSdkVersion := j . MinSdkVersion ( ctx )
if ! minSdkVersion . Specified ( ) {
2021-03-17 23:56:23 +01:00
return fmt . Errorf ( "min_sdk_version is not specified" )
}
2023-02-24 19:38:56 +01:00
// If the module is compiling against core (via sdk_version), skip comparison check.
if sdkVersionSpec . Kind == android . SdkCore {
2021-03-17 23:56:23 +01:00
return nil
}
2023-02-24 19:38:56 +01:00
if minSdkVersion . GreaterThan ( sdkVersion ) {
return fmt . Errorf ( "newer SDK(%v)" , minSdkVersion )
2021-03-17 23:56:23 +01:00
}
return nil
}
func ( j * Module ) Stem ( ) string {
2023-07-01 02:13:47 +02:00
if j . stem == "" {
panic ( "Stem() called before stem property was set" )
}
return j . stem
2021-03-17 23:56:23 +01:00
}
func ( j * Module ) JacocoReportClassesFile ( ) android . Path {
return j . jacocoReportClassesFile
}
2023-09-20 15:39:57 +02:00
func ( j * Module ) collectTransitiveSrcFiles ( ctx android . ModuleContext , mine android . Paths ) {
var fromDeps [ ] * android . DepSet [ android . Path ]
ctx . VisitDirectDeps ( func ( module android . Module ) {
tag := ctx . OtherModuleDependencyTag ( module )
if tag == staticLibTag {
2023-12-13 22:47:44 +01:00
depInfo , _ := android . OtherModuleProvider ( ctx , module , JavaInfoProvider )
2023-09-20 15:39:57 +02:00
if depInfo . TransitiveSrcFiles != nil {
fromDeps = append ( fromDeps , depInfo . TransitiveSrcFiles )
}
}
} )
j . transitiveSrcFiles = android . NewDepSet ( android . POSTORDER , mine , fromDeps )
}
2021-03-17 23:56:23 +01:00
func ( j * Module ) IsInstallable ( ) bool {
return Bool ( j . properties . Installable )
}
type sdkLinkType int
const (
// TODO(jiyong) rename these for better readability. Make the allowed
// and disallowed link types explicit
// order is important here. See rank()
javaCore sdkLinkType = iota
javaSdk
javaSystem
javaModule
javaSystemServer
javaPlatform
)
func ( lt sdkLinkType ) String ( ) string {
switch lt {
case javaCore :
return "core Java API"
case javaSdk :
return "Android API"
case javaSystem :
return "system API"
case javaModule :
return "module API"
case javaSystemServer :
return "system server API"
case javaPlatform :
return "private API"
default :
panic ( fmt . Errorf ( "unrecognized linktype: %d" , lt ) )
}
}
// rank determines the total order among sdkLinkType. An SDK link type of rank A can link to
// another SDK link type of rank B only when B <= A. For example, a module linking to Android SDK
// can't statically depend on modules that use Platform API.
func ( lt sdkLinkType ) rank ( ) int {
return int ( lt )
}
type moduleWithSdkDep interface {
android . Module
2021-04-02 01:45:46 +02:00
getSdkLinkType ( ctx android . BaseModuleContext , name string ) ( ret sdkLinkType , stubs bool )
2021-03-17 23:56:23 +01:00
}
2021-04-02 01:45:46 +02:00
func ( m * Module ) getSdkLinkType ( ctx android . BaseModuleContext , name string ) ( ret sdkLinkType , stubs bool ) {
2021-03-17 23:56:23 +01:00
switch name {
2023-05-30 21:12:28 +02:00
case android . SdkCore . DefaultJavaLibraryName ( ) ,
"legacy.core.platform.api.stubs" ,
"stable.core.platform.api.stubs" ,
2021-03-17 23:56:23 +01:00
"stub-annotations" , "private-stub-annotations-jar" ,
2023-05-30 21:12:28 +02:00
"core-lambda-stubs" ,
2023-03-30 01:25:49 +02:00
"core-generated-annotation-stubs" :
2021-03-17 23:56:23 +01:00
return javaCore , true
2023-05-30 21:12:28 +02:00
case android . SdkPublic . DefaultJavaLibraryName ( ) :
2021-03-17 23:56:23 +01:00
return javaSdk , true
2023-05-30 21:12:28 +02:00
case android . SdkSystem . DefaultJavaLibraryName ( ) :
2021-03-17 23:56:23 +01:00
return javaSystem , true
2023-05-30 21:12:28 +02:00
case android . SdkModule . DefaultJavaLibraryName ( ) :
2021-03-17 23:56:23 +01:00
return javaModule , true
2023-05-30 21:12:28 +02:00
case android . SdkSystemServer . DefaultJavaLibraryName ( ) :
2021-03-17 23:56:23 +01:00
return javaSystemServer , true
2023-05-30 21:12:28 +02:00
case android . SdkTest . DefaultJavaLibraryName ( ) :
2021-03-17 23:56:23 +01:00
return javaSystem , true
}
if stub , linkType := moduleStubLinkType ( name ) ; stub {
return linkType , true
}
2021-04-02 01:45:46 +02:00
ver := m . SdkVersion ( ctx )
2021-03-29 13:11:58 +02:00
switch ver . Kind {
case android . SdkCore :
2021-03-17 23:56:23 +01:00
return javaCore , false
2021-03-29 13:11:58 +02:00
case android . SdkSystem :
2021-03-17 23:56:23 +01:00
return javaSystem , false
2021-03-29 13:11:58 +02:00
case android . SdkPublic :
2021-03-17 23:56:23 +01:00
return javaSdk , false
2021-03-29 13:11:58 +02:00
case android . SdkModule :
2021-03-17 23:56:23 +01:00
return javaModule , false
2021-03-29 13:11:58 +02:00
case android . SdkSystemServer :
2021-03-17 23:56:23 +01:00
return javaSystemServer , false
2021-03-29 13:11:58 +02:00
case android . SdkPrivate , android . SdkNone , android . SdkCorePlatform , android . SdkTest :
2021-03-17 23:56:23 +01:00
return javaPlatform , false
}
2021-03-29 13:11:58 +02:00
if ! ver . Valid ( ) {
panic ( fmt . Errorf ( "sdk_version is invalid. got %q" , ver . Raw ) )
2021-03-17 23:56:23 +01:00
}
return javaSdk , false
}
// checkSdkLinkType make sures the given dependency doesn't have a lower SDK link type rank than
// this module's. See the comment on rank() for details and an example.
func ( j * Module ) checkSdkLinkType (
ctx android . ModuleContext , dep moduleWithSdkDep , tag dependencyTag ) {
if ctx . Host ( ) {
return
}
2021-04-02 01:45:46 +02:00
myLinkType , stubs := j . getSdkLinkType ( ctx , ctx . ModuleName ( ) )
2021-03-17 23:56:23 +01:00
if stubs {
return
}
2021-04-02 01:45:46 +02:00
depLinkType , _ := dep . getSdkLinkType ( ctx , ctx . OtherModuleName ( dep ) )
2021-03-17 23:56:23 +01:00
if myLinkType . rank ( ) < depLinkType . rank ( ) {
ctx . ModuleErrorf ( "compiles against %v, but dependency %q is compiling against %v. " +
"In order to fix this, consider adjusting sdk_version: OR platform_apis: " +
"property of the source or target module so that target module is built " +
"with the same or smaller API set when compared to the source." ,
myLinkType , ctx . OtherModuleName ( dep ) , depLinkType )
}
}
func ( j * Module ) collectDeps ( ctx android . ModuleContext ) deps {
var deps deps
if ctx . Device ( ) {
2021-03-29 13:11:58 +02:00
sdkDep := decodeSdkDep ( ctx , android . SdkContext ( j ) )
2021-03-17 23:56:23 +01:00
if sdkDep . invalidVersion {
ctx . AddMissingDependencies ( sdkDep . bootclasspath )
ctx . AddMissingDependencies ( sdkDep . java9Classpath )
} else if sdkDep . useFiles {
// sdkDep.jar is actually equivalent to turbine header.jar.
deps . classpath = append ( deps . classpath , sdkDep . jars ... )
2022-03-17 19:12:32 +01:00
deps . dexClasspath = append ( deps . dexClasspath , sdkDep . jars ... )
2021-03-17 23:56:23 +01:00
deps . aidlPreprocess = sdkDep . aidl
} else {
deps . aidlPreprocess = sdkDep . aidl
}
}
2021-04-02 01:45:46 +02:00
sdkLinkType , _ := j . getSdkLinkType ( ctx , ctx . ModuleName ( ) )
2021-03-17 23:56:23 +01:00
2022-11-29 17:19:37 +01:00
j . collectTransitiveHeaderJars ( ctx )
2021-03-17 23:56:23 +01:00
ctx . VisitDirectDeps ( func ( module android . Module ) {
otherName := ctx . OtherModuleName ( module )
tag := ctx . OtherModuleDependencyTag ( module )
if IsJniDepTag ( tag ) {
// Handled by AndroidApp.collectAppDeps
return
}
if tag == certificateTag {
// Handled by AndroidApp.collectAppDeps
return
}
if dep , ok := module . ( SdkLibraryDependency ) ; ok {
switch tag {
2022-09-23 22:50:56 +02:00
case sdkLibTag , libTag :
2022-03-17 19:12:32 +01:00
depHeaderJars := dep . SdkHeaderJars ( ctx , j . SdkVersion ( ctx ) )
deps . classpath = append ( deps . classpath , depHeaderJars ... )
deps . dexClasspath = append ( deps . dexClasspath , depHeaderJars ... )
2021-03-17 23:56:23 +01:00
case staticLibTag :
ctx . ModuleErrorf ( "dependency on java_sdk_library %q can only be in libs" , otherName )
}
2023-12-13 22:47:44 +01:00
} else if dep , ok := android . OtherModuleProvider ( ctx , module , JavaInfoProvider ) ; ok {
if sdkLinkType != javaPlatform {
if syspropDep , ok := android . OtherModuleProvider ( ctx , module , SyspropPublicStubInfoProvider ) ; ok {
// dep is a sysprop implementation library, but this module is not linking against
// the platform, so it gets the sysprop public stubs library instead. Replace
// dep with the JavaInfo from the SyspropPublicStubInfoProvider.
dep = syspropDep . JavaInfo
}
2021-03-17 23:56:23 +01:00
}
switch tag {
case bootClasspathTag :
deps . bootClasspath = append ( deps . bootClasspath , dep . HeaderJars ... )
2022-09-23 22:50:56 +02:00
case sdkLibTag , libTag , instrumentationForTag :
2022-04-26 20:34:55 +02:00
if _ , ok := module . ( * Plugin ) ; ok {
ctx . ModuleErrorf ( "a java_plugin (%s) cannot be used as a libs dependency" , otherName )
}
2021-03-17 23:56:23 +01:00
deps . classpath = append ( deps . classpath , dep . HeaderJars ... )
2022-03-17 19:12:32 +01:00
deps . dexClasspath = append ( deps . dexClasspath , dep . HeaderJars ... )
2024-02-05 23:46:00 +01:00
if len ( dep . RepackagedHeaderJars ) == 1 && ! slices . Contains ( dep . HeaderJars , dep . RepackagedHeaderJars [ 0 ] ) {
deps . classpath = append ( deps . classpath , dep . RepackagedHeaderJars ... )
deps . dexClasspath = append ( deps . dexClasspath , dep . RepackagedHeaderJars ... )
}
2021-03-17 23:56:23 +01:00
deps . aidlIncludeDirs = append ( deps . aidlIncludeDirs , dep . AidlIncludeDirs ... )
addPlugins ( & deps , dep . ExportedPlugins , dep . ExportedPluginClasses ... )
deps . disableTurbine = deps . disableTurbine || dep . ExportedPluginDisableTurbine
case java9LibTag :
deps . java9Classpath = append ( deps . java9Classpath , dep . HeaderJars ... )
case staticLibTag :
2022-04-26 20:34:55 +02:00
if _ , ok := module . ( * Plugin ) ; ok {
ctx . ModuleErrorf ( "a java_plugin (%s) cannot be used as a static_libs dependency" , otherName )
}
2021-03-17 23:56:23 +01:00
deps . classpath = append ( deps . classpath , dep . HeaderJars ... )
deps . staticJars = append ( deps . staticJars , dep . ImplementationJars ... )
deps . staticHeaderJars = append ( deps . staticHeaderJars , dep . HeaderJars ... )
deps . staticResourceJars = append ( deps . staticResourceJars , dep . ResourceJars ... )
deps . aidlIncludeDirs = append ( deps . aidlIncludeDirs , dep . AidlIncludeDirs ... )
addPlugins ( & deps , dep . ExportedPlugins , dep . ExportedPluginClasses ... )
// Turbine doesn't run annotation processors, so any module that uses an
// annotation processor that generates API is incompatible with the turbine
// optimization.
deps . disableTurbine = deps . disableTurbine || dep . ExportedPluginDisableTurbine
2024-03-13 02:21:16 +01:00
deps . aconfigProtoFiles = append ( deps . aconfigProtoFiles , dep . AconfigIntermediateCacheOutputPaths ... )
2021-03-17 23:56:23 +01:00
case pluginTag :
if plugin , ok := module . ( * Plugin ) ; ok {
if plugin . pluginProperties . Processor_class != nil {
addPlugins ( & deps , dep . ImplementationAndResourcesJars , * plugin . pluginProperties . Processor_class )
} else {
addPlugins ( & deps , dep . ImplementationAndResourcesJars )
}
// Turbine doesn't run annotation processors, so any module that uses an
// annotation processor that generates API is incompatible with the turbine
// optimization.
deps . disableTurbine = deps . disableTurbine || Bool ( plugin . pluginProperties . Generates_api )
} else {
ctx . PropertyErrorf ( "plugins" , "%q is not a java_plugin module" , otherName )
}
case errorpronePluginTag :
if _ , ok := module . ( * Plugin ) ; ok {
deps . errorProneProcessorPath = append ( deps . errorProneProcessorPath , dep . ImplementationAndResourcesJars ... )
} else {
ctx . PropertyErrorf ( "plugins" , "%q is not a java_plugin module" , otherName )
}
case exportedPluginTag :
if plugin , ok := module . ( * Plugin ) ; ok {
j . exportedPluginJars = append ( j . exportedPluginJars , dep . ImplementationAndResourcesJars ... )
if plugin . pluginProperties . Processor_class != nil {
j . exportedPluginClasses = append ( j . exportedPluginClasses , * plugin . pluginProperties . Processor_class )
}
// Turbine doesn't run annotation processors, so any module that uses an
// annotation processor that generates API is incompatible with the turbine
// optimization.
j . exportedDisableTurbine = Bool ( plugin . pluginProperties . Generates_api )
} else {
ctx . PropertyErrorf ( "exported_plugins" , "%q is not a java_plugin module" , otherName )
}
case kotlinStdlibTag :
deps . kotlinStdlib = append ( deps . kotlinStdlib , dep . HeaderJars ... )
case kotlinAnnotationsTag :
deps . kotlinAnnotations = dep . HeaderJars
2021-09-17 23:11:52 +02:00
case kotlinPluginTag :
deps . kotlinPlugins = append ( deps . kotlinPlugins , dep . ImplementationAndResourcesJars ... )
2021-03-17 23:56:23 +01:00
case syspropPublicStubDepTag :
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , SyspropPublicStubInfoProvider , SyspropPublicStubInfo {
2021-03-17 23:56:23 +01:00
JavaInfo : dep ,
} )
}
} else if dep , ok := module . ( android . SourceFileProducer ) ; ok {
switch tag {
2022-09-23 22:50:56 +02:00
case sdkLibTag , libTag :
2021-03-17 23:56:23 +01:00
checkProducesJars ( ctx , dep )
deps . classpath = append ( deps . classpath , dep . Srcs ( ) ... )
2022-03-17 19:12:32 +01:00
deps . dexClasspath = append ( deps . classpath , dep . Srcs ( ) ... )
2021-03-17 23:56:23 +01:00
case staticLibTag :
checkProducesJars ( ctx , dep )
deps . classpath = append ( deps . classpath , dep . Srcs ( ) ... )
deps . staticJars = append ( deps . staticJars , dep . Srcs ( ) ... )
deps . staticHeaderJars = append ( deps . staticHeaderJars , dep . Srcs ( ) ... )
}
2024-03-13 02:21:16 +01:00
} else if dep , ok := android . OtherModuleProvider ( ctx , module , android . CodegenInfoProvider ) ; ok {
deps . aconfigProtoFiles = append ( deps . aconfigProtoFiles , dep . IntermediateCacheOutputPaths ... )
2021-03-17 23:56:23 +01:00
} else {
switch tag {
case bootClasspathTag :
// If a system modules dependency has been added to the bootclasspath
// then add its libs to the bootclasspath.
sm := module . ( SystemModulesProvider )
deps . bootClasspath = append ( deps . bootClasspath , sm . HeaderJars ( ) ... )
case systemModulesTag :
if deps . systemModules != nil {
panic ( "Found two system module dependencies" )
}
sm := module . ( SystemModulesProvider )
outputDir , outputDeps := sm . OutputDirAndDeps ( )
deps . systemModules = & systemModules { outputDir , outputDeps }
2022-01-11 15:35:55 +01:00
case instrumentationForTag :
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 ) )
2021-03-17 23:56:23 +01:00
}
}
addCLCFromDep ( ctx , module , j . classLoaderContexts )
} )
return deps
}
2024-02-05 23:46:00 +01:00
// Provider for jarjar renaming rules.
//
// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be
// passed to all rdeps. The typical way that these renamings will NOT be inherited is when a module
// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on
// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
// be renamed from that module.
// TODO: Add another property to suppress the forwarding of
2024-02-08 23:30:45 +01:00
type DependencyUse int
const (
RenameUseInvalid DependencyUse = iota
RenameUseInclude
RenameUseExclude
)
type RenameUseElement struct {
DepName string
RenameUse DependencyUse
Why string // token for determining where in the logic the decision was made.
}
2024-02-05 23:46:00 +01:00
type JarJarProviderData struct {
// Mapping of class names: original --> renamed. If the value is "", the class will be
// renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
// attribute). Rdeps of that module will inherit the renaming.
2024-02-08 23:30:45 +01:00
Rename map [ string ] string
RenameUse [ ] RenameUseElement
2024-02-05 23:46:00 +01:00
}
func ( this JarJarProviderData ) GetDebugString ( ) string {
result := ""
2024-02-28 06:28:59 +01:00
for _ , k := range android . SortedKeys ( this . Rename ) {
v := this . Rename [ k ]
2024-02-05 23:46:00 +01:00
if strings . Contains ( k , "android.companion.virtual.flags.FakeFeatureFlagsImpl" ) {
result += k + "-->" + v + ";"
}
}
return result
}
var JarJarProvider = blueprint . NewProvider [ JarJarProviderData ] ( )
var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"
func init ( ) {
android . SetJarJarPrefixHandler ( mergeJarJarPrefixes )
}
// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
// whether they are java modules or not.
type BaseJarJarProviderData struct {
JarJarProviderData JarJarProviderData
}
func ( this BaseJarJarProviderData ) GetDebugString ( ) string {
return this . JarJarProviderData . GetDebugString ( )
}
var BaseJarJarProvider = blueprint . NewProvider [ BaseJarJarProviderData ] ( )
// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called.
// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have
// either JarJarProvider or BaseJarJarProvider.
func mergeJarJarPrefixes ( ctx android . ModuleContext ) {
mod := ctx . Module ( )
// Explicitly avoid propagating into some module types.
switch reflect . TypeOf ( mod ) . String ( ) {
case "*java.Droidstubs" :
return
}
jarJarData := collectDirectDepsProviders ( ctx )
if jarJarData != nil {
providerData := BaseJarJarProviderData {
JarJarProviderData : * jarJarData ,
}
android . SetProvider ( ctx , BaseJarJarProvider , providerData )
}
}
// Add a jarjar renaming rule to this module, to be inherited to all dependent modules.
func ( module * Module ) addJarJarRenameRule ( original string , renamed string ) {
if module . jarjarRenameRules == nil {
module . jarjarRenameRules = make ( map [ string ] string )
}
module . jarjarRenameRules [ original ] = renamed
}
func collectDirectDepsProviders ( ctx android . ModuleContext ) ( result * JarJarProviderData ) {
// Gather repackage information from deps
// If the dep jas a JarJarProvider, it is used. Otherwise, any BaseJarJarProvider is used.
2024-02-08 23:30:45 +01:00
module := ctx . Module ( )
moduleName := module . Name ( )
2024-02-05 23:46:00 +01:00
ctx . VisitDirectDepsIgnoreBlueprint ( func ( m android . Module ) {
2024-02-08 23:30:45 +01:00
tag := ctx . OtherModuleDependencyTag ( m )
// This logic mirrors that in (*Module).collectDeps above. There are several places
// where we explicitly return RenameUseExclude, even though it is the default, to
// indicate that it has been verified to be the case.
//
// Note well: there are probably cases that are getting to the unconditional return
// and are therefore wrong.
shouldIncludeRenames := func ( ) ( DependencyUse , string ) {
if moduleName == m . Name ( ) {
return RenameUseInclude , "name" // If we have the same module name, include the renames.
}
if sc , ok := module . ( android . SdkContext ) ; ok {
if ctx . Device ( ) {
sdkDep := decodeSdkDep ( ctx , sc )
if ! sdkDep . invalidVersion && sdkDep . useFiles {
return RenameUseExclude , "useFiles"
}
}
}
if IsJniDepTag ( tag ) || tag == certificateTag || tag == proguardRaiseTag {
return RenameUseExclude , "tags"
}
if _ , ok := m . ( SdkLibraryDependency ) ; ok {
switch tag {
case sdkLibTag , libTag :
return RenameUseExclude , "sdklibdep" // matches collectDeps()
}
return RenameUseInvalid , "sdklibdep" // dep is not used in collectDeps()
} else if ji , ok := android . OtherModuleProvider ( ctx , m , JavaInfoProvider ) ; ok {
switch ji . StubsLinkType {
case Stubs :
return RenameUseExclude , "info"
case Implementation :
return RenameUseInclude , "info"
default :
//fmt.Printf("LJ: %v -> %v StubsLinkType unknown\n", module, m)
// Fall through to the heuristic logic.
}
switch reflect . TypeOf ( m ) . String ( ) {
case "*java.GeneratedJavaLibraryModule" :
// Probably a java_aconfig_library module.
// TODO: make this check better.
return RenameUseInclude , "reflect"
}
switch tag {
case bootClasspathTag :
return RenameUseExclude , "tagswitch"
case sdkLibTag , libTag , instrumentationForTag :
return RenameUseInclude , "tagswitch"
case java9LibTag :
return RenameUseExclude , "tagswitch"
case staticLibTag :
return RenameUseInclude , "tagswitch"
case pluginTag :
return RenameUseInclude , "tagswitch"
case errorpronePluginTag :
return RenameUseInclude , "tagswitch"
case exportedPluginTag :
return RenameUseInclude , "tagswitch"
case kotlinStdlibTag , kotlinAnnotationsTag :
return RenameUseExclude , "tagswitch"
case kotlinPluginTag :
return RenameUseInclude , "tagswitch"
default :
return RenameUseExclude , "tagswitch"
}
} else if _ , ok := m . ( android . SourceFileProducer ) ; ok {
switch tag {
case sdkLibTag , libTag , staticLibTag :
return RenameUseInclude , "srcfile"
default :
return RenameUseExclude , "srcfile"
}
2024-03-05 01:36:31 +01:00
} else if _ , ok := android . OtherModuleProvider ( ctx , m , android . CodegenInfoProvider ) ; ok {
2024-02-16 23:22:18 +01:00
return RenameUseInclude , "aconfig_declarations_group"
2024-02-08 23:30:45 +01:00
} else {
switch tag {
case bootClasspathTag :
return RenameUseExclude , "else"
case systemModulesTag :
return RenameUseInclude , "else"
}
}
// If we got here, choose the safer option, which may lead to a build failure, rather
// than runtime failures on the device.
return RenameUseExclude , "end"
}
if result == nil {
result = & JarJarProviderData {
Rename : make ( map [ string ] string ) ,
RenameUse : make ( [ ] RenameUseElement , 0 ) ,
}
}
how , why := shouldIncludeRenames ( )
result . RenameUse = append ( result . RenameUse , RenameUseElement { DepName : m . Name ( ) , RenameUse : how , Why : why } )
if how != RenameUseInclude {
// Nothing to merge.
2024-02-07 20:57:14 +01:00
return
}
2024-02-08 23:30:45 +01:00
2024-02-05 23:46:00 +01:00
merge := func ( theirs * JarJarProviderData ) {
for orig , renamed := range theirs . Rename {
if preexisting , exists := ( * result ) . Rename [ orig ] ; ! exists || preexisting == "" {
result . Rename [ orig ] = renamed
} else if preexisting != "" && renamed != "" && preexisting != renamed {
if strings . HasPrefix ( preexisting , overridableJarJarPrefix ) {
result . Rename [ orig ] = renamed
} else if ! strings . HasPrefix ( renamed , overridableJarJarPrefix ) {
ctx . ModuleErrorf ( "1. Conflicting jarjar rules inherited for class: %s (%s and %s)" , orig , renamed , preexisting , ctx . ModuleName ( ) , m . Name ( ) )
continue
}
}
}
}
if theirs , ok := android . OtherModuleProvider ( ctx , m , JarJarProvider ) ; ok {
merge ( & theirs )
} else if theirs , ok := android . OtherModuleProvider ( ctx , m , BaseJarJarProvider ) ; ok {
// TODO: if every java.Module should have a JarJarProvider, and we find only the
// BaseJarJarProvider, then there is a bug. Consider seeing if m can be cast
// to java.Module.
merge ( & theirs . JarJarProviderData )
}
} )
return
}
func ( this Module ) GetDebugString ( ) string {
return "sdk_version=" + proptools . String ( this . deviceProperties . Sdk_version )
}
// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
// us, and if it's been set, apply the jarjar_prefix property to rename them.
func ( module * Module ) collectJarJarRules ( ctx android . ModuleContext ) * JarJarProviderData {
// Gather repackage information from deps
result := collectDirectDepsProviders ( ctx )
// Update that with entries we've stored for ourself
for orig , renamed := range module . jarjarRenameRules {
if result == nil {
result = & JarJarProviderData {
Rename : make ( map [ string ] string ) ,
}
}
if renamed != "" {
if preexisting , exists := ( * result ) . Rename [ orig ] ; exists && preexisting != renamed {
ctx . ModuleErrorf ( "Conflicting jarjar rules inherited for class: %s (%s and %s)" , orig , renamed , preexisting )
continue
}
}
( * result ) . Rename [ orig ] = renamed
}
// If there are no renamings, then jarjar_prefix does nothing, so skip the extra work.
if result == nil {
return nil
}
// If they've given us a jarjar_prefix property, then we will use that to rename any classes
// that have not yet been renamed.
prefix := proptools . String ( module . properties . Jarjar_prefix )
if prefix != "" {
if prefix [ 0 ] == '.' {
ctx . PropertyErrorf ( "jarjar_prefix" , "jarjar_prefix can not start with '.'" )
return nil
}
if prefix [ len ( prefix ) - 1 ] == '.' {
ctx . PropertyErrorf ( "jarjar_prefix" , "jarjar_prefix can not end with '.'" )
return nil
}
var updated map [ string ] string
for orig , renamed := range ( * result ) . Rename {
if renamed == "" {
if updated == nil {
updated = make ( map [ string ] string )
}
updated [ orig ] = prefix + "." + orig
}
}
for orig , renamed := range updated {
( * result ) . Rename [ orig ] = renamed
}
}
return result
}
// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
// to "" won't be in this list because they shouldn't be renamed yet.
func getJarJarRuleText ( provider * JarJarProviderData ) string {
result := ""
2024-02-28 06:28:59 +01:00
for _ , orig := range android . SortedKeys ( provider . Rename ) {
renamed := provider . Rename [ orig ]
2024-02-05 23:46:00 +01:00
if renamed != "" {
result += "rule " + orig + " " + renamed + "\n"
}
}
return result
}
2021-03-17 23:56:23 +01:00
func addPlugins ( deps * deps , pluginJars android . Paths , pluginClasses ... string ) {
deps . processorPath = append ( deps . processorPath , pluginJars ... )
deps . processorClasses = append ( deps . processorClasses , pluginClasses ... )
}
// TODO(b/132357300) Generalize SdkLibrarComponentDependency to non-SDK libraries and merge with
// this interface.
type ProvidesUsesLib interface {
ProvidesUsesLib ( ) * string
}
func ( j * Module ) ProvidesUsesLib ( ) * string {
return j . usesLibraryProperties . Provides_uses_lib
}
2021-05-25 20:50:30 +02:00
type ModuleWithStem interface {
Stem ( ) string
}
var _ ModuleWithStem = ( * Module ) ( nil )