Merge "Add PLATFORM_SYSTEMSDK_VERSIONS and BOARD_SYSTEMSDK_VERSIONS"
diff --git a/OWNERS b/OWNERS
index 004d638..c0c3762 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,9 @@
ccross@android.com
dwillemsen@google.com
+nanzhang@google.com
per-file * = ccross@android.com
per-file * = dwillemsen@google.com
+per-file * = nanzhang@google.com
per-file *gen_stub_libs.py = danalbert@google.com
per-file ndk_*.go = danalbert@google.com
diff --git a/cc/builder.go b/cc/builder.go
index fcc4318..fe35d5c 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -38,7 +38,6 @@
var (
abiCheckAllowFlags = []string{
- "-allow-extensions",
"-allow-unreferenced-changes",
"-allow-unreferenced-elf-symbol-changes",
}
@@ -711,8 +710,18 @@
}
func SourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName 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(),
@@ -723,7 +732,7 @@
"referenceDump": referenceDump.String(),
"libName": baseName,
"arch": ctx.Arch().ArchType.Name,
- "allowFlags": strings.Join(abiCheckAllowFlags, " "),
+ "allowFlags": strings.Join(localAbiCheckAllowFlags, " "),
},
})
return android.OptionalPathForPath(outputFile)
diff --git a/cc/cc.go b/cc/cc.go
index e5a483d..9b1f220 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -205,9 +205,11 @@
useVndk() bool
isVndk() bool
isVndkSp() bool
+ isVndkExt() bool
createVndkSourceAbiDump() bool
selectedStl() string
baseModuleName() string
+ getVndkExtendsModuleName() string
}
type ModuleContext interface {
@@ -289,6 +291,7 @@
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) 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 @@
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 @@
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 @@
{"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 @@
// 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 @@
// 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 @@
}
}
- checkLinkType(ctx, c, ccDep)
+ checkLinkType(ctx, c, ccDep, t)
}
var ptr *android.Paths
@@ -1411,21 +1453,47 @@
}
// 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
+ }
}
}
@@ -1442,20 +1510,25 @@
mod := mctx.CreateVariations(vendorMode)
vendor := mod[0].(*Module)
vendor.Properties.UseVndk = true
- } else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
+ } else if prebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
mod := mctx.CreateVariations(vendorMode)
vendor := mod[0].(*Module)
vendor.Properties.UseVndk = true
- } else if m.hasVendorVariant() {
+ arches := mctx.DeviceConfig().Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != prebuilt.arch() {
+ vendor.Properties.PreventInstall = true
+ vendor.Properties.HideFromMake = true
+ }
+ } 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)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 4d8c4fb..19e4703 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -22,6 +22,7 @@
"io/ioutil"
"os"
"reflect"
+ "regexp"
"sort"
"strings"
"testing"
@@ -52,10 +53,7 @@
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 @@
cc_library {
name: "libc",
- no_libgcc : true,
- nocrt : true,
+ no_libgcc: true,
+ nocrt: true,
system_shared_libs: [],
}
llndk_library {
@@ -100,8 +98,8 @@
}
cc_library {
name: "libm",
- no_libgcc : true,
- nocrt : true,
+ no_libgcc: true,
+ nocrt: true,
system_shared_libs: [],
}
llndk_library {
@@ -110,8 +108,8 @@
}
cc_library {
name: "libdl",
- no_libgcc : true,
- nocrt : true,
+ no_libgcc: true,
+ nocrt: true,
system_shared_libs: [],
}
llndk_library {
@@ -142,6 +140,12 @@
"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 @@
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 @@
}
`)
- 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 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 failIfErrored(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
@@ -508,6 +1073,29 @@
}
}
+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 @@
shared_libs: ["libllndk"],
vendor: true,
srcs: ["foo.c"],
- no_libgcc : true,
- nocrt : true,
+ no_libgcc: true,
+ nocrt: true,
}
`)
diff --git a/cc/config/global.go b/cc/config/global.go
index ef710c8..5e99cde 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -112,7 +112,7 @@
ExperimentalCStdVersion = "gnu11"
ExperimentalCppStdVersion = "gnu++1z"
- NdkMaxPrebuiltVersionInt = 24
+ NdkMaxPrebuiltVersionInt = 27
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
diff --git a/cc/library.go b/cc/library.go
index adbd6b5..00282fc 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -416,6 +416,10 @@
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) 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 @@
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)
+ library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
+ unzippedRefDump, fileName, exportedHeaderFlags, ctx.isVndkExt())
}
}
}
@@ -721,15 +731,21 @@
} 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)
}
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
- !ctx.useVndk() && ctx.Device() {
+ !ctx.useVndk() && ctx.Device() &&
+ library.sanitize.isUnsanitizedVariant() {
installPath := getNdkSysrootBase(ctx).Join(
ctx, "usr/lib", ctx.toolchain().ClangTriple(), file.Base())
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 1afec26..02aedc8 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -514,6 +514,12 @@
}
}
+func (sanitize *sanitize) isUnsanitizedVariant() bool {
+ return !sanitize.isSanitizerEnabled(asan) &&
+ !sanitize.isSanitizerEnabled(tsan) &&
+ !sanitize.isSanitizerEnabled(cfi)
+}
+
func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
switch t {
case asan:
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() {
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index b4fcb57..99e35f3 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -111,12 +111,10 @@
func (p *vndkPrebuiltLibraryDecorator) install(ctx ModuleContext, file android.Path) {
if p.shared() {
- if ctx.Device() && ctx.useVndk() {
- if ctx.isVndkSp() {
- p.baseInstaller.subDir = "vndk-sp-" + p.version()
- } else if ctx.isVndk() {
- p.baseInstaller.subDir = "vndk-" + p.version()
- }
+ if ctx.isVndkSp() {
+ p.baseInstaller.subDir = "vndk-sp-" + p.version()
+ } else if ctx.isVndk() {
+ p.baseInstaller.subDir = "vndk-" + p.version()
}
p.baseInstaller.install(ctx, file)
}
diff --git a/ui/build/config.go b/ui/build/config.go
index 0c37724..363121f 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -168,6 +168,8 @@
}()
absJavaHome := absPath(ctx, javaHome)
+ ret.configureLocale(ctx)
+
newPath := []string{filepath.Join(absJavaHome, "bin")}
if path, ok := ret.environ.Get("PATH"); ok && path != "" {
newPath = append(newPath, path)
@@ -228,6 +230,52 @@
}
}
+func (c *configImpl) configureLocale(ctx Context) {
+ cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
+ output, err := cmd.Output()
+
+ var locales []string
+ if err == nil {
+ locales = strings.Split(string(output), "\n")
+ } else {
+ // If we're unable to list the locales, let's assume en_US.UTF-8
+ locales = []string{"en_US.UTF-8"}
+ ctx.Verbosef("Failed to list locales (%q), falling back to %q", err, locales)
+ }
+
+ // gettext uses LANGUAGE, which is passed directly through
+
+ // For LANG and LC_*, only preserve the evaluated version of
+ // LC_MESSAGES
+ user_lang := ""
+ if lc_all, ok := c.environ.Get("LC_ALL"); ok {
+ user_lang = lc_all
+ } else if lc_messages, ok := c.environ.Get("LC_MESSAGES"); ok {
+ user_lang = lc_messages
+ } else if lang, ok := c.environ.Get("LANG"); ok {
+ user_lang = lang
+ }
+
+ c.environ.UnsetWithPrefix("LC_")
+
+ if user_lang != "" {
+ c.environ.Set("LC_MESSAGES", user_lang)
+ }
+
+ // The for LANG, use C.UTF-8 if it exists (Debian currently, proposed
+ // for others)
+ if inList("C.UTF-8", locales) {
+ c.environ.Set("LANG", "C.UTF-8")
+ } else if inList("en_US.UTF-8", locales) {
+ c.environ.Set("LANG", "en_US.UTF-8")
+ } else if inList("en_US.utf8", locales) {
+ // These normalize to the same thing
+ c.environ.Set("LANG", "en_US.UTF-8")
+ } else {
+ ctx.Fatalln("System doesn't support either C.UTF-8 or en_US.UTF-8")
+ }
+}
+
// Lunch configures the environment for a specific product similarly to the
// `lunch` bash function.
func (c *configImpl) Lunch(ctx Context, product, variant string) {
diff --git a/ui/build/environment.go b/ui/build/environment.go
index baab101..8589937 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -63,6 +63,18 @@
*e = out
}
+// UnsetWithPrefix removes all keys that start with prefix.
+func (e *Environment) UnsetWithPrefix(prefix string) {
+ out := (*e)[:0]
+ for _, env := range *e {
+ if key, _, ok := decodeKeyValue(env); ok && strings.HasPrefix(key, prefix) {
+ continue
+ }
+ out = append(out, env)
+ }
+ *e = out
+}
+
// Environ returns the []string required for exec.Cmd.Env
func (e *Environment) Environ() []string {
return []string(*e)