f9e2172aec
Refactors parts of CC to prepare for preliminary support for using Rust static libraries in vendor images. Some previously private functions are made public, and additional functions are added to LinkableInterface so GetMakeLinkType can be passed a LinkableInterface. Bug: 172525289 Test: m Change-Id: I5fda48e79532fe9ceab255e18d910af58048a123
465 lines
16 KiB
Go
465 lines
16 KiB
Go
// Copyright 2020 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
package cc
|
|
|
|
// This file contains image variant related things, including image mutator functions, utility
|
|
// functions to determine where a module is installed, etc.
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"android/soong/android"
|
|
)
|
|
|
|
var _ android.ImageInterface = (*Module)(nil)
|
|
|
|
type imageVariantType string
|
|
|
|
const (
|
|
coreImageVariant imageVariantType = "core"
|
|
vendorImageVariant imageVariantType = "vendor"
|
|
productImageVariant imageVariantType = "product"
|
|
ramdiskImageVariant imageVariantType = "ramdisk"
|
|
vendorRamdiskImageVariant imageVariantType = "vendor_ramdisk"
|
|
recoveryImageVariant imageVariantType = "recovery"
|
|
hostImageVariant imageVariantType = "host"
|
|
)
|
|
|
|
func (c *Module) getImageVariantType() imageVariantType {
|
|
if c.Host() {
|
|
return hostImageVariant
|
|
} else if c.inVendor() {
|
|
return vendorImageVariant
|
|
} else if c.InProduct() {
|
|
return productImageVariant
|
|
} else if c.InRamdisk() {
|
|
return ramdiskImageVariant
|
|
} else if c.InVendorRamdisk() {
|
|
return vendorRamdiskImageVariant
|
|
} else if c.InRecovery() {
|
|
return recoveryImageVariant
|
|
} else {
|
|
return coreImageVariant
|
|
}
|
|
}
|
|
|
|
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."
|
|
)
|
|
|
|
func (ctx *moduleContext) ProductSpecific() bool {
|
|
//TODO(b/150902910): Replace HasNonSystemVariants() with HasProductVariant()
|
|
return ctx.ModuleContext.ProductSpecific() ||
|
|
(ctx.mod.HasNonSystemVariants() && ctx.mod.InProduct())
|
|
}
|
|
|
|
func (ctx *moduleContext) SocSpecific() bool {
|
|
return ctx.ModuleContext.SocSpecific() ||
|
|
(ctx.mod.HasVendorVariant() && ctx.mod.inVendor())
|
|
}
|
|
|
|
func (ctx *moduleContextImpl) inProduct() bool {
|
|
return ctx.mod.InProduct()
|
|
}
|
|
|
|
func (ctx *moduleContextImpl) inVendor() bool {
|
|
return ctx.mod.inVendor()
|
|
}
|
|
|
|
func (ctx *moduleContextImpl) inRamdisk() bool {
|
|
return ctx.mod.InRamdisk()
|
|
}
|
|
|
|
func (ctx *moduleContextImpl) inVendorRamdisk() bool {
|
|
return ctx.mod.InVendorRamdisk()
|
|
}
|
|
|
|
func (ctx *moduleContextImpl) inRecovery() bool {
|
|
return ctx.mod.InRecovery()
|
|
}
|
|
|
|
// Returns true when this module is configured to have core and vendor variants.
|
|
func (c *Module) HasVendorVariant() bool {
|
|
return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
|
|
}
|
|
|
|
// Returns true when this module is configured to have core and product variants.
|
|
func (c *Module) HasProductVariant() bool {
|
|
return c.IsVndk() || Bool(c.VendorProperties.Product_available)
|
|
}
|
|
|
|
// Returns true when this module is configured to have core and either product or vendor variants.
|
|
func (c *Module) HasNonSystemVariants() bool {
|
|
return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Product_available)
|
|
}
|
|
|
|
// 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) InRamdisk() bool {
|
|
return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
|
|
}
|
|
|
|
func (c *Module) InVendorRamdisk() bool {
|
|
return c.ModuleBase.InVendorRamdisk() || c.ModuleBase.InstallInVendorRamdisk()
|
|
}
|
|
|
|
func (c *Module) InRecovery() bool {
|
|
return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
|
|
}
|
|
|
|
func (c *Module) OnlyInRamdisk() bool {
|
|
return c.ModuleBase.InstallInRamdisk()
|
|
}
|
|
|
|
func (c *Module) OnlyInVendorRamdisk() bool {
|
|
return c.ModuleBase.InstallInVendorRamdisk()
|
|
}
|
|
|
|
func (c *Module) OnlyInRecovery() bool {
|
|
return c.ModuleBase.InstallInRecovery()
|
|
}
|
|
|
|
func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
|
|
// Validation check
|
|
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
|
|
productSpecific := mctx.ProductSpecific()
|
|
|
|
if m.VendorProperties.Vendor_available != nil {
|
|
if vendorSpecific {
|
|
mctx.PropertyErrorf("vendor_available",
|
|
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
|
|
}
|
|
// If defined, make sure vendor_available and product_available has the
|
|
// same value since `false` for these properties means the module is
|
|
// for system only but provides the variant.
|
|
if m.VendorProperties.Product_available != nil {
|
|
if Bool(m.VendorProperties.Vendor_available) != Bool(m.VendorProperties.Product_available) {
|
|
mctx.PropertyErrorf("product_available", "may not have different value than `vendor_available`")
|
|
}
|
|
}
|
|
}
|
|
|
|
if m.VendorProperties.Product_available != nil {
|
|
if productSpecific {
|
|
mctx.PropertyErrorf("product_available",
|
|
"doesn't make sense at the same time as `product_specific: true`")
|
|
}
|
|
if vendorSpecific {
|
|
mctx.PropertyErrorf("product_available",
|
|
"cannot provide product variant from a vendor module. Please use `product_specific: true` with `vendor_available: true`")
|
|
}
|
|
}
|
|
|
|
if vndkdep := m.vndkdep; vndkdep != nil {
|
|
if vndkdep.isVndk() {
|
|
if vendorSpecific || productSpecific {
|
|
if !vndkdep.isVndkExt() {
|
|
mctx.PropertyErrorf("vndk",
|
|
"must set `extends: \"...\"` to vndk extension")
|
|
} else if m.VendorProperties.Vendor_available != nil {
|
|
mctx.PropertyErrorf("vendor_available",
|
|
"must not set at the same time as `vndk: {extends: \"...\"}`")
|
|
} else if m.VendorProperties.Product_available != nil {
|
|
mctx.PropertyErrorf("product_available",
|
|
"must not set at the same time as `vndk: {extends: \"...\"}`")
|
|
}
|
|
} else {
|
|
if vndkdep.isVndkExt() {
|
|
mctx.PropertyErrorf("vndk",
|
|
"must set `vendor: true` or `product_specific: true` to set `extends: %q`",
|
|
m.getVndkExtendsModuleName())
|
|
}
|
|
if m.VendorProperties.Vendor_available == nil {
|
|
mctx.PropertyErrorf("vndk",
|
|
"vendor_available must be set to either true or false when `vndk: {enabled: true}`")
|
|
}
|
|
}
|
|
} else {
|
|
if vndkdep.isVndkSp() {
|
|
mctx.PropertyErrorf("vndk",
|
|
"must set `enabled: true` to set `support_system_process: true`")
|
|
}
|
|
if vndkdep.isVndkExt() {
|
|
mctx.PropertyErrorf("vndk",
|
|
"must set `enabled: true` to set `extends: %q`",
|
|
m.getVndkExtendsModuleName())
|
|
}
|
|
}
|
|
}
|
|
|
|
var coreVariantNeeded bool = false
|
|
var ramdiskVariantNeeded bool = false
|
|
var vendorRamdiskVariantNeeded bool = false
|
|
var recoveryVariantNeeded bool = false
|
|
|
|
var vendorVariants []string
|
|
var productVariants []string
|
|
|
|
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
|
|
boardVndkVersion := mctx.DeviceConfig().VndkVersion()
|
|
productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
|
|
if boardVndkVersion == "current" {
|
|
boardVndkVersion = platformVndkVersion
|
|
}
|
|
if productVndkVersion == "current" {
|
|
productVndkVersion = platformVndkVersion
|
|
}
|
|
|
|
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 and product variants,
|
|
// since the real libraries will be used in the core variant.
|
|
vendorVariants = append(vendorVariants,
|
|
platformVndkVersion,
|
|
boardVndkVersion,
|
|
)
|
|
productVariants = append(productVariants,
|
|
platformVndkVersion,
|
|
productVndkVersion,
|
|
)
|
|
} else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
|
|
// ... and LL-NDK headers as well
|
|
vendorVariants = append(vendorVariants,
|
|
platformVndkVersion,
|
|
boardVndkVersion,
|
|
)
|
|
productVariants = append(productVariants,
|
|
platformVndkVersion,
|
|
productVndkVersion,
|
|
)
|
|
} else if m.isSnapshotPrebuilt() {
|
|
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
|
|
// PRODUCT_EXTRA_VNDK_VERSIONS.
|
|
if snapshot, ok := m.linker.(interface {
|
|
version() string
|
|
}); ok {
|
|
vendorVariants = append(vendorVariants, snapshot.version())
|
|
} else {
|
|
mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
|
|
}
|
|
} else if m.HasNonSystemVariants() && !m.IsVndkExt() {
|
|
// This will be available to /system unless it is product_specific
|
|
// which will be handled later.
|
|
coreVariantNeeded = true
|
|
|
|
// We assume that modules under proprietary paths are compatible for
|
|
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
|
|
// PLATFORM_VNDK_VERSION.
|
|
if m.HasVendorVariant() {
|
|
if isVendorProprietaryModule(mctx) {
|
|
vendorVariants = append(vendorVariants, boardVndkVersion)
|
|
} else {
|
|
vendorVariants = append(vendorVariants, platformVndkVersion)
|
|
}
|
|
}
|
|
|
|
// vendor_available modules are also available to /product.
|
|
// TODO(b/150902910): product variant will be created only if
|
|
// m.HasProductVariant() is true.
|
|
productVariants = append(productVariants, platformVndkVersion)
|
|
// VNDK is always PLATFORM_VNDK_VERSION
|
|
if !m.IsVndk() {
|
|
productVariants = append(productVariants, productVndkVersion)
|
|
}
|
|
} else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
|
|
// This will be available in /vendor (or /odm) only
|
|
|
|
// kernel_headers is a special module type whose exported headers
|
|
// are coming from DeviceKernelHeaders() which is always vendor
|
|
// dependent. They'll always have both vendor variants.
|
|
// For other modules, we assume that modules under proprietary
|
|
// paths are compatible for BOARD_VNDK_VERSION. The other modules
|
|
// are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
|
|
if _, ok := m.linker.(*kernelHeadersDecorator); ok {
|
|
vendorVariants = append(vendorVariants,
|
|
platformVndkVersion,
|
|
boardVndkVersion,
|
|
)
|
|
} else if isVendorProprietaryModule(mctx) {
|
|
vendorVariants = append(vendorVariants, boardVndkVersion)
|
|
} else {
|
|
vendorVariants = append(vendorVariants, platformVndkVersion)
|
|
}
|
|
} else {
|
|
// This is either in /system (or similar: /data), or is a
|
|
// modules built with the NDK. Modules built with the NDK
|
|
// will be restricted using the existing link type checks.
|
|
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.Ramdisk_available) {
|
|
ramdiskVariantNeeded = true
|
|
}
|
|
|
|
if m.ModuleBase.InstallInRamdisk() {
|
|
ramdiskVariantNeeded = true
|
|
coreVariantNeeded = false
|
|
}
|
|
|
|
if Bool(m.Properties.Vendor_ramdisk_available) {
|
|
vendorRamdiskVariantNeeded = true
|
|
}
|
|
|
|
if m.ModuleBase.InstallInVendorRamdisk() {
|
|
vendorRamdiskVariantNeeded = true
|
|
coreVariantNeeded = false
|
|
}
|
|
|
|
if Bool(m.Properties.Recovery_available) {
|
|
recoveryVariantNeeded = true
|
|
}
|
|
|
|
if m.ModuleBase.InstallInRecovery() {
|
|
recoveryVariantNeeded = true
|
|
coreVariantNeeded = false
|
|
}
|
|
|
|
for _, variant := range android.FirstUniqueStrings(vendorVariants) {
|
|
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.RamdiskVariantNeeded = ramdiskVariantNeeded
|
|
m.Properties.VendorRamdiskVariantNeeded = vendorRamdiskVariantNeeded
|
|
m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
|
|
m.Properties.CoreVariantNeeded = coreVariantNeeded
|
|
}
|
|
|
|
func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
|
|
return c.Properties.CoreVariantNeeded
|
|
}
|
|
|
|
func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
|
|
return c.Properties.RamdiskVariantNeeded
|
|
}
|
|
|
|
func (c *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
|
|
return c.Properties.VendorRamdiskVariantNeeded
|
|
}
|
|
|
|
func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
|
|
return c.Properties.RecoveryVariantNeeded
|
|
}
|
|
|
|
func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
|
|
return c.Properties.ExtraVariants
|
|
}
|
|
|
|
func squashVendorSrcs(m *Module) {
|
|
if lib, ok := m.compiler.(*libraryDecorator); ok {
|
|
lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
|
|
lib.baseCompiler.Properties.Target.Vendor.Srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
|
|
lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
|
|
lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
|
|
}
|
|
}
|
|
|
|
func squashProductSrcs(m *Module) {
|
|
if lib, ok := m.compiler.(*libraryDecorator); ok {
|
|
lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
|
|
lib.baseCompiler.Properties.Target.Product.Srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
|
|
lib.baseCompiler.Properties.Target.Product.Exclude_srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
|
|
lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
|
|
}
|
|
}
|
|
|
|
func squashRecoverySrcs(m *Module) {
|
|
if lib, ok := m.compiler.(*libraryDecorator); ok {
|
|
lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
|
|
lib.baseCompiler.Properties.Target.Recovery.Srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
|
|
lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
|
|
|
|
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
|
|
lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
|
|
}
|
|
}
|
|
|
|
func squashVendorRamdiskSrcs(m *Module) {
|
|
if lib, ok := m.compiler.(*libraryDecorator); ok {
|
|
lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, lib.baseCompiler.Properties.Target.Vendor_ramdisk.Exclude_srcs...)
|
|
}
|
|
}
|
|
|
|
func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
|
|
m := module.(*Module)
|
|
if variant == android.RamdiskVariation {
|
|
m.MakeAsPlatform()
|
|
} else if variant == android.VendorRamdiskVariation {
|
|
m.MakeAsPlatform()
|
|
squashVendorRamdiskSrcs(m)
|
|
} else if variant == android.RecoveryVariation {
|
|
m.MakeAsPlatform()
|
|
squashRecoverySrcs(m)
|
|
} else if strings.HasPrefix(variant, VendorVariationPrefix) {
|
|
m.Properties.ImageVariationPrefix = VendorVariationPrefix
|
|
m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
|
|
squashVendorSrcs(m)
|
|
|
|
// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
|
|
// Hide other vendor variants to avoid collision.
|
|
vndkVersion := ctx.DeviceConfig().VndkVersion()
|
|
if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
|
|
m.Properties.HideFromMake = true
|
|
m.SkipInstall()
|
|
}
|
|
} else if strings.HasPrefix(variant, ProductVariationPrefix) {
|
|
m.Properties.ImageVariationPrefix = ProductVariationPrefix
|
|
m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
|
|
// TODO (b/150902910): This will be replaced with squashProductSrcs(m).
|
|
squashVendorSrcs(m)
|
|
}
|
|
}
|