Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 727173ec authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Create product variant for product partition"

parents dcee89ca 5f7f7e8a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -948,6 +948,10 @@ func (c *deviceConfig) PlatformVndkVersion() string {
	return String(c.config.productVariables.Platform_vndk_version)
}

func (c *deviceConfig) ProductVndkVersion() string {
	return String(c.config.productVariables.ProductVndkVersion)
}

func (c *deviceConfig) ExtraVndkVersions() []string {
	return c.config.productVariables.ExtraVndkVersions
}
+2 −0
Original line number Diff line number Diff line
@@ -307,6 +307,8 @@ type productVariables struct {
	ProductPrivateSepolicyDirs []string `json:",omitempty"`
	ProductCompatibleProperty  *bool    `json:",omitempty"`

	ProductVndkVersion *string `json:",omitempty"`

	TargetFSConfigGen []string `json:",omitempty"`

	MissingUsesLibraries []string `json:",omitempty"`
+3 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import (

var (
	nativeBridgeSuffix = ".native_bridge"
	productSuffix      = ".product"
	vendorSuffix       = ".vendor"
	recoverySuffix     = ".recovery"
)
@@ -37,7 +38,7 @@ type AndroidMkContext interface {
	Os() android.OsType
	Host() bool
	UseVndk() bool
	vndkVersion() string
	VndkVersion() string
	static() bool
	InRecovery() bool
}
@@ -92,7 +93,7 @@ func (c *Module) AndroidMk() android.AndroidMkData {
				if c.UseVndk() {
					fmt.Fprintln(w, "LOCAL_USE_VNDK := true")
					if c.IsVndk() && !c.static() {
						fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion())
						fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.VndkVersion())
						// VNDK libraries available to vendor are not installed because
						// they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go)
						if !c.isVndkExt() {
+148 −64
Original line number Diff line number Diff line
@@ -215,6 +215,7 @@ type BaseProperties struct {
	PreventInstall            bool     `blueprint:"mutated"`
	ApexesProvidingSharedLibs []string `blueprint:"mutated"`

	ImageVariationPrefix string `blueprint:"mutated"`
	VndkVersion          string `blueprint:"mutated"`
	SubName              string `blueprint:"mutated"`

@@ -228,7 +229,7 @@ type BaseProperties struct {
	// Set by imageMutator
	CoreVariantNeeded     bool     `blueprint:"mutated"`
	RecoveryVariantNeeded bool     `blueprint:"mutated"`
	VendorVariants        []string `blueprint:"mutated"`
	ExtraVariants         []string `blueprint:"mutated"`

	// Allows this module to use non-APEX version of libraries. Useful
	// for building binaries that are started before APEXes are activated.
@@ -242,20 +243,24 @@ type BaseProperties struct {
type VendorProperties struct {
	// 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.
	// In addition, this module should be allowed to be directly depended by
	// product modules with `product_specific: true`.
	// If set to true, three variants will be built separately, one like
	// normal, another limited to the set of libraries and headers
	// that are exposed to /vendor modules, and the other to /product modules.
	//
	// The vendor variant may be used with a different (newer) /system,
	// The vendor and product variants 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.
	// If set to false, this module becomes inaccessible from /vendor or /product
	// 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
	// If PRODUCT_PRODUCT_VNDK_VERSION isn't set, product variant will not be used.
	Vendor_available *bool

	// whether this module is capable of being loaded with other instance
@@ -283,6 +288,8 @@ type ModuleContextIntf interface {
	isVndk() bool
	isVndkSp() bool
	isVndkExt() bool
	inProduct() bool
	inVendor() bool
	inRecovery() bool
	shouldCreateSourceAbiDump() bool
	selectedStl() string
@@ -683,7 +690,7 @@ func (c *Module) RelativeInstallPath() string {
}

func (c *Module) VndkVersion() string {
	return c.vndkVersion()
	return c.Properties.VndkVersion
}

func (c *Module) Init() android.Module {
@@ -755,6 +762,12 @@ func (c *Module) isDependencyRoot() bool {
	return false
}

// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64.
// "product" and "vendor" variant modules return true for this function.
// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
// "soc_specific: true" and more vendor installed modules are included here.
// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or
// "product_specific: true" modules are included here.
func (c *Module) UseVndk() bool {
	return c.Properties.VndkVersion != ""
}
@@ -790,10 +803,6 @@ func (c *Module) IsVndk() bool {
	return false
}

func (c *Module) vndkVersion() string {
	return c.Properties.VndkVersion
}

func (c *Module) isPgoCompile() bool {
	if pgo := c.pgo; pgo != nil {
		return pgo.Properties.PgoCompile
@@ -833,12 +842,32 @@ func (c *Module) getVndkExtendsModuleName() string {
	return ""
}

// Returns true only when this module is configured to have core and vendor
// Returns true only when this module is configured to have core, product and vendor
// variants.
func (c *Module) HasVendorVariant() bool {
	return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
}

const (
	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
	// against the VNDK.
	VendorVariationPrefix = "vendor."

	// ProductVariationPrefix is the variant prefix used for /product code that compiles
	// against the VNDK.
	ProductVariationPrefix = "product."
)

// Returns true if the module is "product" variant. Usually these modules are installed in /product
func (c *Module) inProduct() bool {
	return c.Properties.ImageVariationPrefix == ProductVariationPrefix
}

// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
func (c *Module) inVendor() bool {
	return c.Properties.ImageVariationPrefix == VendorVariationPrefix
}

func (c *Module) InRecovery() bool {
	return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
}
@@ -947,9 +976,14 @@ type moduleContext struct {
	moduleContextImpl
}

func (ctx *moduleContext) ProductSpecific() bool {
	return ctx.ModuleContext.ProductSpecific() ||
		(ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
}

func (ctx *moduleContext) SocSpecific() bool {
	return ctx.ModuleContext.SocSpecific() ||
		(ctx.mod.HasVendorVariant() && ctx.mod.UseVndk() && !ctx.mod.IsVndk())
		(ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
}

type moduleContextImpl struct {
@@ -983,15 +1017,11 @@ func (ctx *moduleContextImpl) useSdk() bool {
func (ctx *moduleContextImpl) sdkVersion() string {
	if ctx.ctx.Device() {
		if ctx.useVndk() {
			vndk_ver := ctx.ctx.DeviceConfig().VndkVersion()
			if vndk_ver == "current" {
				platform_vndk_ver := ctx.ctx.DeviceConfig().PlatformVndkVersion()
				if inList(platform_vndk_ver, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
			vndkVer := ctx.mod.VndkVersion()
			if inList(vndkVer, ctx.ctx.Config().PlatformVersionCombinedCodenames()) {
				return "current"
			}
				return platform_vndk_ver
			}
			return vndk_ver
			return vndkVer
		}
		return String(ctx.mod.Properties.Sdk_version)
	}
@@ -1042,6 +1072,14 @@ func (ctx *moduleContextImpl) mustUseVendorVariant() bool {
	return ctx.mod.MustUseVendorVariant()
}

func (ctx *moduleContextImpl) inProduct() bool {
	return ctx.mod.inProduct()
}

func (ctx *moduleContextImpl) inVendor() bool {
	return ctx.mod.inVendor()
}

func (ctx *moduleContextImpl) inRecovery() bool {
	return ctx.mod.InRecovery()
}
@@ -1225,6 +1263,29 @@ func (c *Module) IsTestPerSrcAllTestsVariation() bool {
	return ok && test.isAllTestsVariation()
}

func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string {
	// Returns the name suffix for product and vendor variants. If the VNDK version is not
	// "current", it will append the VNDK version to the name suffix.
	var vndkVersion string
	var nameSuffix string
	if c.inProduct() {
		vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
		nameSuffix = productSuffix
	} else {
		vndkVersion = ctx.DeviceConfig().VndkVersion()
		nameSuffix = vendorSuffix
	}
	if vndkVersion == "current" {
		vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
	}
	if c.Properties.VndkVersion != vndkVersion {
		// add version suffix only if the module is using different vndk version than the
		// version in product or vendor partition.
		nameSuffix += "." + c.Properties.VndkVersion
	}
	return nameSuffix
}

func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
	// Handle the case of a test module split by `test_per_src` mutator.
	//
@@ -1244,21 +1305,17 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
		c.Properties.SubName += nativeBridgeSuffix
	}

	if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
	_, llndk := c.linker.(*llndkStubDecorator)
	_, llndkHeader := c.linker.(*llndkHeadersDecorator)
	if llndk || llndkHeader || (c.UseVndk() && c.HasVendorVariant()) {
		// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
		// added for product variant only when we have vendor and product variants with core
		// variant. The suffix is not added for vendor-only or product-only module.
		c.Properties.SubName += c.getNameSuffixWithVndkVersion(actx)
	} else if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
		// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
		// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
		c.Properties.SubName += vendorSuffix
	} else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.UseVndk() && c.HasVendorVariant()) {
		// .vendor.{version} suffix is added only when we will have two variants: core and vendor.
		// The suffix is not added for vendor-only module.
		c.Properties.SubName += vendorSuffix
		vendorVersion := actx.DeviceConfig().VndkVersion()
		if vendorVersion == "current" {
			vendorVersion = actx.DeviceConfig().PlatformVndkVersion()
		}
		if c.Properties.VndkVersion != vendorVersion {
			c.Properties.SubName += "." + c.Properties.VndkVersion
		}
	} else if c.InRecovery() && !c.OnlyInRecovery() {
		c.Properties.SubName += recoverySuffix
	}
@@ -2206,15 +2263,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
			} else if c.UseVndk() && bothVendorAndCoreVariantsExist {
				// The vendor module in Make will have been renamed to not conflict with the core
				// module, so update the dependency name here accordingly.
				ret := libName + vendorSuffix
				vendorVersion := ctx.DeviceConfig().VndkVersion()
				if vendorVersion == "current" {
					vendorVersion = ctx.DeviceConfig().PlatformVndkVersion()
				}
				if c.Properties.VndkVersion != vendorVersion {
					ret += "." + c.Properties.VndkVersion
				}
				return ret
				return libName + c.getNameSuffixWithVndkVersion(ctx)
			} else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
				return libName + vendorPublicLibrarySuffix
			} else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
@@ -2367,6 +2416,9 @@ func (c *Module) getMakeLinkType(actx android.ModuleContext) string {
			}
			return "native:vndk_private"
		}
		if c.inProduct() {
			return "native:product"
		}
		return "native:vendor"
	} else if c.InRecovery() {
		return "native:recovery"
@@ -2492,12 +2544,6 @@ func DefaultsFactory(props ...interface{}) android.Module {
	return module
}

const (
	// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
	// against the VNDK.
	VendorVariationPrefix = "vendor."
)

func squashVendorSrcs(m *Module) {
	if lib, ok := m.compiler.(*libraryDecorator); ok {
		lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
@@ -2569,49 +2615,65 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
	var recoveryVariantNeeded bool = false

	var vendorVariants []string
	var productVariants []string

	platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
	deviceVndkVersion := mctx.DeviceConfig().VndkVersion()
	if deviceVndkVersion == "current" {
		deviceVndkVersion = platformVndkVersion
	boardVndkVersion := mctx.DeviceConfig().VndkVersion()
	productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
	if boardVndkVersion == "current" {
		boardVndkVersion = platformVndkVersion
	}
	if productVndkVersion == "current" {
		productVndkVersion = platformVndkVersion
	}

	if mctx.DeviceConfig().VndkVersion() == "" {
	if boardVndkVersion == "" {
		// If the device isn't compiling against the VNDK, we always
		// use the core mode.
		coreVariantNeeded = true
	} else if _, ok := m.linker.(*llndkStubDecorator); ok {
		// LL-NDK stubs only exist in the vendor variant, since the
		// real libraries will be used in the core variant.
		// LL-NDK stubs only exist in the vendor and product variants,
		// since the real libraries will be used in the core variant.
		vendorVariants = append(vendorVariants,
			platformVndkVersion,
			deviceVndkVersion,
			boardVndkVersion,
		)
		productVariants = append(productVariants,
			platformVndkVersion,
			productVndkVersion,
		)
	} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
		// ... and LL-NDK headers as well
		vendorVariants = append(vendorVariants,
			platformVndkVersion,
			deviceVndkVersion,
			boardVndkVersion,
		)
		productVariants = append(productVariants,
			platformVndkVersion,
			productVndkVersion,
		)
	} else if lib, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok {
		// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
		// PRODUCT_EXTRA_VNDK_VERSIONS.
		vendorVariants = append(vendorVariants, lib.version())
	} else if m.HasVendorVariant() && !vendorSpecific {
		// This will be available in both /system and /vendor
		// or a /system directory that is available to vendor.
		// This will be available in /system, /vendor and /product
		// or a /system directory that is available to vendor and product.
		coreVariantNeeded = true
		vendorVariants = append(vendorVariants, platformVndkVersion)
		productVariants = append(productVariants, platformVndkVersion)
		// VNDK modules must not create BOARD_VNDK_VERSION variant because its
		// code is PLATFORM_VNDK_VERSION.
		// On the other hand, vendor_available modules which are not VNDK should
		// also build BOARD_VNDK_VERSION because it's installed in /vendor.
		// vendor_available modules are also available to /product.
		if !m.IsVndk() {
			vendorVariants = append(vendorVariants, deviceVndkVersion)
			vendorVariants = append(vendorVariants, boardVndkVersion)
			productVariants = append(productVariants, productVndkVersion)
		}
	} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
		// This will be available in /vendor (or /odm) only
		vendorVariants = append(vendorVariants, deviceVndkVersion)
		vendorVariants = append(vendorVariants, boardVndkVersion)
	} else {
		// This is either in /system (or similar: /data), or is a
		// modules built with the NDK. Modules built with the NDK
@@ -2619,6 +2681,19 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
		coreVariantNeeded = true
	}

	if boardVndkVersion != "" && productVndkVersion != "" {
		if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
			// The module has "product_specific: true" that does not create core variant.
			coreVariantNeeded = false
			productVariants = append(productVariants, productVndkVersion)
		}
	} else {
		// Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
		// restriction to use system libs.
		// No product variants defined in this case.
		productVariants = []string{}
	}

	if Bool(m.Properties.Recovery_available) {
		recoveryVariantNeeded = true
	}
@@ -2629,7 +2704,11 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
	}

	for _, variant := range android.FirstUniqueStrings(vendorVariants) {
		m.Properties.VendorVariants = append(m.Properties.VendorVariants, VendorVariationPrefix+variant)
		m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
	}

	for _, variant := range android.FirstUniqueStrings(productVariants) {
		m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
	}

	m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
@@ -2645,7 +2724,7 @@ func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
}

func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
	return c.Properties.VendorVariants
	return c.Properties.ExtraVariants
}

func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
@@ -2654,8 +2733,13 @@ func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string
		m.MakeAsPlatform()
		squashRecoverySrcs(m)
	} else if strings.HasPrefix(variant, VendorVariationPrefix) {
		m.Properties.ImageVariationPrefix = VendorVariationPrefix
		m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
		squashVendorSrcs(m)
	} else if strings.HasPrefix(variant, ProductVariationPrefix) {
		m.Properties.ImageVariationPrefix = ProductVariationPrefix
		m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
		squashVendorSrcs(m)
	}
}

+173 −4
Original line number Diff line number Diff line
@@ -82,11 +82,8 @@ func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
	return testCcWithConfig(t, config)
}

func testCcError(t *testing.T, pattern string, bp string) {
func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
	t.Helper()
	config := TestConfig(buildDir, android.Android, nil, bp, nil)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")

	ctx := CreateTestContext()
	ctx.Register(config)
@@ -106,9 +103,27 @@ func testCcError(t *testing.T, pattern string, bp string) {
	t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}

func testCcError(t *testing.T, pattern string, bp string) {
	config := TestConfig(buildDir, android.Android, nil, bp, nil)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
	testCcErrorWithConfig(t, pattern, config)
	return
}

func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
	config := TestConfig(buildDir, android.Android, nil, bp, nil)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
	testCcErrorWithConfig(t, pattern, config)
	return
}

const (
	coreVariant     = "android_arm64_armv8-a_shared"
	vendorVariant   = "android_vendor.VER_arm64_armv8-a_shared"
	productVariant  = "android_product.VER_arm64_armv8-a_shared"
	recoveryVariant = "android_recovery_arm64_armv8-a_shared"
)

@@ -1445,6 +1460,160 @@ func TestVndkUseVndkExtError(t *testing.T) {
	`)
}

func TestEnforceProductVndkVersion(t *testing.T) {
	bp := `
		cc_library {
			name: "libllndk",
		}
		llndk_library {
			name: "libllndk",
			symbol_file: "",
		}
		cc_library {
			name: "libvndk",
			vendor_available: true,
			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: "libva",
			vendor_available: true,
			nocrt: true,
		}
		cc_library {
			name: "libproduct_va",
			product_specific: true,
			vendor_available: true,
			nocrt: true,
		}
		cc_library {
			name: "libprod",
			product_specific: true,
			shared_libs: [
				"libllndk",
				"libvndk",
				"libvndk_sp",
				"libva",
				"libproduct_va",
			],
			nocrt: true,
		}
		cc_library {
			name: "libvendor",
			vendor: true,
			shared_libs: [
				"libllndk",
				"libvndk",
				"libvndk_sp",
				"libva",
				"libproduct_va",
			],
			nocrt: true,
		}
	`

	config := TestConfig(buildDir, android.Android, nil, bp, nil)
	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
	config.TestProductVariables.ProductVndkVersion = StringPtr("current")
	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")

	ctx := testCcWithConfig(t, config)

	checkVndkModule(t, ctx, "libvndk", "vndk-VER", false, "")
	checkVndkModule(t, ctx, "libvndk_sp", "vndk-sp-VER", true, "")
}

func TestEnforceProductVndkVersionErrors(t *testing.T) {
	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
		cc_library {
			name: "libprod",
			product_specific: true,
			shared_libs: [
				"libvendor",
			],
			nocrt: true,
		}
		cc_library {
			name: "libvendor",
			vendor: true,
			nocrt: true,
		}
	`)
	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
		cc_library {
			name: "libprod",
			product_specific: true,
			shared_libs: [
				"libsystem",
			],
			nocrt: true,
		}
		cc_library {
			name: "libsystem",
			nocrt: true,
		}
	`)
	testCcErrorProductVndk(t, "Vendor module that is not VNDK should not link to \".*\" which is marked as `vendor_available: false`", `
		cc_library {
			name: "libprod",
			product_specific: true,
			shared_libs: [
				"libvndk_private",
			],
			nocrt: true,
		}
		cc_library {
			name: "libvndk_private",
			vendor_available: false,
			vndk: {
				enabled: true,
			},
			nocrt: true,
		}
	`)
	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:product.VER", `
		cc_library {
			name: "libprod",
			product_specific: true,
			shared_libs: [
				"libsystem_ext",
			],
			nocrt: true,
		}
		cc_library {
			name: "libsystem_ext",
			system_ext_specific: true,
			nocrt: true,
		}
	`)
	testCcErrorProductVndk(t, "dependency \".*\" of \".*\" missing variant:\n.*image:", `
		cc_library {
			name: "libsystem",
			shared_libs: [
				"libproduct_va",
			],
			nocrt: true,
		}
		cc_library {
			name: "libproduct_va",
			product_specific: true,
			vendor_available: true,
			nocrt: true,
		}
	`)
}

func TestMakeLinkType(t *testing.T) {
	bp := `
		cc_library {
Loading