diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 328 |
1 files changed, 263 insertions, 65 deletions
diff --git a/java/java.go b/java/java.go index fef9912b5..0dfb968e9 100644 --- a/java/java.go +++ b/java/java.go @@ -300,19 +300,11 @@ var _ android.LicenseAnnotationsDependencyTag = dependencyTag{} type usesLibraryDependencyTag struct { dependencyTag - - // SDK version in which the library appared as a standalone library. - sdkVersion int - - // If the dependency is optional or required. - optional bool - - // Whether this is an implicit dependency inferred by Soong, or an explicit one added via - // `uses_libs`/`optional_uses_libs` properties. - implicit bool + sdkVersion int // SDK version in which the library appared as a standalone library. + optional bool // If the dependency is optional or required. } -func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag { +func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag { return usesLibraryDependencyTag{ dependencyTag: dependencyTag{ name: fmt.Sprintf("uses-library-%d", sdkVersion), @@ -320,7 +312,6 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) }, sdkVersion: sdkVersion, optional: optional, - implicit: implicit, } } @@ -351,6 +342,11 @@ var ( syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} jniInstallTag = installDependencyTag{name: "jni install"} binaryInstallTag = installDependencyTag{name: "binary install"} + usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false) + usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true) + usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true) + usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false) + usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true) ) func IsLibDepTag(depTag blueprint.DependencyTag) bool { @@ -421,9 +417,25 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, } type deps struct { - classpath classpath - java9Classpath classpath - bootClasspath classpath + // bootClasspath is the list of jars that form the boot classpath (generally the java.* and + // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses + // systemModules and java9Classpath instead. + bootClasspath classpath + + // classpath is the list of jars that form the classpath for javac and kotlinc rules. It + // contains header jars for all static and non-static dependencies. + classpath classpath + + // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains + // header jars for all non-static dependencies. Static dependencies have already been + // combined into the program jar. + dexClasspath classpath + + // java9Classpath is the list of jars that will be added to the classpath when targeting + // 1.9 or higher. It generally contains the android.* classes, while the java.* classes + // are provided by systemModules. + java9Classpath classpath + processorPath classpath errorProneProcessorPath classpath processorClasses []string @@ -456,6 +468,12 @@ func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext an return normalizeJavaVersion(ctx, javaVersion) } else if ctx.Device() { return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx)) + } else if ctx.Config().TargetsJava17() { + // Temporary experimental flag to be able to try and build with + // java version 17 options. The flag, if used, just sets Java + // 17 as the default version, leaving any components that + // target an older version intact. + return JAVA_VERSION_17 } else { return JAVA_VERSION_11 } @@ -470,6 +488,7 @@ const ( JAVA_VERSION_8 = 8 JAVA_VERSION_9 = 9 JAVA_VERSION_11 = 11 + JAVA_VERSION_17 = 17 ) func (v javaVersion) String() string { @@ -484,6 +503,8 @@ func (v javaVersion) String() string { return "1.9" case JAVA_VERSION_11: return "11" + case JAVA_VERSION_17: + return "17" default: return "unsupported" } @@ -506,8 +527,10 @@ func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) jav return JAVA_VERSION_9 case "11": return JAVA_VERSION_11 - case "10": - ctx.PropertyErrorf("java_version", "Java language levels 10 is not supported") + case "17": + return JAVA_VERSION_11 + case "10", "12", "13", "14", "15", "16": + ctx.PropertyErrorf("java_version", "Java language level %s is not supported", javaVersion) return JAVA_VERSION_UNSUPPORTED default: ctx.PropertyErrorf("java_version", "Unrecognized Java language level") @@ -580,12 +603,14 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.checkSdkVersions(ctx) - j.dexpreopter.installPath = j.dexpreopter.getInstallPath( - ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) - j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - setUncompressDex(ctx, &j.dexpreopter, &j.dexer) - j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex - j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + if ctx.Device() { + j.dexpreopter.installPath = j.dexpreopter.getInstallPath( + ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) + j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary + setUncompressDex(ctx, &j.dexpreopter, &j.dexer) + j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex + j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + } j.compile(ctx, nil) // Collect the module directory for IDE info in java/jdeps.go. @@ -1233,10 +1258,10 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { - if ctx.Arch().ArchType == android.Common || ctx.BazelConversionMode() { + if ctx.Arch().ArchType == android.Common { j.deps(ctx) } - if ctx.Arch().ArchType != android.Common || ctx.BazelConversionMode() { + if ctx.Arch().ArchType != android.Common { // These dependencies ensure the host installation rules will install the jar file and // the jni libraries when the wrapper is installed. ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...) @@ -1458,7 +1483,10 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if ctx.OtherModuleHasProvider(module, JavaInfoProvider) { dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) switch tag { - case libTag, staticLibTag: + case libTag: + flags.classpath = append(flags.classpath, dep.HeaderJars...) + flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...) + case staticLibTag: flags.classpath = append(flags.classpath, dep.HeaderJars...) case bootClasspathTag: flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...) @@ -1706,6 +1734,7 @@ func ImportFactoryHost() android.Module { android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) + android.InitBazelModule(module) InitJavaModule(module, android.HostSupported) return module } @@ -1976,10 +2005,8 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, depTag := ctx.OtherModuleDependencyTag(depModule) if depTag == libTag { // Ok, propagate <uses-library> through non-static library dependencies. - } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && - tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit { - // Ok, propagate <uses-library> through non-compatibility implicit <uses-library> - // dependencies. + } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion { + // Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies. } else if depTag == staticLibTag { // Propagate <uses-library> through static library dependencies, unless it is a component // library (such as stubs). Component libraries have a dependency on their SDK library, @@ -1997,31 +2024,193 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, // <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies // from its CLC should be added to the current CLC. if sdkLib != nil { - clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true, + clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts()) } else { clcMap.AddContextMap(dep.ClassLoaderContexts(), depName) } } -type javaLibraryAttributes struct { +type javaResourcesAttributes struct { + Resources bazel.LabelListAttribute + Resource_strip_prefix *string +} + +func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes { + var resources bazel.LabelList + var resourceStripPrefix *string + + if m.properties.Java_resources != nil { + resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources)) + } + + //TODO(b/179889880) handle case where glob includes files outside package + resDeps := ResourceDirsToFiles( + ctx, + m.properties.Java_resource_dirs, + m.properties.Exclude_java_resource_dirs, + m.properties.Exclude_java_resources, + ) + + for i, resDep := range resDeps { + dir, files := resDep.dir, resDep.files + + resources.Append(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files))) + + // Bazel includes the relative path from the WORKSPACE root when placing the resource + // inside the JAR file, so we need to remove that prefix + resourceStripPrefix = proptools.StringPtr(dir.String()) + if i > 0 { + // TODO(b/226423379) allow multiple resource prefixes + ctx.ModuleErrorf("bp2build does not support more than one directory in java_resource_dirs (b/226423379)") + } + } + + return &javaResourcesAttributes{ + Resources: bazel.MakeLabelListAttribute(resources), + Resource_strip_prefix: resourceStripPrefix, + } +} + +type javaCommonAttributes struct { + *javaResourcesAttributes Srcs bazel.LabelListAttribute - Deps bazel.LabelListAttribute + Plugins bazel.LabelListAttribute Javacopts bazel.StringListAttribute } -func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { - srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)) - attrs := &javaLibraryAttributes{ - Srcs: srcs, +type javaDependencyLabels struct { + // Dependencies which DO NOT contribute to the API visible to upstream dependencies. + Deps bazel.LabelListAttribute + // Dependencies which DO contribute to the API visible to upstream dependencies. + StaticDeps bazel.LabelListAttribute +} + +// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules +// and also separates dependencies into dynamic dependencies and static dependencies. +// Each corresponding Bazel target type, can have a different method for handling +// dynamic vs. static dependencies, and so these are returned to the calling function. +type eventLogTagsAttributes struct { + Srcs bazel.LabelListAttribute +} + +func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { + var srcs bazel.LabelListAttribute + archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*CommonProperties); ok { + archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs) + srcs.SetSelectValue(axis, config, archSrcs) + } + } } + javaSrcPartition := "java" + protoSrcPartition := "proto" + logtagSrcPartition := "logtag" + srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ + javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true}, + logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, + protoSrcPartition: android.ProtoSrcLabelPartition, + }) + + javaSrcs := srcPartitions[javaSrcPartition] + + var logtagsSrcs bazel.LabelList + if !srcPartitions[logtagSrcPartition].IsEmpty() { + logtagsLibName := m.Name() + "_logtags" + logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}}) + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "event_log_tags", + Bzl_load_location: "//build/make/tools:event_log_tags.bzl", + }, + android.CommonAttributes{Name: logtagsLibName}, + &eventLogTagsAttributes{ + Srcs: srcPartitions[logtagSrcPartition], + }, + ) + } + javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs)) + + var javacopts []string if m.properties.Javacflags != nil { - attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags) + javacopts = append(javacopts, m.properties.Javacflags...) + } + if m.properties.Java_version != nil { + javaVersion := normalizeJavaVersion(ctx, *m.properties.Java_version).String() + javacopts = append(javacopts, fmt.Sprintf("-source %s -target %s", javaVersion, javaVersion)) } + epEnabled := m.properties.Errorprone.Enabled + //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable + if Bool(epEnabled) { + javacopts = append(javacopts, m.properties.Errorprone.Javacflags...) + } + + commonAttrs := &javaCommonAttributes{ + Srcs: javaSrcs, + javaResourcesAttributes: m.convertJavaResourcesAttributes(ctx), + Plugins: bazel.MakeLabelListAttribute( + android.BazelLabelForModuleDeps(ctx, m.properties.Plugins), + ), + Javacopts: bazel.MakeStringListAttribute(javacopts), + } + + depLabels := &javaDependencyLabels{} + + var deps bazel.LabelList if m.properties.Libs != nil { - attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Libs)) + deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs)) + } + + var staticDeps bazel.LabelList + if m.properties.Static_libs != nil { + staticDeps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs)) + } + + protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition]) + // Soong does not differentiate between a java_library and the Bazel equivalent of + // a java_proto_library + proto_library pair. Instead, in Soong proto sources are + // listed directly in the srcs of a java_library, and the classes produced + // by protoc are included directly in the resulting JAR. Thus upstream dependencies + // that depend on a java_library with proto sources can link directly to the protobuf API, + // and so this should be a static dependency. + staticDeps.Add(protoDepLabel) + + depLabels.Deps = bazel.MakeLabelListAttribute(deps) + depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) + + return commonAttrs, depLabels +} + +type javaLibraryAttributes struct { + *javaCommonAttributes + Deps bazel.LabelListAttribute + Exports bazel.LabelListAttribute +} + +func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { + commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + + deps := depLabels.Deps + if !commonAttrs.Srcs.IsEmpty() { + deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them + + sdkVersion := m.SdkVersion(ctx) + if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel { + // TODO(b/220869005) remove forced dependency on current public android.jar + deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import")) + } + } else if !depLabels.Deps.IsEmpty() { + ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") + } + + attrs := &javaLibraryAttributes{ + javaCommonAttributes: commonAttrs, + Deps: deps, + Exports: depLabels.StaticDeps, } props := bazel.BazelTargetModuleProperties{ @@ -2033,15 +2222,30 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { } type javaBinaryHostAttributes struct { - Srcs bazel.LabelListAttribute - Deps bazel.LabelListAttribute - Main_class string - Jvm_flags bazel.StringListAttribute - Javacopts bazel.StringListAttribute + *javaCommonAttributes + Deps bazel.LabelListAttribute + Runtime_deps bazel.LabelListAttribute + Main_class string + Jvm_flags bazel.StringListAttribute } // JavaBinaryHostBp2Build is for java_binary_host bp2build. func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { + commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + + deps := depLabels.Deps + deps.Append(depLabels.StaticDeps) + if m.binaryProperties.Jni_libs != nil { + deps.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs))) + } + + var runtimeDeps bazel.LabelListAttribute + if commonAttrs.Srcs.IsEmpty() { + // if there are no sources, then the dependencies can only be used at runtime + runtimeDeps = deps + deps = bazel.LabelListAttribute{} + } + mainClass := "" if m.binaryProperties.Main_class != nil { mainClass = *m.binaryProperties.Main_class @@ -2053,26 +2257,12 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { } mainClass = mainClassInManifest } - srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)) - attrs := &javaBinaryHostAttributes{ - Srcs: srcs, - Main_class: mainClass, - } - if m.properties.Javacflags != nil { - attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags) - } - - // Attribute deps - deps := []string{} - if m.properties.Static_libs != nil { - deps = append(deps, m.properties.Static_libs...) - } - if m.binaryProperties.Jni_libs != nil { - deps = append(deps, m.binaryProperties.Jni_libs...) - } - if len(deps) > 0 { - attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, deps)) + attrs := &javaBinaryHostAttributes{ + javaCommonAttributes: commonAttrs, + Deps: deps, + Runtime_deps: runtimeDeps, + Main_class: mainClass, } // Attribute jvm_flags @@ -2115,8 +2305,16 @@ type bazelJavaImportAttributes struct { // java_import bp2Build converter. func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { - //TODO(b/209577426): Support multiple arch variants - jars := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, i.properties.Jars, []string(nil))) + var jars bazel.LabelListAttribute + archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{}) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*ImportProperties); ok { + archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil)) + jars.SetSelectValue(axis, config, archJars) + } + } + } attrs := &bazelJavaImportAttributes{ Jars: jars, |