summaryrefslogtreecommitdiff
path: root/java/java.go
diff options
context:
space:
mode:
Diffstat (limited to 'java/java.go')
-rw-r--r--java/java.go319
1 files changed, 279 insertions, 40 deletions
diff --git a/java/java.go b/java/java.go
index b6fc6b831..ad46e9880 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
@@ -86,11 +89,11 @@ func RegisterJavaSdkMemberTypes() {
var (
// Supports adding java header libraries to module_exports and sdk.
javaHeaderLibsSdkMemberType = &librarySdkMemberType{
- android.SdkMemberTypeBase{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "java_header_libs",
SupportsSdk: true,
},
- func(_ android.SdkMemberContext, j *Library) android.Path {
+ jarToExportGetter: func(_ android.SdkMemberContext, j *Library) android.Path {
headerJars := j.HeaderJars()
if len(headerJars) != 1 {
panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
@@ -98,8 +101,8 @@ var (
return headerJars[0]
},
- sdkSnapshotFilePathForJar,
- copyEverythingToSnapshot,
+ snapshotPathGetter: sdkSnapshotFilePathForJar,
+ onlyCopyJarToSnapshot: copyEverythingToSnapshot,
}
// Export implementation classes jar as part of the sdk.
@@ -113,12 +116,12 @@ var (
// Supports adding java implementation libraries to module_exports but not sdk.
javaLibsSdkMemberType = &librarySdkMemberType{
- android.SdkMemberTypeBase{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "java_libs",
},
- exportImplementationClassesJar,
- sdkSnapshotFilePathForJar,
- copyEverythingToSnapshot,
+ jarToExportGetter: exportImplementationClassesJar,
+ snapshotPathGetter: sdkSnapshotFilePathForJar,
+ onlyCopyJarToSnapshot: copyEverythingToSnapshot,
}
snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool {
@@ -143,11 +146,11 @@ var (
// necessary. The java_boot_libs property to allow those modules to be exported as part of the
// sdk/module_exports without exposing any unnecessary information.
javaBootLibsSdkMemberType = &librarySdkMemberType{
- android.SdkMemberTypeBase{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "java_boot_libs",
SupportsSdk: true,
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
+ jarToExportGetter: func(ctx android.SdkMemberContext, j *Library) android.Path {
if snapshotRequiresImplementationJar(ctx) {
return exportImplementationClassesJar(ctx, j)
}
@@ -156,9 +159,9 @@ var (
// jar for use by dexpreopting and boot jars package check. They do not need to provide an
// actual implementation jar but the java_import will need a file that exists so just copy an
// empty file. Any attempt to use that file as a jar will cause a build error.
- return ctx.SnapshotBuilder().EmptyFile()
+ return nil
},
- func(ctx android.SdkMemberContext, osPrefix, name string) string {
+ snapshotPathGetter: func(ctx android.SdkMemberContext, osPrefix, name string) string {
if snapshotRequiresImplementationJar(ctx) {
return sdkSnapshotFilePathForJar(ctx, osPrefix, name)
}
@@ -168,7 +171,7 @@ var (
// TODO(b/175714559): Provide a proper error message in Soong not ninja.
return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
},
- onlyCopyJarToSnapshot,
+ onlyCopyJarToSnapshot: onlyCopyJarToSnapshot,
}
// Supports adding java systemserver libraries to module_exports and sdk.
@@ -182,27 +185,27 @@ var (
// necessary. The java_systemserver_libs property to allow those modules to be exported as part of
// the sdk/module_exports without exposing any unnecessary information.
javaSystemserverLibsSdkMemberType = &librarySdkMemberType{
- android.SdkMemberTypeBase{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "java_systemserver_libs",
SupportsSdk: true,
// This was only added in Tiramisu.
SupportedBuildReleaseSpecification: "Tiramisu+",
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
+ jarToExportGetter: func(ctx android.SdkMemberContext, j *Library) android.Path {
// Java systemserver libs are only provided in the SDK to provide access to their dex
// implementation jar for use by dexpreopting. They do not need to provide an actual
// implementation jar but the java_import will need a file that exists so just copy an empty
// file. Any attempt to use that file as a jar will cause a build error.
- return ctx.SnapshotBuilder().EmptyFile()
+ return nil
},
- func(_ android.SdkMemberContext, osPrefix, name string) string {
+ snapshotPathGetter: func(_ android.SdkMemberContext, osPrefix, name string) string {
// Create a special name for the implementation jar to try and provide some useful information
// to a developer that attempts to compile against this.
// TODO(b/175714559): Provide a proper error message in Soong not ninja.
return filepath.Join(osPrefix, "java_systemserver_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
},
- onlyCopyJarToSnapshot,
+ onlyCopyJarToSnapshot: onlyCopyJarToSnapshot,
}
// Supports adding java test libraries to module_exports but not sdk.
@@ -232,7 +235,7 @@ type JavaInfo struct {
ImplementationAndResourcesJars android.Paths
// ImplementationJars is a list of jars that contain the implementations of classes in the
- //module.
+ // module.
ImplementationJars android.Paths
// ResourceJars is a list of jars that contain the resources included in the module.
@@ -718,7 +721,8 @@ type librarySdkMemberType struct {
android.SdkMemberTypeBase
// Function to retrieve the appropriate output jar (implementation or header) from
- // the library.
+ // the library, if this returns nil then it is assumed that the snapshot must not provide access
+ // to the jar.
jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path
// Function to compute the snapshot relative path to which the named library's
@@ -755,7 +759,11 @@ func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMembe
type librarySdkMemberProperties struct {
android.SdkMemberPropertiesBase
- JarToExport android.Path `android:"arch_variant"`
+ JarToExport android.Path `android:"arch_variant"`
+
+ // The path to a script to use when the jar is invalid.
+ InvalidJarScript android.Path
+
AidlIncludeDirs android.Paths
// The list of permitted packages that need to be passed to the prebuilts as they are used to
@@ -766,7 +774,15 @@ type librarySdkMemberProperties struct {
func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
j := variant.(*Library)
- p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j)
+ memberType := ctx.MemberType().(*librarySdkMemberType)
+ p.JarToExport = memberType.jarToExportGetter(ctx, j)
+
+ // If no jar was provided for export then disallow access to it completely.
+ if p.JarToExport == nil {
+ // Copy the script to prevent access to the jar into the snapshot.
+ p.InvalidJarScript = android.PathForSource(ctx.SdkModuleContext(),
+ "build/soong/java/invalid_implementation_jar.sh")
+ }
p.AidlIncludeDirs = j.AidlIncludeDirs()
@@ -789,6 +805,21 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte
propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
+ if scriptSrc := p.InvalidJarScript; scriptSrc != nil {
+ // Copy the script to prevent access to the jar into the snapshot.
+ scriptDest := filepath.Join("scripts", scriptSrc.Base())
+ builder.CopyToSnapshot(scriptSrc, scriptDest)
+
+ // Generate a genrule module that will invoke the script passing in the module name.
+ genrule := builder.AddInternalModule(p, "genrule", "error")
+ genRuleName := genrule.Name()
+ genrule.AddProperty("out", []string{"this-file-will-never-be-created.jar"})
+ genrule.AddProperty("tool_files", []string{scriptDest})
+ genrule.AddProperty("cmd", fmt.Sprintf("$(location %s) %s", scriptDest, p.Name()))
+
+ propertySet.AddPropertyWithTag("jars", []string{":" + genRuleName}, builder.SdkMemberReferencePropertyTag(true))
+ }
+
if len(p.PermittedPackages) > 0 {
propertySet.AddProperty("permitted_packages", p.PermittedPackages)
}
@@ -1501,6 +1532,182 @@ 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 API provider modules that consists this API surface
+ Api_providers []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 javaApiProviderTag = dependencyTag{name: "java-api-provider"}
+
+func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ apiProviders := al.properties.Api_providers
+ for _, apiProviderName := range apiProviders {
+ ctx.AddDependency(ctx.Module(), javaApiProviderTag, apiProviderName)
+ }
+}
+
+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")
+
+ apiProviders := al.properties.Api_providers
+ srcFiles := make([]android.Path, len(apiProviders))
+ for i, apiProviderName := range apiProviders {
+ apiProvider := ctx.GetDirectDepWithTag(apiProviderName, javaApiProviderTag)
+ if apiProvider == nil {
+ panic(fmt.Errorf("Java API provider module %s not found, called from %s", apiProviderName, al.Name()))
+ }
+ provider := ctx.OtherModuleProvider(apiProvider, JavaApiImportProvider).(JavaApiImportInfo)
+ srcFiles[i] = android.PathForModuleSrc(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{})
+}
+
//
// Java prebuilts
//
@@ -1650,7 +1857,7 @@ func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (j *Import) commonBuildActions(ctx android.ModuleContext) {
- //TODO(b/231322772) these should come from Bazel once available
+ // TODO(b/231322772) these should come from Bazel once available
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
@@ -2253,7 +2460,7 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte
resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources))
}
- //TODO(b/179889880) handle case where glob includes files outside package
+ // TODO(b/179889880) handle case where glob includes files outside package
resDeps := ResourceDirsToFiles(
ctx,
m.properties.Java_resource_dirs,
@@ -2307,11 +2514,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
@@ -2330,14 +2547,18 @@ 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"
@@ -2401,7 +2622,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)
}
epEnabled := m.properties.Errorprone.Enabled
- //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
+ // TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
if Bool(epEnabled) {
javacopts = append(javacopts, m.properties.Errorprone.Javacflags...)
}
@@ -2447,18 +2668,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
- Neverlink bazel.BoolAttribute
+ 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() {
@@ -2473,15 +2701,25 @@ 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,
}
- 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",
+ }
+ } 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",
+ }
}
name := m.Name()
@@ -2498,7 +2736,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)
@@ -2637,7 +2876,7 @@ func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile),
ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile),
- //TODO(b/240308299) include AIDL information from Bazel
+ // TODO(b/240308299) include AIDL information from Bazel
})
i.maybeInstall(ctx, jarName, outputFile)