diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/base.go | 45 | ||||
| -rw-r--r-- | java/bootclasspath_fragment.go | 20 | ||||
| -rw-r--r-- | java/builder.go | 17 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars.go | 95 | ||||
| -rw-r--r-- | java/dexpreopt_config.go | 8 | ||||
| -rw-r--r-- | java/hiddenapi.go | 1 | ||||
| -rw-r--r-- | java/hiddenapi_modular.go | 209 | ||||
| -rw-r--r-- | java/hiddenapi_monolithic.go | 2 | ||||
| -rw-r--r-- | java/java_test.go | 28 | ||||
| -rw-r--r-- | java/kotlin_test.go | 1 | ||||
| -rw-r--r-- | java/lint.go | 5 | ||||
| -rw-r--r-- | java/platform_bootclasspath.go | 15 | ||||
| -rw-r--r-- | java/platform_bootclasspath_test.go | 112 |
13 files changed, 304 insertions, 254 deletions
diff --git a/java/base.go b/java/base.go index 440b00478..1daa10876 100644 --- a/java/base.go +++ b/java/base.go @@ -155,6 +155,11 @@ type CommonProperties struct { // List of java_plugin modules that provide extra errorprone checks. Extra_check_modules []string + + // Whether to run errorprone on a normal build. If this is false, errorprone + // will still be run if the RUN_ERROR_PRONE environment variable is true. + // Default false. + Enabled *bool } Proto struct { @@ -701,7 +706,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB // javaVersion flag. flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j)) - if ctx.Config().RunErrorProne() { + if ctx.Config().RunErrorProne() || Bool(j.properties.Errorprone.Enabled) { if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil { ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?") } @@ -972,14 +977,23 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 { var extraJarDeps android.Paths - if ctx.Config().RunErrorProne() { - // If error-prone is enabled, add an additional rule to compile the java files into - // a separate set of classes (so that they don't overwrite the normal ones and require - // a rebuild when error-prone is turned off). - // TODO(ccross): Once we always compile with javac9 we may be able to conditionally - // enable error-prone without affecting the output class files. + if Bool(j.properties.Errorprone.Enabled) { + // If error-prone is enabled, enable errorprone flags on the regular + // build. + flags = enableErrorproneFlags(flags) + } else if ctx.Config().RunErrorProne() { + // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create + // a new jar file just for compiling with the errorprone compiler to. + // This is because we don't want to cause the java files to get completely + // rebuilt every time the state of the RUN_ERROR_PRONE variable changes. + // We also don't want to run this if errorprone is enabled by default for + // this module, or else we could have duplicated errorprone messages. + errorproneFlags := enableErrorproneFlags(flags) errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) - RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags) + + transformJavaToClasses(ctx, errorprone, -1, uniqueSrcFiles, srcJars, errorproneFlags, nil, + "errorprone", "errorprone") + extraJarDeps = append(extraJarDeps, errorprone) } @@ -1303,6 +1317,21 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.outputFile = outputFile.WithoutRel() } +// 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 { + flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...) + + if len(flags.errorProneExtraJavacFlags) > 0 { + if len(flags.javacFlags) > 0 { + flags.javacFlags += " " + flags.errorProneExtraJavacFlags + } else { + flags.javacFlags = flags.errorProneExtraJavacFlags + } + } + return flags +} + func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int, srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 1c7ad78ec..fc8f5571e 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -140,7 +140,7 @@ type commonBootclasspathFragment interface { // produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files. // // Updates the supplied hiddenAPIInfo with the paths to the generated files set. - produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput + produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput } var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil) @@ -465,7 +465,7 @@ func (b *BootclasspathFragmentModule) populateApexContentInfoDexJars(ctx android if unencodedDex == nil { // This is an error. Sometimes Soong will report the error directly, other times it will // defer the error reporting to happen only when trying to use the missing file in ninja. - // Either way it is handled by extractBootDexJarsFromHiddenAPIModules which must have been + // Either way it is handled by extractBootDexJarsFromModules which must have been // called before this as it generates the flags that are used to encode these files. continue } @@ -561,12 +561,9 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. // TODO(b/179354495): Stop hidden API processing being conditional once all bootclasspath_fragment // modules have been updated to support it. if input.canPerformHiddenAPIProcessing(ctx, b.properties) { - // Get the content modules that contribute to the hidden API processing. - hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents) - // Delegate the production of the hidden API all-flags.csv file to a module type specific method. common := ctx.Module().(commonBootclasspathFragment) - output = common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, input) + output = common.produceHiddenAPIAllFlagsFile(ctx, contents, input) } // Initialize a HiddenAPIInfo structure. @@ -620,7 +617,7 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files) // for the fragment. -func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { +func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { // Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the // paths to the created files. return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, input) @@ -648,7 +645,8 @@ func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android. } // Copy the dex jars of this fragment's content modules to their predefined locations. - copyBootJarsToPredefinedLocations(ctx, contents, imageConfig.modules, imageConfig.dexPaths) + bootDexJarByModule := extractEncodedDexJarsFromModules(ctx, contents) + copyBootJarsToPredefinedLocations(ctx, bootDexJarByModule, imageConfig.dexPathsByModule) // Build a profile for the image config and then use that to build the boot image. profile := bootImageProfileRule(ctx, imageConfig) @@ -763,7 +761,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android. // Copy manually curated flag files specified on the bootclasspath_fragment. if b.Flag_files_by_category != nil { - for _, category := range hiddenAPIFlagFileCategories { + for _, category := range HiddenAPIFlagFileCategories { paths := b.Flag_files_by_category[category] if len(paths) > 0 { dests := []string{} @@ -772,7 +770,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android. builder.CopyToSnapshot(p, dest) dests = append(dests, dest) } - hiddenAPISet.AddProperty(category.propertyName, dests) + hiddenAPISet.AddProperty(category.PropertyName, dests) } } } @@ -840,7 +838,7 @@ func (module *prebuiltBootclasspathFragmentModule) Name() string { // produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is // specified. -func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput { +func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput { pathForOptionalSrc := func(src *string) android.Path { if src == nil { // TODO(b/179354495): Fail if this is not provided once prebuilts have been updated. diff --git a/java/builder.go b/java/builder.go index cde87310f..ea011b8e1 100644 --- a/java/builder.go +++ b/java/builder.go @@ -279,23 +279,6 @@ func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc) } -func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath, - srcFiles, srcJars android.Paths, flags javaBuilderFlags) { - - flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...) - - if len(flags.errorProneExtraJavacFlags) > 0 { - if len(flags.javacFlags) > 0 { - flags.javacFlags += " " + flags.errorProneExtraJavacFlags - } else { - flags.javacFlags = flags.errorProneExtraJavacFlags - } - } - - transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil, - "errorprone", "errorprone") -} - // Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars // to compile with given set of builder flags, etc. func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx int, diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index e1a36507a..dc8df5ec1 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -15,7 +15,6 @@ package java import ( - "fmt" "path/filepath" "sort" "strings" @@ -254,6 +253,9 @@ type bootImageConfig struct { dexPaths android.WritablePaths // for this image dexPathsDeps android.WritablePaths // for the dependency images and in this image + // Map from module name (without prebuilt_ prefix) to the predefined build path. + dexPathsByModule map[string]android.WritablePath + // File path to a zip archive with all image files (or nil, if not needed). zip android.WritablePath @@ -276,13 +278,24 @@ type bootImageVariant struct { dexLocationsDeps []string // for the dependency images and in this image // Paths to image files. - imagePathOnHost android.OutputPath // first image file path on host - imagePathOnDevice string // first image file path on device - imagesDeps android.OutputPaths // all files + imagePathOnHost android.OutputPath // first image file path on host + imagePathOnDevice string // first image file path on device + + // All the files that constitute this image variant, i.e. .art, .oat and .vdex files. + imagesDeps android.OutputPaths - // Only for extensions, paths to the primary boot images. + // The path to the primary image variant's imagePathOnHost field, where primary image variant + // means the image variant that this extends. + // + // This is only set for a variant of an image that extends another image. primaryImages android.OutputPath + // The paths to the primary image variant's imagesDeps field, where primary image variant + // means the image variant that this extends. + // + // This is only set for a variant of an image that extends another image. + primaryImagesDeps android.Paths + // Rules which should be used in make to install the outputs. installs android.RuleBuilderInstalls vdexInstalls android.RuleBuilderInstalls @@ -450,53 +463,27 @@ func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig return true } -// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to -// predefined paths in the global config. -func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, bootModules []android.Module, bootjars android.ConfiguredJarList, jarPathsPredefined android.WritablePaths) { - jarPaths := make(android.Paths, bootjars.Len()) - for i, module := range bootModules { - if module != nil { - bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath() - jarPaths[i] = bootDexJar - - name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(module)) - if bootjars.Jar(i) != name { - ctx.ModuleErrorf("expected module %s at position %d but found %s", bootjars.Jar(i), i, name) - } - } - } - - // The paths to bootclasspath DEX files need to be known at module GenerateAndroidBuildAction - // time, before the boot images are built (these paths are used in dexpreopt rule generation for - // Java libraries and apps). Generate rules that copy bootclasspath DEX jars to the predefined - // paths. - for i := range jarPaths { - input := jarPaths[i] - output := jarPathsPredefined[i] - module := bootjars.Jar(i) - if input == nil { - if ctx.Config().AllowMissingDependencies() { - apex := bootjars.Apex(i) - - // Create an error rule that pretends to create the output file but will actually fail if it - // is run. - ctx.Build(pctx, android.BuildParams{ - Rule: android.ErrorRule, - Output: output, - Args: map[string]string{ - "error": fmt.Sprintf("missing dependencies: dex jar for %s:%s", module, apex), - }, - }) - } else { - ctx.ModuleErrorf("failed to find a dex jar path for module '%s'"+ - ", note that some jars may be filtered out by module constraints", module) - } - +// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined +// paths in the global config. +func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) { + // Create the super set of module names. + names := []string{} + names = append(names, android.SortedStringKeys(srcBootDexJarsByModule)...) + names = append(names, android.SortedStringKeys(dstBootJarsByModule)...) + names = android.SortedUniqueStrings(names) + for _, name := range names { + src := srcBootDexJarsByModule[name] + dst := dstBootJarsByModule[name] + + if src == nil { + ctx.ModuleErrorf("module %s does not provide a dex boot jar", name) + } else if dst == nil { + ctx.ModuleErrorf("module %s is not part of the boot configuration", name) } else { ctx.Build(pctx, android.BuildParams{ Rule: android.Cp, - Input: input, - Output: output, + Input: src, + Output: dst, }) } } @@ -588,7 +575,15 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p cmd. Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":"). Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":"). - FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage) + // Add the path to the first file in the boot image with the arch specific directory removed, + // dex2oat will reconstruct the path to the actual file when it needs it. As the actual path + // to the file cannot be passed to the command make sure to add the actual path as an Implicit + // dependency to ensure that it is built before the command runs. + FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage). + // Similarly, the dex2oat tool will automatically find the paths to other files in the base + // boot image so make sure to add them as implicit dependencies to ensure that they are built + // before this command is run. + Implicits(image.primaryImagesDeps) } else { // It is a primary image, so it needs a base address. cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress()) diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 39a3e11a5..b13955fba 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -100,6 +100,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { // TODO(b/143682396): use module dependencies instead inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input") c.dexPaths = c.modules.BuildPaths(ctx, inputDir) + c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir) c.dexPathsDeps = c.dexPaths // Create target-specific variants. @@ -125,6 +126,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig { frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...) for i := range targets { frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost + frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths() frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...) } @@ -152,6 +154,9 @@ type updatableBootConfig struct { // later on a singleton adds commands to copy actual jars to the predefined paths. dexPaths android.WritablePaths + // Map from module name (without prebuilt_ prefix) to the predefined build path. + dexPathsByModule map[string]android.WritablePath + // A list of dex locations (a.k.a. on-device paths) to the boot jars. dexLocations []string } @@ -165,10 +170,11 @@ func GetUpdatableBootConfig(ctx android.PathContext) updatableBootConfig { dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "updatable_bootjars") dexPaths := updatableBootJars.BuildPaths(ctx, dir) + dexPathsByModuleName := updatableBootJars.BuildPathsByModule(ctx, dir) dexLocations := updatableBootJars.DevicePaths(ctx.Config(), android.Android) - return updatableBootConfig{updatableBootJars, dexPaths, dexLocations} + return updatableBootConfig{updatableBootJars, dexPaths, dexPathsByModuleName, dexLocations} }).(updatableBootConfig) } diff --git a/java/hiddenapi.go b/java/hiddenapi.go index e9693c68e..f901434a0 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -219,7 +219,6 @@ func buildRuleToGenerateIndex(ctx android.ModuleContext, desc string, classesJar BuiltTool("merge_csv"). Flag("--zip_input"). Flag("--key_field signature"). - FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties"). FlagWithOutput("--output=", indexCSV). Inputs(classesJars) rule.Build(desc, desc) diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index f2649d3c0..643c5cba2 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -248,8 +248,8 @@ type HiddenAPIFlagFileProperties struct { } type hiddenAPIFlagFileCategory struct { - // propertyName is the name of the property for this category. - propertyName string + // PropertyName is the name of the property for this category. + PropertyName string // propertyValueReader retrieves the value of the property for this category from the set of // properties. @@ -262,12 +262,12 @@ type hiddenAPIFlagFileCategory struct { // The flag file category for removed members of the API. // -// This is extracted from hiddenAPIFlagFileCategories as it is needed to add the dex signatures +// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures // list of removed API members that are generated automatically from the removed.txt files provided // by API stubs. var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{ // See HiddenAPIFlagFileProperties.Removed - propertyName: "removed", + PropertyName: "removed", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Removed }, @@ -276,10 +276,10 @@ var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{ }, } -var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ +var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ // See HiddenAPIFlagFileProperties.Unsupported { - propertyName: "unsupported", + PropertyName: "unsupported", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Unsupported }, @@ -290,7 +290,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ hiddenAPIRemovedFlagFileCategory, // See HiddenAPIFlagFileProperties.Max_target_r_low_priority { - propertyName: "max_target_r_low_priority", + PropertyName: "max_target_r_low_priority", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Max_target_r_low_priority }, @@ -300,7 +300,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, // See HiddenAPIFlagFileProperties.Max_target_q { - propertyName: "max_target_q", + PropertyName: "max_target_q", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Max_target_q }, @@ -310,7 +310,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, // See HiddenAPIFlagFileProperties.Max_target_p { - propertyName: "max_target_p", + PropertyName: "max_target_p", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Max_target_p }, @@ -320,7 +320,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, // See HiddenAPIFlagFileProperties.Max_target_o_low_priority { - propertyName: "max_target_o_low_priority", + PropertyName: "max_target_o_low_priority", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Max_target_o_low_priority }, @@ -330,7 +330,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, // See HiddenAPIFlagFileProperties.Blocked { - propertyName: "blocked", + PropertyName: "blocked", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Blocked }, @@ -340,7 +340,7 @@ var hiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ }, // See HiddenAPIFlagFileProperties.Unsupported_packages { - propertyName: "unsupported_packages", + PropertyName: "unsupported_packages", propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string { return properties.Unsupported_packages }, @@ -355,7 +355,7 @@ type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths // append appends the supplied flags files to the corresponding category in this map. func (s FlagFilesByCategory) append(other FlagFilesByCategory) { - for _, category := range hiddenAPIFlagFileCategories { + for _, category := range HiddenAPIFlagFileCategories { s[category] = append(s[category], other[category]...) } } @@ -540,7 +540,7 @@ func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, conten // extractFlagFilesFromProperties extracts the paths to flag files that are specified in the // supplied properties and stores them in this struct. func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) { - for _, category := range hiddenAPIFlagFileCategories { + for _, category := range HiddenAPIFlagFileCategories { paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p)) i.FlagFilesByCategory[category] = paths } @@ -571,6 +571,15 @@ type HiddenAPIFlagOutput struct { AllFlagsPath android.Path } +// bootDexJarByModule is a map from base module name (without prebuilt_ prefix) to the boot dex +// path. +type bootDexJarByModule map[string]android.Path + +// addPath adds the path for a module to the map. +func (b bootDexJarByModule) addPath(module android.Module, path android.Path) { + b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path +} + // pathForValidation creates a path of the same type as the supplied type but with a name of // <path>.valid. // @@ -630,7 +639,7 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st FlagWithOutput("--output ", tempPath) // Add the options for the different categories of flag files. - for _, category := range hiddenAPIFlagFileCategories { + for _, category := range HiddenAPIFlagFileCategories { paths := flagFilesByCategory[category] for _, path := range paths { category.commandMutator(command, path) @@ -670,11 +679,11 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st // * metadata.csv // * index.csv // * all-flags.csv -func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { +func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { hiddenApiSubDir := "modular-hiddenapi" // Gather the dex files for the boot libraries provided by this fragment. - bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents) + bootDexJars := extractBootDexJarsFromModules(ctx, contents) // Generate the stub-flags.csv. stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv") @@ -682,7 +691,7 @@ func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags") // Extract the classes jars from the contents. - classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents) + classesJars := extractClassesJarsFromModules(contents) // Generate the set of flags from the annotations in the source code. annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv") @@ -737,29 +746,18 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedT return android.OptionalPathForPath(output) } -// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents. -func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule { - hiddenAPIModules := []hiddenAPIModule{} - for _, module := range contents { - if hiddenAPI, ok := module.(hiddenAPIModule); ok { - hiddenAPIModules = append(hiddenAPIModules, hiddenAPI) - } else if _, ok := module.(*DexImport); ok { - // Ignore this for the purposes of hidden API processing - } else { - ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module) - } - } - return hiddenAPIModules -} - -// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules. -func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths { +// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules. +func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) android.Paths { bootDexJars := android.Paths{} for _, module := range contents { - bootDexJar := module.bootDexJar() + hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module) + if hiddenAPIModule == nil { + continue + } + bootDexJar := hiddenAPIModule.bootDexJar() if bootDexJar == nil { if ctx.Config().AlwaysUsePrebuiltSdks() { - // TODO(b/179354495): Remove this work around when it is unnecessary. + // TODO(b/179354495): Remove this workaround when it is unnecessary. // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So, // create a fake one that will cause a build error only if it is used. fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name()) @@ -784,11 +782,142 @@ func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents return bootDexJars } -// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules. -func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths { +func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule { + if hiddenAPIModule, ok := module.(hiddenAPIModule); ok { + return hiddenAPIModule + } else if _, ok := module.(*DexImport); ok { + // Ignore this for the purposes of hidden API processing + } else { + ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module) + } + + return nil +} + +// extractClassesJarsFromModules extracts the class jars from the supplied modules. +func extractClassesJarsFromModules(contents []android.Module) android.Paths { classesJars := android.Paths{} for _, module := range contents { - classesJars = append(classesJars, module.classesJars()...) + classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...) } return classesJars } + +// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module. +func retrieveClassesJarsFromModule(module android.Module) android.Paths { + if hiddenAPIModule, ok := module.(hiddenAPIModule); ok { + return hiddenAPIModule.classesJars() + } + + return nil +} + +// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by +// Soong but should instead only be reported in ninja if the file is actually built. +func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool { + // TODO(b/179354495): Remove this workaround when it is unnecessary. + // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So, + // create a fake one that will cause a build error only if it is used. + if ctx.Config().AlwaysUsePrebuiltSdks() { + return true + } + + // This is called for both platform_bootclasspath and bootclasspath_fragment modules. + // + // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules. + // Ideally, a bootclasspath_fragment module should never have a platform variant created for it + // but unfortunately, due to b/187910671 it does. + // + // That causes issues when obtaining a boot dex jar for a prebuilt module as a prebuilt module + // used by a bootclasspath_fragment can only provide a boot dex jar when it is part of APEX, i.e. + // has an APEX variant not a platform variant. + // + // There are some other situations when a prebuilt module used by a bootclasspath_fragment cannot + // provide a boot dex jar: + // 1. If the bootclasspath_fragment is not exported by the prebuilt_apex/apex_set module then it + // does not have an APEX variant and only has a platform variant and neither do its content + // modules. + // 2. Some build configurations, e.g. setting TARGET_BUILD_USE_PREBUILT_SDKS causes all + // java_sdk_library_import modules to be treated as preferred and as many of them are not part + // of an apex they cannot provide a boot dex jar. + // + // The first case causes problems when the affected prebuilt modules are preferred but that is an + // invalid configuration and it is ok for it to fail as the work to enable that is not yet + // complete. The second case is used for building targets that do not use boot dex jars and so + // deferring error reporting to ninja is fine as the affected ninja targets should never be built. + // That is handled above. + // + // A platform_bootclasspath module can use libraries from both platform and APEX variants. Unlike + // the bootclasspath_fragment it supports dex_import modules which provides the dex file. So, it + // can obtain a boot dex jar from a prebuilt that is not part of an APEX. However, it is assumed + // that if the library can be part of an APEX then it is the APEX variant that is used. + // + // This check handles the slightly different requirements of the bootclasspath_fragment and + // platform_bootclasspath modules by only deferring error reporting for the platform variant of + // a prebuilt modules that has other variants which are part of an APEX. + // + // TODO(b/187910671): Remove this once platform variants are no longer created unnecessarily. + if android.IsModulePrebuilt(module) { + if am, ok := module.(android.ApexModule); ok && am.InAnyApex() { + apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) + if apexInfo.IsForPlatform() { + return true + } + } + } + + // A bootclasspath module that is part of a versioned sdk never provides a boot dex jar as there + // is no equivalently versioned prebuilt APEX file from which it can be obtained. However, + // versioned bootclasspath modules are processed by Soong so in order to avoid them causing build + // failures missing boot dex jars need to be deferred. + if android.IsModuleInVersionedSdk(ctx.Module()) { + return true + } + + return false +} + +// handleMissingDexBootFile will either log a warning or create an error rule to create the fake +// file depending on the value returned from deferReportingMissingBootDexJar. +func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath) { + if deferReportingMissingBootDexJar(ctx, module) { + // Create an error rule that pretends to create the output file but will actually fail if it + // is run. + ctx.Build(pctx, android.BuildParams{ + Rule: android.ErrorRule, + Output: fake, + Args: map[string]string{ + "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module), + }, + }) + } else { + ctx.ModuleErrorf("module %s does not provide a dex jar", module) + } +} + +// retrieveEncodedBootDexJarFromModule returns a path to the boot dex jar from the supplied module's +// DexJarBuildPath() method. +// +// The returned path will usually be to a dex jar file that has been encoded with hidden API flags. +// However, under certain conditions, e.g. errors, or special build configurations it will return +// a path to a fake file. +func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path { + bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath() + if bootDexJar == nil { + fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name())) + bootDexJar = fake + + handleMissingDexBootFile(ctx, module, fake) + } + return bootDexJar +} + +// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules. +func extractEncodedDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule { + encodedDexJarsByModuleName := bootDexJarByModule{} + for _, module := range contents { + path := retrieveEncodedBootDexJarFromModule(ctx, module) + encodedDexJarsByModuleName.addPath(module, path) + } + return encodedDexJarsByModuleName +} diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go index a6bf8c705..edf42351f 100644 --- a/java/hiddenapi_monolithic.go +++ b/java/hiddenapi_monolithic.go @@ -99,4 +99,4 @@ func (i *MonolithicHiddenAPIInfo) dedup() { i.AllFlagsPaths = android.FirstUniquePaths(i.AllFlagsPaths) } -var monolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{}) +var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{}) diff --git a/java/java_test.go b/java/java_test.go index bd373c177..78d9ab4c7 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1392,3 +1392,31 @@ func TestDefaultInstallable(t *testing.T) { assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true), module.properties.Installable) } + +func TestErrorproneEnabled(t *testing.T) { + ctx, _ := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + errorprone: { + enabled: true, + }, + } + `) + + javac := ctx.ModuleForTests("foo", "android_common").Description("javac") + + // Test that the errorprone plugins are passed to javac + expectedSubstring := "-Xplugin:ErrorProne" + if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) { + t.Errorf("expected javacFlags to conain %q, got %q", expectedSubstring, javac.Args["javacFlags"]) + } + + // Modules with errorprone { enabled: true } will include errorprone checks + // in the main javac build rule. Only when RUN_ERROR_PRONE is true will + // the explicit errorprone build rule be created. + errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone") + if errorprone.RuleParams.Description != "" { + t.Errorf("expected errorprone build rule to not exist, but it did") + } +} diff --git a/java/kotlin_test.go b/java/kotlin_test.go index 1c146a192..fd2f3ca61 100644 --- a/java/kotlin_test.go +++ b/java/kotlin_test.go @@ -185,7 +185,6 @@ func TestKapt(t *testing.T) { buildOS := android.BuildOs.String() kapt := result.ModuleForTests("foo", "android_common").Rule("kapt") - //kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc") javac := result.ModuleForTests("foo", "android_common").Description("javac") errorprone := result.ModuleForTests("foo", "android_common").Description("errorprone") diff --git a/java/lint.go b/java/lint.go index 9f769dfe3..1511cfe26 100644 --- a/java/lint.go +++ b/java/lint.go @@ -361,10 +361,7 @@ func (l *linter) lint(ctx android.ModuleContext) { Labels: map[string]string{"type": "tool", "name": "lint"}, ExecStrategy: lintRBEExecStrategy(ctx), ToolchainInputs: []string{config.JavaCmd(ctx).String()}, - EnvironmentVariables: []string{ - "LANG", - }, - Platform: map[string]string{remoteexec.PoolKey: pool}, + Platform: map[string]string{remoteexec.PoolKey: pool}, }) } diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 87c695cb5..fba73d0c1 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -280,7 +280,6 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. } monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments) - // Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile input := newHiddenAPIFlagInput() @@ -291,16 +290,14 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. // Use the flag files from this module and all the fragments. input.FlagFilesByCategory = monolithicInfo.FlagsFilesByCategory - hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules) - // Generate the monolithic stub-flags.csv file. - bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules) + bootDexJars := extractBootDexJarsFromModules(ctx, modules) stubFlags := hiddenAPISingletonPaths(ctx).stubFlags rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, input) rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags") // Extract the classes jars from the contents. - classesJars := extractClassJarsFromHiddenAPIModules(ctx, hiddenAPIModules) + classesJars := extractClassesJarsFromModules(modules) // Generate the annotation-flags.csv file from all the module annotations. annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv") @@ -342,7 +339,7 @@ func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ct monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments) // Store the information for testing. - ctx.SetProvider(monolithicHiddenAPIInfoProvider, monolithicInfo) + ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo) return monolithicInfo } @@ -390,11 +387,13 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android. generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules) // Copy non-updatable module dex jars to their predefined locations. - copyBootJarsToPredefinedLocations(ctx, nonUpdatableModules, imageConfig.modules, imageConfig.dexPaths) + nonUpdatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, nonUpdatableModules) + copyBootJarsToPredefinedLocations(ctx, nonUpdatableBootDexJarsByModule, imageConfig.dexPathsByModule) // Copy updatable module dex jars to their predefined locations. config := GetUpdatableBootConfig(ctx) - copyBootJarsToPredefinedLocations(ctx, updatableModules, config.modules, config.dexPaths) + updatableBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, updatableModules) + copyBootJarsToPredefinedLocations(ctx, updatableBootDexJarsByModule, config.dexPathsByModule) // Build a profile for the image config and then use that to build the boot image. profile := bootImageProfileRule(ctx, imageConfig) diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go index ed5549d35..0318a07d4 100644 --- a/java/platform_bootclasspath_test.go +++ b/java/platform_bootclasspath_test.go @@ -15,8 +15,6 @@ package java import ( - "fmt" - "strings" "testing" "android/soong/android" @@ -152,116 +150,6 @@ func TestPlatformBootclasspath(t *testing.T) { }) } -func TestPlatformBootclasspath_Fragments(t *testing.T) { - result := android.GroupFixturePreparers( - prepareForTestWithPlatformBootclasspath, - PrepareForTestWithJavaSdkLibraryFiles, - FixtureWithLastReleaseApis("foo"), - android.FixtureWithRootAndroidBp(` - platform_bootclasspath { - name: "platform-bootclasspath", - fragments: [ - {module:"bar-fragment"}, - ], - hidden_api: { - unsupported: [ - "unsupported.txt", - ], - removed: [ - "removed.txt", - ], - max_target_r_low_priority: [ - "max-target-r-low-priority.txt", - ], - max_target_q: [ - "max-target-q.txt", - ], - max_target_p: [ - "max-target-p.txt", - ], - max_target_o_low_priority: [ - "max-target-o-low-priority.txt", - ], - blocked: [ - "blocked.txt", - ], - unsupported_packages: [ - "unsupported-packages.txt", - ], - }, - } - - bootclasspath_fragment { - name: "bar-fragment", - contents: ["bar"], - api: { - stub_libs: ["foo"], - }, - hidden_api: { - unsupported: [ - "bar-unsupported.txt", - ], - removed: [ - "bar-removed.txt", - ], - max_target_r_low_priority: [ - "bar-max-target-r-low-priority.txt", - ], - max_target_q: [ - "bar-max-target-q.txt", - ], - max_target_p: [ - "bar-max-target-p.txt", - ], - max_target_o_low_priority: [ - "bar-max-target-o-low-priority.txt", - ], - blocked: [ - "bar-blocked.txt", - ], - unsupported_packages: [ - "bar-unsupported-packages.txt", - ], - }, - } - - java_library { - name: "bar", - srcs: ["a.java"], - system_modules: "none", - sdk_version: "none", - compile_dex: true, - } - - java_sdk_library { - name: "foo", - srcs: ["a.java"], - public: { - enabled: true, - }, - compile_dex: true, - } - `), - ).RunTest(t) - - pbcp := result.Module("platform-bootclasspath", "android_common") - info := result.ModuleProvider(pbcp, monolithicHiddenAPIInfoProvider).(MonolithicHiddenAPIInfo) - - for _, category := range hiddenAPIFlagFileCategories { - name := category.propertyName - message := fmt.Sprintf("category %s", name) - filename := strings.ReplaceAll(name, "_", "-") - expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)} - android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category]) - } - - android.AssertPathsRelativeToTopEquals(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/stub-flags.csv"}, info.StubFlagsPaths) - android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths) - android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/metadata.csv"}, info.MetadataPaths) - android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/index.csv"}, info.IndexPaths) - android.AssertPathsRelativeToTopEquals(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common/modular-hiddenapi/all-flags.csv"}, info.AllFlagsPaths) -} - func TestPlatformBootclasspathVariant(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, |