Merge "Collect paths to transitive SDK Java library dependencies."

This commit is contained in:
Ulyana Trafimovich 2020-08-20 10:37:58 +00:00 committed by Gerrit Code Review
commit 9ce2221791
9 changed files with 117 additions and 55 deletions

View file

@ -17,6 +17,7 @@ package dexpreopt
import (
"encoding/json"
"fmt"
"sort"
"strings"
"github.com/google/blueprint"
@ -100,6 +101,8 @@ type GlobalSoongConfig struct {
ConstructContext android.Path
}
const UnknownInstallLibraryPath = "error"
// LibraryPath contains paths to the library DEX jar on host and on device.
type LibraryPath struct {
Host android.Path
@ -109,6 +112,46 @@ type LibraryPath struct {
// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
type LibraryPaths map[string]*LibraryPath
// Add a new path to the map of library paths, unless a path for this library already exists.
func (libPaths LibraryPaths) AddLibraryPath(ctx android.PathContext, lib *string, hostPath, installPath android.Path) {
if lib == nil {
return
}
if _, present := libPaths[*lib]; !present {
var devicePath string
if installPath != nil {
devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
} else {
// For some stub libraries the only known thing is the name of their implementation
// library, but the library itself is unavailable (missing or part of a prebuilt). In
// such cases we still need to add the library to <uses-library> tags in the manifest,
// but we cannot use if for dexpreopt.
devicePath = UnknownInstallLibraryPath
}
libPaths[*lib] = &LibraryPath{hostPath, devicePath}
}
return
}
// Add library paths from the second map to the first map (do not override existing entries).
func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
for lib, path := range otherPaths {
if _, present := libPaths[lib]; !present {
libPaths[lib] = path
}
}
}
// Return sorted names of the libraries in the map.
func (libPaths LibraryPaths) Names() []string {
keys := make([]string, 0, len(libPaths))
for k := range libPaths {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
type ModuleConfig struct {
Name string
DexLocation string // dex location on device

View file

@ -20,6 +20,7 @@ import (
"strings"
"android/soong/android"
"android/soong/dexpreopt"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@ -99,7 +100,7 @@ type aapt struct {
useEmbeddedNativeLibs bool
useEmbeddedDex bool
usesNonSdkApis bool
sdkLibraries []string
sdkLibraries dexpreopt.LibraryPaths
hasNoCode bool
LoggingParent string
resourceFiles android.Paths
@ -231,6 +232,8 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
aaptLibs(ctx, sdkContext)
a.sdkLibraries = sdkLibraries
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
@ -357,7 +360,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) {
staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries dexpreopt.LibraryPaths) {
var sharedLibs android.Paths
@ -366,6 +369,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
sdkLibraries = make(dexpreopt.LibraryPaths)
ctx.VisitDirectDeps(func(module android.Module) {
var exportPackage android.Path
aarDep, _ := module.(AndroidLibraryDependency)
@ -385,7 +390,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
// (including the java_sdk_library) itself then append any implicit sdk library
// names to the list of sdk libraries to be added to the manifest.
if component, ok := module.(SdkLibraryComponentDependency); ok {
sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...)
sdkLibraries.AddLibraryPath(ctx, component.OptionalImplicitSdkLibrary(),
component.DexJarBuildPath(), component.DexJarInstallPath())
}
case frameworkResTag:
@ -397,7 +403,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
sdkLibraries.AddLibraryPaths(aarDep.ExportedSdkLibs())
if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path())
}
@ -428,7 +434,6 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
transitiveStaticLibs = android.FirstUniquePaths(transitiveStaticLibs)
transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
sdkLibraries = android.FirstUniqueStrings(sdkLibraries)
return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
}
@ -465,8 +470,8 @@ func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.aapt.sdkLibraries = a.exportedSdkLibs
a.aapt.buildActions(ctx, sdkContext(a))
a.exportedSdkLibs = a.aapt.sdkLibraries
ctx.CheckbuildFile(a.proguardOptionsFile)
ctx.CheckbuildFile(a.exportPackage)
@ -749,7 +754,7 @@ func (a *AARImport) AidlIncludeDirs() android.Paths {
return nil
}
func (a *AARImport) ExportedSdkLibs() []string {
func (a *AARImport) ExportedSdkLibs() dexpreopt.LibraryPaths {
return nil
}

View file

@ -21,6 +21,7 @@ import (
"github.com/google/blueprint"
"android/soong/android"
"android/soong/dexpreopt"
)
var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
@ -52,7 +53,7 @@ var optionalUsesLibs = []string{
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries []string,
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries dexpreopt.LibraryPaths,
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
var args []string
@ -79,7 +80,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
args = append(args, "--use-embedded-dex")
}
for _, usesLib := range sdkLibraries {
for usesLib, _ := range sdkLibraries {
if inList(usesLib, optionalUsesLibs) {
args = append(args, "--optional-uses-library", usesLib)
} else {

View file

@ -121,7 +121,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
}
entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs.Names()...)
if len(library.additionalCheckedModules) != 0 {
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)

View file

@ -598,6 +598,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
a.dexpreopter.manifestFile = a.mergedManifestFile
a.exportedSdkLibs = make(dexpreopt.LibraryPaths)
if ctx.ModuleName() != "framework-res" {
a.Module.compile(ctx, a.aaptSrcJar)

View file

@ -19,6 +19,7 @@ import (
"io"
"android/soong/android"
"android/soong/dexpreopt"
)
type DeviceHostConverter struct {
@ -162,7 +163,7 @@ func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
return nil
}
func (d *DeviceHostConverter) ExportedSdkLibs() []string {
func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.LibraryPaths {
return nil
}

View file

@ -29,6 +29,7 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/dexpreopt"
"android/soong/java/config"
"android/soong/tradefed"
)
@ -411,8 +412,8 @@ type Module struct {
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
// list of SDK lib names that this java module is exporting
exportedSdkLibs []string
// map of SDK libs exported by this java module to their build and install paths
exportedSdkLibs dexpreopt.LibraryPaths
// list of plugins that this java module is exporting
exportedPluginJars android.Paths
@ -488,14 +489,19 @@ type ApexDependency interface {
ImplementationAndResourcesJars() android.Paths
}
type Dependency interface {
ApexDependency
ImplementationJars() android.Paths
ResourceJars() android.Paths
// Provides build path and install path to DEX jars.
type UsesLibraryDependency interface {
DexJarBuildPath() android.Path
DexJarInstallPath() android.Path
}
type Dependency interface {
ApexDependency
UsesLibraryDependency
ImplementationJars() android.Paths
ResourceJars() android.Paths
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
ExportedSdkLibs() dexpreopt.LibraryPaths
ExportedPlugins() (android.Paths, []string)
SrcJarArgs() ([]string, android.Paths)
BaseModuleName() string
@ -966,12 +972,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
}
// If this is a component library (stubs, etc.) for a java_sdk_library then
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@ -991,7 +991,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...)
j.exportedSdkLibs.AddLibraryPath(ctx, dep.OptionalImplicitSdkLibrary(), dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
@ -1002,7 +1002,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@ -1014,7 +1014,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...)
@ -1077,8 +1077,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
})
j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
return deps
}
@ -1819,8 +1817,7 @@ func (j *Module) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
func (j *Module) ExportedSdkLibs() []string {
// exportedSdkLibs is type []string
func (j *Module) ExportedSdkLibs() dexpreopt.LibraryPaths {
return j.exportedSdkLibs
}
@ -1953,6 +1950,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
}
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
j.compile(ctx, nil)
// Collect the module directory for IDE info in java/jdeps.go.
@ -1968,6 +1966,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
// If this is a component library (stubs, etc.) for a java_sdk_library then
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs.AddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), j.DexJarBuildPath(), j.DexJarInstallPath())
j.distFiles = j.GenerateTaggedDistFiles(ctx)
}
@ -2518,7 +2522,7 @@ type Import struct {
properties ImportProperties
combinedClasspathFile android.Path
exportedSdkLibs []string
exportedSdkLibs dexpreopt.LibraryPaths
exportAidlIncludeDirs android.Paths
}
@ -2571,12 +2575,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
TransformJetifier(ctx, outputFile, inputFile)
}
j.combinedClasspathFile = outputFile
// If this is a component library (impl, stubs, etc.) for a java_sdk_library then
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
@ -2587,23 +2586,29 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
switch tag {
case libTag, staticLibTag:
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
}
case SdkLibraryDependency:
switch tag {
case libTag:
// names of sdk libs that are directly depended are exported
j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
j.exportedSdkLibs.AddLibraryPath(ctx, &otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
})
j.exportedSdkLibs = android.FirstUniqueStrings(j.exportedSdkLibs)
var installFile android.Path
if Bool(j.properties.Installable) {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
jarName, outputFile)
}
// If this is a component library (impl, stubs, etc.) for a java_sdk_library then
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs.AddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), outputFile, installFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
}
@ -2646,7 +2651,7 @@ func (j *Import) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
func (j *Import) ExportedSdkLibs() []string {
func (j *Import) ExportedSdkLibs() dexpreopt.LibraryPaths {
return j.exportedSdkLibs
}

View file

@ -20,7 +20,6 @@ import (
"path/filepath"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"testing"
@ -1496,8 +1495,7 @@ func TestJavaSdkLibrary(t *testing.T) {
// test if baz has exported SDK lib names foo and bar to qux
qux := ctx.ModuleForTests("qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
sdkLibs := quxLib.ExportedSdkLibs()
sort.Strings(sdkLibs)
sdkLibs := quxLib.ExportedSdkLibs().Names()
if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
}

View file

@ -849,22 +849,20 @@ func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *andr
}
// to satisfy SdkLibraryComponentDependency
func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string {
if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil {
return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack}
}
return nil
func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() *string {
return e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack
}
// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
// (including the java_sdk_library) itself.
type SdkLibraryComponentDependency interface {
UsesLibraryDependency
// The optional name of the sdk library that should be implicitly added to the
// AndroidManifest of an app that contains code which references the sdk library.
//
// Returns an array containing 0 or 1 items rather than a *string to make it easier
// to append this to the list of exported sdk libraries.
OptionalImplicitSdkLibrary() []string
// Returns the name of the optional implicit SDK library or nil, if there isn't one.
OptionalImplicitSdkLibrary() *string
}
// Make sure that all the module types that are components of java_sdk_library/_import
@ -878,6 +876,7 @@ var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
// Provides access to sdk_version related header and implentation jars.
type SdkLibraryDependency interface {
SdkLibraryComponentDependency
UsesLibraryDependency
// Get the header jars appropriate for the supplied sdk_version.
//
@ -1972,7 +1971,7 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
return module.sdkJars(ctx, sdkVersion, false)
}
// to satisfy apex.javaDependency interface
// to satisfy SdkLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
if module.implLibraryModule == nil {
return nil
@ -1981,6 +1980,15 @@ func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
}
}
// to satisfy SdkLibraryDependency interface
func (module *SdkLibraryImport) DexJarInstallPath() android.Path {
if module.implLibraryModule == nil {
return nil
} else {
return module.implLibraryModule.DexJarInstallPath()
}
}
// to satisfy apex.javaDependency interface
func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
if module.implLibraryModule == nil {