Support VNDK extensions
am: f351174107
Change-Id: Ic8694308013e535da7431da1520e5ea023f5f0e1
This commit is contained in:
@@ -38,7 +38,6 @@ const (
|
||||
|
||||
var (
|
||||
abiCheckAllowFlags = []string{
|
||||
"-allow-extensions",
|
||||
"-allow-unreferenced-changes",
|
||||
"-allow-unreferenced-elf-symbol-changes",
|
||||
}
|
||||
@@ -711,12 +710,18 @@ func UnzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseNam
|
||||
}
|
||||
|
||||
func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
|
||||
baseName, exportedHeaderFlags string) android.OptionalPath {
|
||||
baseName, exportedHeaderFlags string, isVndkExt bool) android.OptionalPath {
|
||||
|
||||
outputFile := android.PathForModuleOut(ctx, baseName+".abidiff")
|
||||
|
||||
localAbiCheckAllowFlags := append([]string(nil), abiCheckAllowFlags...)
|
||||
if exportedHeaderFlags == "" {
|
||||
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
|
||||
}
|
||||
if isVndkExt {
|
||||
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
|
||||
}
|
||||
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: sAbiDiff,
|
||||
Description: "header-abi-diff " + outputFile.Base(),
|
||||
|
118
cc/cc.go
118
cc/cc.go
@@ -205,9 +205,11 @@ type ModuleContextIntf interface {
|
||||
useVndk() bool
|
||||
isVndk() bool
|
||||
isVndkSp() bool
|
||||
isVndkExt() bool
|
||||
createVndkSourceAbiDump() bool
|
||||
selectedStl() string
|
||||
baseModuleName() string
|
||||
getVndkExtendsModuleName() string
|
||||
}
|
||||
|
||||
type ModuleContext interface {
|
||||
@@ -289,6 +291,7 @@ var (
|
||||
reuseObjTag = dependencyTag{name: "reuse objects"}
|
||||
ndkStubDepTag = dependencyTag{name: "ndk stub", library: true}
|
||||
ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true}
|
||||
vndkExtDepTag = dependencyTag{name: "vndk extends", library: true}
|
||||
)
|
||||
|
||||
// Module contains the properties and members used by all C/C++ module types, and implements
|
||||
@@ -398,12 +401,33 @@ func (c *Module) useVndk() bool {
|
||||
}
|
||||
|
||||
func (c *Module) isVndk() bool {
|
||||
if c.vndkdep != nil {
|
||||
return c.vndkdep.isVndk()
|
||||
if vndkdep := c.vndkdep; vndkdep != nil {
|
||||
return vndkdep.isVndk()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) isVndkSp() bool {
|
||||
if vndkdep := c.vndkdep; vndkdep != nil {
|
||||
return vndkdep.isVndkSp()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) isVndkExt() bool {
|
||||
if vndkdep := c.vndkdep; vndkdep != nil {
|
||||
return vndkdep.isVndkExt()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) getVndkExtendsModuleName() string {
|
||||
if vndkdep := c.vndkdep; vndkdep != nil {
|
||||
return vndkdep.getVndkExtendsModuleName()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Returns true only when this module is configured to have core and vendor
|
||||
// variants.
|
||||
func (c *Module) hasVendorVariant() bool {
|
||||
@@ -474,18 +498,20 @@ func (ctx *moduleContextImpl) sdkVersion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isVndk() bool {
|
||||
return ctx.mod.isVndk()
|
||||
}
|
||||
func (ctx *moduleContextImpl) useVndk() bool {
|
||||
return ctx.mod.useVndk()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isVndk() bool {
|
||||
return ctx.mod.isVndk()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isVndkSp() bool {
|
||||
if vndk := ctx.mod.vndkdep; vndk != nil {
|
||||
return vndk.isVndkSp()
|
||||
}
|
||||
return false
|
||||
return ctx.mod.isVndkSp()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) isVndkExt() bool {
|
||||
return ctx.mod.isVndkExt()
|
||||
}
|
||||
|
||||
// Create source abi dumps if the module belongs to the list of VndkLibraries.
|
||||
@@ -504,6 +530,10 @@ func (ctx *moduleContextImpl) baseModuleName() string {
|
||||
return ctx.mod.ModuleBase.BaseModuleName()
|
||||
}
|
||||
|
||||
func (ctx *moduleContextImpl) getVndkExtendsModuleName() string {
|
||||
return ctx.mod.getVndkExtendsModuleName()
|
||||
}
|
||||
|
||||
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
||||
return &Module{
|
||||
hod: hod,
|
||||
@@ -935,6 +965,18 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
{"ndk_api", version}, {"link", "shared"}}, ndkStubDepTag, variantNdkLibs...)
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{"ndk_api", version}, {"link", "shared"}}, ndkLateStubDepTag, variantLateNdkLibs...)
|
||||
|
||||
if vndkdep := c.vndkdep; vndkdep != nil {
|
||||
if vndkdep.isVndkExt() {
|
||||
baseModuleMode := vendorMode
|
||||
if actx.DeviceConfig().VndkVersion() == "" {
|
||||
baseModuleMode = coreMode
|
||||
}
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{"image", baseModuleMode}, {"link", "shared"}}, vndkExtDepTag,
|
||||
vndkdep.getVndkExtendsModuleName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func beginMutator(ctx android.BottomUpMutatorContext) {
|
||||
@@ -959,7 +1001,7 @@ func (c *Module) clang(ctx BaseModuleContext) bool {
|
||||
|
||||
// Whether a module can link to another module, taking into
|
||||
// account NDK linking.
|
||||
func checkLinkType(ctx android.ModuleContext, from *Module, to *Module) {
|
||||
func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag dependencyTag) {
|
||||
if from.Target().Os != android.Android {
|
||||
// Host code is not restricted
|
||||
return
|
||||
@@ -969,7 +1011,7 @@ func checkLinkType(ctx android.ModuleContext, from *Module, to *Module) {
|
||||
// each vendor-available module needs to check
|
||||
// link-type for VNDK.
|
||||
if from.vndkdep != nil {
|
||||
from.vndkdep.vndkCheckLinkType(ctx, to)
|
||||
from.vndkdep.vndkCheckLinkType(ctx, to, tag)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1151,7 +1193,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||
}
|
||||
}
|
||||
|
||||
checkLinkType(ctx, c, ccDep)
|
||||
checkLinkType(ctx, c, ccDep, t)
|
||||
}
|
||||
|
||||
var ptr *android.Paths
|
||||
@@ -1411,21 +1453,47 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if m.VendorProperties.Vendor_available != nil && (mctx.SocSpecific() || mctx.DeviceSpecific()) {
|
||||
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
|
||||
|
||||
if m.VendorProperties.Vendor_available != nil && vendorSpecific {
|
||||
mctx.PropertyErrorf("vendor_available",
|
||||
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
|
||||
return
|
||||
}
|
||||
if vndk := m.vndkdep; vndk != nil {
|
||||
if vndk.isVndk() && m.VendorProperties.Vendor_available == nil {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
|
||||
return
|
||||
}
|
||||
if !vndk.isVndk() && vndk.isVndkSp() {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"must set `enabled: true` to set `support_system_process: true`")
|
||||
return
|
||||
|
||||
if vndkdep := m.vndkdep; vndkdep != nil {
|
||||
if vndkdep.isVndk() {
|
||||
if vendorSpecific {
|
||||
if !vndkdep.isVndkExt() {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"must set `extends: \"...\"` to vndk extension")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if vndkdep.isVndkExt() {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"must set `vendor: true` to set `extends: %q`",
|
||||
m.getVndkExtendsModuleName())
|
||||
return
|
||||
}
|
||||
if m.VendorProperties.Vendor_available == nil {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if vndkdep.isVndkSp() {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"must set `enabled: true` to set `support_system_process: true`")
|
||||
return
|
||||
}
|
||||
if vndkdep.isVndkExt() {
|
||||
mctx.PropertyErrorf("vndk",
|
||||
"must set `enabled: true` to set `extends: %q`",
|
||||
m.getVndkExtendsModuleName())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,14 +1521,14 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
|
||||
vendor.Properties.PreventInstall = true
|
||||
vendor.Properties.HideFromMake = true
|
||||
}
|
||||
} else if m.hasVendorVariant() {
|
||||
} else if m.hasVendorVariant() && !vendorSpecific {
|
||||
// This will be available in both /system and /vendor
|
||||
// or a /system directory that is available to vendor.
|
||||
mod := mctx.CreateVariations(coreMode, vendorMode)
|
||||
vendor := mod[1].(*Module)
|
||||
vendor.Properties.UseVndk = true
|
||||
squashVendorSrcs(vendor)
|
||||
} else if (mctx.SocSpecific() || mctx.DeviceSpecific()) && String(m.Properties.Sdk_version) == "" {
|
||||
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
|
||||
// This will be available in /vendor (or /odm) only
|
||||
mod := mctx.CreateVariations(vendorMode)
|
||||
vendor := mod[0].(*Module)
|
||||
|
620
cc/cc_test.go
620
cc/cc_test.go
@@ -22,6 +22,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -52,10 +53,7 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(run())
|
||||
}
|
||||
|
||||
func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
config := android.TestArchConfig(buildDir, nil)
|
||||
config.ProductVariables.DeviceVndkVersion = StringPtr("current")
|
||||
|
||||
func createTestContext(t *testing.T, config android.Config, bp string) *android.TestContext {
|
||||
ctx := android.NewTestArchContext()
|
||||
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
|
||||
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
|
||||
@@ -90,8 +88,8 @@ func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
|
||||
cc_library {
|
||||
name: "libc",
|
||||
no_libgcc : true,
|
||||
nocrt : true,
|
||||
no_libgcc: true,
|
||||
nocrt: true,
|
||||
system_shared_libs: [],
|
||||
}
|
||||
llndk_library {
|
||||
@@ -100,8 +98,8 @@ func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
}
|
||||
cc_library {
|
||||
name: "libm",
|
||||
no_libgcc : true,
|
||||
nocrt : true,
|
||||
no_libgcc: true,
|
||||
nocrt: true,
|
||||
system_shared_libs: [],
|
||||
}
|
||||
llndk_library {
|
||||
@@ -110,8 +108,8 @@ func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
}
|
||||
cc_library {
|
||||
name: "libdl",
|
||||
no_libgcc : true,
|
||||
nocrt : true,
|
||||
no_libgcc: true,
|
||||
nocrt: true,
|
||||
system_shared_libs: [],
|
||||
}
|
||||
llndk_library {
|
||||
@@ -142,6 +140,12 @@ func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
"my_include": nil,
|
||||
})
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func testCcWithConfig(t *testing.T, bp string, config android.Config) *android.TestContext {
|
||||
ctx := createTestContext(t, config, bp)
|
||||
|
||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||
failIfErrored(t, errs)
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
@@ -150,14 +154,56 @@ func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func testCc(t *testing.T, bp string) *android.TestContext {
|
||||
config := android.TestArchConfig(buildDir, nil)
|
||||
config.ProductVariables.DeviceVndkVersion = StringPtr("current")
|
||||
config.ProductVariables.Platform_vndk_version = StringPtr("VER")
|
||||
|
||||
return testCcWithConfig(t, bp, config)
|
||||
}
|
||||
|
||||
func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
|
||||
config := android.TestArchConfig(buildDir, nil)
|
||||
config.ProductVariables.Platform_vndk_version = StringPtr("VER")
|
||||
|
||||
return testCcWithConfig(t, bp, config)
|
||||
}
|
||||
|
||||
func testCcError(t *testing.T, pattern string, bp string) {
|
||||
config := android.TestArchConfig(buildDir, nil)
|
||||
config.ProductVariables.DeviceVndkVersion = StringPtr("current")
|
||||
config.ProductVariables.Platform_vndk_version = StringPtr("VER")
|
||||
|
||||
ctx := createTestContext(t, config, bp)
|
||||
|
||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||
if len(errs) > 0 {
|
||||
failIfNoMatchingErrors(t, pattern, errs)
|
||||
return
|
||||
}
|
||||
|
||||
_, errs = ctx.PrepareBuildActions(config)
|
||||
if len(errs) > 0 {
|
||||
failIfNoMatchingErrors(t, pattern, errs)
|
||||
return
|
||||
}
|
||||
|
||||
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
|
||||
}
|
||||
|
||||
const (
|
||||
coreVariant = "android_arm64_armv8-a_core_shared"
|
||||
vendorVariant = "android_arm64_armv8-a_vendor_shared"
|
||||
)
|
||||
|
||||
func TestVendorSrc(t *testing.T) {
|
||||
ctx := testCc(t, `
|
||||
cc_library {
|
||||
name: "libTest",
|
||||
srcs: ["foo.c"],
|
||||
no_libgcc : true,
|
||||
nocrt : true,
|
||||
system_shared_libs : [],
|
||||
no_libgcc: true,
|
||||
nocrt: true,
|
||||
system_shared_libs: [],
|
||||
vendor_available: true,
|
||||
target: {
|
||||
vendor: {
|
||||
@@ -167,7 +213,7 @@ func TestVendorSrc(t *testing.T) {
|
||||
}
|
||||
`)
|
||||
|
||||
ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
|
||||
ld := ctx.ModuleForTests("libTest", vendorVariant).Rule("ld")
|
||||
var objs []string
|
||||
for _, o := range ld.Inputs {
|
||||
objs = append(objs, o.Base())
|
||||
@@ -177,6 +223,524 @@ func TestVendorSrc(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
|
||||
isVndkSp bool, extends string) {
|
||||
|
||||
mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
|
||||
if !mod.hasVendorVariant() {
|
||||
t.Error("%q must have vendor variant", name)
|
||||
}
|
||||
|
||||
// Check library properties.
|
||||
lib, ok := mod.compiler.(*libraryDecorator)
|
||||
if !ok {
|
||||
t.Errorf("%q must have libraryDecorator", name)
|
||||
} else if lib.baseInstaller.subDir != subDir {
|
||||
t.Errorf("%q must use %q as subdir but it is using %q", name, subDir,
|
||||
lib.baseInstaller.subDir)
|
||||
}
|
||||
|
||||
// Check VNDK properties.
|
||||
if mod.vndkdep == nil {
|
||||
t.Fatalf("%q must have `vndkdep`", name)
|
||||
}
|
||||
if !mod.isVndk() {
|
||||
t.Errorf("%q isVndk() must equal to true", name)
|
||||
}
|
||||
if mod.isVndkSp() != isVndkSp {
|
||||
t.Errorf("%q isVndkSp() must equal to %t", name, isVndkSp)
|
||||
}
|
||||
|
||||
// Check VNDK extension properties.
|
||||
isVndkExt := extends != ""
|
||||
if mod.isVndkExt() != isVndkExt {
|
||||
t.Errorf("%q isVndkExt() must equal to %t", name, isVndkExt)
|
||||
}
|
||||
|
||||
if actualExtends := mod.getVndkExtendsModuleName(); actualExtends != extends {
|
||||
t.Errorf("%q must extend from %q but get %q", name, extends, actualExtends)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVndk(t *testing.T) {
|
||||
ctx := testCc(t, `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_private",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_private",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
|
||||
checkVndkModule(t, ctx, "libvndk_private", "vndk-VER", false, "")
|
||||
checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
|
||||
checkVndkModule(t, ctx, "libvndk_sp_private", "vndk-sp-VER", true, "")
|
||||
}
|
||||
|
||||
func TestVndkExt(t *testing.T) {
|
||||
// This test checks the VNDK-Ext properties.
|
||||
ctx := testCc(t, `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
checkVndkModule(t, ctx, "libvndk_ext", "vndk", false, "libvndk")
|
||||
}
|
||||
|
||||
func TestVndkExtNoVndk(t *testing.T) {
|
||||
// This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
|
||||
ctx := testCcNoVndk(t, `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// Ensures that the core variant of "libvndk_ext" can be found.
|
||||
mod := ctx.ModuleForTests("libvndk_ext", coreVariant).Module().(*Module)
|
||||
if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
|
||||
t.Errorf("\"libvndk_ext\" must extend from \"libvndk\" but get %q", extends)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVndkExtError(t *testing.T) {
|
||||
// This test ensures an error is emitted in ill-formed vndk-ext definition.
|
||||
testCcError(t, "must set `vendor: true` to set `extends: \".*\"`", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
testCcError(t, "must set `extends: \"\\.\\.\\.\"` to vndk extension", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkExtInconsistentSupportSystemProcessError(t *testing.T) {
|
||||
// This test ensures an error is emitted for inconsistent support_system_process.
|
||||
testCcError(t, "module \".*\" with mismatched support_system_process", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
testCcError(t, "module \".*\" with mismatched support_system_process", `
|
||||
cc_library {
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk_sp",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkExtVendorAvailableFalseError(t *testing.T) {
|
||||
// This test ensures an error is emitted when a vndk-ext library extends a vndk library
|
||||
// with `vendor_available: false`.
|
||||
testCcError(t, "`extends` refers module \".*\" which does not have `vendor_available: true`", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: false,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVendorModuleUsesVndkExt(t *testing.T) {
|
||||
// This test ensures a vendor module can depend on a vndk-ext library.
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk_sp",
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvendor",
|
||||
vendor: true,
|
||||
shared_libs: ["libvndk_ext", "libvndk_sp_ext"],
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkExtUsesVendorLib(t *testing.T) {
|
||||
// This test ensures a vndk-ext library can depend on a vendor library.
|
||||
testCc(t, `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
shared_libs: ["libvendor"],
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvendor",
|
||||
vendor: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkSpExtUsesVendorLibError(t *testing.T) {
|
||||
// This test ensures an error is emitted if a vndk-sp-ext library depends on a vendor
|
||||
// library.
|
||||
testCcError(t, "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\"", `
|
||||
cc_library {
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk_sp",
|
||||
support_system_process: true,
|
||||
},
|
||||
shared_libs: ["libvendor"], // Cause an error
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvendor",
|
||||
vendor: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestVndkUsesVndkExtError(t *testing.T) {
|
||||
// This test ensures an error is emitted if a vndk/vndk-sp library depends on a
|
||||
// vndk-ext/vndk-sp-ext library.
|
||||
testCcError(t, "dependency \".*\" of \".*\" missing variant", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk2",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: ["libvndk_ext"],
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
|
||||
// but target.vendor.shared_libs has not been supported yet.
|
||||
testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
|
||||
cc_library {
|
||||
name: "libvndk",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk2",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
target: {
|
||||
vendor: {
|
||||
shared_libs: ["libvndk_ext"],
|
||||
},
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
testCcError(t, "dependency \".*\" of \".*\" missing variant", `
|
||||
cc_library {
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk_sp",
|
||||
support_system_process: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_2",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
support_system_process: true,
|
||||
},
|
||||
shared_libs: ["libvndk_sp_ext"],
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
// The pattern should be "module \".*\" variant \".*\": \\(.*\\) should not link to \".*\""
|
||||
// but target.vendor.shared_libs has not been supported yet.
|
||||
testCcError(t, "unrecognized property \"target.vendor.shared_libs\"", `
|
||||
cc_library {
|
||||
name: "libvndk_sp",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp_ext",
|
||||
vendor: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
extends: "libvndk_sp",
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libvndk_sp2",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
target: {
|
||||
vendor: {
|
||||
shared_libs: ["libvndk_sp_ext"],
|
||||
},
|
||||
},
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
var (
|
||||
str11 = "01234567891"
|
||||
str10 = str11[:10]
|
||||
@@ -499,6 +1063,7 @@ func TestLinkReordering(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func failIfErrored(t *testing.T, errs []error) {
|
||||
if len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
@@ -508,6 +1073,29 @@ func failIfErrored(t *testing.T, errs []error) {
|
||||
}
|
||||
}
|
||||
|
||||
func failIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
|
||||
matcher, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
t.Errorf("failed to compile regular expression %q because %s", pattern, err)
|
||||
}
|
||||
|
||||
found := false
|
||||
|
||||
for _, err := range errs {
|
||||
if matcher.FindStringIndex(err.Error()) != nil {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
|
||||
for i, err := range errs {
|
||||
t.Errorf("errs[%d] = %s", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
|
||||
for _, moduleName := range moduleNames {
|
||||
module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
|
||||
@@ -597,8 +1185,8 @@ func TestLlndkHeaders(t *testing.T) {
|
||||
shared_libs: ["libllndk"],
|
||||
vendor: true,
|
||||
srcs: ["foo.c"],
|
||||
no_libgcc : true,
|
||||
nocrt : true,
|
||||
no_libgcc: true,
|
||||
nocrt: true,
|
||||
}
|
||||
`)
|
||||
|
||||
|
@@ -416,6 +416,10 @@ func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
|
||||
name = ctx.baseModuleName()
|
||||
}
|
||||
|
||||
if ctx.isVndkExt() {
|
||||
name = ctx.getVndkExtendsModuleName()
|
||||
}
|
||||
|
||||
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
|
||||
if !strings.HasSuffix(name, "-host") {
|
||||
name = name + "-host"
|
||||
@@ -619,7 +623,12 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
|
||||
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
|
||||
//Also take into account object re-use.
|
||||
if len(objs.sAbiDumpFiles) > 0 && ctx.createVndkSourceAbiDump() {
|
||||
refSourceDumpFile := android.PathForVndkRefAbiDump(ctx, "current", fileName, vndkVsNdk(ctx), true)
|
||||
vndkVersion := "current"
|
||||
if ver := ctx.DeviceConfig().VndkVersion(); ver != "" {
|
||||
vndkVersion = ver
|
||||
}
|
||||
|
||||
refSourceDumpFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, vndkVsNdk(ctx), true)
|
||||
exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
|
||||
var SourceAbiFlags []string
|
||||
for _, dir := range exportIncludeDirs.Strings() {
|
||||
@@ -632,7 +641,8 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec
|
||||
library.sAbiOutputFile = TransformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags)
|
||||
if refSourceDumpFile.Valid() {
|
||||
unzippedRefDump := UnzipRefDump(ctx, refSourceDumpFile.Path(), fileName)
|
||||
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(), unzippedRefDump, fileName, exportedHeaderFlags)
|
||||
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
|
||||
unzippedRefDump, fileName, exportedHeaderFlags, ctx.isVndkExt())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -721,8 +731,13 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
|
||||
} else if ctx.isVndk() {
|
||||
library.baseInstaller.subDir = "vndk"
|
||||
}
|
||||
if ctx.isVndk() && ctx.DeviceConfig().PlatformVndkVersion() != "current" {
|
||||
library.baseInstaller.subDir += "-" + ctx.DeviceConfig().PlatformVndkVersion()
|
||||
|
||||
// Append a version to vndk or vndk-sp directories on the system partition.
|
||||
if ctx.isVndk() && !ctx.isVndkExt() {
|
||||
vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
|
||||
if vndkVersion != "current" && vndkVersion != "" {
|
||||
library.baseInstaller.subDir += "-" + vndkVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
library.baseInstaller.install(ctx, file)
|
||||
|
63
cc/vndk.go
63
cc/vndk.go
@@ -42,6 +42,9 @@ type VndkProperties struct {
|
||||
// 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 @@ func (vndk *vndkdep) isVndkSp() bool {
|
||||
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 @@ func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module) {
|
||||
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 @@ func vndkMutator(mctx android.BottomUpMutatorContext) {
|
||||
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() {
|
||||
|
Reference in New Issue
Block a user