Support VNDK extensions
This commit adds `extends: "name"` property and provides basic support
to VNDK extensions. This is the simplest example:
```
cc_library {
name: "libvndk",
vendor_available: true,
vndk {
enabled: true,
},
}
cc_library {
name: "libvndk_ext",
vendor: true,
vndk: {
enabled: true,
extends: "libvndk",
},
}
```
A vndk extension library must extend an existing vndk library which has
`vendor_available: true`. These two libraries must have the same
`support_system_process` property.
VNDK-ext libraries are installed to `/vendor/lib[64]/vndk` and
VNDK-SP-ext libraries are installed to `/vendor/lib[64]/vndk-sp` by
default.
If there is a matching abi-dumps in `prebuilts/abi-dumps`,
`header-abi-diff` will be invoked to check for ABI breakages.
Bug: 38340960
Test: lunch aosp_walleye-userdebug && make -j8 # runs unit tests
Test: lunch aosp_arm-userdebug && make -j8 # build a target w/o VNDK
Test: Create a lsdump for a vndk lib, add an exported API to vndk lib,
and build fails as expected.
Test: Create a lsdump for a vndk lib, create an vndk extension lib with
extra API, and build succeeds as expected.
Test: Create libutils_ext, add an extra function to libutils_ext, and
call it from a HIDL service.
Change-Id: Iba90e08848ee99814405457f047321e6b52b2df0
diff --git a/cc/vndk.go b/cc/vndk.go
index a61b74c..d417bea 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -42,6 +42,9 @@
// the module is VNDK-core and can link to other VNDK-core,
// VNDK-SP or LL-NDK modules only.
Support_system_process *bool
+
+ // Extending another module
+ Extends *string
}
}
@@ -67,17 +70,31 @@
return Bool(vndk.Properties.Vndk.Support_system_process)
}
+func (vndk *vndkdep) isVndkExt() bool {
+ return vndk.Properties.Vndk.Extends != nil
+}
+
+func (vndk *vndkdep) getVndkExtendsModuleName() string {
+ return String(vndk.Properties.Vndk.Extends)
+}
+
func (vndk *vndkdep) typeName() string {
if !vndk.isVndk() {
return "native:vendor"
}
- if !vndk.isVndkSp() {
- return "native:vendor:vndk"
+ if !vndk.isVndkExt() {
+ if !vndk.isVndkSp() {
+ return "native:vendor:vndk"
+ }
+ return "native:vendor:vndksp"
}
- return "native:vendor:vndksp"
+ if !vndk.isVndkSp() {
+ return "native:vendor:vndkext"
+ }
+ return "native:vendor:vndkspext"
}
-func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module) {
+func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag dependencyTag) {
if to.linker == nil {
return
}
@@ -109,11 +126,43 @@
vndk.typeName(), to.Name())
return
}
+ if tag == vndkExtDepTag {
+ // Ensure `extends: "name"` property refers a vndk module that has vendor_available
+ // and has identical vndk properties.
+ if to.vndkdep == nil || !to.vndkdep.isVndk() {
+ ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name())
+ return
+ }
+ if vndk.isVndkSp() != to.vndkdep.isVndkSp() {
+ ctx.ModuleErrorf(
+ "`extends` refers a module %q with mismatched support_system_process",
+ to.Name())
+ return
+ }
+ if !Bool(to.VendorProperties.Vendor_available) {
+ ctx.ModuleErrorf(
+ "`extends` refers module %q which does not have `vendor_available: true`",
+ to.Name())
+ return
+ }
+ }
if to.vndkdep == nil {
return
}
- if (vndk.isVndk() && !to.vndkdep.isVndk()) || (vndk.isVndkSp() && !to.vndkdep.isVndkSp()) {
- ctx.ModuleErrorf("(%s) should not link to %q(%s)",
+
+ // VNDK-core and VNDK-SP must not depend on VNDK extensions.
+ if (vndk.isVndk() || vndk.isVndkSp()) && !vndk.isVndkExt() && to.vndkdep.isVndkExt() {
+ ctx.ModuleErrorf("(%s) should not link to %q (%s)",
+ vndk.typeName(), to.Name(), to.vndkdep.typeName())
+ return
+ }
+
+ // VNDK-core must be only depend on VNDK-SP or LL-NDK. VNDK-SP must only depend on
+ // LL-NDK, regardless the extension status. VNDK-Ext may depend on vendor libraries, but
+ // VNDK-SP-Ext must remain self-contained.
+ if (vndk.isVndk() && !to.vndkdep.isVndk() && !vndk.isVndkExt()) ||
+ (vndk.isVndkSp() && !to.vndkdep.isVndkSp()) {
+ ctx.ModuleErrorf("(%s) should not link to %q (%s)",
vndk.typeName(), to.Name(), to.vndkdep.typeName())
return
}
@@ -149,7 +198,7 @@
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() {
+ if m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
vndkLibrariesLock.Lock()
defer vndkLibrariesLock.Unlock()
if m.vndkdep.isVndkSp() {