diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 337 |
1 files changed, 313 insertions, 24 deletions
diff --git a/java/java.go b/java/java.go index d04e52a2c..e37a77e46 100644 --- a/java/java.go +++ b/java/java.go @@ -25,6 +25,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" + "android/soong/remoteexec" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -59,6 +60,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory) ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory) ctx.RegisterModuleType("dex_import", DexImportFactory) + ctx.RegisterModuleType("java_api_library", ApiLibraryFactory) + ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory) // This mutator registers dependencies on dex2oat for modules that should be // dexpreopted. This is done late when the final variants have been @@ -211,6 +214,14 @@ var ( PropertyName: "java_tests", }, } + + // Rule for generating device binary default wrapper + deviceBinaryWrapper = pctx.StaticRule("deviceBinaryWrapper", blueprint.RuleParams{ + Command: `echo -e '#!/system/bin/sh\n` + + `export CLASSPATH=/system/framework/$jar_name\n` + + `exec app_process /$partition/bin $main_class "$$@"'> ${out}`, + Description: "Generating device binary wrapper ${jar_name}", + }, "jar_name", "partition", "main_class") ) // JavaInfo contains information about a java module for use by modules that depend on it. @@ -348,6 +359,7 @@ var ( dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"} staticLibTag = dependencyTag{name: "staticlib"} libTag = dependencyTag{name: "javalib", runtimeLinked: true} + sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true} java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true} pluginTag = dependencyTag{name: "plugin", toolchain: true} errorpronePluginTag = dependencyTag{name: "errorprone-plugin", toolchain: true} @@ -374,7 +386,7 @@ var ( ) func IsLibDepTag(depTag blueprint.DependencyTag) bool { - return depTag == libTag + return depTag == libTag || depTag == sdkLibTag } func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool { @@ -420,6 +432,7 @@ type jniLib struct { target android.Target coverageFile android.OptionalPath unstrippedFile android.Path + partition string } func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) { @@ -427,7 +440,7 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) - ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...) + ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...) if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...) } @@ -751,6 +764,9 @@ type librarySdkMemberProperties struct { // The list of permitted packages that need to be passed to the prebuilts as they are used to // create the updatable-bcp-packages.txt file. PermittedPackages []string + + // The value of the min_sdk_version property, translated into a number where possible. + MinSdkVersion *string `supported_build_releases:"Tiramisu+"` } func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { @@ -761,6 +777,13 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberCo p.AidlIncludeDirs = j.AidlIncludeDirs() p.PermittedPackages = j.PermittedPackagesForUpdatableBootJars() + + // If the min_sdk_version was set then add the canonical representation of the API level to the + // snapshot. + if j.deviceProperties.Min_sdk_version != nil { + canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String()) + p.MinSdkVersion = proptools.StringPtr(canonical) + } } func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { @@ -779,6 +802,10 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) } + if p.MinSdkVersion != nil { + propertySet.AddProperty("min_sdk_version", *p.MinSdkVersion) + } + if len(p.PermittedPackages) > 0 { propertySet.AddProperty("permitted_packages", p.PermittedPackages) } @@ -1396,7 +1423,31 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("wrapper", "wrapper is required for Windows") } - j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh") + if ctx.Device() { + // device binary should have a main_class property if it does not + // have a specific wrapper, so that a default wrapper can + // be generated for it. + if j.binaryProperties.Main_class == nil { + ctx.PropertyErrorf("main_class", "main_class property "+ + "is required for device binary if no default wrapper is assigned") + } else { + wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh") + jarName := j.Stem() + ".jar" + partition := j.PartitionTag(ctx.DeviceConfig()) + ctx.Build(pctx, android.BuildParams{ + Rule: deviceBinaryWrapper, + Output: wrapper, + Args: map[string]string{ + "jar_name": jarName, + "partition": partition, + "main_class": String(j.binaryProperties.Main_class), + }, + }) + j.wrapperFile = wrapper + } + } else { + j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh") + } } ext := "" @@ -1467,6 +1518,179 @@ func BinaryHostFactory() android.Module { return module } +type JavaApiContribution struct { + android.ModuleBase + android.DefaultableModuleBase + + properties struct { + // name of the API surface + Api_surface *string + + // relative path to the API signature text file + Api_file *string `android:"path"` + } +} + +func ApiContributionFactory() android.Module { + module := &JavaApiContribution{} + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + return module +} + +type JavaApiImportInfo struct { + ApiFile android.Path +} + +var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{}) + +func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) { + apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file)) + ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{ + ApiFile: apiFile, + }) +} + +type ApiLibrary struct { + android.ModuleBase + android.DefaultableModuleBase + + properties JavaApiLibraryProperties + + stubsSrcJar android.WritablePath + stubsJar android.WritablePath +} + +type JavaApiLibraryProperties struct { + // name of the API surface + Api_surface *string + + // list of Java API contribution modules that consists this API surface + Api_contributions []string + + // List of flags to be passed to the javac compiler to generate jar file + Javacflags []string +} + +func ApiLibraryFactory() android.Module { + module := &ApiLibrary{} + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + return module +} + +func (al *ApiLibrary) ApiSurface() *string { + return al.properties.Api_surface +} + +func (al *ApiLibrary) StubsJar() android.Path { + return al.stubsJar +} + +func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, + srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand { + rule.Command().Text("rm -rf").Flag(homeDir.String()) + rule.Command().Text("mkdir -p").Flag(homeDir.String()) + + cmd := rule.Command() + cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String()) + + if metalavaUseRbe(ctx) { + rule.Remoteable(android.RemoteRuleSupports{RBE: true}) + execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy) + labels := map[string]string{"type": "tool", "name": "metalava"} + + pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16") + rule.Rewrapper(&remoteexec.REParams{ + Labels: labels, + ExecStrategy: execStrategy, + ToolchainInputs: []string{config.JavaCmd(ctx).String()}, + Platform: map[string]string{remoteexec.PoolKey: pool}, + }) + } + + cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")). + Flag(config.JavacVmFlags). + Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED"). + FlagWithArg("-encoding ", "UTF-8"). + FlagWithInputList("--source-files ", srcs, " ") + + cmd.Flag("--no-banner"). + Flag("--color"). + Flag("--quiet"). + Flag("--format=v2"). + FlagWithArg("--repeat-errors-max ", "10"). + FlagWithArg("--hide ", "UnresolvedImport"). + FlagWithArg("--hide ", "InvalidNullabilityOverride"). + FlagWithArg("--hide ", "ChangedDefault") + + return cmd +} + +func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) { + if stubsDir.Valid() { + cmd.FlagWithArg("--stubs ", stubsDir.String()) + } +} + +var javaApiContributionTag = dependencyTag{name: "java-api-contribution"} + +func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + apiContributions := al.properties.Api_contributions + for _, apiContributionName := range apiContributions { + ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName) + } +} + +func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + + rule := android.NewRuleBuilder(pctx, ctx) + + rule.Sbox(android.PathForModuleOut(ctx, "metalava"), + android.PathForModuleOut(ctx, "metalava.sbox.textproto")). + SandboxInputs() + + var stubsDir android.OptionalPath + stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir")) + rule.Command().Text("rm -rf").Text(stubsDir.String()) + rule.Command().Text("mkdir -p").Text(stubsDir.String()) + + homeDir := android.PathForModuleOut(ctx, "metalava", "home") + + var srcFiles []android.Path + ctx.VisitDirectDepsWithTag(javaApiContributionTag, func(dep android.Module) { + provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo) + srcFiles = append(srcFiles, android.PathForSource(ctx, provider.ApiFile.String())) + }) + + cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir) + + al.stubsFlags(ctx, cmd, stubsDir) + + al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar") + rule.Command(). + BuiltTool("soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", al.stubsSrcJar). + FlagWithArg("-C ", stubsDir.String()). + FlagWithArg("-D ", stubsDir.String()) + + rule.Build("metalava", "metalava merged") + + al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar") + + var flags javaBuilderFlags + flags.javacFlags = strings.Join(al.properties.Javacflags, " ") + + TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{}, + android.Paths{al.stubsSrcJar}, flags, android.Paths{}) + + ctx.Phony(ctx.ModuleName(), al.stubsJar) +} + // // Java prebuilts // @@ -1654,7 +1878,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if ctx.OtherModuleHasProvider(module, JavaInfoProvider) { dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) switch tag { - case libTag: + case libTag, sdkLibTag: flags.classpath = append(flags.classpath, dep.HeaderJars...) flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...) case staticLibTag: @@ -1664,7 +1888,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } else if dep, ok := module.(SdkLibraryDependency); ok { switch tag { - case libTag: + case libTag, sdkLibTag: flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...) } } @@ -2178,7 +2402,7 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, } depTag := ctx.OtherModuleDependencyTag(depModule) - if depTag == libTag { + if IsLibDepTag(depTag) { // Ok, propagate <uses-library> through non-static library dependencies. } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion { // Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies. @@ -2273,11 +2497,21 @@ type javaAidlLibraryAttributes struct { Deps 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. -func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { +// bp2BuildJavaInfo has information needed for the conversion of java*_modules +// that is needed bor Bp2Build conversion but that requires different handling +// depending on the module type. +type bp2BuildJavaInfo struct { + // separates dependencies into dynamic dependencies and static dependencies. + DepLabels *javaDependencyLabels + hasKotlinSrcs bool +} + +// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with +// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct +// which has other non-attribute information needed for bp2build conversion +// that needs different handling depending on the module types, and thus needs +// to be returned to the calling function. +func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) { var srcs bazel.LabelListAttribute var deps bazel.LabelList var staticDeps bazel.LabelList @@ -2296,21 +2530,25 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) protoSrcPartition := "proto" logtagSrcPartition := "logtag" aidlSrcPartition := "aidl" + kotlinPartition := "kotlin" 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, aidlSrcPartition: android.AidlSrcLabelPartition, + kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}}, }) javaSrcs := srcPartitions[javaSrcPartition] + kotlinSrcs := srcPartitions[kotlinPartition] + javaSrcs.Append(kotlinSrcs) if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "event_log_tags", - Bzl_load_location: "//build/make/tools:event_log_tags.bzl", + Bzl_load_location: "//build/bazel/rules/java:event_log_tags.bzl", }, android.CommonAttributes{Name: logtagsLibName}, &eventLogTagsAttributes{ @@ -2382,7 +2620,18 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } if m.properties.Libs != nil { - deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) + + // TODO 244210934 ALIX Check if this else statement breaks presubmits get rid of it if it doesn't + if strings.HasPrefix(ctx.ModuleType(), "java_binary") || strings.HasPrefix(ctx.ModuleType(), "java_library") { + for _, d := range m.properties.Libs { + neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d) + neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink" + deps.Add(&neverlinkLabel) + } + + } else { + deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) + } } if m.properties.Static_libs != nil { @@ -2402,17 +2651,25 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) depLabels.Deps = bazel.MakeLabelListAttribute(deps) depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) - return commonAttrs, depLabels + bp2BuildInfo := &bp2BuildJavaInfo{ + DepLabels: depLabels, + hasKotlinSrcs: !kotlinSrcs.IsEmpty(), + } + + return commonAttrs, bp2BuildInfo } type javaLibraryAttributes struct { *javaCommonAttributes - Deps bazel.LabelListAttribute - Exports bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Exports bazel.LabelListAttribute + Neverlink bazel.BoolAttribute + Common_srcs bazel.LabelListAttribute } func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { - commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps if !commonAttrs.Srcs.IsEmpty() { @@ -2427,18 +2684,38 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") } + var props bazel.BazelTargetModuleProperties attrs := &javaLibraryAttributes{ javaCommonAttributes: commonAttrs, Deps: deps, Exports: depLabels.StaticDeps, } + name := m.Name() - props := bazel.BazelTargetModuleProperties{ - Rule_class: "java_library", - Bzl_load_location: "//build/bazel/rules/java:library.bzl", + if !bp2BuildInfo.hasKotlinSrcs && len(m.properties.Common_srcs) == 0 { + props = bazel.BazelTargetModuleProperties{ + Rule_class: "java_library", + Bzl_load_location: "//build/bazel/rules/java:library.bzl", + } + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) + neverlinkProp := true + neverLinkAttrs := &javaLibraryAttributes{ + Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}), + Neverlink: bazel.BoolAttribute{Value: &neverlinkProp}, + } + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs) + } else { + attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)) + + props = bazel.BazelTargetModuleProperties{ + Rule_class: "kt_jvm_library", + Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl", + } + // TODO (b/244210934): create neverlink-duplicate target once kt_jvm_library supports neverlink attribute + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) } - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) } type javaBinaryHostAttributes struct { @@ -2451,7 +2728,8 @@ type javaBinaryHostAttributes struct { // JavaBinaryHostBp2Build is for java_binary_host bp2build. func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { - commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx) + commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) + depLabels := bp2BuildInfo.DepLabels deps := depLabels.Deps deps.Append(depLabels.StaticDeps) @@ -2520,7 +2798,8 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { } type bazelJavaImportAttributes struct { - Jars bazel.LabelListAttribute + Jars bazel.LabelListAttribute + Exports bazel.LabelListAttribute } // java_import bp2Build converter. @@ -2541,7 +2820,17 @@ func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"} - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs) + name := android.RemoveOptionalPrebuiltPrefix(i.Name()) + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) + + neverlink := true + neverlinkAttrs := &javaLibraryAttributes{ + Neverlink: bazel.BoolAttribute{Value: &neverlink}, + Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}), + } + ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs) + } var _ android.MixedBuildBuildable = (*Import)(nil) |