summaryrefslogtreecommitdiff
path: root/java/base.go
diff options
context:
space:
mode:
Diffstat (limited to 'java/base.go')
-rw-r--r--java/base.go919
1 files changed, 740 insertions, 179 deletions
diff --git a/java/base.go b/java/base.go
index 991132321..caac98abc 100644
--- a/java/base.go
+++ b/java/base.go
@@ -17,9 +17,12 @@ package java
import (
"fmt"
"path/filepath"
+ "reflect"
+ "slices"
"strconv"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
@@ -79,12 +82,18 @@ type CommonProperties struct {
// list of java libraries that will be compiled into the resulting jar
Static_libs []string `android:"arch_variant"`
+ // list of java libraries that should not be used to build this module
+ Exclude_static_libs []string `android:"arch_variant"`
+
// manifest file to be included in resulting jar
Manifest *string `android:"path"`
// if not blank, run jarjar using the specified rules file
Jarjar_rules *string `android:"path,arch_variant"`
+ // if not blank, used as prefix to generate repackage rule
+ Jarjar_prefix *string
+
// If not blank, set the java version passed to javac as -source and -target
Java_version *string
@@ -129,7 +138,7 @@ type CommonProperties struct {
// 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"`
+ Patch_module *string
Jacoco struct {
// List of classes to include for instrumentation with jacoco to collect coverage
@@ -184,6 +193,28 @@ type CommonProperties struct {
// A list of java_library instances that provide additional hiddenapi annotations for the library.
Hiddenapi_additional_annotations []string
+
+ // Additional srcJars tacked in by GeneratedJavaLibraryModule
+ Generated_srcjars []android.Path `android:"mutated"`
+
+ // intermediate aconfig cache file tacked in by GeneratedJavaLibraryModule
+ Aconfig_Cache_files []android.Path `android:"mutated"`
+
+ // If true, then only the headers are built and not the implementation jar.
+ Headers_only *bool
+
+ // A list of files or dependencies to make available to the build sandbox. This is
+ // useful if source files are symlinks, the targets of the symlinks must be listed here.
+ // Note that currently not all actions implemented by android_apps are sandboxed, so you
+ // may only see this being necessary in lint builds.
+ Compile_data []string `android:"path"`
+
+ // Property signifying whether the module compiles stubs or not.
+ // Should be set to true when srcs of this module are stub files.
+ // This property does not need to be set to true when the module depends on
+ // the stubs via libs, but should be set to true when the module depends on
+ // the stubs via static libs.
+ Is_stubs_module *bool
}
// Properties that are specific to device modules. Host module factories should not add these when
@@ -198,10 +229,6 @@ type DeviceProperties struct {
// If the SDK kind is empty, it will be set to public.
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. See sdk_version for possible values.
- Min_sdk_version *string
-
// if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
// Defaults to empty string "". See sdk_version for possible values.
Max_sdk_version *string
@@ -274,13 +301,17 @@ type DeviceProperties struct {
HiddenAPIFlagFileProperties
}
-// Device properties that can be overridden by overriding module (e.g. override_android_app)
-type OverridableDeviceProperties struct {
+// Properties that can be overridden by overriding module (e.g. override_android_app)
+type OverridableProperties struct {
// set the name of the output. If not set, `name` is used.
// To override a module with this property set, overriding module might need to set this as well.
// Otherwise, both the overridden and the overriding modules will have the same output name, which
// can cause the duplicate output error.
Stem *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. See sdk_version for possible values.
+ Min_sdk_version *string
}
// Functionality common to Module and Import
@@ -395,7 +426,6 @@ type Module struct {
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
// Functionality common to Module and Import.
embeddableInModuleAndImport
@@ -404,12 +434,15 @@ type Module struct {
protoProperties android.ProtoProperties
deviceProperties DeviceProperties
- overridableDeviceProperties OverridableDeviceProperties
+ overridableProperties OverridableProperties
+ sourceProperties android.SourceProperties
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
+ repackagedHeaderJarFile android.Path
+
// jar file containing implementation classes including static library dependencies but no
// resources
implementationJarFile android.Path
@@ -421,6 +454,9 @@ type Module struct {
srcJarArgs []string
srcJarDeps android.Paths
+ // the source files of this module and all its static dependencies
+ transitiveSrcFiles *android.DepSet[android.Path]
+
// jar file containing implementation classes and resources including static library
// dependencies
implementationAndResourcesJar android.Path
@@ -471,6 +507,9 @@ type Module struct {
// expanded Jarjar_rules
expandJarjarRules android.Path
+ // jarjar rule for inherited jarjar rules
+ repackageJarjarRules android.Path
+
// Extra files generated by the module type to be added as java resources.
extraResources android.Paths
@@ -483,9 +522,6 @@ type Module struct {
// list of the xref extraction files
kytheFiles android.Paths
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
-
hideApexVariantFromMake bool
sdkVersion android.SdkSpec
@@ -493,6 +529,36 @@ type Module struct {
maxSdkVersion android.ApiLevel
sourceExtensions []string
+
+ annoSrcJars android.Paths
+
+ // output file name based on Stem property.
+ // This should be set in every ModuleWithStem's GenerateAndroidBuildActions
+ // or the module should override Stem().
+ stem string
+
+ // Values that will be set in the JarJarProvider data for jarjar repackaging,
+ // and merged with our dependencies' rules.
+ jarjarRenameRules map[string]string
+
+ stubsLinkType StubsLinkType
+
+ // Paths to the aconfig intermediate cache files that are provided by the
+ // java_aconfig_library or java_library modules that are statically linked
+ // to this module. Does not contain cache files from all transitive dependencies.
+ aconfigCacheFiles android.Paths
+}
+
+var _ android.InstallableModule = (*Module)(nil)
+
+// To satisfy the InstallableModule interface
+func (j *Module) EnforceApiContainerChecks() bool {
+ return true
+}
+
+// Overrides android.ModuleBase.InstallInProduct()
+func (j *Module) InstallInProduct() bool {
+ return j.ProductSpecific()
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -551,9 +617,21 @@ func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
}
}
+func (j *Module) checkHeadersOnly(ctx android.ModuleContext) {
+ if _, ok := ctx.Module().(android.SdkContext); ok {
+ headersOnly := proptools.Bool(j.properties.Headers_only)
+ installable := proptools.Bool(j.properties.Installable)
+
+ if headersOnly && installable {
+ ctx.PropertyErrorf("headers_only", "This module has conflicting settings. headers_only is true which, which means this module doesn't generate an implementation jar. However installable is set to true.")
+ }
+ }
+}
+
func (j *Module) addHostProperties() {
j.AddProperties(
&j.properties,
+ &j.overridableProperties,
&j.protoProperties,
&j.usesLibraryProperties,
)
@@ -563,7 +641,6 @@ func (j *Module) addHostAndDeviceProperties() {
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
- &j.overridableDeviceProperties,
&j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
@@ -581,31 +658,24 @@ func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) {
// Populate with package rules from the properties.
hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties)
- ctx.SetProvider(hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
+ android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}
-func (j *Module) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil
- case android.DefaultDistTag:
- return android.Paths{j.outputFile}, nil
- case ".jar":
- return android.Paths{j.implementationAndResourcesJar}, nil
- case ".hjar":
- return android.Paths{j.headerJarFile}, nil
- case ".proguard_map":
- if j.dexer.proguardDictionary.Valid() {
- return android.Paths{j.dexer.proguardDictionary.Path()}, nil
- }
- return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+// helper method for java modules to set OutputFilesProvider
+func setOutputFiles(ctx android.ModuleContext, m Module) {
+ ctx.SetOutputFiles(append(android.Paths{m.outputFile}, m.extraOutputFiles...), "")
+ ctx.SetOutputFiles(android.Paths{m.outputFile}, android.DefaultDistTag)
+ ctx.SetOutputFiles(android.Paths{m.implementationAndResourcesJar}, ".jar")
+ ctx.SetOutputFiles(android.Paths{m.headerJarFile}, ".hjar")
+ if m.dexer.proguardDictionary.Valid() {
+ ctx.SetOutputFiles(android.Paths{m.dexer.proguardDictionary.Path()}, ".proguard_map")
+ }
+ ctx.SetOutputFiles(m.properties.Generated_srcjars, ".generated_srcjars")
+ if m.linter.outputs.xml != nil {
+ ctx.SetOutputFiles(android.Paths{m.linter.outputs.xml}, ".lint")
}
}
-var _ android.OutputFileProducer = (*Module)(nil)
-
func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) {
initJavaModule(module, hod, false)
}
@@ -641,8 +711,9 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
// Force enable the instrumentation for java code that is built for APEXes ...
// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
// doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+
if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
return true
@@ -666,12 +737,16 @@ func (j *Module) SystemModules() string {
}
func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
- if j.deviceProperties.Min_sdk_version != nil {
- return android.ApiLevelFrom(ctx, *j.deviceProperties.Min_sdk_version)
+ if j.overridableProperties.Min_sdk_version != nil {
+ return android.ApiLevelFrom(ctx, *j.overridableProperties.Min_sdk_version)
}
return j.SdkVersion(ctx).ApiLevel
}
+func (j *Module) GetDeviceProperties() *DeviceProperties {
+ return &j.deviceProperties
+}
+
func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.deviceProperties.Max_sdk_version != nil {
return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
@@ -724,12 +799,14 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
}
libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+
+ j.properties.Static_libs = android.RemoveListFromList(j.properties.Static_libs, j.properties.Exclude_static_libs)
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
- if ctx.DeviceConfig().VndkVersion() != "" && ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
+ if ctx.Config().EnforceInterPartitionJavaSdkLibrary() {
// Require java_sdk_library at inter-partition java dependency to ensure stable
// interface between partitions. If inter-partition java_library dependency is detected,
// raise build error because java_library doesn't have a stable interface.
@@ -762,9 +839,11 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if dep != nil {
if component, ok := dep.(SdkLibraryComponentDependency); ok {
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
- // Add library as optional if it's one of the optional compatibility libs.
+ // Add library as optional if it's one of the optional compatibility libs or it's
+ // explicitly listed in the optional_uses_libs property.
tag := usesLibReqTag
- if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
+ if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
+ android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) {
tag = usesLibOptTag
}
ctx.AddVariationDependencies(nil, tag, *lib)
@@ -961,8 +1040,16 @@ func (j *Module) collectJavacFlags(
ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
// javac flags.
javacFlags := j.properties.Javacflags
+ var needsDebugInfo bool
+
+ needsDebugInfo = false
+ for _, flag := range javacFlags {
+ if strings.HasPrefix(flag, "-g") {
+ needsDebugInfo = true
+ }
+ }
- if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() && !needsDebugInfo {
// For non-host binaries, override the -g flag passed globally to remove
// local variable debug info to reduce disk and memory usage.
javacFlags = append(javacFlags, "-g:source,lines")
@@ -971,44 +1058,18 @@ func (j *Module) collectJavacFlags(
if flags.javaVersion.usesJavaModules() {
javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.javacflags", "JDK version defaults to higher than 9")
+ }
+ if flags.javaVersion.usesJavaModules() {
if j.properties.Patch_module != nil {
// Manually specify build directory in case it is not under the repo root.
// (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
// just adding a symlink under the root doesn't help.)
patchPaths := []string{".", ctx.Config().SoongOutDir()}
- // b/150878007
- //
- // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
- // execution root for --patch-module. If this javac command line is
- // invoked within Bazel's execution root working directory, the top
- // level directories (e.g. libcore/, tools/, frameworks/) are all
- // symlinks. JDK9 javac does not traverse into symlinks, which causes
- // --patch-module to fail source file lookups when invoked in the
- // execution root.
- //
- // Short of patching javac or enumerating *all* directories as possible
- // input dirs, manually add the top level dir of the source files to be
- // compiled.
- topLevelDirs := map[string]bool{}
- for _, srcFilePath := range srcFiles {
- srcFileParts := strings.Split(srcFilePath.String(), "/")
- // Ignore source files that are already in the top level directory
- // as well as generated files in the out directory. The out
- // directory may be an absolute path, which means srcFileParts[0] is the
- // empty string, so check that as well. Note that "out" in Bazel's execution
- // root is *not* a symlink, which doesn't cause problems for --patch-modules
- // anyway, so it's fine to not apply this workaround for generated
- // source files.
- if len(srcFileParts) > 1 &&
- srcFileParts[0] != "" &&
- srcFileParts[0] != "out" {
- topLevelDirs[srcFileParts[0]] = true
- }
- }
- patchPaths = append(patchPaths, android.SortedKeys(topLevelDirs)...)
-
classPath := flags.classpath.FormJavaClassPath("")
if classPath != "" {
patchPaths = append(patchPaths, classPath)
@@ -1036,7 +1097,24 @@ func (j *Module) AddJSONData(d *map[string]interface{}) {
}
-func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
+func (j *Module) addGeneratedSrcJars(path android.Path) {
+ j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
+}
+
+func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
+
+ // Auto-propagating jarjar rules
+ jarjarProviderData := j.collectJarJarRules(ctx)
+ if jarjarProviderData != nil {
+ android.SetProvider(ctx, JarJarProvider, *jarjarProviderData)
+ text := getJarJarRuleText(jarjarProviderData)
+ if text != "" {
+ ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt")
+ android.WriteFileRule(ctx, ruleTextFile, text)
+ j.repackageJarjarRules = ruleTextFile
+ }
+ }
+
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
deps := j.collectDeps(ctx)
@@ -1044,6 +1122,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
if flags.javaVersion.usesJavaModules() {
j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.srcs", "JDK version defaults to higher than 9")
}
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
@@ -1074,16 +1155,15 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
srcJars := srcFiles.FilterByExt(".srcjar")
srcJars = append(srcJars, deps.srcJars...)
- if aaptSrcJar != nil {
- srcJars = append(srcJars, aaptSrcJar)
- }
+ srcJars = append(srcJars, extraSrcJars...)
+ srcJars = append(srcJars, j.properties.Generated_srcjars...)
srcFiles = srcFiles.FilterOutByExt(".srcjar")
if j.properties.Jarjar_rules != nil {
j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
}
- jarName := ctx.ModuleName() + ".jar"
+ jarName := j.Stem() + ".jar"
var uniqueJavaFiles android.Paths
set := make(map[string]bool)
@@ -1105,6 +1185,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
j.uniqueSrcFiles = uniqueSrcFiles
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()})
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
@@ -1118,6 +1199,45 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
var kotlinJars android.Paths
var kotlinHeaderJars android.Paths
+ // Prepend extraClasspathJars to classpath so that the resource processor R.jar comes before
+ // any dependencies so that it can override any non-final R classes from dependencies with the
+ // final R classes from the app.
+ flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...)
+
+ j.aconfigCacheFiles = append(deps.aconfigProtoFiles, j.properties.Aconfig_Cache_files...)
+
+ // If compiling headers then compile them and skip the rest
+ if proptools.Bool(j.properties.Headers_only) {
+ if srcFiles.HasExt(".kt") {
+ ctx.ModuleErrorf("Compiling headers_only with .kt not supported")
+ }
+ if ctx.Config().IsEnvFalse("TURBINE_ENABLED") || disableTurbine {
+ ctx.ModuleErrorf("headers_only is enabled but Turbine is disabled.")
+ }
+
+ _, j.headerJarFile, _ =
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName,
+ extraCombinedJars)
+ if ctx.Failed() {
+ return
+ }
+
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: deps.aconfigProtoFiles,
+ })
+
+ j.outputFile = j.headerJarFile
+ return
+ }
+
if srcFiles.HasExt(".kt") {
// When using kotlin sources turbine is used to generate annotation processor sources,
// including for annotation processors that generate API, so we can use turbine for
@@ -1178,10 +1298,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
return
}
+ kotlinJarPath := j.repackageFlagsIfNecessary(ctx, kotlinJar.OutputPath, jarName, "kotlinc")
+
// Make javac rule depend on the kotlinc rule
flags.classpath = append(classpath{kotlinHeaderJar}, flags.classpath...)
- kotlinJars = append(kotlinJars, kotlinJar)
+ kotlinJars = append(kotlinJars, kotlinJarPath)
kotlinHeaderJars = append(kotlinHeaderJars, kotlinHeaderJar)
// Jar kotlin classes into the final jar after javac
@@ -1196,7 +1318,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
- jars := append(android.Paths(nil), kotlinJars...)
+ jars := slices.Clone(kotlinJars)
j.compiledSrcJars = srcJars
@@ -1211,8 +1333,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
+ extraJars := append(slices.Clone(kotlinHeaderJars), extraCombinedJars...)
+ headerJarFileWithoutDepsOrJarjar, j.headerJarFile, j.repackagedHeaderJarFile =
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, extraJars)
if ctx.Failed() {
return
}
@@ -1241,8 +1364,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// this module, or else we could have duplicated errorprone messages.
errorproneFlags := enableErrorproneFlags(flags)
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
+ errorproneAnnoSrcJar := android.PathForModuleOut(ctx, "errorprone", "anno.srcjar")
- transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneAnnoSrcJar, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1259,16 +1383,26 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(idx))
jars = append(jars, classes)
}
}
+ // Assume approximately 5 sources per srcjar.
+ // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean
+ // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files.
if len(srcJars) > 0 {
- classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
- nil, srcJars, flags, extraJarDeps)
- jars = append(jars, classes)
+ startIdx := len(shardSrcs)
+ shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5)
+ for idx, shardSrcJars := range shardSrcJarsList {
+ classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
+ nil, shardSrcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac-"+strconv.Itoa(startIdx+idx))
+ jars = append(jars, classes)
+ }
}
} else {
classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
+ classes = j.repackageFlagsIfNecessary(ctx, classes, jarName, "javac")
jars = append(jars, classes)
}
if ctx.Failed() {
@@ -1276,6 +1410,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
+ jars = append(jars, extraCombinedJars...)
+
j.srcJarArgs, j.srcJarDeps = resourcePathsToJarArgs(srcFiles), srcFiles
var includeSrcJar android.WritablePath
@@ -1372,12 +1508,20 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// prebuilt dependencies until we support modules in the platform build, so there shouldn't be
// any if len(jars) == 1.
+ // moduleStubLinkType determines if the module is the TopLevelStubLibrary generated
+ // from sdk_library. The TopLevelStubLibrary contains only one static lib,
+ // either with .from-source or .from-text suffix.
+ // outputFile should be agnostic to the build configuration,
+ // thus "combine" the single static lib in order to prevent the static lib from being exposed
+ // to the copy rules.
+ stub, _ := moduleStubLinkType(ctx.ModuleName())
+
// Transform the single path to the jar into an OutputPath as that is required by the following
// code.
- if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok {
+ if moduleOutPath, ok := jars[0].(android.ModuleOutPath); ok && !stub {
// The path contains an embedded OutputPath so reuse that.
outputFile = moduleOutPath.OutputPath
- } else if outputPath, ok := jars[0].(android.OutputPath); ok {
+ } else if outputPath, ok := jars[0].(android.OutputPath); ok && !stub {
// The path is an OutputPath so reuse it directly.
outputFile = outputPath
} else {
@@ -1446,7 +1590,13 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.implementationJarFile = outputFile
if j.headerJarFile == nil {
- j.headerJarFile = j.implementationJarFile
+ // If this module couldn't generate a header jar (for example due to api generating annotation processors)
+ // then use the implementation jar. Run it through zip2zip first to remove any files in META-INF/services
+ // so that javac on modules that depend on this module don't pick up annotation processors (which may be
+ // missing their implementations) from META-INF/services/javax.annotation.processing.Processor.
+ headerJarFile := android.PathForModuleOut(ctx, "javac-header", jarName)
+ convertImplementationJarToHeaderJar(ctx, j.implementationJarFile, headerJarFile)
+ j.headerJarFile = headerJarFile
}
// enforce syntax check to jacoco filters for any build (http://b/183622051)
@@ -1473,7 +1623,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
compileDex := j.dexProperties.Compile_dex
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
if compileDex == nil {
compileDex = proptools.BoolPtr(true)
@@ -1486,7 +1636,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) {
if j.hasCode(ctx) {
if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles,
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
@@ -1498,11 +1648,28 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
classesJar: implementationAndResourcesJar,
jarName: jarName,
}
- dexOutputFile = j.dexer.compileDex(ctx, params)
+ if j.GetProfileGuided() && j.optimizeOrObfuscateEnabled() && !j.EnableProfileRewriting() {
+ ctx.PropertyErrorf("enable_profile_rewriting",
+ "Enable_profile_rewriting must be true when profile_guided dexpreopt and R8 optimization/obfuscation is turned on. The attached profile should be sourced from an unoptimized/unobfuscated APK.",
+ )
+ }
+ if j.EnableProfileRewriting() {
+ profile := j.GetProfile()
+ if profile == "" || !j.GetProfileGuided() {
+ ctx.PropertyErrorf("enable_profile_rewriting", "Profile and Profile_guided must be set when enable_profile_rewriting is true")
+ }
+ params.artProfileInput = &profile
+ }
+ dexOutputFile, dexArtProfileOutput := j.dexer.compileDex(ctx, params)
if ctx.Failed() {
return
}
+ // If r8/d8 provides a profile that matches the optimized dex, use that for dexpreopt.
+ if dexArtProfileOutput != nil {
+ j.dexpreopter.SetRewrittenProfile(*dexArtProfileOutput)
+ }
+
// merge dex jar with resources if necessary
if j.resourceJar != nil {
jars := android.Paths{dexOutputFile, j.resourceJar}
@@ -1511,7 +1678,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
false, nil, nil)
if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
- TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar, nil)
dexOutputFile = combinedAlignedJar
} else {
dexOutputFile = combinedJar
@@ -1528,7 +1695,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
+ libName := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
+ if j.SdkLibraryName() != nil && strings.HasSuffix(ctx.ModuleName(), ".impl") {
+ libName = strings.TrimSuffix(libName, ".impl")
+ }
+ j.dexpreopt(ctx, libName, dexOutputFile)
outputFile = dexOutputFile
} else {
@@ -1546,30 +1717,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
if ctx.Device() {
- lintSDKVersion := func(apiLevel android.ApiLevel) int {
+ lintSDKVersion := func(apiLevel android.ApiLevel) android.ApiLevel {
if !apiLevel.IsPreview() {
- return apiLevel.FinalInt()
+ return apiLevel
} else {
- // When running metalava, we pass --version-codename. When that value
- // is not REL, metalava will add 1 to the --current-version argument.
- // On old branches, PLATFORM_SDK_VERSION is the latest version (for that
- // branch) and the codename is REL, except potentially on the most
- // recent non-master branch. On that branch, it goes through two other
- // phases before it gets to the phase previously described:
- // - PLATFORM_SDK_VERSION has not been updated yet, and the codename
- // is not rel. This happens for most of the internal branch's life
- // while the branch has been cut but is still under active development.
- // - PLATFORM_SDK_VERSION has been set, but the codename is still not
- // REL. This happens briefly during the release process. During this
- // state the code to add --current-version is commented out, and then
- // that commenting out is reverted after the codename is set to REL.
- // On the master branch, the PLATFORM_SDK_VERSION always represents a
- // prior version and the codename is always non-REL.
- //
- // We need to add one here to match metalava adding 1. Technically
- // this means that in the state described in the second bullet point
- // above, this number is 1 higher than it should be.
- return ctx.Config().PlatformSdkVersion().FinalInt() + 1
+ return ctx.Config().DefaultAppTargetSdk(ctx)
}
}
@@ -1584,28 +1736,35 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
+ j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data)
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
j.linter.buildModuleReportZip = true
}
j.linter.lint(ctx)
}
+ j.collectTransitiveSrcFiles(ctx, srcFiles)
+
ctx.CheckbuildFile(outputFile)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(j.headerJarFile),
- TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
- TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
- ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
- ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
- ResourceJars: android.PathsIfNonNil(j.resourceJar),
- AidlIncludeDirs: j.exportAidlIncludeDirs,
- SrcJarArgs: j.srcJarArgs,
- SrcJarDeps: j.srcJarDeps,
- ExportedPlugins: j.exportedPluginJars,
- ExportedPluginClasses: j.exportedPluginClasses,
- ExportedPluginDisableTurbine: j.exportedDisableTurbine,
- JacocoReportClassesFile: j.jacocoReportClassesFile,
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
+ HeaderJars: android.PathsIfNonNil(j.headerJarFile),
+ RepackagedHeaderJars: android.PathsIfNonNil(j.repackagedHeaderJarFile),
+ TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
+ TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
+ ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
+ ImplementationJars: android.PathsIfNonNil(j.implementationJarFile),
+ ResourceJars: android.PathsIfNonNil(j.resourceJar),
+ AidlIncludeDirs: j.exportAidlIncludeDirs,
+ SrcJarArgs: j.srcJarArgs,
+ SrcJarDeps: j.srcJarDeps,
+ TransitiveSrcFiles: j.transitiveSrcFiles,
+ ExportedPlugins: j.exportedPluginJars,
+ ExportedPluginClasses: j.exportedPluginClasses,
+ ExportedPluginDisableTurbine: j.exportedDisableTurbine,
+ JacocoReportClassesFile: j.jacocoReportClassesFile,
+ StubsLinkType: j.stubsLinkType,
+ AconfigIntermediateCacheOutputPaths: j.aconfigCacheFiles,
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1616,6 +1775,52 @@ func (j *Module) useCompose() bool {
return android.InList("androidx.compose.runtime_runtime", j.properties.Static_libs)
}
+func collectDepProguardSpecInfo(ctx android.ModuleContext) (transitiveProguardFlags, transitiveUnconditionalExportedFlags []*android.DepSet[android.Path]) {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
+ depTag := ctx.OtherModuleDependencyTag(m)
+
+ if depProguardInfo.UnconditionallyExportedProguardFlags != nil {
+ transitiveUnconditionalExportedFlags = append(transitiveUnconditionalExportedFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
+ transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.UnconditionallyExportedProguardFlags)
+ }
+
+ if depTag == staticLibTag && depProguardInfo.ProguardFlagsFiles != nil {
+ transitiveProguardFlags = append(transitiveProguardFlags, depProguardInfo.ProguardFlagsFiles)
+ }
+ })
+
+ return transitiveProguardFlags, transitiveUnconditionalExportedFlags
+}
+
+func (j *Module) collectProguardSpecInfo(ctx android.ModuleContext) ProguardSpecInfo {
+ transitiveProguardFlags, transitiveUnconditionalExportedFlags := collectDepProguardSpecInfo(ctx)
+
+ directUnconditionalExportedFlags := android.Paths{}
+ proguardFlagsForThisModule := android.PathsForModuleSrc(ctx, j.dexProperties.Optimize.Proguard_flags_files)
+ exportUnconditionally := proptools.Bool(j.dexProperties.Optimize.Export_proguard_flags_files)
+ if exportUnconditionally {
+ // if we explicitly export, then our unconditional exports are the same as our transitive flags
+ transitiveUnconditionalExportedFlags = transitiveProguardFlags
+ directUnconditionalExportedFlags = proguardFlagsForThisModule
+ }
+
+ return ProguardSpecInfo{
+ Export_proguard_flags_files: exportUnconditionally,
+ ProguardFlagsFiles: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ proguardFlagsForThisModule,
+ transitiveProguardFlags,
+ ),
+ UnconditionallyExportedProguardFlags: android.NewDepSet[android.Path](
+ android.POSTORDER,
+ directUnconditionalExportedFlags,
+ transitiveUnconditionalExportedFlags,
+ ),
+ }
+
+}
+
// Returns a copy of the supplied flags, but with all the errorprone-related
// fields copied to the regular build's fields.
func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
@@ -1635,20 +1840,26 @@ func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, i
srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
kzipName := pathtools.ReplaceExtension(jarName, "kzip")
+ annoSrcJar := android.PathForModuleOut(ctx, "javac", "anno.srcjar")
if idx >= 0 {
kzipName = strings.TrimSuffix(jarName, filepath.Ext(jarName)) + strconv.Itoa(idx) + ".kzip"
+ annoSrcJar = android.PathForModuleOut(ctx, "javac", "anno-"+strconv.Itoa(idx)+".srcjar")
jarName += strconv.Itoa(idx)
}
classes := android.PathForModuleOut(ctx, "javac", jarName).OutputPath
- TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, flags, extraJarDeps)
+ TransformJavaToClasses(ctx, classes, idx, srcFiles, srcJars, annoSrcJar, flags, extraJarDeps)
- if ctx.Config().EmitXrefRules() {
+ if ctx.Config().EmitXrefRules() && ctx.Module() == ctx.PrimaryModule() {
extractionFile := android.PathForModuleOut(ctx, kzipName)
emitXrefRule(ctx, extractionFile, idx, srcFiles, srcJars, flags, extraJarDeps)
j.kytheFiles = append(j.kytheFiles, extractionFile)
}
+ if len(flags.processorPath) > 0 {
+ j.annoSrcJars = append(j.annoSrcJars, annoSrcJar)
+ }
+
return classes
}
@@ -1679,7 +1890,7 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) {
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar android.Path) {
+ extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1687,7 +1898,7 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
jars = append(jars, turbineJar)
headerJar = turbineJar
@@ -1712,11 +1923,22 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars
TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules)
jarjarAndDepsHeaderJar = jarjarFile
if ctx.Failed() {
- return nil, nil
+ return nil, nil, nil
}
}
- return headerJar, jarjarAndDepsHeaderJar
+ if j.repackageJarjarRules != nil {
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-turbine-jarjar", jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, jarjarAndDepsHeaderJar, j.repackageJarjarRules)
+ jarjarAndDepsRepackagedHeaderJar = repackagedJarjarFile
+ if ctx.Failed() {
+ return nil, nil, nil
+ }
+ } else {
+ jarjarAndDepsRepackagedHeaderJar = jarjarAndDepsHeaderJar
+ }
+
+ return headerJar, jarjarAndDepsHeaderJar, jarjarAndDepsRepackagedHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
@@ -1734,44 +1956,47 @@ func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
type providesTransitiveHeaderJars struct {
// set of header jars for all transitive libs deps
- transitiveLibsHeaderJars *android.DepSet
+ transitiveLibsHeaderJars *android.DepSet[android.Path]
// set of header jars for all transitive static libs deps
- transitiveStaticLibsHeaderJars *android.DepSet
+ transitiveStaticLibsHeaderJars *android.DepSet[android.Path]
}
-func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet {
+func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet[android.Path] {
return j.transitiveLibsHeaderJars
}
-func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet {
+func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet[android.Path] {
return j.transitiveStaticLibsHeaderJars
}
func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) {
directLibs := android.Paths{}
directStaticLibs := android.Paths{}
- transitiveLibs := []*android.DepSet{}
- transitiveStaticLibs := []*android.DepSet{}
+ transitiveLibs := []*android.DepSet[android.Path]{}
+ transitiveStaticLibs := []*android.DepSet[android.Path]{}
ctx.VisitDirectDeps(func(module android.Module) {
// don't add deps of the prebuilt version of the same library
if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
return
}
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if dep.TransitiveLibsHeaderJars != nil {
- transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
- }
- if dep.TransitiveStaticLibsHeaderJars != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
- }
-
+ dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
tag := ctx.OtherModuleDependencyTag(module)
_, isUsesLibDep := tag.(usesLibraryDependencyTag)
if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
directLibs = append(directLibs, dep.HeaderJars...)
} else if tag == staticLibTag {
directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
+ } else {
+ // Don't propagate transitive libs for other kinds of dependencies.
+ return
+ }
+
+ if dep.TransitiveLibsHeaderJars != nil {
+ transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
}
})
j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
@@ -1792,7 +2017,7 @@ func (j *Module) ImplementationJars() android.Paths {
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJarBuildPath() OptionalDexJarPath {
+func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile
}
@@ -1825,9 +2050,9 @@ func (j *Module) IDEInfo(dpInfo *android.IdeInfo) {
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
}
- dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
+ dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
}
func (j *Module) CompilerDeps() []string {
@@ -1865,13 +2090,31 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi
}
func (j *Module) Stem() string {
- return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name())
+ if j.stem == "" {
+ panic("Stem() called before stem property was set")
+ }
+ return j.stem
}
func (j *Module) JacocoReportClassesFile() android.Path {
return j.jacocoReportClassesFile
}
+func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
+ var fromDeps []*android.DepSet[android.Path]
+ ctx.VisitDirectDeps(func(module android.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ if tag == staticLibTag {
+ depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if depInfo.TransitiveSrcFiles != nil {
+ fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
+ }
+ }
+ })
+
+ j.transitiveSrcFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
+}
+
func (j *Module) IsInstallable() bool {
return Bool(j.properties.Installable)
}
@@ -1923,19 +2166,22 @@ type moduleWithSdkDep interface {
func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
switch name {
- case android.SdkCore.JavaLibraryName(ctx.Config()), "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ case android.SdkCore.DefaultJavaLibraryName(),
+ "legacy.core.platform.api.stubs",
+ "stable.core.platform.api.stubs",
"stub-annotations", "private-stub-annotations-jar",
- "core-lambda-stubs", "core-generated-annotation-stubs":
+ "core-lambda-stubs",
+ "core-generated-annotation-stubs":
return javaCore, true
- case android.SdkPublic.JavaLibraryName(ctx.Config()):
+ case android.SdkPublic.DefaultJavaLibraryName():
return javaSdk, true
- case android.SdkSystem.JavaLibraryName(ctx.Config()):
+ case android.SdkSystem.DefaultJavaLibraryName():
return javaSystem, true
- case android.SdkModule.JavaLibraryName(ctx.Config()):
+ case android.SdkModule.DefaultJavaLibraryName():
return javaModule, true
- case android.SdkSystemServer.JavaLibraryName(ctx.Config()):
+ case android.SdkSystemServer.DefaultJavaLibraryName():
return javaSystemServer, true
- case android.SdkTest.JavaLibraryName(ctx.Config()):
+ case android.SdkTest.DefaultJavaLibraryName():
return javaSystem, true
}
@@ -2031,15 +2277,14 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if sdkLinkType != javaPlatform &&
- ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
- // dep is a sysprop implementation library, but this module is not linking against
- // the platform, so it gets the sysprop public stubs library instead. Replace
- // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
- syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
- dep = syspropDep.JavaInfo
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if sdkLinkType != javaPlatform {
+ if syspropDep, ok := android.OtherModuleProvider(ctx, module, SyspropPublicStubInfoProvider); ok {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ dep = syspropDep.JavaInfo
+ }
}
switch tag {
case bootClasspathTag:
@@ -2050,6 +2295,10 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...)
+ if len(dep.RepackagedHeaderJars) == 1 && !slices.Contains(dep.HeaderJars, dep.RepackagedHeaderJars[0]) {
+ deps.classpath = append(deps.classpath, dep.RepackagedHeaderJars...)
+ deps.dexClasspath = append(deps.dexClasspath, dep.RepackagedHeaderJars...)
+ }
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...)
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
@@ -2069,6 +2318,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
// annotation processor that generates API is incompatible with the turbine
// optimization.
deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.AconfigIntermediateCacheOutputPaths...)
case pluginTag:
if plugin, ok := module.(*Plugin); ok {
if plugin.pluginProperties.Processor_class != nil {
@@ -2111,7 +2361,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case syspropPublicStubDepTag:
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
- ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ android.SetProvider(ctx, SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
JavaInfo: dep,
})
}
@@ -2127,6 +2377,11 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.staticJars = append(deps.staticJars, dep.Srcs()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.Srcs()...)
}
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, android.CodegenInfoProvider); ok {
+ switch tag {
+ case staticLibTag:
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPaths...)
+ }
} else {
switch tag {
case bootClasspathTag:
@@ -2149,11 +2404,320 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
addCLCFromDep(ctx, module, j.classLoaderContexts)
+ addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary)
})
return deps
}
+// Provider for jarjar renaming rules.
+//
+// Modules can set their jarjar renaming rules with addJarJarRenameRule, and those renamings will be
+// passed to all rdeps. The typical way that these renamings will NOT be inherited is when a module
+// links against stubs -- these are not passed through stubs. The classes will remain unrenamed on
+// classes until a module with jarjar_prefix is reached, and all as yet unrenamed classes will then
+// be renamed from that module.
+// TODO: Add another property to suppress the forwarding of
+type DependencyUse int
+
+const (
+ RenameUseInvalid DependencyUse = iota
+ RenameUseInclude
+ RenameUseExclude
+)
+
+type RenameUseElement struct {
+ DepName string
+ RenameUse DependencyUse
+ Why string // token for determining where in the logic the decision was made.
+}
+
+type JarJarProviderData struct {
+ // Mapping of class names: original --> renamed. If the value is "", the class will be
+ // renamed by the next rdep that has the jarjar_prefix attribute (or this module if it has
+ // attribute). Rdeps of that module will inherit the renaming.
+ Rename map[string]string
+ RenameUse []RenameUseElement
+}
+
+func (this JarJarProviderData) GetDebugString() string {
+ result := ""
+ for _, k := range android.SortedKeys(this.Rename) {
+ v := this.Rename[k]
+ if strings.Contains(k, "android.companion.virtual.flags.FakeFeatureFlagsImpl") {
+ result += k + "-->" + v + ";"
+ }
+ }
+ return result
+}
+
+var JarJarProvider = blueprint.NewProvider[JarJarProviderData]()
+
+var overridableJarJarPrefix = "com.android.internal.hidden_from_bootclasspath"
+
+func init() {
+ android.SetJarJarPrefixHandler(mergeJarJarPrefixes)
+}
+
+// BaseJarJarProviderData contains information that will propagate across dependencies regardless of
+// whether they are java modules or not.
+type BaseJarJarProviderData struct {
+ JarJarProviderData JarJarProviderData
+}
+
+func (this BaseJarJarProviderData) GetDebugString() string {
+ return this.JarJarProviderData.GetDebugString()
+}
+
+var BaseJarJarProvider = blueprint.NewProvider[BaseJarJarProviderData]()
+
+// mergeJarJarPrefixes is called immediately before module.GenerateAndroidBuildActions is called.
+// Since there won't be a JarJarProvider, we create the BaseJarJarProvider if any of our deps have
+// either JarJarProvider or BaseJarJarProvider.
+func mergeJarJarPrefixes(ctx android.ModuleContext) {
+ mod := ctx.Module()
+ // Explicitly avoid propagating into some module types.
+ switch reflect.TypeOf(mod).String() {
+ case "*java.Droidstubs":
+ return
+ }
+ jarJarData := collectDirectDepsProviders(ctx)
+ if jarJarData != nil {
+ providerData := BaseJarJarProviderData{
+ JarJarProviderData: *jarJarData,
+ }
+ android.SetProvider(ctx, BaseJarJarProvider, providerData)
+ }
+
+}
+
+// Add a jarjar renaming rule to this module, to be inherited to all dependent modules.
+func (module *Module) addJarJarRenameRule(original string, renamed string) {
+ if module.jarjarRenameRules == nil {
+ module.jarjarRenameRules = make(map[string]string)
+ }
+ module.jarjarRenameRules[original] = renamed
+}
+
+func collectDirectDepsProviders(ctx android.ModuleContext) (result *JarJarProviderData) {
+ // Gather repackage information from deps
+ // If the dep jas a JarJarProvider, it is used. Otherwise, any BaseJarJarProvider is used.
+
+ module := ctx.Module()
+ moduleName := module.Name()
+
+ ctx.VisitDirectDepsIgnoreBlueprint(func(m android.Module) {
+ tag := ctx.OtherModuleDependencyTag(m)
+ // This logic mirrors that in (*Module).collectDeps above. There are several places
+ // where we explicitly return RenameUseExclude, even though it is the default, to
+ // indicate that it has been verified to be the case.
+ //
+ // Note well: there are probably cases that are getting to the unconditional return
+ // and are therefore wrong.
+ shouldIncludeRenames := func() (DependencyUse, string) {
+ if moduleName == m.Name() {
+ return RenameUseInclude, "name" // If we have the same module name, include the renames.
+ }
+ if sc, ok := module.(android.SdkContext); ok {
+ if ctx.Device() {
+ sdkDep := decodeSdkDep(ctx, sc)
+ if !sdkDep.invalidVersion && sdkDep.useFiles {
+ return RenameUseExclude, "useFiles"
+ }
+ }
+ }
+ if IsJniDepTag(tag) || tag == certificateTag || tag == proguardRaiseTag {
+ return RenameUseExclude, "tags"
+ }
+ if _, ok := m.(SdkLibraryDependency); ok {
+ switch tag {
+ case sdkLibTag, libTag:
+ return RenameUseExclude, "sdklibdep" // matches collectDeps()
+ }
+ return RenameUseInvalid, "sdklibdep" // dep is not used in collectDeps()
+ } else if ji, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
+ switch ji.StubsLinkType {
+ case Stubs:
+ return RenameUseExclude, "info"
+ case Implementation:
+ return RenameUseInclude, "info"
+ default:
+ //fmt.Printf("collectDirectDepsProviders: %v -> %v StubsLinkType unknown\n", module, m)
+ // Fall through to the heuristic logic.
+ }
+ switch reflect.TypeOf(m).String() {
+ case "*java.GeneratedJavaLibraryModule":
+ // Probably a java_aconfig_library module.
+ // TODO: make this check better.
+ return RenameUseInclude, "reflect"
+ }
+ switch tag {
+ case bootClasspathTag:
+ return RenameUseExclude, "tagswitch"
+ case sdkLibTag, libTag, instrumentationForTag:
+ return RenameUseInclude, "tagswitch"
+ case java9LibTag:
+ return RenameUseExclude, "tagswitch"
+ case staticLibTag:
+ return RenameUseInclude, "tagswitch"
+ case pluginTag:
+ return RenameUseInclude, "tagswitch"
+ case errorpronePluginTag:
+ return RenameUseInclude, "tagswitch"
+ case exportedPluginTag:
+ return RenameUseInclude, "tagswitch"
+ case kotlinStdlibTag, kotlinAnnotationsTag:
+ return RenameUseExclude, "tagswitch"
+ case kotlinPluginTag:
+ return RenameUseInclude, "tagswitch"
+ default:
+ return RenameUseExclude, "tagswitch"
+ }
+ } else if _, ok := m.(android.SourceFileProducer); ok {
+ switch tag {
+ case sdkLibTag, libTag, staticLibTag:
+ return RenameUseInclude, "srcfile"
+ default:
+ return RenameUseExclude, "srcfile"
+ }
+ } else if _, ok := android.OtherModuleProvider(ctx, m, android.CodegenInfoProvider); ok {
+ return RenameUseInclude, "aconfig_declarations_group"
+ } else {
+ switch tag {
+ case bootClasspathTag:
+ return RenameUseExclude, "else"
+ case systemModulesTag:
+ return RenameUseInclude, "else"
+ }
+ }
+ // If we got here, choose the safer option, which may lead to a build failure, rather
+ // than runtime failures on the device.
+ return RenameUseExclude, "end"
+ }
+
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ RenameUse: make([]RenameUseElement, 0),
+ }
+ }
+ how, why := shouldIncludeRenames()
+ result.RenameUse = append(result.RenameUse, RenameUseElement{DepName: m.Name(), RenameUse: how, Why: why})
+ if how != RenameUseInclude {
+ // Nothing to merge.
+ return
+ }
+
+ merge := func(theirs *JarJarProviderData) {
+ for orig, renamed := range theirs.Rename {
+ if preexisting, exists := (*result).Rename[orig]; !exists || preexisting == "" {
+ result.Rename[orig] = renamed
+ } else if preexisting != "" && renamed != "" && preexisting != renamed {
+ if strings.HasPrefix(preexisting, overridableJarJarPrefix) {
+ result.Rename[orig] = renamed
+ } else if !strings.HasPrefix(renamed, overridableJarJarPrefix) {
+ ctx.ModuleErrorf("1. Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting, ctx.ModuleName(), m.Name())
+ continue
+ }
+ }
+ }
+ }
+ if theirs, ok := android.OtherModuleProvider(ctx, m, JarJarProvider); ok {
+ merge(&theirs)
+ } else if theirs, ok := android.OtherModuleProvider(ctx, m, BaseJarJarProvider); ok {
+ // TODO: if every java.Module should have a JarJarProvider, and we find only the
+ // BaseJarJarProvider, then there is a bug. Consider seeing if m can be cast
+ // to java.Module.
+ merge(&theirs.JarJarProviderData)
+ }
+ })
+ return
+}
+
+func (this Module) GetDebugString() string {
+ return "sdk_version=" + proptools.String(this.deviceProperties.Sdk_version)
+}
+
+// Merge the jarjar rules we inherit from our dependencies, any that have been added directly to
+// us, and if it's been set, apply the jarjar_prefix property to rename them.
+func (module *Module) collectJarJarRules(ctx android.ModuleContext) *JarJarProviderData {
+ // Gather repackage information from deps
+ result := collectDirectDepsProviders(ctx)
+
+ // Update that with entries we've stored for ourself
+ for orig, renamed := range module.jarjarRenameRules {
+ if result == nil {
+ result = &JarJarProviderData{
+ Rename: make(map[string]string),
+ }
+ }
+ if renamed != "" {
+ if preexisting, exists := (*result).Rename[orig]; exists && preexisting != renamed {
+ ctx.ModuleErrorf("Conflicting jarjar rules inherited for class: %s (%s and %s)", orig, renamed, preexisting)
+ continue
+ }
+ }
+ (*result).Rename[orig] = renamed
+ }
+
+ // If there are no renamings, then jarjar_prefix does nothing, so skip the extra work.
+ if result == nil {
+ return nil
+ }
+
+ // If they've given us a jarjar_prefix property, then we will use that to rename any classes
+ // that have not yet been renamed.
+ prefix := proptools.String(module.properties.Jarjar_prefix)
+ if prefix != "" {
+ if prefix[0] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not start with '.'")
+ return nil
+ }
+ if prefix[len(prefix)-1] == '.' {
+ ctx.PropertyErrorf("jarjar_prefix", "jarjar_prefix can not end with '.'")
+ return nil
+ }
+
+ var updated map[string]string
+ for orig, renamed := range (*result).Rename {
+ if renamed == "" {
+ if updated == nil {
+ updated = make(map[string]string)
+ }
+ updated[orig] = prefix + "." + orig
+ }
+ }
+ for orig, renamed := range updated {
+ (*result).Rename[orig] = renamed
+ }
+ }
+
+ return result
+}
+
+// Get the jarjar rule text for a given provider for the fully resolved rules. Classes that map
+// to "" won't be in this list because they shouldn't be renamed yet.
+func getJarJarRuleText(provider *JarJarProviderData) string {
+ result := ""
+ for _, orig := range android.SortedKeys(provider.Rename) {
+ renamed := provider.Rename[orig]
+ if renamed != "" {
+ result += "rule " + orig + " " + renamed + "\n"
+ }
+ }
+ return result
+}
+
+// Repackage the flags if the jarjar rule txt for the flags is generated
+func (j *Module) repackageFlagsIfNecessary(ctx android.ModuleContext, infile android.WritablePath, jarName, info string) android.WritablePath {
+ if j.repackageJarjarRules == nil {
+ return infile
+ }
+ repackagedJarjarFile := android.PathForModuleOut(ctx, "repackaged-jarjar", info+jarName)
+ TransformJarJar(ctx, repackagedJarjarFile, infile, j.repackageJarjarRules)
+ return repackagedJarjarFile
+}
+
func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
deps.processorPath = append(deps.processorPath, pluginJars...)
deps.processorClasses = append(deps.processorClasses, pluginClasses...)
@@ -2175,15 +2739,12 @@ type ModuleWithStem interface {
var _ ModuleWithStem = (*Module)(nil)
-func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- switch ctx.ModuleType() {
- case "java_library", "java_library_host", "java_library_static":
- if lib, ok := ctx.Module().(*Library); ok {
- javaLibraryBp2Build(ctx, lib)
- }
- case "java_binary_host":
- if binary, ok := ctx.Module().(*Binary); ok {
- javaBinaryHostBp2Build(ctx, binary)
- }
- }
+type ModuleWithUsesLibrary interface {
+ UsesLibrary() *usesLibrary
}
+
+func (j *Module) UsesLibrary() *usesLibrary {
+ return &j.usesLibrary
+}
+
+var _ ModuleWithUsesLibrary = (*Module)(nil)