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.
This commit is contained in:
Martin Stjernholm
2021-09-24 09:32:24 +00:00
committed by Gerrit Code Review
17 changed files with 233 additions and 137 deletions

View File

@@ -69,6 +69,8 @@ import (
// 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 @@ type DeapexerInfo struct {
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 @@ var DeapexerProvider = blueprint.NewProvider(DeapexerInfo{})
// 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 @@ type RequiresFilesFromPrebuiltApexTag interface {
// 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
}

View File

@@ -1545,7 +1545,7 @@ func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.Platform
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 @@ var _ javaModule = (*java.SdkLibraryImport)(nil)
// 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.

View File

@@ -4799,9 +4799,10 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
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 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
}
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 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
}
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 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
// 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)

View File

@@ -22,6 +22,7 @@ import (
"android/soong/android"
"android/soong/java"
"github.com/google/blueprint/proptools"
)
@@ -737,7 +738,7 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) {
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

View File

@@ -15,6 +15,8 @@
package apex
import (
"strings"
"android/soong/android"
)
@@ -75,6 +77,17 @@ type Deapexer struct {
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 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 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 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
for _, p := range exportedPaths {
command.Output(p.(android.WritablePath))
}
builder.Build("deapexer", "deapex "+ctx.ModuleName())
builder.Build("deapexer", "deapex "+apexModuleName(ctx.ModuleName()))
}
}

View File

@@ -176,13 +176,15 @@ func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) {
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 createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerNam
)
}
func deapexerModuleName(baseModuleName string) string {
return baseModuleName + ".deapexer"
}
func apexSelectorModuleName(baseModuleName string) string {
return baseModuleName + ".apex.selector"
}

View File

@@ -29,8 +29,8 @@ func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
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 (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
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 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
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 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
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 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
}
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 (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
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 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
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)

View File

@@ -476,7 +476,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
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 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
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 {

View File

@@ -276,6 +276,87 @@ func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleCont
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 @@ type Module struct {
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 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
// 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 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
// 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 @@ func (j *Module) ImplementationJars() android.Paths {
return android.Paths{j.implementationJarFile}
}
func (j *Module) DexJarBuildPath() android.Path {
func (j *Module) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}

View File

@@ -954,23 +954,11 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and
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

View File

@@ -30,14 +30,14 @@ type hiddenAPI struct {
// 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 @@ type hiddenAPI struct {
uncompressDexState *bool
}
func (h *hiddenAPI) bootDexJar() android.Path {
func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
return h.bootDexJarPath
}
@@ -68,7 +68,7 @@ type hiddenAPIModule interface {
}
type hiddenAPIIntf interface {
bootDexJar() android.Path
bootDexJar() OptionalDexJarPath
classesJars() android.Paths
uncompressDex() *bool
}
@@ -79,7 +79,7 @@ var _ hiddenAPIIntf = (*hiddenAPI)(nil)
//
// 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.

View File

@@ -19,6 +19,7 @@ import (
"strings"
"android/soong/android"
"github.com/google/blueprint"
)
@@ -277,7 +278,7 @@ func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScop
// 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 @@ func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.
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 @@ func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android
// 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 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M
// 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 @@ func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module,
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 @@ func handleMissingDexBootFile(ctx android.ModuleContext, module android.Module,
// 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.

View File

@@ -20,6 +20,7 @@ import (
"testing"
"android/soong/android"
"github.com/google/blueprint/proptools"
)
@@ -306,7 +307,7 @@ func TestHiddenAPIEncoding_JavaSdkLibrary(t *testing.T) {
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)
}

View File

@@ -219,7 +219,7 @@ type ApexDependency interface {
// 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 @@ type Import struct {
properties ImportProperties
// output file containing classes.dex and resources
dexJarFile android.Path
dexJarFile OptionalDexJarPath
dexJarInstallFile android.Path
combinedClasspathFile android.Path
@@ -1319,7 +1319,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
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 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
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 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 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 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
// 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 @@ func (j *Import) ImplementationAndResourcesJars() android.Paths {
return android.Paths{j.combinedClasspathFile}
}
func (j *Import) DexJarBuildPath() android.Path {
func (j *Import) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}
@@ -1595,7 +1585,7 @@ type DexImport struct {
properties DexImportProperties
dexJarFile android.Path
dexJarFile OptionalDexJarPath
dexpreopter
@@ -1686,7 +1676,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
})
}
j.dexJarFile = dexOutputFile
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
j.dexpreopt(ctx, dexOutputFile)
@@ -1696,7 +1686,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
func (j *DexImport) DexJarBuildPath() android.Path {
func (j *DexImport) DexJarBuildPath() OptionalDexJarPath {
return j.dexJarFile
}
@@ -1865,7 +1855,7 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
// 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)
}

View File

@@ -600,8 +600,8 @@ func TestPrebuilts(t *testing.T) {
}
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 @@ func TestPrebuilts(t *testing.T) {
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)

View File

@@ -540,7 +540,7 @@ type scopePaths struct {
// 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 @@ func sdkKindToApiScope(kind android.SdkKind) *apiScope {
}
// 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 @@ type SdkLibraryDependency interface {
// 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 @@ type SdkLibraryImport struct {
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) OutputFiles(tag string) (android.Paths, error) {
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 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
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 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
// 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 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
} 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 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
}
// 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()
}

View File

@@ -1307,7 +1307,7 @@ java_sdk_library_import {
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()
}