diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 230 | 
1 files changed, 171 insertions, 59 deletions
| diff --git a/java/java.go b/java/java.go index f29f7383a..270f45615 100644 --- a/java/java.go +++ b/java/java.go @@ -21,11 +21,13 @@ package java  import (  	"fmt"  	"path/filepath" +	"sort"  	"strings"  	"android/soong/bazel"  	"android/soong/bazel/cquery"  	"android/soong/remoteexec" +	"android/soong/ui/metrics/bp2build_metrics_proto"  	"github.com/google/blueprint"  	"github.com/google/blueprint/proptools" @@ -224,6 +226,23 @@ var (  	}, "jar_name", "partition", "main_class")  ) +type ProguardSpecInfo struct { +	// If true, proguard flags files will be exported to reverse dependencies across libs edges +	// If false, proguard flags files will only be exported to reverse dependencies across +	// static_libs edges. +	Export_proguard_flags_files bool + +	// TransitiveDepsProguardSpecFiles is a depset of paths to proguard flags files that are exported from +	// all transitive deps. This list includes all proguard flags files from transitive static dependencies, +	// and all proguard flags files from transitive libs dependencies which set `export_proguard_spec: true`. +	ProguardFlagsFiles *android.DepSet[android.Path] + +	// implementation detail to store transitive proguard flags files from exporting shared deps +	UnconditionallyExportedProguardFlags *android.DepSet[android.Path] +} + +var ProguardSpecInfoProvider = blueprint.NewProvider(ProguardSpecInfo{}) +  // JavaInfo contains information about a java module for use by modules that depend on it.  type JavaInfo struct {  	// HeaderJars is a list of jars that can be passed as the javac classpath in order to link @@ -309,11 +328,6 @@ type UsesLibraryDependency interface {  	ClassLoaderContexts() dexpreopt.ClassLoaderContextMap  } -// Provides transitive Proguard flag files to downstream DEX jars. -type LibraryDependency interface { -	ExportedProguardFlagFiles() android.Paths -} -  // TODO(jungjw): Move this to kythe.go once it's created.  type xref interface {  	XrefJavaFiles() android.Paths @@ -625,12 +639,6 @@ type Library struct {  	InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)  } -var _ LibraryDependency = (*Library)(nil) - -func (j *Library) ExportedProguardFlagFiles() android.Paths { -	return j.exportedProguardFlagFiles -} -  var _ android.ApexModule = (*Library)(nil)  // Provides access to the list of permitted packages from apex boot jars. @@ -691,6 +699,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {  	}  	j.checkSdkVersions(ctx) +	j.checkHeadersOnly(ctx)  	if ctx.Device() {  		j.dexpreopter.installPath = j.dexpreopter.getInstallPath(  			ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) @@ -729,15 +738,9 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {  		j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)  	} -	j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles, -		android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)...) -	ctx.VisitDirectDeps(func(m android.Module) { -		if lib, ok := m.(LibraryDependency); ok && ctx.OtherModuleDependencyTag(m) == staticLibTag { -			j.exportedProguardFlagFiles = append(j.exportedProguardFlagFiles, lib.ExportedProguardFlagFiles()...) -		} -	}) -	j.exportedProguardFlagFiles = android.FirstUniquePaths(j.exportedProguardFlagFiles) - +	proguardSpecInfo := j.collectProguardSpecInfo(ctx) +	ctx.SetProvider(ProguardSpecInfoProvider, proguardSpecInfo) +	j.exportedProguardFlagFiles = proguardSpecInfo.ProguardFlagsFiles.ToList()  }  func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1682,6 +1685,9 @@ type JavaApiLibraryProperties struct {  	// extracting the compiled class files provided by the  	// full_api_surface_stub module.  	Full_api_surface_stub *string + +	// Version of previously released API file for compatibility check. +	Previous_api *string `android:"path"`  }  func ApiLibraryFactory() android.Module { @@ -1725,12 +1731,10 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,  	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("--color").  		Flag("--quiet"). -		Flag("--format=v2").  		Flag("--include-annotations").  		// The flag makes nullability issues as warnings rather than errors by replacing  		// @Nullable/@NonNull in the listed packages APIs with @RecentlyNullable/@RecentlyNonNull, @@ -1742,14 +1746,13 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,  		FlagWithArg("--hide ", "InvalidNullabilityOverride").  		FlagWithArg("--hide ", "ChangedDefault") -	// Force metalava to ignore classes on the classpath when an API file contains missing classes. -	// See b/285140653 for more information. +	// The main purpose of the `--api-class-resolution api` option is to force metalava to ignore +	// classes on the classpath when an API file contains missing classes. However, as this command +	// does not specify `--classpath` this is not needed for that. However, this is also used as a +	// signal to the special metalava code for generating stubs from text files that it needs to add +	// some additional items into the API (e.g. default constructors).  	cmd.FlagWithArg("--api-class-resolution ", "api") -	// Force metalava to sort overloaded methods by their order in the source code. -	// See b/285312164 for more information. -	cmd.FlagWithArg("--api-overloaded-method-order ", "source") -  	return cmd  } @@ -1795,6 +1798,7 @@ func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.Ru  		Flag("-jar").  		Flag("-write_if_changed").  		Flag("-ignore_missing_files"). +		Flag("-quiet").  		FlagWithArg("-C ", unzippedSrcJarDir.String()).  		FlagWithInput("-l ", classFilesList).  		FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs) @@ -1812,6 +1816,28 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {  	}  } +// API signature file names sorted from +// the narrowest api scope to the widest api scope +var scopeOrderedSourceFileNames = allApiScopes.Strings( +	func(s *apiScope) string { return s.apiFilePrefix + "current.txt" }) + +func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths { +	sortedSrcFiles := android.Paths{} + +	for _, scopeSourceFileName := range scopeOrderedSourceFileNames { +		for _, sourceFileName := range srcFiles { +			if sourceFileName.Base() == scopeSourceFileName { +				sortedSrcFiles = append(sortedSrcFiles, sourceFileName) +			} +		} +	} +	if len(srcFiles) != len(sortedSrcFiles) { +		ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles) +	} + +	return sortedSrcFiles +} +  func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {  	rule := android.NewRuleBuilder(pctx, ctx) @@ -1862,10 +1888,18 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {  		ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())  	} +	srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles) +  	cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)  	al.stubsFlags(ctx, cmd, stubsDir) +	migratingNullability := String(al.properties.Previous_api) != "" +	if migratingNullability { +		previousApi := android.PathForModuleSrc(ctx, String(al.properties.Previous_api)) +		cmd.FlagWithInput("--migrate-nullness ", previousApi) +	} +  	al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")  	al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")  	al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName())) @@ -1881,7 +1915,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {  		FlagWithArg("-C ", stubsDir.String()).  		FlagWithArg("-D ", stubsDir.String()) -	rule.Build("metalava", "metalava merged") +	rule.Build("metalava", "metalava merged text")  	if depApiSrcsStubsJar == nil {  		var flags javaBuilderFlags @@ -2722,32 +2756,41 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,  type javaResourcesAttributes struct {  	Resources             bazel.LabelListAttribute  	Resource_strip_prefix *string +	Additional_resources  bazel.LabelListAttribute  } -func (m *Library) javaResourcesGetSingleFilegroupStripPrefix(ctx android.TopDownMutatorContext) (string, bool) { -	if otherM, ok := ctx.ModuleFromName(m.properties.Java_resources[0]); ok && len(m.properties.Java_resources) == 1 { +func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorContext, resourceFilegroup string) (*string, bool) { +	if otherM, ok := ctx.ModuleFromName(resourceFilegroup); ok {  		if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup { -			return filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx)), true +			return proptools.StringPtr(filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx))), true  		}  	} -	return "", false +	return proptools.StringPtr(""), false  }  func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes {  	var resources bazel.LabelList  	var resourceStripPrefix *string -	if m.properties.Java_resources != nil && len(m.properties.Java_resource_dirs) > 0 { -		ctx.ModuleErrorf("bp2build doesn't support both java_resources and java_resource_dirs being set on the same module.") -	} +	additionalJavaResourcesMap := make(map[string]*javaResourcesAttributes)  	if m.properties.Java_resources != nil { -		if prefix, ok := m.javaResourcesGetSingleFilegroupStripPrefix(ctx); ok { -			resourceStripPrefix = proptools.StringPtr(prefix) -		} else { +		for _, res := range m.properties.Java_resources { +			if prefix, isFilegroup := m.getResourceFilegroupStripPrefix(ctx, res); isFilegroup { +				otherM, _ := ctx.ModuleFromName(res) +				resourcesTargetName := ctx.ModuleName() + "_filegroup_resources_" + otherM.Name() +				additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{ +					Resources:             bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, []string{res})), +					Resource_strip_prefix: prefix, +				} +			} else { +				resources.Append(android.BazelLabelForModuleSrc(ctx, []string{res})) +			} +		} + +		if !resources.IsEmpty() {  			resourceStripPrefix = proptools.StringPtr(ctx.ModuleDir())  		} -		resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources))  	}  	//TODO(b/179889880) handle case where glob includes files outside package @@ -2758,23 +2801,51 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte  		m.properties.Exclude_java_resources,  	) -	for i, resDep := range resDeps { +	for _, 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)") +		prefix := proptools.StringPtr(dir.String()) +		resourcesTargetName := ctx.ModuleName() + "_resource_dir_" + dir.String() +		additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{ +			Resources:             bazel.MakeLabelListAttribute(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files))), +			Resource_strip_prefix: prefix, +		} +	} + +	var additionalResourceLabels bazel.LabelList +	if len(additionalJavaResourcesMap) > 0 { +		var additionalResources []string +		for resName, _ := range additionalJavaResourcesMap { +			additionalResources = append(additionalResources, resName)  		} +		sort.Strings(additionalResources) + +		for i, resName := range additionalResources { +			resAttr := additionalJavaResourcesMap[resName] +			if resourceStripPrefix == nil && i == 0 { +				resourceStripPrefix = resAttr.Resource_strip_prefix +				resources = resAttr.Resources.Value +			} else if !resAttr.Resources.IsEmpty() { +				ctx.CreateBazelTargetModule( +					bazel.BazelTargetModuleProperties{ +						Rule_class:        "java_resources", +						Bzl_load_location: "//build/bazel/rules/java:java_resources.bzl", +					}, +					android.CommonAttributes{Name: resName}, +					resAttr, +				) +				additionalResourceLabels.Append(android.BazelLabelForModuleSrc(ctx, []string{resName})) +			} +		} +  	}  	return &javaResourcesAttributes{  		Resources:             bazel.MakeLabelListAttribute(resources),  		Resource_strip_prefix: resourceStripPrefix, +		Additional_resources:  bazel.MakeLabelListAttribute(additionalResourceLabels),  	}  } @@ -2815,8 +2886,9 @@ type javaAidlLibraryAttributes struct {  // depending on the module type.  type bp2BuildJavaInfo struct {  	// separates dependencies into dynamic dependencies and static dependencies. -	DepLabels *javaDependencyLabels -	hasKotlin bool +	DepLabels       *javaDependencyLabels +	hasKotlin       bool +	onlyProtoInSrcs bool  }  func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string { @@ -2828,17 +2900,31 @@ func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string {  // 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) { +func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) {  	var srcs bazel.LabelListAttribute  	var deps bazel.LabelListAttribute  	var staticDeps bazel.LabelListAttribute +	if proptools.String(m.deviceProperties.Sdk_version) == "" && m.DeviceSupported() { +		// TODO(b/297356704): handle platform apis in bp2build +		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version unset") +		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false +	} else if proptools.String(m.deviceProperties.Sdk_version) == "core_platform" { +		// TODO(b/297356582): handle core_platform in bp2build +		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version core_platform") +		return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false +	} +  	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) +				if archProps.Jarjar_rules != nil { +					ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "jarjar_rules") +					return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false +				}  			}  		}  	} @@ -2865,6 +2951,9 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)  	staticDeps.Append(srcPartitions[xsdSrcPartition]) +	_, protoInSrcs := srcPartitions[protoSrcPartition] +	onlyProtoInSrcs := protoInSrcs && len(srcPartitions) == 1 +  	if !srcPartitions[logtagSrcPartition].IsEmpty() {  		logtagsLibName := m.Name() + "_logtags"  		ctx.CreateBazelTargetModule( @@ -3002,11 +3091,12 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext)  	}  	bp2BuildInfo := &bp2BuildJavaInfo{ -		DepLabels: depLabels, -		hasKotlin: hasKotlin, +		DepLabels:       depLabels, +		hasKotlin:       hasKotlin, +		onlyProtoInSrcs: onlyProtoInSrcs,  	} -	return commonAttrs, bp2BuildInfo +	return commonAttrs, bp2BuildInfo, true  }  type javaLibraryAttributes struct { @@ -3036,20 +3126,36 @@ func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties  }  func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { -	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) +	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) +	if !supported { +		return +	}  	depLabels := bp2BuildInfo.DepLabels  	deps := depLabels.Deps +	exports := depLabels.StaticDeps  	if !commonAttrs.Srcs.IsEmpty() { -		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them +		deps.Append(exports) // we should only append these if there are sources to use them  	} else if !deps.IsEmpty() { -		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") +		if bp2BuildInfo.onlyProtoInSrcs { +			// java_library does not accept deps when there are no srcs because +			// there is no compilation happening, but it accepts exports. +			// bp2build converts this module to 2 java_libraries + java_xx_proto_library + proto_library +			// the non-empty deps here are not necessary for compiling the protos, in which case +			// they're unnecessary as deps on the java_library as well since they aren't +			// being propagated to any dependencies. +			// so we can put the deps to exports and drop deps here. +			exports.Append(deps) +			deps = bazel.LabelListAttribute{} +		} else { +			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, +		Exports:              exports,  	}  	name := m.Name() @@ -3083,7 +3189,10 @@ type javaBinaryHostAttributes struct {  // JavaBinaryHostBp2Build is for java_binary_host bp2build.  func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { -	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) +	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) +	if !supported { +		return +	}  	depLabels := bp2BuildInfo.DepLabels  	deps := depLabels.Deps @@ -3167,7 +3276,10 @@ type javaTestHostAttributes struct {  // javaTestHostBp2Build is for java_test_host bp2build.  func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) { -	commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx) +	commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx) +	if !supported { +		return +	}  	depLabels := bp2BuildInfo.DepLabels  	deps := depLabels.Deps |