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"
"strconv"
"strings"
"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" `
// 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" `
// 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
}
2021-12-20 12:51:24 +01:00
Openjdk11 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
}
2021-03-17 23:56:23 +01:00
// 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.
Patch_module * string ` android:"arch_variant" `
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
}
Instrument bool ` blueprint:"mutated" `
// 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
}
// 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.
2021-03-17 23:56:23 +01:00
// Defaults to compiling against the current platform.
2021-11-05 20:30:24 +01:00
// Values are of one of the following forms:
// 1) numerical API level or "current"
// 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 value 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
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
// is ignored when module's type isn't android_app.
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
// 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
// set the name of the output
Stem * 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" `
}
// 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
android . SdkBase
2021-12-10 12:14:59 +01:00
android . BazelModuleBase
2021-03-17 23:56:23 +01:00
// Functionality common to Module and Import.
embeddableInModuleAndImport
properties CommonProperties
protoProperties android . ProtoProperties
deviceProperties DeviceProperties
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
headerJarFile android . Path
// 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
// 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
exportAidlIncludeDirs android . Paths
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
2021-03-17 23:56:23 +01:00
// list of .java files and srcjars that was passed to javac
compiledJavaSrcs android . Paths
compiledSrcJars android . Paths
// manifest file to use instead of properties.Manifest
overrideManifest android . OptionalPath
// map of SDK version to class loader context
classLoaderContexts dexpreopt . ClassLoaderContextMap
// 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
// 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
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths [ ] string
hideApexVariantFromMake bool
2021-04-02 01:45:46 +02:00
sdkVersion android . SdkSpec
minSdkVersion android . SdkSpec
2021-11-29 18:25:52 +01:00
maxSdkVersion android . SdkSpec
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 {
case bootClasspathTag , libTag , staticLibTag , java9LibTag :
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
}
}
}
func ( j * Module ) addHostProperties ( ) {
j . AddProperties (
& j . properties ,
& j . protoProperties ,
& j . usesLibraryProperties ,
)
}
func ( j * Module ) addHostAndDeviceProperties ( ) {
j . addHostProperties ( )
j . AddProperties (
& j . deviceProperties ,
& j . dexer . dexProperties ,
& j . dexpreoptProperties ,
& j . linter . properties ,
)
}
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
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 )
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 {
return j . shouldInstrument ( ctx ) &&
( 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.
apexInfo := ctx . Provider ( android . ApexInfoProvider ) . ( android . ApexInfo )
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
}
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 )
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) MinSdkVersion ( ctx android . EarlyModuleContext ) android . SdkSpec {
2021-03-17 23:56:23 +01:00
if j . deviceProperties . Min_sdk_version != nil {
2021-04-02 01:45:46 +02:00
return android . SdkSpecFrom ( ctx , * j . deviceProperties . Min_sdk_version )
2021-03-17 23:56:23 +01:00
}
2021-04-02 01:45:46 +02:00
return j . SdkVersion ( ctx )
2021-03-17 23:56:23 +01:00
}
2021-11-29 18:25:52 +01:00
func ( j * Module ) MaxSdkVersion ( ctx android . EarlyModuleContext ) android . SdkSpec {
maxSdkVersion := proptools . StringDefault ( j . deviceProperties . Max_sdk_version , "" )
// SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
// TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
return android . SdkSpecFrom ( ctx , maxSdkVersion )
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) MinSdkVersionString ( ) string {
return j . minSdkVersion . Raw
2021-03-17 23:56:23 +01:00
}
2021-04-02 01:45:46 +02:00
func ( j * Module ) TargetSdkVersion ( ctx android . EarlyModuleContext ) android . SdkSpec {
if j . deviceProperties . Target_sdk_version != nil {
return android . SdkSpecFrom ( ctx , * j . deviceProperties . Target_sdk_version )
}
return j . SdkVersion ( ctx )
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 ... )
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.
2021-08-20 16:39:12 +02:00
optional := android . InList ( * lib , dexpreopt . OptionalCompatUsesLibs )
tag := makeUsesLibraryDependencyTag ( dexpreopt . AnySdkVersion , optional , true )
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" )
if len ( j . properties . Plugins ) > 0 {
ctx . AddVariationDependencies ( nil , kotlinAnnotationsTag , "kotlin-annotations" )
}
}
// 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 )
}
func ( j * Module ) aidlFlags ( ctx android . ModuleContext , aidlPreprocess android . OptionalPath ,
aidlIncludeDirs android . Paths ) ( string , android . Paths ) {
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
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 {
flags = append ( flags , android . JoinWithPrefix ( aidlIncludeDirs . Strings ( ) , "-I" ) )
}
if len ( j . exportAidlIncludeDirs ) > 0 {
flags = append ( flags , android . JoinWithPrefix ( j . exportAidlIncludeDirs . Strings ( ) , "-I" ) )
}
if len ( aidlIncludes ) > 0 {
flags = append ( flags , android . JoinWithPrefix ( aidlIncludes . Strings ( ) , "-I" ) )
}
flags = append ( flags , "-I" + android . PathForModuleSrc ( ctx ) . String ( ) )
if src := android . ExistentPathForSource ( ctx , ctx . ModuleDir ( ) , "src" ) ; src . Valid ( ) {
flags = append ( flags , "-I" + src . String ( ) )
}
if Bool ( j . deviceProperties . Aidl . Generate_traces ) {
flags = append ( flags , "-t" )
}
if Bool ( j . deviceProperties . Aidl . Generate_get_transaction_name ) {
flags = append ( flags , "--transaction_names" )
}
2021-11-05 23:08:45 +01:00
aidlMinSdkVersion := j . MinSdkVersion ( ctx ) . ApiLevel . String ( )
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 ) {
2021-03-17 23:56:23 +01:00
if config . ErrorProneClasspath == nil && ctx . Config ( ) . TestProductVariables == nil {
ctx . ModuleErrorf ( "cannot build with Error Prone, missing external/error_prone?" )
}
errorProneFlags := [ ] string {
"-Xplugin:ErrorProne" ,
"${config.ErrorProneChecks}" ,
}
errorProneFlags = append ( errorProneFlags , j . properties . Errorprone . Javacflags ... )
flags . errorProneExtraJavacFlags = "${config.ErrorProneFlags} " +
"'" + 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 ... )
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
// aidl flags.
flags . aidlFlags , flags . aidlDeps = j . aidlFlags ( ctx , deps . aidlPreprocess , deps . aidlIncludeDirs )
return flags
}
func ( j * Module ) collectJavacFlags (
ctx android . ModuleContext , flags javaBuilderFlags , srcFiles android . Paths ) javaBuilderFlags {
// javac flags.
javacFlags := j . properties . Javacflags
if ctx . Config ( ) . MinimizeJavaDebugInfo ( ) && ! ctx . Host ( ) {
// 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 ... )
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
// b/150878007
//
// Workaround to support *Bazel-executed* JDK9 javac in Bazel's
// execution root for --patch-module. If this javac command line is
// invoked within Bazel's execution root working directory, the top
// level directories (e.g. libcore/, tools/, frameworks/) are all
// symlinks. JDK9 javac does not traverse into symlinks, which causes
// --patch-module to fail source file lookups when invoked in the
// execution root.
//
// Short of patching javac or enumerating *all* directories as possible
// input dirs, manually add the top level dir of the source files to be
// compiled.
topLevelDirs := map [ string ] bool { }
for _ , srcFilePath := range srcFiles {
srcFileParts := strings . Split ( srcFilePath . String ( ) , "/" )
// Ignore source files that are already in the top level directory
// as well as generated files in the out directory. The out
// directory may be an absolute path, which means srcFileParts[0] is the
// empty string, so check that as well. Note that "out" in Bazel's execution
// root is *not* a symlink, which doesn't cause problems for --patch-modules
// anyway, so it's fine to not apply this workaround for generated
// source files.
if len ( srcFileParts ) > 1 &&
srcFileParts [ 0 ] != "" &&
srcFileParts [ 0 ] != "out" {
topLevelDirs [ srcFileParts [ 0 ] ] = true
}
}
patchPaths = append ( patchPaths , android . SortedStringKeys ( topLevelDirs ) ... )
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
}
func ( j * Module ) compile ( ctx android . ModuleContext , aaptSrcJar android . Path ) {
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 ... )
}
2021-12-20 12:51:24 +01:00
if ctx . Config ( ) . TargetsJava11 ( ) {
j . properties . Srcs = append ( j . properties . Srcs , j . properties . Openjdk11 . Srcs ... )
}
2021-03-17 23:56:23 +01:00
srcFiles := android . PathsForModuleSrcExcludes ( ctx , j . properties . Srcs , j . properties . Exclude_srcs )
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" )
}
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 ... )
if aaptSrcJar != nil {
srcJars = append ( srcJars , aaptSrcJar )
}
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 )
}
jarName := ctx . ModuleName ( ) + ".jar"
javaSrcFiles := srcFiles . FilterByExt ( ".java" )
var uniqueSrcFiles android . Paths
set := make ( map [ string ] bool )
for _ , v := range javaSrcFiles {
if _ , found := set [ v . String ( ) ] ; ! found {
set [ v . String ( ) ] = true
uniqueSrcFiles = append ( uniqueSrcFiles , v )
}
}
// Collect .java files for AIDEGen
j . expandIDEInfoCompiledSrcs = append ( j . expandIDEInfoCompiledSrcs , uniqueSrcFiles . Strings ( ) ... )
var kotlinJars android . Paths
if srcFiles . HasExt ( ".kt" ) {
// 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"
}
var kotlinSrcFiles android . Paths
kotlinSrcFiles = append ( kotlinSrcFiles , uniqueSrcFiles ... )
kotlinSrcFiles = append ( kotlinSrcFiles , srcFiles . FilterByExt ( ".kt" ) ... )
// Collect .kt files for AIDEGen
j . expandIDEInfoCompiledSrcs = append ( j . expandIDEInfoCompiledSrcs , srcFiles . FilterByExt ( ".kt" ) . Strings ( ) ... )
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 ... )
if len ( flags . processorPath ) > 0 {
// Use kapt for annotation processing
kaptSrcJar := android . PathForModuleOut ( ctx , "kapt" , "kapt-sources.jar" )
kaptResJar := android . PathForModuleOut ( ctx , "kapt" , "kapt-res.jar" )
kotlinKapt ( ctx , kaptSrcJar , kaptResJar , kotlinSrcFiles , kotlinCommonSrcFiles , srcJars , flags )
srcJars = append ( srcJars , kaptSrcJar )
kotlinJars = append ( kotlinJars , kaptResJar )
// Disable annotation processing in javac, it's already been handled by kapt
flags . processorPath = nil
flags . processors = nil
}
kotlinJar := android . PathForModuleOut ( ctx , "kotlin" , jarName )
kotlinCompile ( ctx , kotlinJar , kotlinSrcFiles , kotlinCommonSrcFiles , srcJars , flags )
if ctx . Failed ( ) {
return
}
// Make javac rule depend on the kotlinc rule
flags . classpath = append ( flags . classpath , kotlinJar )
kotlinJars = append ( kotlinJars , kotlinJar )
// Jar kotlin classes into the final jar after javac
if BoolDefault ( j . properties . Static_kotlin_stdlib , true ) {
kotlinJars = append ( kotlinJars , deps . kotlinStdlib ... )
}
}
jars := append ( android . Paths ( nil ) , kotlinJars ... )
// Store the list of .java files that was passed to javac
j . compiledJavaSrcs = uniqueSrcFiles
j . compiledSrcJars = srcJars
enableSharding := false
2021-11-19 07:23:12 +01:00
var headerJarFileWithoutDepsOrJarjar android . Path
2021-03-17 23:56:23 +01:00
if ctx . Device ( ) && ! ctx . Config ( ) . IsEnvFalse ( "TURBINE_ENABLED" ) && ! deps . disableTurbine {
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.
}
2021-11-19 07:23:12 +01:00
headerJarFileWithoutDepsOrJarjar , j . headerJarFile =
2021-03-17 23:56:23 +01:00
j . compileJavaHeader ( ctx , uniqueSrcFiles , srcJars , deps , flags , jarName , kotlinJars )
if ctx . Failed ( ) {
return
}
}
if len ( uniqueSrcFiles ) > 0 || len ( srcJars ) > 0 {
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 )
2021-06-18 21:25:54 +02:00
} else if 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 )
2021-06-14 00:23:16 +02:00
transformJavaToClasses ( ctx , errorprone , - 1 , uniqueSrcFiles , srcJars , errorproneFlags , nil ,
"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
if len ( uniqueSrcFiles ) > 0 {
shardSrcs = android . ShardPaths ( uniqueSrcFiles , shardSize )
for idx , shardSrc := range shardSrcs {
classes := j . compileJavaClasses ( ctx , jarName , idx , shardSrc ,
nil , flags , extraJarDeps )
jars = append ( jars , classes )
}
}
if len ( srcJars ) > 0 {
classes := j . compileJavaClasses ( ctx , jarName , len ( shardSrcs ) ,
nil , srcJars , flags , extraJarDeps )
jars = append ( jars , classes )
}
} else {
classes := j . compileJavaClasses ( ctx , jarName , - 1 , uniqueSrcFiles , srcJars , flags , extraJarDeps )
jars = append ( jars , classes )
}
if ctx . Failed ( ) {
return
}
}
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.
// Transform the single path to the jar into an OutputPath as that is required by the following
// code.
if moduleOutPath , ok := jars [ 0 ] . ( android . ModuleOutPath ) ; ok {
// The path contains an embedded OutputPath so reuse that.
outputFile = moduleOutPath . OutputPath
} else if outputPath , ok := jars [ 0 ] . ( android . OutputPath ) ; ok {
// 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
}
}
// 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 {
j . headerJarFile = j . implementationJarFile
}
if j . shouldInstrumentInApex ( ctx ) {
j . properties . Instrument = true
}
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
apexInfo := ctx . Provider ( android . ApexInfoProvider ) . ( android . ApexInfo )
if j . DirectlyInAnyApex ( ) && ! apexInfo . IsForPlatform ( ) {
if j . dexProperties . Compile_dex == nil {
j . dexProperties . Compile_dex = proptools . BoolPtr ( true )
}
if j . deviceProperties . Hostdex == nil {
j . deviceProperties . Hostdex = proptools . BoolPtr ( true )
}
}
if ctx . Device ( ) && ( Bool ( j . properties . Installable ) || Bool ( j . dexProperties . Compile_dex ) ) {
if j . hasCode ( ctx ) {
if j . shouldInstrumentStatic ( ctx ) {
j . dexer . extraProguardFlagFiles = append ( j . dexer . extraProguardFlagFiles ,
android . PathForSource ( ctx , "build/make/core/proguard.jacoco.flags" ) )
}
// Dex compilation
var dexOutputFile android . OutputPath
2021-08-04 19:52:44 +02:00
dexOutputFile = j . dexer . compileDex ( ctx , flags , j . MinSdkVersion ( ctx ) , implementationAndResourcesJar , jarName )
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
TransformZipAlign ( ctx , combinedAlignedJar , combinedJar )
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
j . dexpreopt ( ctx , dexOutputFile )
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 ( ) {
2021-03-29 13:11:58 +02:00
lintSDKVersionString := func ( sdkSpec android . SdkSpec ) string {
2021-03-31 11:17:53 +02:00
if v := sdkSpec . ApiLevel ; ! v . IsPreview ( ) {
2021-03-17 23:56:23 +01:00
return v . String ( )
} else {
return ctx . Config ( ) . DefaultAppTargetSdk ( ctx ) . String ( )
}
}
j . linter . name = ctx . ModuleName ( )
j . linter . srcs = srcFiles
j . linter . srcJars = srcJars
j . linter . classpath = append ( append ( android . Paths ( nil ) , flags . bootClasspath ... ) , flags . classpath ... )
j . linter . classes = j . implementationJarFile
2021-04-02 01:45:46 +02:00
j . linter . minSdkVersion = lintSDKVersionString ( j . MinSdkVersion ( ctx ) )
j . linter . targetSdkVersion = lintSDKVersionString ( j . TargetSdkVersion ( ctx ) )
j . linter . compileSdkVersion = lintSDKVersionString ( j . SdkVersion ( ctx ) )
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"
if ! apexInfo . IsForPlatform ( ) && ctx . Config ( ) . UnbundledBuildApps ( ) {
j . linter . buildModuleReportZip = true
}
j . linter . lint ( ctx )
}
ctx . CheckbuildFile ( outputFile )
ctx . SetProvider ( JavaInfoProvider , JavaInfo {
HeaderJars : android . PathsIfNonNil ( j . headerJarFile ) ,
ImplementationAndResourcesJars : android . PathsIfNonNil ( j . implementationAndResourcesJar ) ,
ImplementationJars : android . PathsIfNonNil ( j . implementationJarFile ) ,
ResourceJars : android . PathsIfNonNil ( j . resourceJar ) ,
AidlIncludeDirs : j . exportAidlIncludeDirs ,
SrcJarArgs : j . srcJarArgs ,
SrcJarDeps : j . srcJarDeps ,
ExportedPlugins : j . exportedPluginJars ,
ExportedPluginClasses : j . exportedPluginClasses ,
ExportedPluginDisableTurbine : j . exportedDisableTurbine ,
JacocoReportClassesFile : j . jacocoReportClassesFile ,
} )
// 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 )
}
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" )
if idx >= 0 {
kzipName = strings . TrimSuffix ( jarName , filepath . Ext ( jarName ) ) + strconv . Itoa ( idx ) + ".kzip"
jarName += strconv . Itoa ( idx )
}
classes := android . PathForModuleOut ( ctx , "javac" , jarName ) . OutputPath
TransformJavaToClasses ( ctx , classes , idx , srcFiles , srcJars , flags , extraJarDeps )
if ctx . Config ( ) . EmitXrefRules ( ) {
extractionFile := android . PathForModuleOut ( ctx , kzipName )
emitXrefRule ( ctx , extractionFile , idx , srcFiles , srcJars , flags , extraJarDeps )
j . kytheFiles = append ( j . kytheFiles , extractionFile )
}
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 ,
2021-11-19 07:23:12 +01:00
extraJars android . Paths ) ( headerJar , jarjarAndDepsHeaderJar 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 ( ) {
return nil , nil
}
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 ( ) {
return nil , nil
}
}
2021-11-19 07:23:12 +01:00
return headerJar , jarjarAndDepsHeaderJar
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
}
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 }
}
2021-09-15 04:34:04 +02:00
func ( j * Module ) DexJarBuildPath ( ) 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 ( ) )
}
dpInfo . Paths = append ( dpInfo . Paths , j . modulePaths ... )
}
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 {
2021-04-02 01:45:46 +02:00
sdkSpec := j . MinSdkVersion ( ctx )
2021-03-29 13:11:58 +02:00
if ! sdkSpec . Specified ( ) {
2021-03-17 23:56:23 +01:00
return fmt . Errorf ( "min_sdk_version is not specified" )
}
2021-03-29 13:11:58 +02:00
if sdkSpec . Kind == android . SdkCore {
2021-03-17 23:56:23 +01:00
return nil
}
2021-06-23 03:23:16 +02:00
if sdkSpec . ApiLevel . GreaterThan ( sdkVersion ) {
return fmt . Errorf ( "newer SDK(%v)" , sdkSpec . ApiLevel )
2021-03-17 23:56:23 +01:00
}
return nil
}
func ( j * Module ) Stem ( ) string {
return proptools . StringDefault ( j . deviceProperties . Stem , j . Name ( ) )
}
func ( j * Module ) JacocoReportClassesFile ( ) android . Path {
return j . jacocoReportClassesFile
}
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 {
case "core.current.stubs" , "legacy.core.platform.api.stubs" , "stable.core.platform.api.stubs" ,
"stub-annotations" , "private-stub-annotations-jar" ,
"core-lambda-stubs" , "core-generated-annotation-stubs" :
return javaCore , true
case "android_stubs_current" :
return javaSdk , true
case "android_system_stubs_current" :
return javaSystem , true
case "android_module_lib_stubs_current" :
return javaModule , true
case "android_system_server_stubs_current" :
return javaSystemServer , true
case "android_test_stubs_current" :
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 ... )
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
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 {
case libTag :
2021-04-02 01:45:46 +02:00
deps . classpath = append ( deps . classpath , dep . SdkHeaderJars ( ctx , j . SdkVersion ( ctx ) ) ... )
2021-03-17 23:56:23 +01:00
case staticLibTag :
ctx . ModuleErrorf ( "dependency on java_sdk_library %q can only be in libs" , otherName )
}
} else if ctx . OtherModuleHasProvider ( module , JavaInfoProvider ) {
dep := ctx . OtherModuleProvider ( module , JavaInfoProvider ) . ( JavaInfo )
if sdkLinkType != javaPlatform &&
ctx . OtherModuleHasProvider ( module , SyspropPublicStubInfoProvider ) {
// 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.
syspropDep := ctx . OtherModuleProvider ( module , SyspropPublicStubInfoProvider ) . ( SyspropPublicStubInfo )
dep = syspropDep . JavaInfo
}
switch tag {
case bootClasspathTag :
deps . bootClasspath = append ( deps . bootClasspath , dep . HeaderJars ... )
case libTag , instrumentationForTag :
deps . classpath = append ( deps . classpath , dep . HeaderJars ... )
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 :
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
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.
ctx . SetProvider ( SyspropPublicStubInfoProvider , SyspropPublicStubInfo {
JavaInfo : dep ,
} )
}
} else if dep , ok := module . ( android . SourceFileProducer ) ; ok {
switch tag {
case libTag :
checkProducesJars ( ctx , dep )
deps . classpath = append ( deps . classpath , dep . Srcs ( ) ... )
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 ( ) ... )
}
} 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 }
}
}
addCLCFromDep ( ctx , module , j . classLoaderContexts )
} )
return deps
}
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 )
2021-12-10 12:14:59 +01:00
func ( j * Module ) ConvertWithBp2build ( ctx android . TopDownMutatorContext ) {
switch ctx . ModuleType ( ) {
case "java_library" , "java_library_host" :
if lib , ok := ctx . Module ( ) . ( * Library ) ; ok {
javaLibraryBp2Build ( ctx , lib )
}
case "java_binary_host" :
if binary , ok := ctx . Module ( ) . ( * Binary ) ; ok {
javaBinaryHostBp2Build ( ctx , binary )
}
}
}