Merge "Add a build flag to always enable errorprone per-target"
diff --git a/android/config.go b/android/config.go
index da78c7a..ed90c31 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1690,6 +1690,16 @@
return paths
}
+// BuildPathsByModule returns a map from module name to build paths based on the given directory
+// prefix.
+func (l *ConfiguredJarList) BuildPathsByModule(ctx PathContext, dir OutputPath) map[string]WritablePath {
+ paths := map[string]WritablePath{}
+ for _, jar := range l.jars {
+ paths[jar] = dir.Join(ctx, ModuleStem(jar)+".jar")
+ }
+ return paths
+}
+
// UnmarshalJSON converts JSON configuration from raw bytes into a
// ConfiguredJarList structure.
func (l *ConfiguredJarList) UnmarshalJSON(b []byte) error {
diff --git a/android/testing.go b/android/testing.go
index 191cb8d..b36f62c 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -713,9 +713,11 @@
func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
var searchedRules []string
- for _, p := range b.provider.BuildParamsForTests() {
- searchedRules = append(searchedRules, p.Rule.String())
- if strings.Contains(p.Rule.String(), rule) {
+ buildParams := b.provider.BuildParamsForTests()
+ for _, p := range buildParams {
+ ruleAsString := p.Rule.String()
+ searchedRules = append(searchedRules, ruleAsString)
+ if strings.Contains(ruleAsString, rule) {
return b.newTestingBuildParams(p), searchedRules
}
}
@@ -725,7 +727,7 @@
func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
p, searchRules := b.maybeBuildParamsFromRule(rule)
if p.Rule == nil {
- panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
+ panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
}
return p
}
diff --git a/apex/apex.go b/apex/apex.go
index 926085b..33b83c0 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -170,9 +170,10 @@
// Default is false.
Ignore_system_library_special_case *bool
- // Whenever apex_payload.img of the APEX should include dm-verity hashtree. Should be only
- // used in tests.
- Test_only_no_hashtree *bool
+ // Whenever apex_payload.img of the APEX should include dm-verity hashtree.
+ // Default value is false.
+ // TODO(b/190621617): change default value to true.
+ Generate_hashtree *bool
// Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only
// used in tests.
@@ -1317,9 +1318,9 @@
return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable))
}
-// See the test_only_no_hashtree property
-func (a *apexBundle) testOnlyShouldSkipHashtreeGeneration() bool {
- return proptools.Bool(a.properties.Test_only_no_hashtree)
+// See the generate_hashtree property
+func (a *apexBundle) shouldGenerateHashtree() bool {
+ return proptools.BoolDefault(a.properties.Generate_hashtree, false)
}
// See the test_only_unsigned_payload property
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 6a7c35c..1bfe7e9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4769,7 +4769,7 @@
// prebuilt_apex module always depends on the prebuilt, and so it doesn't
// find the dex boot jar in it. We either need to disable the source libfoo
// or make the prebuilt libfoo preferred.
- testDexpreoptWithApexes(t, bp, "failed to find a dex jar path for module 'libfoo'", preparer)
+ testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer)
})
t.Run("prebuilt library preferred with source", func(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 021e499..24c049b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -630,11 +630,7 @@
optFlags = append(optFlags, "--assets_dir "+filepath.Dir(a.mergedNotices.HtmlGzOutput.String()))
}
- if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && ctx.ModuleDir() != "system/apex/shim/build" && a.testOnlyShouldSkipHashtreeGeneration() {
- ctx.PropertyErrorf("test_only_no_hashtree", "not available")
- return
- }
- if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) || a.testOnlyShouldSkipHashtreeGeneration()) && !compressionEnabled {
+ if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) && !a.shouldGenerateHashtree()) && !compressionEnabled {
// Apexes which are supposed to be installed in builtin dirs(/system, etc)
// don't need hashtree for activation. Therefore, by removing hashtree from
// apex bundle (filesystem image in it, to be specific), we can save storage.
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 4aaf3d4..fc8f557 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -140,7 +140,7 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
}
// 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)
@@ -840,7 +838,7 @@
// 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/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index e1a3650..dc8df5e 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 @@
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 @@
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
- // Only for extensions, paths to the primary boot images.
+ // All the files that constitute this image variant, i.e. .art, .oat and .vdex files.
+ imagesDeps android.OutputPaths
+
+ // 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 @@
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
+// 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]
- 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)
- }
-
+ 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 @@
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 39a3e11..b13955f 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -100,6 +100,7 @@
// 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 @@
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 @@
// 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 @@
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_modular.go b/java/hiddenapi_modular.go
index 54effa9..643c5cb 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -571,6 +571,15 @@
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.
//
@@ -670,11 +679,11 @@
// * 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 @@
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 @@
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 @@
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/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 7d1e53f..fba73d0 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -290,16 +290,14 @@
// 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")
@@ -389,11 +387,13 @@
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)