Merge "Add checks for double_loadable dependencies" am: f14277fc3a
am: 4b75790b30
Change-Id: I55a480df1a035ff80531a86e0dcd0f535b088bf4
This commit is contained in:
commit
ba30c798c9
|
@ -132,11 +132,15 @@ type TopDownMutatorContext interface {
|
|||
VisitDepsDepthFirst(visit func(Module))
|
||||
VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
|
||||
WalkDeps(visit func(Module, Module) bool)
|
||||
// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
|
||||
// and returns a top-down dependency path from a start module to current child module.
|
||||
GetWalkPath() []Module
|
||||
}
|
||||
|
||||
type androidTopDownMutatorContext struct {
|
||||
blueprint.TopDownMutatorContext
|
||||
androidBaseContextImpl
|
||||
walkPath []Module
|
||||
}
|
||||
|
||||
type AndroidBottomUpMutator func(BottomUpMutatorContext)
|
||||
|
@ -287,10 +291,16 @@ func (a *androidTopDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) b
|
|||
}
|
||||
|
||||
func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
|
||||
a.walkPath = []Module{a.Module()}
|
||||
a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
|
||||
childAndroidModule, _ := child.(Module)
|
||||
parentAndroidModule, _ := parent.(Module)
|
||||
if childAndroidModule != nil && parentAndroidModule != nil {
|
||||
// record walkPath before visit
|
||||
for a.walkPath[len(a.walkPath)-1] != parentAndroidModule {
|
||||
a.walkPath = a.walkPath[0 : len(a.walkPath)-1]
|
||||
}
|
||||
a.walkPath = append(a.walkPath, childAndroidModule)
|
||||
return visit(childAndroidModule, parentAndroidModule)
|
||||
} else {
|
||||
return false
|
||||
|
@ -298,6 +308,10 @@ func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool)
|
|||
})
|
||||
}
|
||||
|
||||
func (a *androidTopDownMutatorContext) GetWalkPath() []Module {
|
||||
return a.walkPath
|
||||
}
|
||||
|
||||
func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) {
|
||||
for _, p := range props {
|
||||
err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties,
|
||||
|
|
57
cc/cc.go
57
cc/cc.go
|
@ -68,6 +68,8 @@ func init() {
|
|||
|
||||
ctx.TopDown("lto_deps", ltoDepsMutator)
|
||||
ctx.BottomUp("lto", ltoMutator).Parallel()
|
||||
|
||||
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
|
||||
})
|
||||
|
||||
pctx.Import("android/soong/cc/config")
|
||||
|
@ -1469,30 +1471,44 @@ func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag depe
|
|||
}
|
||||
|
||||
// Tests whether the dependent library is okay to be double loaded inside a single process.
|
||||
// If a library is a member of VNDK and at the same time dependencies of an LLNDK library,
|
||||
// it is subject to be double loaded. Such lib should be explicitly marked as double_loaded: true
|
||||
// If a library has a vendor variant and is a (transitive) dependency of an LLNDK library,
|
||||
// it is subject to be double loaded. Such lib should be explicitly marked as double_loadable: true
|
||||
// or as vndk-sp (vndk: { enabled: true, support_system_process: true}).
|
||||
func checkDoubleLoadableLibries(ctx android.ModuleContext, from *Module, to *Module) {
|
||||
if _, ok := from.linker.(*libraryDecorator); !ok {
|
||||
return
|
||||
}
|
||||
func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
|
||||
check := func(child, parent android.Module) bool {
|
||||
to, ok := child.(*Module)
|
||||
if !ok {
|
||||
// follow thru cc.Defaults, etc.
|
||||
return true
|
||||
}
|
||||
|
||||
if inList(ctx.ModuleName(), llndkLibraries) ||
|
||||
(from.useVndk() && Bool(from.VendorProperties.Double_loadable)) {
|
||||
_, depIsLlndk := to.linker.(*llndkStubDecorator)
|
||||
depIsVndkSp := false
|
||||
if to.vndkdep != nil && to.vndkdep.isVndkSp() {
|
||||
depIsVndkSp = true
|
||||
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
|
||||
return false
|
||||
}
|
||||
depIsVndk := false
|
||||
if to.vndkdep != nil && to.vndkdep.isVndk() {
|
||||
depIsVndk = true
|
||||
|
||||
// if target lib has no vendor variant, keep checking dependency graph
|
||||
if !to.hasVendorVariant() {
|
||||
return true
|
||||
}
|
||||
depIsDoubleLoadable := Bool(to.VendorProperties.Double_loadable)
|
||||
if !depIsLlndk && !depIsVndkSp && !depIsDoubleLoadable && depIsVndk {
|
||||
ctx.ModuleErrorf("links VNDK library %q that isn't double loadable (not also LL-NDK, "+
|
||||
"VNDK-SP, or explicitly marked as 'double_loadable').",
|
||||
ctx.OtherModuleName(to))
|
||||
|
||||
if to.isVndkSp() || inList(child.Name(), llndkLibraries) || Bool(to.VendorProperties.Double_loadable) {
|
||||
return false
|
||||
}
|
||||
|
||||
var stringPath []string
|
||||
for _, m := range ctx.GetWalkPath() {
|
||||
stringPath = append(stringPath, m.Name())
|
||||
}
|
||||
ctx.ModuleErrorf("links a library %q which is not LL-NDK, "+
|
||||
"VNDK-SP, or explicitly marked as 'double_loadable:true'. "+
|
||||
"(dependency: %s)", ctx.OtherModuleName(to), strings.Join(stringPath, " -> "))
|
||||
return false
|
||||
}
|
||||
if module, ok := ctx.Module().(*Module); ok {
|
||||
if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() {
|
||||
if inList(ctx.ModuleName(), llndkLibraries) || Bool(module.VendorProperties.Double_loadable) {
|
||||
ctx.WalkDeps(check)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1648,7 +1664,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
}
|
||||
|
||||
checkLinkType(ctx, c, ccDep, t)
|
||||
checkDoubleLoadableLibries(ctx, c, ccDep)
|
||||
}
|
||||
|
||||
var ptr *android.Paths
|
||||
|
|
306
cc/cc_test.go
306
cc/cc_test.go
|
@ -71,6 +71,9 @@ func createTestContext(t *testing.T, config android.Config, bp string, os androi
|
|||
ctx.BottomUp("version", VersionMutator).Parallel()
|
||||
ctx.BottomUp("begin", BeginMutator).Parallel()
|
||||
})
|
||||
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
|
||||
})
|
||||
ctx.Register()
|
||||
|
||||
// add some modules that are required by the compiler and/or linker
|
||||
|
@ -428,6 +431,309 @@ func TestVndkDepError(t *testing.T) {
|
|||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a VNDK lib depends on a non-VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: ["libnonvndk"],
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnonvndk",
|
||||
vendor_available: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a VNDK-private lib depends on a non-VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
|
||||
cc_library {
|
||||
name: "libvndkprivate",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: ["libnonvndk"],
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnonvndk",
|
||||
vendor_available: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a VNDK-sp lib depends on a non-VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
|
||||
cc_library {
|
||||
name: "libvndksp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
shared_libs: ["libnonvndk"],
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnonvndk",
|
||||
vendor_available: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a VNDK-sp-private lib depends on a non-VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
|
||||
cc_library {
|
||||
name: "libvndkspprivate",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
shared_libs: ["libnonvndk"],
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnonvndk",
|
||||
vendor_available: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestDoubleLoadbleDep(t *testing.T) {
|
||||
// okay to link : LLNDK -> double_loadable VNDK
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
shared_libs: ["libdoubleloadable"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libdoubleloadable",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
double_loadable: true,
|
||||
}
|
||||
`)
|
||||
// okay to link : LLNDK -> VNDK-SP
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
shared_libs: ["libvndksp"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndksp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
}
|
||||
`)
|
||||
// okay to link : double_loadable -> double_loadable
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libdoubleloadable1",
|
||||
shared_libs: ["libdoubleloadable2"],
|
||||
vendor_available: true,
|
||||
double_loadable: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libdoubleloadable2",
|
||||
vendor_available: true,
|
||||
double_loadable: true,
|
||||
}
|
||||
`)
|
||||
// okay to link : double_loadable VNDK -> double_loadable VNDK private
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libdoubleloadable",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
double_loadable: true,
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
double_loadable: true,
|
||||
}
|
||||
`)
|
||||
// okay to link : LLNDK -> core-only -> vendor_available & double_loadable
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
shared_libs: ["libcoreonly"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libcoreonly",
|
||||
shared_libs: ["libvendoravailable"],
|
||||
}
|
||||
|
||||
// indirect dependency of LLNDK
|
||||
cc_library {
|
||||
name: "libvendoravailable",
|
||||
vendor_available: true,
|
||||
double_loadable: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestDoubleLoadableDepError(t *testing.T) {
|
||||
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable vendor_available lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
no_libgcc: true,
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable vendor_available lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libdoubleloadable",
|
||||
vendor_available: true,
|
||||
double_loadable: true,
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a double_loadable lib depends on a non-double_loadable VNDK lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libdoubleloadable",
|
||||
vendor_available: true,
|
||||
double_loadable: true,
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a double_loadable VNDK depends on a non-double_loadable VNDK private lib.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libdoubleloadable",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
double_loadable: true,
|
||||
shared_libs: ["libnondoubleloadable"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libnondoubleloadable",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
`)
|
||||
|
||||
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable indirectly.
|
||||
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
|
||||
cc_library {
|
||||
name: "libllndk",
|
||||
shared_libs: ["libcoreonly"],
|
||||
}
|
||||
|
||||
llndk_library {
|
||||
name: "libllndk",
|
||||
symbol_file: "",
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libcoreonly",
|
||||
shared_libs: ["libvendoravailable"],
|
||||
}
|
||||
|
||||
// indirect dependency of LLNDK
|
||||
cc_library {
|
||||
name: "libvendoravailable",
|
||||
vendor_available: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkMustNotBeProductSpecific(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue