diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 1007 |
1 files changed, 806 insertions, 201 deletions
diff --git a/java/java.go b/java/java.go index ddfb09a4f..5ed99f7e8 100644 --- a/java/java.go +++ b/java/java.go @@ -29,16 +29,19 @@ 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", LibraryFactory) 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_host", TestHostFactory) android.RegisterModuleType("java_import", ImportFactory) android.RegisterModuleType("java_import_host", ImportFactoryHost) @@ -72,7 +75,7 @@ type CompilerProperties struct { // list of files to use as Java resources Java_resources []string `android:"arch_variant"` - // list of files that should be excluded from java_resources + // list of files that should be excluded from java_resources and java_resource_dirs Exclude_java_resources []string `android:"arch_variant"` // don't build against the default libraries (bootclasspath, legacy-test, core-junit, @@ -86,6 +89,9 @@ type CompilerProperties struct { // 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"` @@ -101,7 +107,8 @@ type CompilerProperties struct { // 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 @@ -127,6 +134,15 @@ type CompilerProperties struct { 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 @@ -162,9 +178,21 @@ 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,11 +206,17 @@ 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 + // If set to true, compile dex regardless of installable. Defaults to false. + Compile_dex *bool + Dex_preopt struct { // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to // true. @@ -203,8 +237,8 @@ type CompilerDeviceProperties struct { } 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 // If true, optimize for size by removing unused code. Defaults to true for apps, @@ -230,6 +264,8 @@ type CompilerDeviceProperties struct { // When targeting 1.9, override the modules to use with --system System_modules *string + + UncompressDex bool `blueprint:"mutated"` } // Module contains the properties and members used by all java module types @@ -241,13 +277,22 @@ 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 containing uninstrumented classes that will be instrumented by jacoco @@ -256,7 +301,7 @@ type Module struct { // output file containing mapping of obfuscated names proguardDictionary android.Path - // output file suitable for installing or running + // output file of the module, which may be a classes jar or a dex jar outputFile android.Path exportAidlIncludeDirs android.Paths @@ -272,10 +317,24 @@ 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 } func (j *Module) Srcs() android.Paths { - return android.Paths{j.implementationJarFile} + return android.Paths{j.outputFile} +} + +func (j *Module) DexJarFile() android.Path { + return j.dexJarFile } var _ android.SourceFileProducer = (*Module)(nil) @@ -283,9 +342,32 @@ var _ android.SourceFileProducer = (*Module)(nil) type Dependency interface { HeaderJars() android.Paths ImplementationJars() android.Paths + ResourceJars() android.Paths + ImplementationAndResourcesJars() android.Paths AidlIncludeDirs() android.Paths + ExportedSdkLibs() []string +} + +type SdkLibraryDependency interface { + HeaderJars(linkType linkType) android.Paths + ImplementationJars(linkType linkType) 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 +378,41 @@ 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"} + annoTag = dependencyTag{name: "annotation processor"} + bootClasspathTag = dependencyTag{name: "bootclasspath"} + systemModulesTag = dependencyTag{name: "system modules"} + frameworkResTag = dependencyTag{name: "framework-res"} + frameworkApkTag = dependencyTag{name: "framework-apk"} + kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"} + 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 + jars android.Paths aidl android.Path } -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,10 +425,71 @@ 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. +func (j *Module) sdkVersion() string { + return String(j.deviceProperties.Sdk_version) +} + +func (j *Module) minSdkVersion() string { + if j.deviceProperties.Min_sdk_version != nil { + return *j.deviceProperties.Min_sdk_version + } + return j.sdkVersion() +} + +func (j *Module) targetSdkVersion() string { + if j.deviceProperties.Target_sdk_version != nil { + return *j.deviceProperties.Target_sdk_version + } + return j.sdkVersion() +} + +type sdkContext interface { + // sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set. + sdkVersion() string + // minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set. + minSdkVersion() string + // targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set. + targetSdkVersion() string +} + +func sdkVersionOrDefault(ctx android.BaseContext, v string) string { + switch v { + case "", "current", "system_current", "test_current", "core_current": + return ctx.Config().DefaultAppTargetSdk() + default: + return v + } +} + +// Returns a sdk version as a number. For modules targeting an unreleased SDK (meaning it does not yet have a number) +// it returns android.FutureApiLevel (10000). +func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) { + switch v { + case "", "current", "test_current", "system_current", "core_current": + return ctx.Config().DefaultAppTargetSdkInt(), nil + default: + n := android.GetNumericSdkVersion(v) + if i, err := strconv.Atoi(n); err != nil { + return -1, fmt.Errorf("invalid sdk version %q", n) + } else { + return i, nil + } + } +} + +func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) { + n, err := sdkVersionToNumber(ctx, v) + if err != nil { + return "", err + } + return strconv.Itoa(n), nil +} + +func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep { + v := sdkContext.sdkVersion() + i, err := sdkVersionToNumber(ctx, v) + if err != nil { + ctx.PropertyErrorf("sdk_version", "%s", err) return sdkDep{} } @@ -365,24 +509,30 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { } } - toFile := func(v string) sdkDep { - isCore := strings.HasPrefix(v, "core_") - if isCore { - v = strings.TrimPrefix(v, "core_") + toPrebuilt := func(sdk string) sdkDep { + var api, v string + if strings.Contains(sdk, "_") { + t := strings.Split(sdk, "_") + api = t[0] + v = t[1] + } else { + api = "public" + v = sdk } - dir := filepath.Join("prebuilts/sdk", v) + dir := filepath.Join("prebuilts", "sdk", v, api) jar := filepath.Join(dir, "android.jar") - if isCore { - jar = filepath.Join(dir, "core.jar") - } - aidl := filepath.Join(dir, "framework.aidl") + // There's no aidl for other SDKs yet. + // TODO(77525052): Add aidl files for other SDKs too. + public_dir := filepath.Join("prebuilts", "sdk", v, "public") + aidl := filepath.Join(public_dir, "framework.aidl") jarPath := android.ExistentPathForSource(ctx, jar) aidlPath := android.ExistentPathForSource(ctx, aidl) + lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath) if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() { return sdkDep{ invalidVersion: true, - module: "sdk_v" + v, + modules: []string{fmt.Sprintf("sdk_%s_%s_android", api, v)}, } } @@ -398,22 +548,28 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { return sdkDep{ useFiles: true, - jar: jarPath.Path(), + jars: android.Paths{jarPath.Path(), lambdaStubsPath}, aidl: aidlPath.Path(), } } - //toModule := func(m string) sdkDep { - // return sdkDep{ - // useModule: true, - // module: m, - // systemModules: m + "_system_modules", - // frameworkResModule: r, - // } - //} + toModule := func(m, r string) sdkDep { + ret := sdkDep{ + useModule: true, + modules: []string{m, config.DefaultLambdaStubsLibrary}, + systemModules: m + "_system_modules", + frameworkResModule: r, + } + if m == "core.current.stubs" { + ret.systemModules = "core-system-modules" + } else if m == "core.platform.api.stubs" { + ret.systemModules = "core-platform-api-stubs-system-modules" + } + return ret + } if ctx.Config().UnbundledBuild() && v != "" { - return toFile(v) + return toPrebuilt(v) } switch v { @@ -422,55 +578,58 @@ func decodeSdkDep(ctx android.BaseContext, v string) 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") + 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") + case "core_current": + return toModule("core.current.stubs", "") default: - return toFile(v) + return toPrebuilt(v) } } 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) + ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) + ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.modules...) if Bool(j.deviceProperties.Optimize.Enabled) { - ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultBootclasspathLibraries...) - ctx.AddDependency(ctx.Module(), proguardRaiseTag, config.DefaultLibraries...) + 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...) + ctx.AddFarVariationDependencies([]blueprint.Variation{ + {Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant}, + }, annoTag, j.properties.Annotation_processors...) android.ExtractSourcesDeps(ctx, j.properties.Srcs) android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs) @@ -484,11 +643,11 @@ 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 j.shouldInstrumentStatic(ctx) { - ctx.AddDependency(ctx.Module(), staticLibTag, "jacocoagent") + ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent") } } @@ -527,7 +686,8 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...) - var flags []string + flags := []string{"-b"} + if aidlPreprocess.Valid() { flags = append(flags, "-p"+aidlPreprocess.String()) } else { @@ -545,16 +705,22 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt flags = append(flags, "-t") } + if Bool(j.deviceProperties.Aidl.Generate_get_transaction_name) { + flags = append(flags, "--transaction_names") + } + return flags } type deps struct { classpath classpath bootClasspath classpath + processorPath classpath 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 @@ -570,31 +736,110 @@ 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.aidlIncludeDirs = append(deps.aidlIncludeDirs, 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: @@ -606,25 +851,52 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { 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()...) 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()...) + case annoTag: + deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...) 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())) } deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) + case SdkLibraryDependency: + switch tag { + case libTag: + linkType, _ := getLinkType(j, ctx.ModuleName()) + deps.classpath = append(deps.classpath, dep.HeaderJars(linkType)...) + // 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 android.SourceFileProducer: switch tag { case libTag: @@ -659,16 +931,43 @@ 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 + sdk, err := sdkVersionToNumber(ctx, sdkContext.sdkVersion()) + 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 +975,29 @@ 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...) - 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,6 +1023,11 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB } } + if j.properties.Patch_module != nil && flags.javaVersion == "1.9" { + patchClasspath := ".:" + flags.classpath.FormJavaClassPath("") + javacFlags = append(javacFlags, "--patch-module="+String(j.properties.Patch_module)+"="+patchClasspath) + } + // systemModules if deps.systemModules != nil { flags.systemModules = append(flags.systemModules, deps.systemModules) @@ -744,6 +1041,12 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB flags.aidlFlags = "$aidlFlags" } + if len(javacFlags) > 0 { + // optimization. + ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " ")) + flags.javacFlags = "$javacFlags" + } + return flags } @@ -754,7 +1057,7 @@ 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) @@ -768,7 +1071,9 @@ 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()...) jarName := ctx.ModuleName() + ".jar" @@ -782,20 +1087,31 @@ 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.bootClasspath...) flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...) flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...) @@ -808,11 +1124,14 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path // 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 @@ -828,18 +1147,14 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars ...android.Path j.properties.Javac_shard_size) } } - // 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 +1192,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 +1205,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,43 +1214,75 @@ 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 } + } - jars = append(jars, resourceJar) + if len(deps.staticResourceJars) > 0 { + var jars android.Paths + if j.resourceJar != nil { + jars = append(jars, j.resourceJar) + } + jars = append(jars, deps.staticResourceJars...) + + 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...) + jars = append(jars, deps.staticResourceJars...) - var manifest android.OptionalPath - if j.properties.Manifest != nil { + manifest := j.overrideManifest + if !manifest.Valid() && j.properties.Manifest != nil { manifest = android.OptionalPathForPath(ctx.ExpandSource(*j.properties.Manifest, "manifest")) } // 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 } + // jarjar implementation jar if necessary if j.properties.Jarjar_rules != nil { jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) // Transform classes.jar into classes-jarjar.jar jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName) TransformJarJar(ctx, jarjarFile, outputFile, jarjar_rules) outputFile = jarjarFile + + // jarjar resource jar if necessary + if j.resourceJar != nil { + resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName) + TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, jarjar_rules) + j.resourceJar = resourceJarJarFile + } + if ctx.Failed() { return } @@ -954,18 +1302,74 @@ 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)) { + var dexOutputFile android.ModuleOutPath + dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName) 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) + TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, + false, nil, nil) + dexOutputFile = combinedJar + } + + j.dexJarFile = dexOutputFile + + outputFile = dexOutputFile + } 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 +1382,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,7 +1392,8 @@ 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 { @@ -1004,7 +1411,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,21 +1425,6 @@ 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)) - } -} - -func (j *Module) installable() bool { - return j.properties.Installable == nil || *j.properties.Installable -} - var _ Dependency = (*Library)(nil) func (j *Module) HeaderJars() android.Paths { @@ -1043,16 +1435,48 @@ func (j *Module) ImplementationJars() android.Paths { return android.Paths{j.implementationJarFile} } +func (j *Module) ResourceJars() android.Paths { + if j.resourceJar == nil { + return nil + } + return android.Paths{j.resourceJar} +} + +func (j *Module) ImplementationAndResourcesJars() android.Paths { + return android.Paths{j.implementationAndResourcesJar} +} + func (j *Module) AidlIncludeDirs() android.Paths { return j.exportAidlIncludeDirs } +func (j *Module) ExportedSdkLibs() []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.properties.Jarjar_rules != nil { + dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, *j.properties.Jarjar_rules) + } +} + +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) // @@ -1064,7 +1488,7 @@ type Library struct { func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.compile(ctx) - if j.installable() { + if Bool(j.properties.Installable) || ctx.Host() { j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile) } @@ -1074,22 +1498,16 @@ func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { j.deps(ctx) } -func LibraryFactory(installable bool) func() android.Module { - return func() android.Module { - module := &Library{} - - if !installable { - module.properties.Installable = proptools.BoolPtr(false) - } +func LibraryFactory() android.Module { + module := &Library{} - module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &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 } func LibraryHostFactory() android.Module { @@ -1099,6 +1517,82 @@ 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:"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:"arch_variant"` + + // list of files or filegroup modules that provide data that should be installed alongside + // the test + Data []string +} + +type Test struct { + Library + + testProperties testProperties + + testConfig android.Path + data android.Paths +} + +func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { + j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template) + j.data = ctx.ExpandSources(j.testProperties.Data, nil) + + j.Library.GenerateAndroidBuildActions(ctx) +} + +func (j *Test) DepsMutator(ctx android.BottomUpMutatorContext) { + j.deps(ctx) + android.ExtractSourceDeps(ctx, j.testProperties.Test_config) + android.ExtractSourceDeps(ctx, j.testProperties.Test_config_template) + android.ExtractSourcesDeps(ctx, j.testProperties.Data) +} + +func TestFactory() android.Module { + module := &Test{} + + module.AddProperties( + &module.Module.properties, + &module.Module.deviceProperties, + &module.Module.protoProperties, + &module.testProperties) + + module.Module.properties.Installable = proptools.BoolPtr(true) + + InitJavaModule(module, android.HostAndDeviceSupported) + return module +} + +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 } @@ -1110,6 +1604,9 @@ func LibraryHostFactory() android.Module { type binaryProperties struct { // installable script to execute the resulting jar Wrapper *string + + // Name of the class containing main to be inserted into the manifest as Main-Class. + Main_class *string } type Binary struct { @@ -1130,6 +1627,15 @@ 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 @@ -1167,6 +1673,8 @@ func BinaryFactory() android.Module { &module.Module.protoProperties, &module.binaryProperties) + module.Module.properties.Installable = proptools.BoolPtr(true) + android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst) android.InitDefaultableModule(module) return module @@ -1177,10 +1685,11 @@ func BinaryHostFactory() android.Module { 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 @@ -1196,16 +1705,37 @@ type ImportProperties struct { 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_enabled *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,30 +1751,97 @@ func (j *Import) Name() string { } func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { + android.ExtractSourcesDeps(ctx, j.properties.Jars) + ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...) } func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { - j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars) + jars := ctx.ExpandSources(j.properties.Jars, nil) - 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_enabled) { + 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 + return android.Paths{j.combinedClasspathFile} } func (j *Import) ImplementationJars() android.Paths { - return j.classpathFiles + return android.Paths{j.combinedClasspathFile} +} + +func (j *Import) ResourceJars() android.Paths { + return nil +} + +func (j *Import) ImplementationAndResourcesJars() android.Paths { + return android.Paths{j.combinedClasspathFile} } func (j *Import) AidlIncludeDirs() android.Paths { return nil } +func (j *Import) ExportedSdkLibs() []string { + return j.exportedSdkLibs +} + +// 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) func ImportFactory() android.Module { @@ -1253,7 +1850,7 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) android.InitPrebuiltModule(module, &module.properties.Jars) - android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) + InitJavaModule(module, android.HostAndDeviceSupported) return module } @@ -1263,7 +1860,7 @@ func ImportFactoryHost() android.Module { module.AddProperties(&module.properties) android.InitPrebuiltModule(module, &module.properties.Jars) - android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon) + InitJavaModule(module, android.HostSupported) return module } @@ -1293,6 +1890,13 @@ func DefaultsFactory(props ...interface{}) android.Module { &CompilerProperties{}, &CompilerDeviceProperties{}, &android.ProtoProperties{}, + &aaptProperties{}, + &androidLibraryProperties{}, + &appProperties{}, + &appTestProperties{}, + &ImportProperties{}, + &AARImportProperties{}, + &sdkLibraryProperties{}, ) android.InitDefaultsModule(module) @@ -1301,5 +1905,6 @@ func DefaultsFactory(props ...interface{}) android.Module { } var Bool = proptools.Bool +var BoolDefault = proptools.BoolDefault var String = proptools.String var inList = android.InList |