summaryrefslogtreecommitdiff
path: root/java/java.go
diff options
context:
space:
mode:
Diffstat (limited to 'java/java.go')
-rw-r--r--java/java.go1523
1 files changed, 1188 insertions, 335 deletions
diff --git a/java/java.go b/java/java.go
index ddfb09a4f..480518e76 100644
--- a/java/java.go
+++ b/java/java.go
@@ -29,18 +29,25 @@ import (
"android/soong/android"
"android/soong/java/config"
+ "android/soong/tradefed"
)
func init() {
android.RegisterModuleType("java_defaults", defaultsFactory)
- android.RegisterModuleType("java_library", LibraryFactory(true))
- android.RegisterModuleType("java_library_static", LibraryFactory(false))
+ android.RegisterModuleType("java_library", LibraryFactory)
+ android.RegisterModuleType("java_library_static", LibraryStaticFactory)
android.RegisterModuleType("java_library_host", LibraryHostFactory)
android.RegisterModuleType("java_binary", BinaryFactory)
android.RegisterModuleType("java_binary_host", BinaryHostFactory)
+ android.RegisterModuleType("java_test", TestFactory)
+ android.RegisterModuleType("java_test_helper_library", TestHelperLibraryFactory)
+ android.RegisterModuleType("java_test_host", TestHostFactory)
android.RegisterModuleType("java_import", ImportFactory)
android.RegisterModuleType("java_import_host", ImportFactoryHost)
+ android.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
+ android.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
+ android.RegisterModuleType("dex_import", DexImportFactory)
android.RegisterSingletonType("logtags", LogtagsSingleton)
}
@@ -57,11 +64,11 @@ func init() {
type CompilerProperties struct {
// list of source files used to compile the Java module. May be .java, .logtags, .proto,
// or .aidl files.
- Srcs []string `android:"arch_variant"`
+ 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:"arch_variant"`
+ Exclude_srcs []string `android:"path,arch_variant"`
// list of directories containing Java resources
Java_resource_dirs []string `android:"arch_variant"`
@@ -70,22 +77,24 @@ type CompilerProperties struct {
Exclude_java_resource_dirs []string `android:"arch_variant"`
// list of files to use as Java resources
- Java_resources []string `android:"arch_variant"`
+ Java_resources []string `android:"path,arch_variant"`
- // list of files that should be excluded from java_resources
- Exclude_java_resources []string `android:"arch_variant"`
+ // list of files that should be excluded from java_resources and java_resource_dirs
+ Exclude_java_resources []string `android:"path,arch_variant"`
- // don't build against the default libraries (bootclasspath, legacy-test, core-junit,
- // ext, and framework for device targets)
+ // don't build against the default libraries (bootclasspath, ext, and framework for device
+ // targets)
No_standard_libs *bool
- // don't build against the framework libraries (legacy-test, core-junit,
- // ext, and framework for device targets)
+ // don't build against the framework libraries (ext, and framework for device targets)
No_framework_libs *bool
// 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 of java libraries that will be in the classpath
Libs []string `android:"arch_variant"`
@@ -93,25 +102,27 @@ type CompilerProperties struct {
Static_libs []string `android:"arch_variant"`
// manifest file to be included in resulting jar
- Manifest *string
+ Manifest *string `android:"path"`
// if not blank, run jarjar using the specified rules file
- Jarjar_rules *string `android:"arch_variant"`
+ 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 false, don't allow this module to be installed. Defaults to true.
+ // 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
- // List of modules to use as annotation processors
- Annotation_processors []string
+ // 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 classes to pass to javac to use as annotation processors
- Annotation_processor_classes []string
+ // List of modules to use as annotation processors
+ Plugins []string
// The number of Java source entries each Javac instance can process
Javac_shard_size *int64
@@ -121,12 +132,21 @@ type CompilerProperties struct {
Openjdk9 struct {
// List of source files that should only be used when passing -source 1.9
- Srcs []string
+ Srcs []string `android:"path"`
// List of javac flags that should only be used when passing -source 1.9
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.
+ 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
@@ -156,15 +176,30 @@ type CompilerProperties struct {
}
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"`
}
type CompilerDeviceProperties struct {
// list of module-specific flags that will be used for dex compiles
Dxflags []string `android:"arch_variant"`
- // if not blank, set to the version of the sdk to compile against
+ // if not blank, set to the version of the sdk to compile against. Defaults to compiling against the current
+ // sdk if platform_apis is not set.
Sdk_version *string
+ // if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
+ // Defaults to sdk_version if not set.
+ Min_sdk_version *string
+
+ // if not blank, set the targetSdkVersion in the AndroidManifest.xml.
+ // Defaults to sdk_version if not set.
+ Target_sdk_version *string
+
+ // if true, compile against the platform APIs instead of an SDK.
+ Platform_apis *bool
+
Aidl struct {
// Top level directories to pass to aidl tool
Include_dirs []string
@@ -178,34 +213,30 @@ type CompilerDeviceProperties struct {
// whether to generate traces (for systrace) for this interface
Generate_traces *bool
+
+ // whether to generate Binder#GetTransaction name method.
+ Generate_get_transaction_name *bool
}
// If true, export a copy of the module as a -hostdex module for host testing.
Hostdex *bool
- Dex_preopt struct {
- // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to
- // true.
- Enabled *bool
-
- // If true, generate an app image (.art file) for this module.
- App_image *bool
-
- // If true, use a checked-in profile to guide optimization. Defaults to false unless
- // a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
- // that matches the name of this module, in which case it is defaulted to true.
- Profile_guided *bool
-
- // If set, provides the path to profile relative to the Android.bp file. If not set,
- // defaults to searching for a file that matches the name of this module in the default
- // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
- Profile *string
+ Target struct {
+ Hostdex struct {
+ // Additional required dependencies to add to -hostdex modules.
+ Required []string
+ }
}
+ // If set to true, compile dex regardless of installable. Defaults to false.
+ Compile_dex *bool
+
Optimize struct {
- // If false, disable all optimization. Defaults to true for apps, false for
- // libraries and tests.
+ // If false, disable all optimization. Defaults to true for android_app and android_test
+ // modules, false for java_library and java_test modules.
Enabled *bool
+ // True if the module containing this has it set by default.
+ EnabledByDefault bool `blueprint:"mutated"`
// If true, optimize for size by removing unused code. Defaults to true for apps,
// false for libraries and tests.
@@ -225,11 +256,18 @@ type CompilerDeviceProperties struct {
Proguard_flags []string
// Specifies the locations of files containing proguard flags.
- Proguard_flags_files []string
+ Proguard_flags_files []string `android:"path"`
}
// When targeting 1.9, override the modules to use with --system
System_modules *string
+
+ UncompressDex bool `blueprint:"mutated"`
+ IsSDKLibrary bool `blueprint:"mutated"`
+}
+
+func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool {
+ return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault)
}
// Module contains the properties and members used by all java module types
@@ -241,23 +279,36 @@ type Module struct {
protoProperties android.ProtoProperties
deviceProperties CompilerDeviceProperties
- // header jar file suitable for inserting into the bootclasspath/classpath of another compile
+ // jar file containing header classes including static library dependencies, suitable for
+ // inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
- // full implementation jar file suitable for static dependency of another module compile
+ // jar file containing implementation classes including static library dependencies but no
+ // resources
implementationJarFile android.Path
- // output file containing classes.dex
+ // jar file containing only resources including from static library dependencies
+ resourceJar android.Path
+
+ // jar file containing implementation classes and resources including static library
+ // dependencies
+ implementationAndResourcesJar android.Path
+
+ // output file containing classes.dex and resources
dexJarFile android.Path
+ // output file that contains classes.dex if it should be in the output file
+ maybeStrippedDexJarFile android.Path
+
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
// output file containing mapping of obfuscated names
proguardDictionary android.Path
- // output file suitable for installing or running
- outputFile 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
@@ -272,10 +323,33 @@ type Module struct {
// list of extra progurad flag files
extraProguardFlagFiles android.Paths
+
+ // manifest file to use instead of properties.Manifest
+ overrideManifest android.OptionalPath
+
+ // list of SDK lib names that this java moudule is exporting
+ exportedSdkLibs []string
+
+ // list of source files, collected from compiledJavaSrcs and compiledSrcJars
+ // filter out Exclude_srcs, will be used by android.IDEInfo struct
+ expandIDEInfoCompiledSrcs []string
+
+ // expanded Jarjar_rules
+ expandJarjarRules android.Path
+
+ // list of additional targets for checkbuild
+ additionalCheckedModules android.Paths
+
+ hiddenAPI
+ dexpreopter
}
func (j *Module) Srcs() android.Paths {
- return android.Paths{j.implementationJarFile}
+ return append(android.Paths{j.outputFile}, j.extraOutputFiles...)
+}
+
+func (j *Module) DexJarFile() android.Path {
+ return j.dexJarFile
}
var _ android.SourceFileProducer = (*Module)(nil)
@@ -283,9 +357,33 @@ var _ android.SourceFileProducer = (*Module)(nil)
type Dependency interface {
HeaderJars() android.Paths
ImplementationJars() android.Paths
+ ResourceJars() android.Paths
+ ImplementationAndResourcesJars() android.Paths
+ DexJar() android.Path
AidlIncludeDirs() android.Paths
+ ExportedSdkLibs() []string
+}
+
+type SdkLibraryDependency interface {
+ SdkHeaderJars(ctx android.BaseContext, sdkVersion string) android.Paths
+ SdkImplementationJars(ctx android.BaseContext, sdkVersion string) android.Paths
+}
+
+type SrcDependency interface {
+ CompiledSrcs() android.Paths
+ CompiledSrcJars() android.Paths
+}
+
+func (j *Module) CompiledSrcs() android.Paths {
+ return j.compiledJavaSrcs
+}
+
+func (j *Module) CompiledSrcJars() android.Paths {
+ return j.compiledSrcJars
}
+var _ SrcDependency = (*Module)(nil)
+
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
android.InitAndroidArchModule(module, hod, android.MultilibCommon)
android.InitDefaultableModule(module)
@@ -296,40 +394,42 @@ type dependencyTag struct {
name string
}
+type jniDependencyTag struct {
+ blueprint.BaseDependencyTag
+ target android.Target
+}
+
var (
- staticLibTag = dependencyTag{name: "staticlib"}
- libTag = dependencyTag{name: "javalib"}
- bootClasspathTag = dependencyTag{name: "bootclasspath"}
- systemModulesTag = dependencyTag{name: "system modules"}
- frameworkResTag = dependencyTag{name: "framework-res"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
- proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ staticLibTag = dependencyTag{name: "staticlib"}
+ libTag = dependencyTag{name: "javalib"}
+ pluginTag = dependencyTag{name: "plugin"}
+ bootClasspathTag = dependencyTag{name: "bootclasspath"}
+ systemModulesTag = dependencyTag{name: "system modules"}
+ frameworkResTag = dependencyTag{name: "framework-res"}
+ frameworkApkTag = dependencyTag{name: "framework-apk"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ certificateTag = dependencyTag{name: "certificate"}
+ instrumentationForTag = dependencyTag{name: "instrumentation_for"}
)
type sdkDep struct {
useModule, useFiles, useDefaultLibs, invalidVersion bool
- module string
+ modules []string
systemModules string
frameworkResModule string
- jar android.Path
- aidl android.Path
+ jars android.Paths
+ aidl android.OptionalPath
}
-func sdkStringToNumber(ctx android.BaseContext, v string) int {
- switch v {
- case "", "current", "system_current", "test_current", "core_current":
- return android.FutureApiLevel
- default:
- if i, err := strconv.Atoi(android.GetNumericSdkVersion(v)); err != nil {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version")
- return -1
- } else {
- return i
- }
- }
+type jniLib struct {
+ name string
+ path android.Path
+ target android.Target
}
func (j *Module) shouldInstrument(ctx android.BaseContext) bool {
@@ -342,141 +442,66 @@ func (j *Module) shouldInstrumentStatic(ctx android.BaseContext) bool {
ctx.Config().UnbundledBuild())
}
-func decodeSdkDep(ctx android.BaseContext, v string) sdkDep {
- i := sdkStringToNumber(ctx, v)
- if i == -1 {
- // Invalid sdk version, error handled by sdkStringToNumber.
- return sdkDep{}
- }
-
- // Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
- // or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
- if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
- allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
- if ctx.DeviceSpecific() || ctx.SocSpecific() {
- if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
- allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
- }
- }
- version := strings.TrimPrefix(v, "system_")
- if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
- ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
- v, allowed_versions)
- }
- }
-
- toFile := func(v string) sdkDep {
- isCore := strings.HasPrefix(v, "core_")
- if isCore {
- v = strings.TrimPrefix(v, "core_")
- }
- dir := filepath.Join("prebuilts/sdk", v)
- jar := filepath.Join(dir, "android.jar")
- if isCore {
- jar = filepath.Join(dir, "core.jar")
- }
- aidl := filepath.Join(dir, "framework.aidl")
- jarPath := android.ExistentPathForSource(ctx, jar)
- aidlPath := android.ExistentPathForSource(ctx, aidl)
-
- if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
- return sdkDep{
- invalidVersion: true,
- module: "sdk_v" + v,
- }
- }
-
- if !jarPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
- return sdkDep{}
- }
-
- if !aidlPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
- return sdkDep{}
- }
-
- return sdkDep{
- useFiles: true,
- jar: jarPath.Path(),
- aidl: aidlPath.Path(),
- }
- }
-
- //toModule := func(m string) sdkDep {
- // return sdkDep{
- // useModule: true,
- // module: m,
- // systemModules: m + "_system_modules",
- // frameworkResModule: r,
- // }
- //}
+func (j *Module) sdkVersion() string {
+ return String(j.deviceProperties.Sdk_version)
+}
- if ctx.Config().UnbundledBuild() && v != "" {
- return toFile(v)
+func (j *Module) minSdkVersion() string {
+ if j.deviceProperties.Min_sdk_version != nil {
+ return *j.deviceProperties.Min_sdk_version
}
+ return j.sdkVersion()
+}
- switch v {
- case "":
- return sdkDep{
- useDefaultLibs: true,
- frameworkResModule: "framework-res",
- }
- // TODO(ccross): re-enable these once we generate stubs, until then
- // use the stubs in prebuilts/sdk/*current
- //case "current":
- // return toModule("android_stubs_current", "framework-res")
- //case "system_current":
- // return toModule("android_system_stubs_current", "framework-res")
- //case "test_current":
- // return toModule("android_test_stubs_current", "framework-res")
- default:
- return toFile(v)
+func (j *Module) targetSdkVersion() string {
+ if j.deviceProperties.Target_sdk_version != nil {
+ return *j.deviceProperties.Target_sdk_version
}
+ return j.sdkVersion()
}
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if ctx.Device() {
- if !proptools.Bool(j.properties.No_standard_libs) {
- sdkDep := decodeSdkDep(ctx, String(j.deviceProperties.Sdk_version))
+ if !Bool(j.properties.No_standard_libs) {
+ sdkDep := decodeSdkDep(ctx, sdkContext(j))
if sdkDep.useDefaultLibs {
- ctx.AddDependency(ctx.Module(), bootClasspathTag, config.DefaultBootclasspathLibraries...)
- if ctx.Config().TargetOpenJDK9() {
- ctx.AddDependency(ctx.Module(), systemModulesTag, config.DefaultSystemModules)
- }
- if !proptools.Bool(j.properties.No_framework_libs) {
- ctx.AddDependency(ctx.Module(), libTag, config.DefaultLibraries...)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules)
+ if !Bool(j.properties.No_framework_libs) {
+ ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...)
}
} else if sdkDep.useModule {
- if ctx.Config().TargetOpenJDK9() {
- ctx.AddDependency(ctx.Module(), systemModulesTag, sdkDep.systemModules)
- }
- ctx.AddDependency(ctx.Module(), bootClasspathTag, sdkDep.module)
- if Bool(j.deviceProperties.Optimize.Enabled) {
- ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultBootclasspathLibraries...)
- ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultLibraries...)
+ ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+ ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.modules...)
+ if j.deviceProperties.EffectiveOptimizeEnabled() {
+ ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
}
}
} else if j.deviceProperties.System_modules == nil {
ctx.PropertyErrorf("no_standard_libs",
"system_modules is required to be set when no_standard_libs is true, did you mean no_framework_libs?")
- } else if *j.deviceProperties.System_modules != "none" && ctx.Config().TargetOpenJDK9() {
- ctx.AddDependency(ctx.Module(), systemModulesTag, *j.deviceProperties.System_modules)
+ } else if *j.deviceProperties.System_modules != "none" {
+ ctx.AddVariationDependencies(nil, systemModulesTag, *j.deviceProperties.System_modules)
}
- if ctx.ModuleName() == "framework" {
- ctx.AddDependency(ctx.Module(), frameworkResTag, "framework-res")
+ if (ctx.ModuleName() == "framework") || (ctx.ModuleName() == "framework-annotation-proc") {
+ ctx.AddVariationDependencies(nil, frameworkResTag, "framework-res")
+ }
+ if ctx.ModuleName() == "android_stubs_current" ||
+ ctx.ModuleName() == "android_system_stubs_current" ||
+ ctx.ModuleName() == "android_test_stubs_current" {
+ ctx.AddVariationDependencies(nil, frameworkApkTag, "framework-res")
}
}
- ctx.AddDependency(ctx.Module(), libTag, j.properties.Libs...)
- ctx.AddDependency(ctx.Module(), staticLibTag, j.properties.Static_libs...)
- ctx.AddDependency(ctx.Module(), libTag, j.properties.Annotation_processors...)
+ ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
- android.ExtractSourcesDeps(ctx, j.properties.Srcs)
- android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
- android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
- android.ExtractSourceDeps(ctx, j.properties.Manifest)
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
+ }, pluginTag, j.properties.Plugins...)
+ android.ProtoDeps(ctx, &j.protoProperties)
if j.hasSrcExt(".proto") {
protoDeps(ctx, &j.protoProperties)
}
@@ -484,11 +509,14 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if j.hasSrcExt(".kt") {
// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
// Kotlin files
- ctx.AddDependency(ctx.Module(), kotlinStdlibTag, "kotlin-stdlib")
+ ctx.AddVariationDependencies(nil, kotlinStdlibTag, "kotlin-stdlib")
+ if len(j.properties.Plugins) > 0 {
+ ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
+ }
}
if j.shouldInstrumentStatic(ctx) {
- ctx.AddDependency(ctx.Module(), staticLibTag, "jacocoagent")
+ ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
}
@@ -519,7 +547,7 @@ func (j *Module) hasSrcExt(ext string) bool {
}
func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
- aidlIncludeDirs android.Paths) []string {
+ aidlIncludeDirs android.Paths) (string, android.Paths) {
aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
aidlIncludes = append(aidlIncludes,
@@ -528,14 +556,23 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt
android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)
var flags []string
+ var deps android.Paths
+
if aidlPreprocess.Valid() {
flags = append(flags, "-p"+aidlPreprocess.String())
- } else {
+ deps = append(deps, aidlPreprocess.Path())
+ } else if len(aidlIncludeDirs) > 0 {
flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
}
- flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
- flags = append(flags, android.JoinWithPrefix(aidlIncludes.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())
@@ -545,20 +582,30 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt
flags = append(flags, "-t")
}
- return flags
+ if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) {
+ flags = append(flags, "--transaction_names")
+ }
+
+ return strings.Join(flags, " "), deps
}
type deps struct {
classpath classpath
bootClasspath classpath
+ processorPath classpath
+ processorClasses []string
staticJars android.Paths
staticHeaderJars android.Paths
- staticJarResources android.Paths
+ staticResourceJars android.Paths
aidlIncludeDirs android.Paths
+ srcs android.Paths
srcJars android.Paths
systemModules android.Path
aidlPreprocess android.OptionalPath
kotlinStdlib android.Paths
+ kotlinAnnotations android.Paths
+
+ disableTurbine bool
}
func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
@@ -570,31 +617,112 @@ func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer
}
}
+type linkType int
+
+const (
+ javaCore linkType = iota
+ javaSdk
+ javaSystem
+ javaPlatform
+)
+
+func getLinkType(m *Module, name string) (ret linkType, stubs bool) {
+ ver := m.sdkVersion()
+ switch {
+ case name == "core.current.stubs" || name == "core.platform.api.stubs" ||
+ name == "stub-annotations" || name == "private-stub-annotations-jar" ||
+ name == "core-lambda-stubs":
+ return javaCore, true
+ case ver == "core_current":
+ return javaCore, false
+ case name == "android_system_stubs_current":
+ return javaSystem, true
+ case strings.HasPrefix(ver, "system_"):
+ return javaSystem, false
+ case name == "android_test_stubs_current":
+ return javaSystem, true
+ case strings.HasPrefix(ver, "test_"):
+ return javaPlatform, false
+ case name == "android_stubs_current":
+ return javaSdk, true
+ case ver == "current":
+ return javaSdk, false
+ case ver == "":
+ return javaPlatform, false
+ default:
+ if _, err := strconv.Atoi(ver); err != nil {
+ panic(fmt.Errorf("expected sdk_version to be a number, got %q", ver))
+ }
+ return javaSdk, false
+ }
+}
+
func checkLinkType(ctx android.ModuleContext, from *Module, to *Library, tag dependencyTag) {
- if strings.HasPrefix(String(from.deviceProperties.Sdk_version), "core_") {
- if !strings.HasPrefix(String(to.deviceProperties.Sdk_version), "core_") {
- ctx.ModuleErrorf("depends on other library %q using non-core Java APIs",
+ if ctx.Host() {
+ return
+ }
+
+ myLinkType, stubs := getLinkType(from, ctx.ModuleName())
+ if stubs {
+ return
+ }
+ otherLinkType, _ := getLinkType(&to.Module, ctx.OtherModuleName(to))
+ commonMessage := "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source."
+
+ switch myLinkType {
+ case javaCore:
+ if otherLinkType != javaCore {
+ ctx.ModuleErrorf("compiles against core Java API, but dependency %q is compiling against non-core Java APIs."+commonMessage,
+ ctx.OtherModuleName(to))
+ }
+ break
+ case javaSdk:
+ if otherLinkType != javaCore && otherLinkType != javaSdk {
+ ctx.ModuleErrorf("compiles against Android API, but dependency %q is compiling against non-public Android API."+commonMessage,
ctx.OtherModuleName(to))
}
+ break
+ case javaSystem:
+ if otherLinkType == javaPlatform {
+ ctx.ModuleErrorf("compiles against system API, but dependency %q is compiling against private API."+commonMessage,
+ ctx.OtherModuleName(to))
+ }
+ break
+ case javaPlatform:
+ // no restriction on link-type
+ break
}
}
func (j *Module) collectDeps(ctx android.ModuleContext) deps {
var deps deps
- sdkDep := decodeSdkDep(ctx, String(j.deviceProperties.Sdk_version))
- if sdkDep.invalidVersion {
- ctx.AddMissingDependencies([]string{sdkDep.module})
- } else if sdkDep.useFiles {
- // sdkDep.jar is actually equivalent to turbine header.jar.
- deps.classpath = append(deps.classpath, sdkDep.jar)
- deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, sdkDep.aidl)
+ if ctx.Device() {
+ sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ if sdkDep.invalidVersion {
+ ctx.AddMissingDependencies(sdkDep.modules)
+ } 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
+ }
}
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
+ if _, ok := tag.(*jniDependencyTag); ok {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+ if tag == certificateTag {
+ // Handled by AndroidApp.collectAppDeps
+ return
+ }
+
if to, ok := module.(*Library); ok {
switch tag {
case bootClasspathTag, libTag, staticLibTag:
@@ -602,29 +730,66 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
}
switch dep := module.(type) {
+ case SdkLibraryDependency:
+ switch tag {
+ case libTag:
+ deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ // names of sdk libs that are directly depended are exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+ default:
+ ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
+ }
case Dependency:
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
- case libTag:
+ case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
+ // sdk lib names from dependencies are re-exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
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()...)
+ // sdk lib names from dependencies are re-exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
+ case pluginTag:
+ if plugin, ok := dep.(*Plugin); ok {
+ deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...)
+ if plugin.pluginProperties.Processor_class != nil {
+ deps.processorClasses = append(deps.processorClasses, *plugin.pluginProperties.Processor_class)
+ }
+ deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
+ } else {
+ ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
+ }
case frameworkResTag:
- if ctx.ModuleName() == "framework" {
+ if (ctx.ModuleName() == "framework") || (ctx.ModuleName() == "framework-annotation-proc") {
// framework.jar has a one-off dependency on the R.java and Manifest.java files
// generated by framework-res.apk
deps.srcJars = append(deps.srcJars, dep.(*AndroidApp).aaptSrcJar)
}
+ case frameworkApkTag:
+ if ctx.ModuleName() == "android_stubs_current" ||
+ ctx.ModuleName() == "android_system_stubs_current" ||
+ ctx.ModuleName() == "android_test_stubs_current" {
+ // framework stubs.jar need to depend on framework-res.apk, in order to pull the
+ // resource files out of there for aapt.
+ //
+ // Normally the package rule runs aapt, which includes the resource,
+ // but we're not running that in our package rule so just copy in the
+ // resource files here.
+ deps.staticResourceJars = append(deps.staticResourceJars, dep.(*AndroidApp).exportPackage)
+ }
case kotlinStdlibTag:
deps.kotlinStdlib = dep.HeaderJars()
- default:
- panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
+ case kotlinAnnotationsTag:
+ deps.kotlinAnnotations = dep.HeaderJars()
}
- deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
case android.SourceFileProducer:
switch tag {
case libTag:
@@ -635,10 +800,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.classpath = append(deps.classpath, dep.Srcs()...)
deps.staticJars = append(deps.staticJars, dep.Srcs()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
- case android.DefaultsDepTag, android.SourceDepTag:
- // Nothing to do
- default:
- ctx.ModuleErrorf("dependency on genrule %q may only be in srcs, libs, or static_libs", otherName)
}
default:
switch tag {
@@ -659,16 +820,54 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
})
+ j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
+
return deps
}
+func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) string {
+ var ret string
+ v := sdkContext.sdkVersion()
+ // For PDK builds, use the latest SDK version instead of "current"
+ if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
+ sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
+ latestSdkVersion := 0
+ if len(sdkVersions) > 0 {
+ latestSdkVersion = sdkVersions[len(sdkVersions)-1]
+ }
+ v = strconv.Itoa(latestSdkVersion)
+ }
+
+ sdk, err := sdkVersionToNumber(ctx, v)
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version", "%s", err)
+ }
+ if javaVersion != "" {
+ ret = javaVersion
+ } else if ctx.Device() && sdk <= 23 {
+ ret = "1.7"
+ } else if ctx.Device() && sdk <= 28 || !ctx.Config().TargetOpenJDK9() {
+ ret = "1.8"
+ } else if ctx.Device() && sdkContext.sdkVersion() != "" && sdk == android.FutureApiLevel {
+ // TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
+ ret = "1.8"
+ } else {
+ ret = "1.9"
+ }
+
+ return ret
+}
+
func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags {
var flags javaBuilderFlags
+ // javaVersion flag.
+ flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
+
// javac flags.
javacFlags := j.properties.Javacflags
- if ctx.Config().TargetOpenJDK9() {
+ if flags.javaVersion == "1.9" {
javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
}
if ctx.Config().MinimizeJavaDebugInfo() {
@@ -676,36 +875,31 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
// disk and memory usage.
javacFlags = append(javacFlags, "-g:source,lines")
}
- if len(javacFlags) > 0 {
- // optimization.
- ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
- flags.javacFlags = "$javacFlags"
- }
- if len(j.properties.Errorprone.Javacflags) > 0 {
- flags.errorProneExtraJavacFlags = strings.Join(j.properties.Errorprone.Javacflags, " ")
- }
+ if ctx.Config().RunErrorProne() {
+ if config.ErrorProneClasspath == nil {
+ ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
+ }
- // javaVersion flag.
- sdk := sdkStringToNumber(ctx, String(j.deviceProperties.Sdk_version))
- if j.properties.Java_version != nil {
- flags.javaVersion = *j.properties.Java_version
- } else if ctx.Device() && sdk <= 23 {
- flags.javaVersion = "1.7"
- } else if ctx.Device() && sdk <= 26 || !ctx.Config().TargetOpenJDK9() {
- flags.javaVersion = "1.8"
- } else if ctx.Device() && String(j.deviceProperties.Sdk_version) != "" && sdk == android.FutureApiLevel {
- // TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current"
- flags.javaVersion = "1.8"
- } else {
- flags.javaVersion = "1.9"
+ 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.processorPath = append(flags.processorPath, deps.processorPath...)
+
+ flags.processor = strings.Join(deps.processorClasses, ",")
- if len(flags.bootClasspath) == 0 && ctx.Host() && !ctx.Config().TargetOpenJDK9() &&
+ if len(flags.bootClasspath) == 0 && ctx.Host() && flags.javaVersion != "1.9" &&
!Bool(j.properties.No_standard_libs) &&
inList(flags.javaVersion, []string{"1.6", "1.7", "1.8"}) {
// Give host-side tools a version of OpenJDK's standard libraries
@@ -731,17 +925,30 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
}
}
+ if j.properties.Patch_module != nil && flags.javaVersion == "1.9" {
+ // Manually specify build directory in case it is not under the repo root.
+ // (javac doesn't seem to expand into symbolc links when searching for patch-module targets, so
+ // just adding a symlink under the root doesn't help.)
+ patchPaths := ".:" + ctx.Config().BuildDir()
+ classPath := flags.classpath.FormJavaClassPath("")
+ if classPath != "" {
+ patchPaths += ":" + classPath
+ }
+ javacFlags = append(javacFlags, "--patch-module="+String(j.properties.Patch_module)+"="+patchPaths)
+ }
+
// systemModules
if deps.systemModules != nil {
flags.systemModules = append(flags.systemModules, deps.systemModules)
}
// aidl flags.
- aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
- if len(aidlFlags) > 0 {
+ flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
+
+ if len(javacFlags) > 0 {
// optimization.
- ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
- flags.aidlFlags = "$aidlFlags"
+ ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " "))
+ flags.javacFlags = "$javacFlags"
}
return flags
@@ -754,10 +961,10 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
deps := j.collectDeps(ctx)
flags := j.collectBuilderFlags(ctx, deps)
- if ctx.Config().TargetOpenJDK9() {
+ if flags.javaVersion == "1.9" {
j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
}
- srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
+ srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
if hasSrcExt(srcFiles.Strings(), ".proto") {
flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
}
@@ -768,7 +975,13 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
srcJars = append(srcJars, deps.srcJars...)
srcJars = append(srcJars, extraSrcJars...)
- var jars android.Paths
+ // Collect source files from compiledJavaSrcs, compiledSrcJars and filter out Exclude_srcs
+ // that IDEInfo struct will use
+ j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.Strings()...)
+
+ if j.properties.Jarjar_rules != nil {
+ j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+ }
jarName := ctx.ModuleName() + ".jar"
@@ -782,64 +995,84 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
}
}
+ var kotlinJars android.Paths
+
if srcFiles.HasExt(".kt") {
+ // user defined kotlin flags.
+ kotlincFlags := j.properties.Kotlincflags
+ CheckKotlincFlags(ctx, kotlincFlags)
+
// 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.
-
- flags.kotlincFlags = "-no-stdlib"
+ kotlincFlags = append(kotlincFlags, "-no-stdlib")
if ctx.Device() {
- flags.kotlincFlags += " -no-jdk"
+ kotlincFlags = append(kotlincFlags, "-no-jdk")
+ }
+ 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")...)
- flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...)
- flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...)
+ 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")
+ kotlinKapt(ctx, kaptSrcJar, kotlinSrcFiles, srcJars, flags)
+ srcJars = append(srcJars, kaptSrcJar)
+ // Disable annotation processing in javac, it's already been handled by kapt
+ flags.processorPath = nil
+ flags.processor = ""
+ }
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
- TransformKotlinToClasses(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
+ kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
// Make javac rule depend on the kotlinc rule
- flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
flags.classpath = append(flags.classpath, kotlinJar)
+
// Jar kotlin classes into the final jar after javac
- jars = append(jars, kotlinJar)
- jars = append(jars, deps.kotlinStdlib...)
+ kotlinJars = append(kotlinJars, kotlinJar)
+ 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
enable_sharding := false
- if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") {
+ if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enable_sharding = true
- if len(j.properties.Annotation_processors) != 0 ||
- len(j.properties.Annotation_processor_classes) != 0 {
- ctx.PropertyErrorf("javac_shard_size",
- "%q cannot be set when annotation processors are enabled.",
- j.properties.Javac_shard_size)
- }
+ // 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.
}
- // If sdk jar is java module, then directly return classesJar as header.jar
- if j.Name() != "android_stubs_current" && j.Name() != "android_system_stubs_current" &&
- j.Name() != "android_test_stubs_current" {
- j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName)
- if ctx.Failed() {
- return
- }
+ j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
+ if ctx.Failed() {
+ return
}
}
if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
var extraJarDeps android.Paths
- if ctx.Config().IsEnvTrue("RUN_ERROR_PRONE") {
+ if ctx.Config().RunErrorProne() {
// If error-prone is enabled, add an additional rule to compile the java files into
// a separate set of classes (so that they don't overwrite the normal ones and require
// a rebuild when error-prone is turned off).
@@ -877,7 +1110,8 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
}
}
- dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs)
+ 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)
var resArgs []string
@@ -889,7 +1123,7 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
resArgs = append(resArgs, fileArgs...)
resDeps = append(resDeps, fileDeps...)
- if proptools.Bool(j.properties.Include_srcs) {
+ if Bool(j.properties.Include_srcs) {
srcArgs, srcDeps := SourceFilesToJarArgs(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
resArgs = append(resArgs, srcArgs...)
resDeps = append(resDeps, srcDeps...)
@@ -898,47 +1132,109 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
if len(resArgs) > 0 {
resourceJar := android.PathForModuleOut(ctx, "res", jarName)
TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps)
+ j.resourceJar = resourceJar
if ctx.Failed() {
return
}
+ }
+
+ if len(deps.staticResourceJars) > 0 {
+ var jars android.Paths
+ if j.resourceJar != nil {
+ jars = append(jars, j.resourceJar)
+ }
+ jars = append(jars, deps.staticResourceJars...)
- jars = append(jars, resourceJar)
+ combinedJar := android.PathForModuleOut(ctx, "res-combined", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ j.resourceJar = combinedJar
}
- // static classpath jars have the resources in them, so the resource jars aren't necessary here
jars = append(jars, deps.staticJars...)
- var manifest android.OptionalPath
- if j.properties.Manifest != nil {
- manifest = android.OptionalPathForPath(ctx.ExpandSource(*j.properties.Manifest, "manifest"))
+ 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)
+ }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: zip,
+ Output: servicesJar,
+ Implicits: services,
+ Args: map[string]string{
+ "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
+ },
+ })
+ 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.Path
+ var outputFile android.ModuleOutPath
if len(jars) == 1 && !manifest.Valid() {
- // Optimization: skip the combine step if 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.
- outputFile = jars[0]
+ if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
+ // Optimization: skip the combine step if 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.
+ outputFile = moduleOutPath
+ } else {
+ combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: jars[0],
+ Output: combinedJar,
+ })
+ outputFile = combinedJar
+ }
} else {
combinedJar := android.PathForModuleOut(ctx, "combined", jarName)
- TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest, false, nil)
+ TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest,
+ false, nil, nil)
outputFile = combinedJar
}
- if j.properties.Jarjar_rules != nil {
- jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+ // jarjar implementation jar if necessary
+ if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName)
- TransformJarJar(ctx, jarjarFile, outputFile, jarjar_rules)
+ 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 {
+ // Check packages and copy to package-checked file.
+ pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp")
+ CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages)
+ j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile)
+
if ctx.Failed() {
return
}
}
+
j.implementationJarFile = outputFile
if j.headerJarFile == nil {
j.headerJarFile = j.implementationJarFile
@@ -954,18 +1250,94 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path
outputFile = j.instrument(ctx, flags, outputFile, jarName)
}
- if ctx.Device() && j.installable() {
- outputFile = j.compileDex(ctx, flags, outputFile, jarName)
+ // merge implementation jar with resources if necessary
+ implementationAndResourcesJar := outputFile
+ if j.resourceJar != nil {
+ jars := android.Paths{implementationAndResourcesJar, j.resourceJar}
+ combinedJar := android.PathForModuleOut(ctx, "withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ implementationAndResourcesJar = combinedJar
+ }
+
+ j.implementationAndResourcesJar = implementationAndResourcesJar
+
+ if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
+ // Dex compilation
+ var dexOutputFile android.ModuleOutPath
+ dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
if ctx.Failed() {
return
}
+
+ // Hidden API CSV generation and dex encoding
+ dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
+ j.deviceProperties.UncompressDex)
+
+ // merge dex jar with resources if necessary
+ if j.resourceJar != nil {
+ jars := android.Paths{dexOutputFile, j.resourceJar}
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
+ TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ if j.deviceProperties.UncompressDex {
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ dexOutputFile = combinedAlignedJar
+ } else {
+ dexOutputFile = combinedJar
+ }
+ }
+
+ j.dexJarFile = dexOutputFile
+
+ // Dexpreopting
+ dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+
+ j.maybeStrippedDexJarFile = dexOutputFile
+
+ outputFile = dexOutputFile
+
+ if ctx.Failed() {
+ return
+ }
+ } else {
+ outputFile = implementationAndResourcesJar
}
+
ctx.CheckbuildFile(outputFile)
- j.outputFile = outputFile
+
+ // 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()
+}
+
+// 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) android.Path {
+ deps deps, flags javaBuilderFlags, jarName string, extraJars android.Paths) android.Path {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -978,6 +1350,8 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
jars = append(jars, turbineJar)
}
+ 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.
var headerJar android.Path
@@ -986,14 +1360,14 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
// 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, []string{"META-INF"})
+ TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
+ false, nil, []string{"META-INF"})
headerJar = combinedJar
- if j.properties.Jarjar_rules != nil {
- jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+ if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
- TransformJarJar(ctx, jarjarFile, headerJar, jarjar_rules)
+ TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
headerJar = jarjarFile
if ctx.Failed() {
return nil
@@ -1004,7 +1378,7 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
- classesJar android.Path, jarName string) android.Path {
+ classesJar android.Path, jarName string) android.ModuleOutPath {
specs := j.jacocoModuleToZipCommand(ctx)
@@ -1018,55 +1392,116 @@ func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
return instrumentedJar
}
-// Returns a sdk version as a string that is guaranteed to be a parseable as a number. For
-// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns "10000".
-func (j *Module) minSdkVersionNumber(ctx android.ModuleContext) string {
- switch String(j.deviceProperties.Sdk_version) {
- case "", "current", "test_current", "system_current", "core_current":
- return strconv.Itoa(ctx.Config().DefaultAppTargetSdkInt())
- default:
- return android.GetNumericSdkVersion(String(j.deviceProperties.Sdk_version))
+var _ Dependency = (*Module)(nil)
+
+func (j *Module) HeaderJars() android.Paths {
+ if j.headerJarFile == nil {
+ return nil
}
+ return android.Paths{j.headerJarFile}
}
-func (j *Module) installable() bool {
- return j.properties.Installable == nil || *j.properties.Installable
+func (j *Module) ImplementationJars() android.Paths {
+ if j.implementationJarFile == nil {
+ return nil
+ }
+ return android.Paths{j.implementationJarFile}
}
-var _ Dependency = (*Library)(nil)
+func (j *Module) DexJar() android.Path {
+ return j.dexJarFile
+}
-func (j *Module) HeaderJars() android.Paths {
- return android.Paths{j.headerJarFile}
+func (j *Module) ResourceJars() android.Paths {
+ if j.resourceJar == nil {
+ return nil
+ }
+ return android.Paths{j.resourceJar}
}
-func (j *Module) ImplementationJars() android.Paths {
- return android.Paths{j.implementationJarFile}
+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) ExportedSdkLibs() []string {
+ // exportedSdkLibs is type []string
+ return j.exportedSdkLibs
+}
+
var _ logtagsProducer = (*Module)(nil)
func (j *Module) logtags() android.Paths {
return j.logtagsSrcs
}
+// 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.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())
+ }
+}
+
+func (j *Module) CompilerDeps() []string {
+ jdeps := []string{}
+ jdeps = append(jdeps, j.properties.Libs...)
+ jdeps = append(jdeps, j.properties.Static_libs...)
+ return jdeps
+}
+
//
// Java libraries (.jar file)
//
type Library struct {
Module
+
+ InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
+}
+
+func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
+ // Store uncompressed (and do not strip) dex files from boot class path jars.
+ if inList(ctx.ModuleName(), ctx.Config().BootJars()) {
+ return true
+ }
+
+ // Store uncompressed dex files that are preopted on /system.
+ if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !odexOnSystemOther(ctx, dexpreopter.installPath)) {
+ return true
+ }
+ if ctx.Config().UncompressPrivAppDex() &&
+ inList(ctx.ModuleName(), ctx.Config().ModulesLoadedByPrivilegedModules()) {
+ return true
+ }
+
+ return false
}
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", ctx.ModuleName()+".jar")
+ j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
+ j.dexpreopter.isInstallable = Bool(j.properties.Installable)
+ j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
+ j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex
j.compile(ctx)
- if j.installable() {
+ if (Bool(j.properties.Installable) || ctx.Host()) && !android.DirectlyInAnyApex(ctx, ctx.ModuleName()) {
+ var extraInstallDeps android.Paths
+ if j.InstallMixin != nil {
+ extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
+ }
j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- ctx.ModuleName()+".jar", j.outputFile)
+ ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...)
}
}
@@ -1074,24 +1509,39 @@ func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
j.deps(ctx)
}
-func LibraryFactory(installable bool) func() android.Module {
- return func() android.Module {
- module := &Library{}
+// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
+//
+// By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
+// compiled against the device bootclasspath. This jar is not suitable for installing on a device, but can be used
+// as a `static_libs` dependency of another module.
+//
+// Specifying `installable: true` will product a `.jar` file containing `classes.dex` files, suitable for installing on
+// a device.
+//
+// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
+// compiled against the host bootclasspath.
+func LibraryFactory() android.Module {
+ module := &Library{}
- if !installable {
- module.properties.Installable = proptools.BoolPtr(false)
- }
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.deviceProperties,
+ &module.Module.dexpreoptProperties,
+ &module.Module.protoProperties)
- module.AddProperties(
- &module.Module.properties,
- &module.Module.deviceProperties,
- &module.Module.protoProperties)
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
- InitJavaModule(module, android.HostAndDeviceSupported)
- return module
- }
+// java_library_static is an obsolete alias for java_library.
+func LibraryStaticFactory() android.Module {
+ return LibraryFactory()
}
+// java_library_host builds and links sources into a `.jar` file for the host.
+//
+// A java_library_host has a single variant that produces a `.jar` file containing `.class` files that were
+// compiled against the host bootclasspath.
func LibraryHostFactory() android.Module {
module := &Library{}
@@ -1099,6 +1549,121 @@ func LibraryHostFactory() android.Module {
&module.Module.properties,
&module.Module.protoProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+
+ InitJavaModule(module, android.HostSupported)
+ return module
+}
+
+//
+// Java Tests
+//
+
+type testProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // the name of the test configuration (for example "AndroidTest.xml") that should be
+ // installed with the module.
+ Test_config *string `android:"path,arch_variant"`
+
+ // the name of the test configuration template (for example "AndroidTestTemplate.xml") that
+ // should be installed with the module.
+ Test_config_template *string `android:"path,arch_variant"`
+
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test
+ Data []string `android:"path"`
+}
+
+type testHelperLibraryProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+}
+
+type Test struct {
+ Library
+
+ testProperties testProperties
+
+ testConfig android.Path
+ data android.Paths
+}
+
+type TestHelperLibrary struct {
+ Library
+
+ testHelperLibraryProperties testHelperLibraryProperties
+}
+
+func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template, j.testProperties.Test_suites)
+ j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
+
+ j.Library.GenerateAndroidBuildActions(ctx)
+}
+
+func (j *TestHelperLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ j.Library.GenerateAndroidBuildActions(ctx)
+}
+
+// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
+// creates an `AndroidTest.xml` file to allow running the test with `atest` or a `TEST_MAPPING` file.
+//
+// By default, a java_test has a single variant that produces a `.jar` file containing `classes.dex` files that were
+// compiled against the device bootclasspath.
+//
+// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
+// compiled against the host bootclasspath.
+func TestFactory() android.Module {
+ module := &Test{}
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.deviceProperties,
+ &module.Module.dexpreoptProperties,
+ &module.Module.protoProperties,
+ &module.testProperties)
+
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.Module.dexpreopter.isTest = true
+
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
+
+// java_test_helper_library creates a java library and makes sure that it is added to the appropriate test suite.
+func TestHelperLibraryFactory() android.Module {
+ module := &TestHelperLibrary{}
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.deviceProperties,
+ &module.Module.dexpreoptProperties,
+ &module.Module.protoProperties,
+ &module.testHelperLibraryProperties)
+
+ InitJavaModule(module, android.HostAndDeviceSupported)
+ return module
+}
+
+// java_test_host builds a and links sources into a `.jar` file for the host, and creates an `AndroidTest.xml` file to
+// allow running the test with `atest` or a `TEST_MAPPING` file.
+//
+// A java_test_host has a single variant that produces a `.jar` file containing `.class` files that were
+// compiled against the host bootclasspath.
+func TestHostFactory() android.Module {
+ module := &Test{}
+
+ module.AddProperties(
+ &module.Module.properties,
+ &module.Module.protoProperties,
+ &module.testProperties)
+
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+
InitJavaModule(module, android.HostSupported)
return module
}
@@ -1109,7 +1674,10 @@ func LibraryHostFactory() android.Module {
type binaryProperties struct {
// installable script to execute the resulting jar
- Wrapper *string
+ Wrapper *string `android:"path"`
+
+ // Name of the class containing main to be inserted into the manifest as Main-Class.
+ Main_class *string
}
type Binary struct {
@@ -1130,13 +1698,22 @@ func (j *Binary) HostToolPath() android.OptionalPath {
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if ctx.Arch().ArchType == android.Common {
// Compile the jar
+ if j.binaryProperties.Main_class != nil {
+ if j.properties.Manifest != nil {
+ ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
+ }
+ manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
+ GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
+ j.overrideManifest = android.OptionalPathForPath(manifestFile)
+ }
+
j.Library.GenerateAndroidBuildActions(ctx)
} else {
// Handle the binary wrapper
j.isWrapperVariant = true
if j.binaryProperties.Wrapper != nil {
- j.wrapperFile = ctx.ExpandSource(*j.binaryProperties.Wrapper, "wrapper")
+ j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
} else {
j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
}
@@ -1153,34 +1730,48 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
if ctx.Arch().ArchType == android.Common {
j.deps(ctx)
- } else {
- android.ExtractSourceDeps(ctx, j.binaryProperties.Wrapper)
}
}
+// java_binary builds a `.jar` file and a shell script that executes it for the device, and possibly for the host
+// as well.
+//
+// By default, a java_binary has a single variant that produces a `.jar` file containing `classes.dex` files that were
+// compiled against the device bootclasspath.
+//
+// Specifying `host_supported: true` will produce two variants, one compiled against the device bootclasspath and one
+// compiled against the host bootclasspath.
func BinaryFactory() android.Module {
module := &Binary{}
module.AddProperties(
&module.Module.properties,
&module.Module.deviceProperties,
+ &module.Module.dexpreoptProperties,
&module.Module.protoProperties,
&module.binaryProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
return module
}
+// java_binary_host builds a `.jar` file and a shell script that executes it for the host.
+//
+// A java_binary_host has a single variant that produces a `.jar` file containing `.class` files that were
+// compiled against the host bootclasspath.
func BinaryHostFactory() android.Module {
module := &Binary{}
module.AddProperties(
&module.Module.properties,
- &module.Module.deviceProperties,
&module.Module.protoProperties,
&module.binaryProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
return module
@@ -1191,21 +1782,42 @@ func BinaryHostFactory() android.Module {
//
type ImportProperties struct {
- Jars []string
+ Jars []string `android:"path"`
Sdk_version *string
Installable *bool
+
+ // List of shared java libs that this module has dependencies to
+ Libs []string
+
+ // List of files to remove from the jar file(s)
+ Exclude_files []string
+
+ // List of directories to remove from the jar file(s)
+ Exclude_dirs []string
+
+ // if set to true, run Jetifier against .jar file. Defaults to false.
+ Jetifier *bool
}
type Import struct {
android.ModuleBase
+ android.DefaultableModuleBase
prebuilt android.Prebuilt
properties ImportProperties
- classpathFiles android.Paths
combinedClasspathFile android.Path
+ exportedSdkLibs []string
+}
+
+func (j *Import) sdkVersion() string {
+ return String(j.properties.Sdk_version)
+}
+
+func (j *Import) minSdkVersion() string {
+ return j.sdkVersion()
}
func (j *Import) Prebuilt() *android.Prebuilt {
@@ -1221,49 +1833,251 @@ func (j *Import) Name() string {
}
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
}
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars)
+ jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
- outputFile := android.PathForModuleOut(ctx, "classes.jar")
- TransformJarsToJar(ctx, outputFile, "for prebuilts", j.classpathFiles, android.OptionalPath{}, false, nil)
+ jarName := ctx.ModuleName() + ".jar"
+ outputFile := android.PathForModuleOut(ctx, "combined", jarName)
+ TransformJarsToJar(ctx, outputFile, "for prebuilts", jars, android.OptionalPath{},
+ false, j.properties.Exclude_files, j.properties.Exclude_dirs)
+ if Bool(j.properties.Jetifier) {
+ inputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "jetifier", jarName)
+ TransformJetifier(ctx, outputFile, inputFile)
+ }
j.combinedClasspathFile = outputFile
+
+ ctx.VisitDirectDeps(func(module android.Module) {
+ otherName := ctx.OtherModuleName(module)
+ tag := ctx.OtherModuleDependencyTag(module)
+
+ switch dep := module.(type) {
+ case Dependency:
+ switch tag {
+ case libTag, staticLibTag:
+ // sdk lib names from dependencies are re-exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ }
+ case SdkLibraryDependency:
+ switch tag {
+ case libTag:
+ // names of sdk libs that are directly depended are exported
+ j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+ }
+ }
+ })
+
+ j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
+ if Bool(j.properties.Installable) {
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ ctx.ModuleName()+".jar", outputFile)
+ }
}
var _ Dependency = (*Import)(nil)
func (j *Import) HeaderJars() android.Paths {
- return j.classpathFiles
+ if j.combinedClasspathFile == nil {
+ return nil
+ }
+ return android.Paths{j.combinedClasspathFile}
}
func (j *Import) ImplementationJars() android.Paths {
- return j.classpathFiles
+ if j.combinedClasspathFile == nil {
+ return nil
+ }
+ return android.Paths{j.combinedClasspathFile}
+}
+
+func (j *Import) ResourceJars() android.Paths {
+ return nil
+}
+
+func (j *Import) ImplementationAndResourcesJars() android.Paths {
+ if j.combinedClasspathFile == nil {
+ return nil
+ }
+ return android.Paths{j.combinedClasspathFile}
+}
+
+func (j *Import) DexJar() android.Path {
+ return nil
}
func (j *Import) AidlIncludeDirs() android.Paths {
return nil
}
+func (j *Import) ExportedSdkLibs() []string {
+ return j.exportedSdkLibs
+}
+
+// Add compile time check for interface implementation
+var _ android.IDEInfo = (*Import)(nil)
+var _ android.IDECustomizedModuleName = (*Import)(nil)
+
+// Collect information for opening IDE project files in java/jdeps.go.
+const (
+ removedPrefix = "prebuilt_"
+)
+
+func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
+ dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
+}
+
+func (j *Import) IDECustomizedModuleName() string {
+ // TODO(b/113562217): Extract the base module name from the Import name, often the Import name
+ // has a prefix "prebuilt_". Remove the prefix explicitly if needed until we find a better
+ // solution to get the Import name.
+ name := j.Name()
+ if strings.HasPrefix(name, removedPrefix) {
+ name = strings.TrimPrefix(name, removedPrefix)
+ }
+ return name
+}
+
var _ android.PrebuiltInterface = (*Import)(nil)
+// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
+//
+// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
+// compiled against an Android classpath.
+//
+// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
+// for host modules.
func ImportFactory() android.Module {
module := &Import{}
module.AddProperties(&module.properties)
android.InitPrebuiltModule(module, &module.properties.Jars)
- android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+ InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
+// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library_host
+// module.
+//
+// A java_import_host has a single variant that expects a `.jar` file containing `.class` files that were
+// compiled against a host bootclasspath.
func ImportFactoryHost() android.Module {
module := &Import{}
module.AddProperties(&module.properties)
android.InitPrebuiltModule(module, &module.properties.Jars)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+ InitJavaModule(module, android.HostSupported)
+ return module
+}
+
+// dex_import module
+
+type DexImportProperties struct {
+ Jars []string
+}
+
+type DexImport struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ prebuilt android.Prebuilt
+
+ properties DexImportProperties
+
+ dexJarFile android.Path
+ maybeStrippedDexJarFile android.Path
+
+ dexpreopter
+}
+
+func (j *DexImport) Prebuilt() *android.Prebuilt {
+ return &j.prebuilt
+}
+
+func (j *DexImport) PrebuiltSrcs() []string {
+ return j.properties.Jars
+}
+
+func (j *DexImport) Name() string {
+ return j.prebuilt.Name(j.ModuleBase.Name())
+}
+
+func (j *DexImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+ android.ExtractSourcesDeps(ctx, j.properties.Jars)
+}
+
+func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if len(j.properties.Jars) != 1 {
+ ctx.PropertyErrorf("jars", "exactly one jar must be provided")
+ }
+
+ j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", ctx.ModuleName()+".jar")
+ j.dexpreopter.isInstallable = true
+ j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
+
+ inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
+ dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
+
+ if j.dexpreopter.uncompressedDex {
+ rule := android.NewRuleBuilder()
+
+ temporary := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar.unaligned")
+ rule.Temporary(temporary)
+
+ // use zip2zip to uncompress classes*.dex files
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
+ FlagWithInput("-i ", inputJar).
+ FlagWithOutput("-o ", temporary).
+ FlagWithArg("-0 ", "'classes*.dex'")
+
+ // use zipalign to align uncompressed classes*.dex files
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "zipalign")).
+ Flag("-f").
+ Text("4").
+ Input(temporary).
+ Output(dexOutputFile)
+
+ rule.DeleteTemporaryFiles()
+
+ rule.Build(pctx, ctx, "uncompress_dex", "uncompress dex")
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: inputJar,
+ Output: dexOutputFile,
+ })
+ }
+
+ j.dexJarFile = dexOutputFile
+
+ dexOutputFile = j.dexpreopt(ctx, dexOutputFile)
+
+ j.maybeStrippedDexJarFile = dexOutputFile
+
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ ctx.ModuleName()+".jar", dexOutputFile)
+}
+
+func (j *DexImport) DexJar() android.Path {
+ return j.dexJarFile
+}
+
+// dex_import imports a `.jar` file containing classes.dex files.
+//
+// A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
+// to the device.
+func DexImportFactory() android.Module {
+ module := &DexImport{}
+
+ module.AddProperties(&module.properties)
+
+ android.InitPrebuiltModule(module, &module.properties.Jars)
+ InitJavaModule(module, android.DeviceSupported)
return module
}
@@ -1278,9 +2092,37 @@ type Defaults struct {
func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
-func (d *Defaults) DepsMutator(ctx android.BottomUpMutatorContext) {
-}
-
+// java_defaults provides a set of properties that can be inherited by other java or android modules.
+//
+// A module can use the properties from a java_defaults module using `defaults: ["defaults_module_name"]`. Each
+// property in the defaults module that exists in the depending module will be prepended to the depending module's
+// value for that property.
+//
+// Example:
+//
+// java_defaults {
+// name: "example_defaults",
+// srcs: ["common/**/*.java"],
+// javacflags: ["-Xlint:all"],
+// aaptflags: ["--auto-add-overlay"],
+// }
+//
+// java_library {
+// name: "example",
+// defaults: ["example_defaults"],
+// srcs: ["example/**/*.java"],
+// }
+//
+// is functionally identical to:
+//
+// java_library {
+// name: "example",
+// srcs: [
+// "common/**/*.java",
+// "example/**/*.java",
+// ],
+// javacflags: ["-Xlint:all"],
+// }
func defaultsFactory() android.Module {
return DefaultsFactory()
}
@@ -1292,7 +2134,17 @@ func DefaultsFactory(props ...interface{}) android.Module {
module.AddProperties(
&CompilerProperties{},
&CompilerDeviceProperties{},
+ &DexpreoptProperties{},
&android.ProtoProperties{},
+ &aaptProperties{},
+ &androidLibraryProperties{},
+ &appProperties{},
+ &appTestProperties{},
+ &overridableAppProperties{},
+ &ImportProperties{},
+ &AARImportProperties{},
+ &sdkLibraryProperties{},
+ &DexImportProperties{},
)
android.InitDefaultsModule(module)
@@ -1301,5 +2153,6 @@ func DefaultsFactory(props ...interface{}) android.Module {
}
var Bool = proptools.Bool
+var BoolDefault = proptools.BoolDefault
var String = proptools.String
var inList = android.InList