vendor_available:false hides a lib from vendors

When a lib is explicitly marked as `vendor_available: false`, then it
can't be directly depended by a vendor lib which is installed to /vendor
partition. This is to hide some VNDK libs (including llndk) from vendors
so that platform owners can have a freedom of modifying their ABI
without breaking vendors.

In addition, the list of the private libs are exported to the make world
as VNDK_PRIVATE_LIBRARIES.

Also, fixed a bug that allowed a vndk lib to link against to vendor
library (or vendor variant of a system lib) if the lib is prebuilt.

Bug: 64730695
Bug: 64994918
Test: Add `vendor_available: false` to libft2 and libcompiler_rt.
Add the libs to shared_libs property of a vendor library in soong
(i.e. libnbaio_mono). The build fails with the error message.

Change-Id: Iab575db96bb4f6739a592f3fa0a75124296bea0c
This commit is contained in:
Jiyong Park 2017-08-16 14:05:54 +09:00
parent c7ba6a2e46
commit 82e2bf3b7f
5 changed files with 85 additions and 30 deletions

View file

@ -89,7 +89,7 @@ func (c *Module) AndroidMk() android.AndroidMkData {
}
c.subAndroidMk(&ret, c.installer)
if c.vndk() && Bool(c.VendorProperties.Vendor_available) {
if c.vndk() && c.hasVendorVariant() {
// .vendor suffix is added only when we will have two variants: core and vendor.
// The suffix is not added for vendor-only module.
ret.SubName += vendorSuffix

View file

@ -168,16 +168,21 @@ type BaseProperties struct {
}
type VendorProperties struct {
// whether this module should be allowed to install onto /vendor as
// well as /system. The two variants will be built separately, one
// like normal, and the other limited to the set of libraries and
// headers that are exposed to /vendor modules.
// whether this module should be allowed to be directly depended by other
// modules with `vendor: true`, `proprietary: true`, or `vendor_available:true`.
// If set to true, two variants will be built separately, one like
// normal, and the other limited to the set of libraries and headers
// that are exposed to /vendor modules.
//
// The vendor variant may be used with a different (newer) /system,
// so it shouldn't have any unversioned runtime dependencies, or
// make assumptions about the system that may not be true in the
// future.
//
// If set to false, this module becomes inaccessible from /vendor modules.
//
// Default value is true when vndk: {enabled: true} or vendor: true.
//
// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
Vendor_available *bool
}
@ -388,6 +393,12 @@ func (c *Module) isVndk() bool {
return false
}
// Returns true only when this module is configured to have core and vendor
// variants.
func (c *Module) hasVendorVariant() bool {
return c.isVndk() || Bool(c.VendorProperties.Vendor_available)
}
type baseModuleContext struct {
android.BaseContext
moduleContextImpl
@ -1159,7 +1170,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
// Export the shared libs to the make world. In doing so, .vendor suffix
// is added if the lib has both core and vendor variants and this module
// is building against vndk. This is because the vendor variant will be
// is building against vndk. This is because the vendor variant will
// have .vendor suffix in its name in the make world. However, if the
// lib is a vendor-only lib or this lib is not building against vndk,
// then the suffix is not added.
@ -1168,7 +1179,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
libName := strings.TrimSuffix(name, llndkLibrarySuffix)
libName = strings.TrimPrefix(libName, "prebuilt_")
isLLndk := inList(libName, llndkLibraries)
if c.vndk() && (Bool(cc.VendorProperties.Vendor_available) || isLLndk) {
if c.vndk() && (cc.hasVendorVariant() || isLLndk) {
libName += vendorSuffix
}
// Note: the order of libs in this list is not important because
@ -1311,15 +1322,15 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
}
// Sanity check
if Bool(m.VendorProperties.Vendor_available) && mctx.Vendor() {
if m.VendorProperties.Vendor_available != nil && mctx.Vendor() {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true` or `proprietary: true`")
return
}
if vndk := m.vndkdep; vndk != nil {
if vndk.isVndk() && !Bool(m.VendorProperties.Vendor_available) {
if vndk.isVndk() && m.VendorProperties.Vendor_available == nil {
mctx.PropertyErrorf("vndk",
"has to define `vendor_available: true` to enable vndk")
"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
return
}
if !vndk.isVndk() && vndk.isVndkSp() {
@ -1337,7 +1348,7 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
// LL-NDK stubs only exist in the vendor variant, since the
// real libraries will be used in the core variant.
mctx.CreateVariations(vendorMode)
} else if Bool(m.VendorProperties.Vendor_available) {
} else if m.hasVendorVariant() {
// This will be available in both /system and /vendor
// or a /system directory that is available to vendor.
mod := mctx.CreateVariations(coreMode, vendorMode)

View file

@ -50,6 +50,11 @@ type llndkLibraryProperties struct {
// Whether the system library uses symbol versions.
Unversioned bool
// whether this module can be directly depended upon by libs that are installed to /vendor.
// When set to false, this module can only be depended on by VNDK libraries, not vendor
// libraries. This effectively hides this module from vendors. Default value is true.
Vendor_available bool
}
type llndkStubDecorator struct {
@ -149,6 +154,7 @@ func newLLndkStubLibrary() *Module {
stub := &llndkStubDecorator{
libraryDecorator: library,
}
stub.Properties.Vendor_available = true
module.compiler = stub
module.linker = stub
module.installer = nil

View file

@ -62,6 +62,7 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.Strict("VNDK_CORE_LIBRARIES", strings.Join(vndkCoreLibraries, " "))
ctx.Strict("VNDK_SAMEPROCESS_LIBRARIES", strings.Join(vndkSpLibraries, " "))
ctx.Strict("LLNDK_LIBRARIES", strings.Join(llndkLibraries, " "))
ctx.Strict("VNDK_PRIVATE_LIBRARIES", strings.Join(vndkPrivateLibraries, " "))
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " "))
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " "))

View file

@ -27,8 +27,8 @@ type VndkProperties struct {
// declared as a VNDK or VNDK-SP module. The vendor variant
// will be installed in /system instead of /vendor partition.
//
// `vendor_available: true` must set to together for VNDK
// modules.
// `vendor_vailable` must be explicitly set to either true or
// false together with `vndk: {enabled: true}`.
Enabled *bool
// declared as a VNDK-SP module, which is a subset of VNDK.
@ -81,6 +81,24 @@ func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module) {
if to.linker == nil {
return
}
if !vndk.isVndk() {
// Non-VNDK modules (those installed to /vendor) can't depend on modules marked with
// vendor_available: false.
violation := false
if lib, ok := to.linker.(*llndkStubDecorator); ok && !lib.Properties.Vendor_available {
violation = true
} else {
if _, ok := to.linker.(libraryInterface); ok && to.VendorProperties.Vendor_available != nil && !Bool(to.VendorProperties.Vendor_available) {
// Vendor_available == nil && !Bool(Vendor_available) should be okay since
// it means a vendor-only library which is a valid dependency for non-VNDK
// modules.
violation = true
}
}
if violation {
ctx.ModuleErrorf("Vendor module that is not VNDK should not link to %q which is marked as `vendor_available: false`", to.Name())
}
}
if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
// Check only shared libraries.
// Other (static and LL-NDK) libraries are allowed to link.
@ -105,13 +123,14 @@ var (
vndkCoreLibraries []string
vndkSpLibraries []string
llndkLibraries []string
vndkPrivateLibraries []string
vndkLibrariesLock sync.Mutex
)
// gather list of vndk-core, vndk-sp, and ll-ndk libs
func vndkMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok {
if _, ok := m.linker.(*llndkStubDecorator); ok {
if lib, ok := m.linker.(*llndkStubDecorator); ok {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
name := strings.TrimSuffix(m.Name(), llndkLibrarySuffix)
@ -119,22 +138,40 @@ func vndkMutator(mctx android.BottomUpMutatorContext) {
llndkLibraries = append(llndkLibraries, name)
sort.Strings(llndkLibraries)
}
} else if lib, ok := m.linker.(*libraryDecorator); ok && lib.shared() {
if !lib.Properties.Vendor_available {
if !inList(name, vndkPrivateLibraries) {
vndkPrivateLibraries = append(vndkPrivateLibraries, name)
sort.Strings(vndkPrivateLibraries)
}
}
} else {
lib, is_lib := m.linker.(*libraryDecorator)
prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker)
if (is_lib && lib.shared()) || (is_prebuilt_lib && prebuilt_lib.shared()) {
name := strings.TrimPrefix(m.Name(), "prebuilt_")
if m.vndkdep.isVndk() {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
if m.vndkdep.isVndkSp() {
if !inList(m.Name(), vndkSpLibraries) {
vndkSpLibraries = append(vndkSpLibraries, m.Name())
if !inList(name, vndkSpLibraries) {
vndkSpLibraries = append(vndkSpLibraries, name)
sort.Strings(vndkSpLibraries)
}
} else {
if !inList(m.Name(), vndkCoreLibraries) {
vndkCoreLibraries = append(vndkCoreLibraries, m.Name())
if !inList(name, vndkCoreLibraries) {
vndkCoreLibraries = append(vndkCoreLibraries, name)
sort.Strings(vndkCoreLibraries)
}
}
if !Bool(m.VendorProperties.Vendor_available) {
if !inList(name, vndkPrivateLibraries) {
vndkPrivateLibraries = append(vndkPrivateLibraries, name)
sort.Strings(vndkPrivateLibraries)
}
}
}
}
}
}
}