Merge changes I957f3df8,I68986dcc
* changes:
Consolidate the code to resolve a deapexer module dependency.
Propagate the dex jar path as an OptionalPath which is either valid or invalid with a message.
diff --git a/android/deapexer.go b/android/deapexer.go
index 9290481..bed6574 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -69,6 +69,8 @@
// The information exported by the `deapexer` module, access it using `DeapxerInfoProvider`.
type DeapexerInfo struct {
+ apexModuleName string
+
// map from the name of an exported file from a prebuilt_apex to the path to that file. The
// exported file name is the apex relative path, e.g. javalib/core-libart.jar.
//
@@ -76,6 +78,11 @@
exports map[string]WritablePath
}
+// ApexModuleName returns the name of the APEX module that provided the info.
+func (i DeapexerInfo) ApexModuleName() string {
+ return i.apexModuleName
+}
+
// PrebuiltExportPath provides the path, or nil if not available, of a file exported from the
// prebuilt_apex that created this ApexInfo.
//
@@ -95,9 +102,10 @@
// for use with a prebuilt_apex module.
//
// See apex/deapexer.go for more information.
-func NewDeapexerInfo(exports map[string]WritablePath) DeapexerInfo {
+func NewDeapexerInfo(apexModuleName string, exports map[string]WritablePath) DeapexerInfo {
return DeapexerInfo{
- exports: exports,
+ apexModuleName: apexModuleName,
+ exports: exports,
}
}
@@ -133,3 +141,20 @@
// Method that differentiates this interface from others.
RequiresFilesFromPrebuiltApex()
}
+
+// FindDeapexerProviderForModule searches through the direct dependencies of the current context
+// module for a DeapexerTag dependency and returns its DeapexerInfo. If there is an error then it is
+// reported with ctx.ModuleErrorf and nil is returned.
+func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo {
+ var di *DeapexerInfo
+ ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
+ p := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo)
+ di = &p
+ })
+ if di != nil {
+ return di
+ }
+ ai := ctx.Provider(ApexInfoProvider).(ApexInfo)
+ ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
+ return nil
+}
diff --git a/apex/apex.go b/apex/apex.go
index 2d153e2..5294b6c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1545,7 +1545,7 @@
type javaModule interface {
android.Module
BaseModuleName() string
- DexJarBuildPath() android.Path
+ DexJarBuildPath() java.OptionalDexJarPath
JacocoReportClassesFile() android.Path
LintDepSets() java.LintDepSets
Stem() string
@@ -1559,7 +1559,7 @@
// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile {
- return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath())
+ return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath().PathOrNil())
}
// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2a2a1f4..420489e 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4799,9 +4799,10 @@
transform := android.NullFixturePreparer
checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
+ t.Helper()
// Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarBuildPath()
+ dexJarBuildPath := p.DexJarBuildPath().PathOrNil()
stem := android.RemoveOptionalPrebuiltPrefix(name)
android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
@@ -4809,6 +4810,7 @@
}
checkDexJarInstallPath := func(t *testing.T, ctx *android.TestContext, name string) {
+ t.Helper()
// Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
dexJarBuildPath := p.DexJarInstallPath()
@@ -4819,6 +4821,7 @@
}
ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) {
+ t.Helper()
// Make sure that an apex variant is not created for the source module.
android.AssertArrayString(t, "Check if there is no source variant",
[]string{"android_common"},
@@ -4856,8 +4859,11 @@
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
+ deapexerName := deapexerModuleName("myapex")
+ android.AssertStringEquals(t, "APEX module name from deapexer name", "myapex", apexModuleName(deapexerName))
+
// Make sure that the deapexer has the correct input APEX.
- deapexer := ctx.ModuleForTests("myapex.deapexer", "android_common")
+ deapexer := ctx.ModuleForTests(deapexerName, "android_common")
rule := deapexer.Rule("deapexer")
if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) {
t.Errorf("expected: %q, found: %q", expected, actual)
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 3e19014..cb7d3d1 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -22,6 +22,7 @@
"android/soong/android"
"android/soong/java"
+
"github.com/google/blueprint/proptools"
)
@@ -737,7 +738,7 @@
func getDexJarPath(result *android.TestResult, name string) string {
module := result.Module(name, "android_common")
- return module.(java.UsesLibraryDependency).DexJarBuildPath().RelativeToTop().String()
+ return module.(java.UsesLibraryDependency).DexJarBuildPath().Path().RelativeToTop().String()
}
// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 2c1835a..8c9030a 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -15,6 +15,8 @@
package apex
import (
+ "strings"
+
"android/soong/android"
)
@@ -75,6 +77,17 @@
inputApex android.Path
}
+// Returns the name of the deapexer module corresponding to an APEX module with the given name.
+func deapexerModuleName(apexModuleName string) string {
+ return apexModuleName + ".deapexer"
+}
+
+// Returns the name of the APEX module corresponding to an deapexer module with
+// the given name. This reverses deapexerModuleName.
+func apexModuleName(deapexerModuleName string) string {
+ return strings.TrimSuffix(deapexerModuleName, ".deapexer")
+}
+
func privateDeapexerFactory() android.Module {
module := &Deapexer{}
module.AddProperties(&module.properties, &module.selectedApexProperties)
@@ -113,7 +126,8 @@
// apex relative path to extracted file path available for other modules.
if len(exports) > 0 {
// Make the information available for other modules.
- ctx.SetProvider(android.DeapexerProvider, android.NewDeapexerInfo(exports))
+ di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports)
+ ctx.SetProvider(android.DeapexerProvider, di)
// Create a sorted list of the files that this exports.
exportedPaths = android.SortedUniquePaths(exportedPaths)
@@ -131,6 +145,6 @@
for _, p := range exportedPaths {
command.Output(p.(android.WritablePath))
}
- builder.Build("deapexer", "deapex "+ctx.ModuleName())
+ builder.Build("deapexer", "deapex "+apexModuleName(ctx.ModuleName()))
}
}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 4833a64..d59f8bf 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -176,13 +176,15 @@
name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child))
if java.IsBootclasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag {
// If the exported java module provides a dex jar path then add it to the list of apexFiles.
- path := child.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
- if path != nil {
+ path := child.(interface {
+ DexJarBuildPath() java.OptionalDexJarPath
+ }).DexJarBuildPath()
+ if path.IsSet() {
af := apexFile{
module: child,
moduleDir: ctx.OtherModuleDir(child),
androidMkModuleName: name,
- builtFile: path,
+ builtFile: path.Path(),
class: javaSharedLib,
}
if module, ok := child.(java.DexpreopterInterface); ok {
@@ -629,10 +631,6 @@
)
}
-func deapexerModuleName(baseModuleName string) string {
- return baseModuleName + ".deapexer"
-}
-
func apexSelectorModuleName(baseModuleName string) string {
return baseModuleName + ".apex.selector"
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 71370c9..1914595 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -29,8 +29,8 @@
if hostDexNeeded {
var output android.Path
- if library.dexJarFile != nil {
- output = library.dexJarFile
+ if library.dexJarFile.IsSet() {
+ output = library.dexJarFile.Path()
} else {
output = library.implementationAndResourcesJar
}
@@ -44,8 +44,8 @@
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_IS_HOST_MODULE", true)
entries.SetPath("LOCAL_PREBUILT_MODULE_FILE", output)
- if library.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
+ if library.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile.Path())
}
entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
@@ -106,8 +106,8 @@
if library.installFile == nil {
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
}
- if library.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
+ if library.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile.Path())
}
if len(library.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
@@ -207,8 +207,8 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
- if prebuilt.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
+ if prebuilt.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path())
}
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
@@ -227,12 +227,12 @@
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.dexJarFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.dexJarFile.Path()),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- if prebuilt.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
+ if prebuilt.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile.Path())
}
if len(prebuilt.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", prebuilt.dexpreopter.builtInstalled)
@@ -279,8 +279,8 @@
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
- if binary.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile)
+ if binary.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile.Path())
}
if len(binary.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
@@ -336,8 +336,8 @@
entries.SetString("LOCAL_MODULE", app.installApkName)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage)
- if app.dexJarFile != nil {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile)
+ if app.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile.Path())
}
if app.implementationAndResourcesJar != nil {
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", app.implementationAndResourcesJar)
diff --git a/java/app.go b/java/app.go
index a62e442..2fd6463 100755
--- a/java/app.go
+++ b/java/app.go
@@ -476,7 +476,7 @@
a.Module.compile(ctx, a.aaptSrcJar)
}
- return a.dexJarFile
+ return a.dexJarFile.PathOrNil()
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
@@ -1305,7 +1305,8 @@
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, tag.implicit,
- lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
+ lib.DexJarBuildPath().PathOrNil(), lib.DexJarInstallPath(),
+ lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
} else {
diff --git a/java/base.go b/java/base.go
index 78aaa19..579085b 100644
--- a/java/base.go
+++ b/java/base.go
@@ -276,6 +276,87 @@
return false
}
+// OptionalDexJarPath can be either unset, hold a valid path to a dex jar file,
+// or an invalid path describing the reason it is invalid.
+//
+// It is unset if a dex jar isn't applicable, i.e. no build rule has been
+// requested to create one.
+//
+// If a dex jar has been requested to be built then it is set, and it may be
+// either a valid android.Path, or invalid with a reason message. The latter
+// happens if the source that should produce the dex file isn't able to.
+//
+// E.g. it is invalid with a reason message if there is a prebuilt APEX that
+// could produce the dex jar through a deapexer module, but the APEX isn't
+// installable so doing so wouldn't be safe.
+type OptionalDexJarPath struct {
+ isSet bool
+ path android.OptionalPath
+}
+
+// IsSet returns true if a path has been set, either invalid or valid.
+func (o OptionalDexJarPath) IsSet() bool {
+ return o.isSet
+}
+
+// Valid returns true if there is a path that is valid.
+func (o OptionalDexJarPath) Valid() bool {
+ return o.isSet && o.path.Valid()
+}
+
+// Path returns the valid path, or panics if it's either not set or is invalid.
+func (o OptionalDexJarPath) Path() android.Path {
+ if !o.isSet {
+ panic("path isn't set")
+ }
+ return o.path.Path()
+}
+
+// PathOrNil returns the path if it's set and valid, or else nil.
+func (o OptionalDexJarPath) PathOrNil() android.Path {
+ if o.Valid() {
+ return o.Path()
+ }
+ return nil
+}
+
+// InvalidReason returns the reason for an invalid path, which is never "". It
+// returns "" for an unset or valid path.
+func (o OptionalDexJarPath) InvalidReason() string {
+ if !o.isSet {
+ return ""
+ }
+ return o.path.InvalidReason()
+}
+
+func (o OptionalDexJarPath) String() string {
+ if !o.isSet {
+ return "<unset>"
+ }
+ return o.path.String()
+}
+
+// makeUnsetDexJarPath returns an unset OptionalDexJarPath.
+func makeUnsetDexJarPath() OptionalDexJarPath {
+ return OptionalDexJarPath{isSet: false}
+}
+
+// makeDexJarPathFromOptionalPath returns an OptionalDexJarPath that is set with
+// the given OptionalPath, which may be valid or invalid.
+func makeDexJarPathFromOptionalPath(path android.OptionalPath) OptionalDexJarPath {
+ return OptionalDexJarPath{isSet: true, path: path}
+}
+
+// makeDexJarPathFromPath returns an OptionalDexJarPath that is set with the
+// valid given path. It returns an unset OptionalDexJarPath if the given path is
+// nil.
+func makeDexJarPathFromPath(path android.Path) OptionalDexJarPath {
+ if path == nil {
+ return makeUnsetDexJarPath()
+ }
+ return makeDexJarPathFromOptionalPath(android.OptionalPathForPath(path))
+}
+
// Module contains the properties and members used by all java module types
type Module struct {
android.ModuleBase
@@ -310,7 +391,7 @@
implementationAndResourcesJar android.Path
// output file containing classes.dex and resources
- dexJarFile android.Path
+ dexJarFile OptionalDexJarPath
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
@@ -1265,12 +1346,13 @@
}
// Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexOutputFile, j.implementationJarFile, j.dexProperties.Uncompress_dex)
+
+ j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), j.implementationJarFile, j.dexProperties.Uncompress_dex)
// Encode hidden API flags in dex file, if needed.
dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
- j.dexJarFile = dexOutputFile
+ j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
j.dexpreopt(ctx, dexOutputFile)
@@ -1280,7 +1362,7 @@
// There is no code to compile into a dex jar, make sure the resources are propagated
// to the APK if this is an app.
outputFile = implementationAndResourcesJar
- j.dexJarFile = j.resourceJar
+ j.dexJarFile = makeDexJarPathFromPath(j.resourceJar)
}
if ctx.Failed() {
@@ -1470,7 +1552,7 @@
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJarBuildPath() android.Path {
+func (j *Module) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index b13e2db..79c73ca 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -954,23 +954,11 @@
return nil
}
- var deapexerModule android.Module
- ctx.VisitDirectDeps(func(module android.Module) {
- tag := ctx.OtherModuleDependencyTag(module)
- // Save away the `deapexer` module on which this depends, if any.
- if tag == android.DeapexerTag {
- deapexerModule = module
- }
- })
-
- if deapexerModule == nil {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // deapexer module has been configured to export the dex implementation jar for this module.
- ctx.ModuleErrorf("internal error: module does not depend on a `deapexer` module")
- return nil
+ di := android.FindDeapexerProviderForModule(ctx)
+ if di == nil {
+ return nil // An error has been reported by FindDeapexerProviderForModule.
}
- di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
files := bootImageFilesByArch{}
for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 30683da..7c8be1e 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -30,14 +30,14 @@
// that information encoded within it.
active bool
- // The path to the dex jar that is in the boot class path. If this is nil then the associated
+ // The path to the dex jar that is in the boot class path. If this is unset then the associated
// module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
// annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
// themselves.
//
// This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
- bootDexJarPath android.Path
+ bootDexJarPath OptionalDexJarPath
// The paths to the classes jars that contain classes and class members annotated with
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
@@ -49,7 +49,7 @@
uncompressDexState *bool
}
-func (h *hiddenAPI) bootDexJar() android.Path {
+func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
return h.bootDexJarPath
}
@@ -68,7 +68,7 @@
}
type hiddenAPIIntf interface {
- bootDexJar() android.Path
+ bootDexJar() OptionalDexJarPath
classesJars() android.Paths
uncompressDex() *bool
}
@@ -79,7 +79,7 @@
//
// uncompressedDexState should be nil when the module is a prebuilt and so does not require hidden
// API encoding.
-func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar, classesJar android.Path, uncompressedDexState *bool) {
+func (h *hiddenAPI) initHiddenAPI(ctx android.ModuleContext, dexJar OptionalDexJarPath, classesJar android.Path, uncompressedDexState *bool) {
// Save the classes jars even if this is not active as they may be used by modular hidden API
// processing.
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 1c6fbac..b9a1ca7 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -19,6 +19,7 @@
"strings"
"android/soong/android"
+
"github.com/google/blueprint"
)
@@ -277,7 +278,7 @@
// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
- var dexJar android.Path
+ var dexJar OptionalDexJarPath
if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
} else if j, ok := module.(UsesLibraryDependency); ok {
@@ -287,10 +288,11 @@
return nil
}
- if dexJar == nil {
- ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
+ if !dexJar.Valid() {
+ ctx.ModuleErrorf("dependency %s does not provide a dex jar: %s", module, dexJar.InvalidReason())
+ return nil
}
- return dexJar
+ return dexJar.Path()
}
// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
@@ -1159,18 +1161,17 @@
// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule.
//
-// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is nil, then that
-// create a fake path and either report an error immediately or defer reporting of the error until
-// the path is actually used.
+// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is unset or
+// invalid, then create a fake path and either report an error immediately or defer reporting of the
+// error until the path is actually used.
func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
bootDexJar := module.bootDexJar()
- if bootDexJar == nil {
+ if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
- bootDexJar = fake
-
- handleMissingDexBootFile(ctx, module, fake)
+ handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
+ return fake
}
- return bootDexJar
+ return bootDexJar.Path()
}
// extractClassesJarsFromModules extracts the class jars from the supplied modules.
@@ -1264,7 +1265,7 @@
// 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) {
+func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module, fake android.WritablePath, reason string) {
if deferReportingMissingBootDexJar(ctx, module) {
// Create an error rule that pretends to create the output file but will actually fail if it
// is run.
@@ -1272,11 +1273,11 @@
Rule: android.ErrorRule,
Output: fake,
Args: map[string]string{
- "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module),
+ "error": fmt.Sprintf("missing boot dex jar dependency for %s: %s", module, reason),
},
})
} else {
- ctx.ModuleErrorf("module %s does not provide a dex jar", module)
+ ctx.ModuleErrorf("module %s does not provide a dex jar: %s", module, reason)
}
}
@@ -1287,14 +1288,13 @@
// 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 {
+ bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath()
+ if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
- bootDexJar = fake
-
- handleMissingDexBootFile(ctx, module, fake)
+ handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
+ return fake
}
- return bootDexJar
+ return bootDexJar.Path()
}
// extractEncodedDexJarsFromModules extracts the encoded dex jars from the supplied modules.
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index dcd363c..75b7bb7 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -20,6 +20,7 @@
"testing"
"android/soong/android"
+
"github.com/google/blueprint/proptools"
)
@@ -306,7 +307,7 @@
android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
// Make sure that the encoded dex jar is the exported one.
- exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath()
+ exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath().Path()
android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
}
diff --git a/java/java.go b/java/java.go
index 4a44866..b2c1999 100644
--- a/java/java.go
+++ b/java/java.go
@@ -219,7 +219,7 @@
// Provides build path and install path to DEX jars.
type UsesLibraryDependency interface {
- DexJarBuildPath() android.Path
+ DexJarBuildPath() OptionalDexJarPath
DexJarInstallPath() android.Path
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
@@ -1215,7 +1215,7 @@
properties ImportProperties
// output file containing classes.dex and resources
- dexJarFile android.Path
+ dexJarFile OptionalDexJarPath
dexJarInstallFile android.Path
combinedClasspathFile android.Path
@@ -1319,7 +1319,6 @@
j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
var flags javaBuilderFlags
- var deapexerModule android.Module
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
@@ -1340,11 +1339,6 @@
}
addCLCFromDep(ctx, module, j.classLoaderContexts)
-
- // Save away the `deapexer` module on which this depends, if any.
- if tag == android.DeapexerTag {
- deapexerModule = module
- }
})
if Bool(j.properties.Installable) {
@@ -1359,26 +1353,22 @@
// obtained from the associated deapexer module.
ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if ai.ForPrebuiltApex {
- if deapexerModule == nil {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // deapexer module has been configured to export the dex implementation jar for this module.
- ctx.ModuleErrorf("internal error: module %q does not depend on a `deapexer` module for prebuilt_apex %q",
- j.Name(), ai.ApexVariationName)
- return
- }
-
// Get the path of the dex implementation jar from the `deapexer` module.
- di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
+ di := android.FindDeapexerProviderForModule(ctx)
+ if di == nil {
+ return // An error has been reported by FindDeapexerProviderForModule.
+ }
if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil {
- j.dexJarFile = dexOutputPath
+ dexJarFile := makeDexJarPathFromPath(dexOutputPath)
+ j.dexJarFile = dexJarFile
j.dexJarInstallFile = android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
// Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexOutputPath, outputFile, nil)
+ j.initHiddenAPI(ctx, dexJarFile, outputFile, nil)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt_apex %q", deapexerModule.Name())
+ ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
}
} else if Bool(j.dexProperties.Compile_dex) {
sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
@@ -1407,12 +1397,12 @@
}
// Initialize the hiddenapi structure.
- j.initHiddenAPI(ctx, dexOutputFile, outputFile, j.dexProperties.Uncompress_dex)
+ j.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), outputFile, j.dexProperties.Uncompress_dex)
// Encode hidden API flags in dex file.
dexOutputFile = j.hiddenAPIEncodeDex(ctx, dexOutputFile)
- j.dexJarFile = dexOutputFile
+ j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
j.dexJarInstallFile = android.PathForModuleInstall(ctx, "framework", jarName)
}
}
@@ -1450,7 +1440,7 @@
return android.Paths{j.combinedClasspathFile}
}
-func (j *Import) DexJarBuildPath() android.Path {
+func (j *Import) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}
@@ -1595,7 +1585,7 @@
properties DexImportProperties
- dexJarFile android.Path
+ dexJarFile OptionalDexJarPath
dexpreopter
@@ -1686,7 +1676,7 @@
})
}
- j.dexJarFile = dexOutputFile
+ j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
j.dexpreopt(ctx, dexOutputFile)
@@ -1696,7 +1686,7 @@
}
}
-func (j *DexImport) DexJarBuildPath() android.Path {
+func (j *DexImport) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}
@@ -1865,7 +1855,7 @@
// from its CLC should be added to the current CLC.
if sdkLib != nil {
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true,
- dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+ dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
diff --git a/java/java_test.go b/java/java_test.go
index 8bb017f..bc9b409 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -600,8 +600,8 @@
}
barDexJar := barModule.Module().(*Import).DexJarBuildPath()
- if barDexJar != nil {
- t.Errorf("bar dex jar build path expected to be nil, got %q", barDexJar)
+ if barDexJar.IsSet() {
+ t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
}
if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
@@ -612,7 +612,7 @@
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
}
- bazDexJar := bazModule.Module().(*Import).DexJarBuildPath()
+ bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path()
expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d469522..58180f7 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -540,7 +540,7 @@
// The dex jar for the stubs.
//
// This is not the implementation jar, it still only contains stubs.
- stubsDexJarPath android.Path
+ stubsDexJarPath OptionalDexJarPath
// The API specification file, e.g. system_current.txt.
currentApiFilePath android.OptionalPath
@@ -915,10 +915,10 @@
}
// to satisfy SdkLibraryDependency interface
-func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path {
+func (c *commonToSdkLibraryAndImport) SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
paths := c.selectScopePaths(ctx, kind)
if paths == nil {
- return nil
+ return makeUnsetDexJarPath()
}
return paths.stubsDexJarPath
@@ -1044,7 +1044,7 @@
// SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
// tool which processes dex files.
- SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) android.Path
+ SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
// SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
@@ -1941,7 +1941,7 @@
xmlPermissionsFileModule *sdkLibraryXml
// Build path to the dex implementation jar obtained from the prebuilt_apex, if any.
- dexJarFile android.Path
+ dexJarFile OptionalDexJarPath
// Expected install file path of the source module(sdk_library)
// or dex implementation jar obtained from the prebuilt_apex, if any.
@@ -2169,8 +2169,6 @@
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.generateCommonBuildActions(ctx)
- var deapexerModule android.Module
-
// Assume that source module(sdk_library) is installed in /<sdk_library partition>/framework
module.installFile = android.PathForModuleInstall(ctx, "framework", module.Stem()+".jar")
@@ -2199,11 +2197,6 @@
ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
}
}
-
- // Save away the `deapexer` module on which this depends, if any.
- if tag == android.DeapexerTag {
- deapexerModule = to
- }
})
// Populate the scope paths with information from the properties.
@@ -2223,21 +2216,18 @@
// obtained from the associated deapexer module.
ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if ai.ForPrebuiltApex {
- if deapexerModule == nil {
- // This should never happen as a variant for a prebuilt_apex is only created if the
- // deapxer module has been configured to export the dex implementation jar for this module.
- ctx.ModuleErrorf("internal error: module %q does not depend on a `deapexer` module for prebuilt_apex %q",
- module.Name(), ai.ApexVariationName)
- }
-
// Get the path of the dex implementation jar from the `deapexer` module.
- di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
+ di := android.FindDeapexerProviderForModule(ctx)
+ if di == nil {
+ return // An error has been reported by FindDeapexerProviderForModule.
+ }
if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil {
- module.dexJarFile = dexOutputPath
+ dexJarFile := makeDexJarPathFromPath(dexOutputPath)
+ module.dexJarFile = dexJarFile
installPath := android.PathForModuleInPartitionInstall(
ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(module.BaseModuleName()))
module.installFile = installPath
- module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
+ module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
// Dexpreopting.
module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath)
@@ -2247,7 +2237,7 @@
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
- ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt_apex %q", deapexerModule.Name())
+ ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt APEX %s", di.ApexModuleName())
}
}
}
@@ -2282,14 +2272,14 @@
}
// to satisfy UsesLibraryDependency interface
-func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
+func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath {
// The dex implementation jar extracted from the .apex file should be used in preference to the
// source.
- if module.dexJarFile != nil {
+ if module.dexJarFile.IsSet() {
return module.dexJarFile
}
if module.implLibraryModule == nil {
- return nil
+ return makeUnsetDexJarPath()
} else {
return module.implLibraryModule.DexJarBuildPath()
}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 43542cb..2b53739 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1307,7 +1307,7 @@
ctx := android.ModuleInstallPathContextForTesting(result.Config)
dexJarBuildPath := func(name string, kind android.SdkKind) string {
dep := result.Module(name, "android_common").(java.SdkLibraryDependency)
- path := dep.SdkApiStubDexJar(ctx, kind)
+ path := dep.SdkApiStubDexJar(ctx, kind).Path()
return path.RelativeToTop().String()
}