Do not propagate <uses-library> deps through static SDK component libs.

If some Java library/app depends on an SDK component library (e.g. stubs
library), then it transitively depends on the SDK library itself
(because the component library has a dependency on its SDK library).

Previously having this transitive dependency resulted in adding the SDK
library to the <uses-library> dependencies of the library/app. However,
this doesn't make sense if the app has a *static* dependency on the
component library. This patch stops adding <uses-library> dependency in
that case.

Bug: 132357300
Test: m nothing
Test: added new Soong test that would previously fail with an error:
   invalid build path for <uses-library> "fred"
Change-Id: I697a65e461037c95ec56b6c321afa4ec52ccbbec
This commit is contained in:
Ulya Trafimovich
2020-12-03 16:50:22 +00:00
parent 78210f6c9b
commit 65b031910b
3 changed files with 51 additions and 15 deletions

View File

@@ -407,6 +407,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderConte
ctx.VisitDirectDeps(func(module android.Module) { ctx.VisitDirectDeps(func(module android.Module) {
depName := ctx.OtherModuleName(module) depName := ctx.OtherModuleName(module)
depTag := ctx.OtherModuleDependencyTag(module)
var exportPackage android.Path var exportPackage android.Path
aarDep, _ := module.(AndroidLibraryDependency) aarDep, _ := module.(AndroidLibraryDependency)
@@ -414,7 +415,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderConte
exportPackage = aarDep.ExportPackage() exportPackage = aarDep.ExportPackage()
} }
switch ctx.OtherModuleDependencyTag(module) { switch depTag {
case instrumentationForTag: case instrumentationForTag:
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2. // Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case libTag: case libTag:
@@ -439,7 +440,6 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderConte
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...) transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage) transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...) transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
classLoaderContexts.AddContextMap(aarDep.ClassLoaderContexts(), depName)
if aarDep.ExportedAssets().Valid() { if aarDep.ExportedAssets().Valid() {
assets = append(assets, aarDep.ExportedAssets().Path()) assets = append(assets, aarDep.ExportedAssets().Path())
} }
@@ -458,11 +458,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderConte
} }
} }
// Add nested dependencies after processing the direct dependency: if it is a <uses-library>, // Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
// nested context is added as its subcontext, and should not be re-added at the top-level. maybeAddCLCFromDep(module, depTag, depName, classLoaderContexts)
if dep, ok := module.(Dependency); ok {
classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}) })
deps = append(deps, sharedLibs...) deps = append(deps, sharedLibs...)

View File

@@ -2729,6 +2729,13 @@ func TestUsesLibraries(t *testing.T) {
sdk_version: "current", sdk_version: "current",
} }
java_sdk_library {
name: "fred",
srcs: ["a.java"],
api_packages: ["fred"],
sdk_version: "current",
}
java_sdk_library { java_sdk_library {
name: "bar", name: "bar",
srcs: ["a.java"], srcs: ["a.java"],
@@ -2753,7 +2760,12 @@ func TestUsesLibraries(t *testing.T) {
name: "app", name: "app",
srcs: ["a.java"], srcs: ["a.java"],
libs: ["qux", "quuz.stubs"], libs: ["qux", "quuz.stubs"],
static_libs: ["static-runtime-helper"], static_libs: [
"static-runtime-helper",
// statically linked component libraries should not pull their SDK libraries,
// so "fred" should not be added to class loader context
"fred.stubs",
],
uses_libs: ["foo"], uses_libs: ["foo"],
sdk_version: "current", sdk_version: "current",
optional_uses_libs: [ optional_uses_libs: [

View File

@@ -1050,7 +1050,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
switch tag { switch tag {
case libTag: case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(), j.classLoaderContexts.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
dep.DexJarBuildPath(), dep.DexJarInstallPath()) dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag: case staticLibTag:
@@ -1062,7 +1061,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...) deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...)
case libTag, instrumentationForTag: case libTag, instrumentationForTag:
deps.classpath = append(deps.classpath, dep.HeaderJars()...) deps.classpath = append(deps.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName) j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins() pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
@@ -1075,8 +1073,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...) deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...) deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...) deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
// sdk lib names from dependencies are re-exported
j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins() pluginJars, pluginClasses, disableTurbine := dep.ExportedPlugins()
addPlugins(&deps, pluginJars, pluginClasses...) addPlugins(&deps, pluginJars, pluginClasses...)
@@ -1151,6 +1147,9 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.systemModules = &systemModules{outputDir, outputDeps} deps.systemModules = &systemModules{outputDir, outputDeps}
} }
} }
// Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
}) })
return deps return deps
@@ -2781,8 +2780,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
switch tag { switch tag {
case libTag, staticLibTag: case libTag, staticLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars()...) flags.classpath = append(flags.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
j.classLoaderContexts.AddContextMap(dep.ClassLoaderContexts(), otherName)
case bootClasspathTag: case bootClasspathTag:
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...) flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
} }
@@ -2790,10 +2787,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
switch tag { switch tag {
case libTag: case libTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.classLoaderContexts.AddContext(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath()) j.classLoaderContexts.AddContext(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
} }
} }
// Merge dep's CLC after processing the dep itself (which may add its own <uses-library>).
maybeAddCLCFromDep(module, tag, otherName, j.classLoaderContexts)
}) })
var installFile android.Path var installFile android.Path
@@ -3214,3 +3213,31 @@ var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault var BoolDefault = proptools.BoolDefault
var String = proptools.String var String = proptools.String
var inList = android.InList var inList = android.InList
// Add class loader context of a given dependency to the given class loader context, provided that
// all the necessary conditions are met.
func maybeAddCLCFromDep(depModule android.Module, depTag blueprint.DependencyTag,
depName string, clcMap dexpreopt.ClassLoaderContextMap) {
if dep, ok := depModule.(Dependency); ok {
if depTag == libTag {
// Ok, propagate <uses-library> through non-static library dependencies.
} else if depTag == staticLibTag {
// Propagate <uses-library> through static library dependencies, unless it is a
// component library (such as stubs). Component libraries have a dependency on their
// SDK library, which should not be pulled just because of a static component library.
if comp, isComp := depModule.(SdkLibraryComponentDependency); isComp {
if compName := comp.OptionalImplicitSdkLibrary(); compName != nil {
dep = nil
}
}
} else {
// Don't propagate <uses-library> for other dependency tags.
dep = nil
}
if dep != nil {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}
}