Merge changes Ie883eb45,If46a2f74,I8f4c5395,Ic4eb169d,I2b2408ef, ... into rvc-dev

* changes:
  Replace references to droiddoc with droidstubs
  Allow walkPayloadDeps visitor to control walk flow
  Add apex_available to sysprop_library
  Improve missing apex_available message
  Split TestApexAvailable into separate tests
  Use reflect.Zero(type) to get value to clear field
  Sdk snapshot set compile_multilib per OsType
  Remove old SdkMemberType API for creating snapshot modules
  Improve consistency of handling java snapshot properties
  Make new module creation API more flexible
  Add abstraction for tracking compile multilib usages
  Add support for using cc_library in sdk/module_exports
  Extract the osTypeSpecificInfo code from module creation loop
  Extract archTypeSpecificInfo code from module creation loop
  Clean up the main module creation loop
  Add support for cc_prebuilt_library
  Refactor prebuilt to use srcs supplier function
  Output properties before sets in snapshot module
  Remove SdkMemberType.FinalizeModule
  Follow up a review comment that was missed
  Copy shared_libs and system_shared_libs to module snapshot
  Support extracting common values from embedded structures
  Refactor common value extraction
  Copy white listed apex available settings into snapshot
  Disable installation for sdk snapshot versioned prebuilts
  Remove special handling of test_ apexes
  Remove special handling of com.android.art.debug/release
  Allow sdk members to vary by os type
  Add support for multiple os types
  Copy sdk_version to cc library snapshots
  Refactor java_library/java_test snapshot processing
  Refactor snapshot module creation
  Enable androidmk processing in sdk testing
  Add a nice install paths for module SDKs and exports.
  Copy apex_available properties to snapshot modules
  Improve documentation of CompileMultiTargets and related properties
  Only check copy rules into the snapshot directory
  Simplify java library sdk member code
  Add CommonOS variant for sdk
  Fix bug in error reporting when adding duplicate properties
  Avoid invoking sdk member to add empty list of dependencies
  Add windows to the list of available OS's in sdk tests
  Add support for cc_library_headers in sdk/module_exports
  Prune any empty property sets from the modules before transforming
  Simplify cc library sdk snapshot handling of include dirs/headers
  Add support for transforming a property set after its contents
  Fix issues with bp transformation
This commit is contained in:
TreeHugger Robot 2020-04-23 15:19:26 +00:00 committed by Android (Google) Code Review
commit 4586da2aae
38 changed files with 3273 additions and 746 deletions

View file

@ -536,6 +536,7 @@ bootstrap_go_package {
"sdk/update.go", "sdk/update.go",
], ],
testSrcs: [ testSrcs: [
"sdk/bp_test.go",
"sdk/cc_sdk_test.go", "sdk/cc_sdk_test.go",
"sdk/exports_test.go", "sdk/exports_test.go",
"sdk/java_sdk_test.go", "sdk/java_sdk_test.go",

View file

@ -29,7 +29,11 @@ import (
) )
func init() { func init() {
RegisterSingletonType("androidmk", AndroidMkSingleton) RegisterAndroidMkBuildComponents(InitRegistrationContext)
}
func RegisterAndroidMkBuildComponents(ctx RegistrationContext) {
ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
} }
// Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to // Deprecated: consider using AndroidMkEntriesProvider instead, especially if you're not going to

View file

@ -126,6 +126,10 @@ func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
return m return m
} }
func (m *ApexModuleBase) ApexAvailable() []string {
return m.ApexProperties.Apex_available
}
func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) { func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
m.apexVariationsLock.Lock() m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock() defer m.apexVariationsLock.Unlock()
@ -163,7 +167,7 @@ func (m *ApexModuleBase) IsInstallableToApex() bool {
const ( const (
AvailableToPlatform = "//apex_available:platform" AvailableToPlatform = "//apex_available:platform"
availableToAnyApex = "//apex_available:anyapex" AvailableToAnyApex = "//apex_available:anyapex"
) )
func CheckAvailableForApex(what string, apex_available []string) bool { func CheckAvailableForApex(what string, apex_available []string) bool {
@ -173,7 +177,7 @@ func CheckAvailableForApex(what string, apex_available []string) bool {
return what == AvailableToPlatform return what == AvailableToPlatform
} }
return InList(what, apex_available) || return InList(what, apex_available) ||
(what != AvailableToPlatform && InList(availableToAnyApex, apex_available)) (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available))
} }
func (m *ApexModuleBase) AvailableFor(what string) bool { func (m *ApexModuleBase) AvailableFor(what string) bool {
@ -199,7 +203,7 @@ func (m *ApexModuleBase) ChooseSdkVersion(versionList []string, maxSdkVersion in
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available { for _, n := range m.ApexProperties.Apex_available {
if n == AvailableToPlatform || n == availableToAnyApex { if n == AvailableToPlatform || n == AvailableToAnyApex {
continue continue
} }
if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() { if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {

View file

@ -596,7 +596,7 @@ var BuildOs = func() OsType {
}() }()
var ( var (
osTypeList []OsType OsTypeList []OsType
commonTargetMap = make(map[string]Target) commonTargetMap = make(map[string]Target)
NoOsType OsType NoOsType OsType
@ -607,6 +607,10 @@ var (
Android = NewOsType("android", Device, false) Android = NewOsType("android", Device, false)
Fuchsia = NewOsType("fuchsia", Device, false) Fuchsia = NewOsType("fuchsia", Device, false)
// A pseudo OSType for a common os variant, which is OSType agnostic and which
// has dependencies on all the OS variants.
CommonOS = NewOsType("common_os", Generic, false)
osArchTypeMap = map[OsType][]ArchType{ osArchTypeMap = map[OsType][]ArchType{
Linux: []ArchType{X86, X86_64}, Linux: []ArchType{X86, X86_64},
LinuxBionic: []ArchType{X86_64}, LinuxBionic: []ArchType{X86_64},
@ -668,7 +672,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType {
DefaultDisabled: defDisabled, DefaultDisabled: defDisabled,
} }
osTypeList = append(osTypeList, os) OsTypeList = append(OsTypeList, os)
if _, found := commonTargetMap[name]; found { if _, found := commonTargetMap[name]; found {
panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name)) panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
@ -680,7 +684,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType {
} }
func osByName(name string) OsType { func osByName(name string) OsType {
for _, os := range osTypeList { for _, os := range OsTypeList {
if os.Name == name { if os.Name == name {
return os return os
} }
@ -746,7 +750,7 @@ func osMutator(mctx BottomUpMutatorContext) {
var moduleOSList []OsType var moduleOSList []OsType
for _, os := range osTypeList { for _, os := range OsTypeList {
supportedClass := false supportedClass := false
for _, osClass := range osClasses { for _, osClass := range osClasses {
if os.Class == osClass { if os.Class == osClass {
@ -775,12 +779,64 @@ func osMutator(mctx BottomUpMutatorContext) {
osNames[i] = os.String() osNames[i] = os.String()
} }
modules := mctx.CreateVariations(osNames...) createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
for i, m := range modules { if createCommonOSVariant {
m.(Module).base().commonProperties.CompileOS = moduleOSList[i] // A CommonOS variant was requested so add it to the list of OS's variants to
m.(Module).base().setOSProperties(mctx) // create. It needs to be added to the end because it needs to depend on the
// the other variants in the list returned by CreateVariations(...) and inter
// variant dependencies can only be created from a later variant in that list to
// an earlier one. That is because variants are always processed in the order in
// which they are returned from CreateVariations(...).
osNames = append(osNames, CommonOS.Name)
moduleOSList = append(moduleOSList, CommonOS)
} }
modules := mctx.CreateVariations(osNames...)
for i, m := range modules {
m.base().commonProperties.CompileOS = moduleOSList[i]
m.base().setOSProperties(mctx)
}
if createCommonOSVariant {
// A CommonOS variant was requested so add dependencies from it (the last one in
// the list) to the OS type specific variants.
last := len(modules) - 1
commonOSVariant := modules[last]
commonOSVariant.base().commonProperties.CommonOSVariant = true
for _, module := range modules[0:last] {
// Ignore modules that are enabled. Note, this will only avoid adding
// dependencies on OsType variants that are explicitly disabled in their
// properties. The CommonOS variant will still depend on disabled variants
// if they are disabled afterwards, e.g. in archMutator if
if module.Enabled() {
mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
}
}
}
}
// Identifies the dependency from CommonOS variant to the os specific variants.
type commonOSTag struct{ blueprint.BaseDependencyTag }
var commonOsToOsSpecificVariantTag = commonOSTag{}
// Get the OsType specific variants for the current CommonOS variant.
//
// The returned list will only contain enabled OsType specific variants of the
// module referenced in the supplied context. An empty list is returned if there
// are no enabled variants or the supplied context is not for an CommonOS
// variant.
func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
var variants []Module
mctx.VisitDirectDeps(func(m Module) {
if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
if m.Enabled() {
variants = append(variants, m)
}
}
})
return variants
} }
// archMutator splits a module into a variant for each Target requested by the module. Target selection // archMutator splits a module into a variant for each Target requested by the module. Target selection
@ -821,6 +877,15 @@ func archMutator(mctx BottomUpMutatorContext) {
} }
os := base.commonProperties.CompileOS os := base.commonProperties.CompileOS
if os == CommonOS {
// Make sure that the target related properties are initialized for the
// CommonOS variant.
addTargetProperties(module, commonTargetMap[os.Name], nil, true)
// Do not create arch specific variants for the CommonOS variant.
return
}
osTargets := mctx.Config().Targets[os] osTargets := mctx.Config().Targets[os]
image := base.commonProperties.ImageVariation image := base.commonProperties.ImageVariation
// Filter NativeBridge targets unless they are explicitly supported // Filter NativeBridge targets unless they are explicitly supported
@ -881,15 +946,17 @@ func archMutator(mctx BottomUpMutatorContext) {
modules := mctx.CreateVariations(targetNames...) modules := mctx.CreateVariations(targetNames...)
for i, m := range modules { for i, m := range modules {
m.(Module).base().commonProperties.CompileTarget = targets[i] addTargetProperties(m, targets[i], multiTargets, i == 0)
m.(Module).base().commonProperties.CompileMultiTargets = multiTargets
if i == 0 {
m.(Module).base().commonProperties.CompilePrimary = true
}
m.(Module).base().setArchProperties(mctx) m.(Module).base().setArchProperties(mctx)
} }
} }
func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
m.base().commonProperties.CompileTarget = target
m.base().commonProperties.CompileMultiTargets = multiTargets
m.base().commonProperties.CompilePrimary = primaryTarget
}
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) { func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
switch class { switch class {
case Device: case Device:
@ -1004,7 +1071,7 @@ func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc {
"Arm_on_x86", "Arm_on_x86",
"Arm_on_x86_64", "Arm_on_x86_64",
} }
for _, os := range osTypeList { for _, os := range OsTypeList {
targets = append(targets, os.Field) targets = append(targets, os.Field)
for _, archType := range osArchTypeMap[os] { for _, archType := range osArchTypeMap[os] {
@ -1711,6 +1778,8 @@ func filterMultilibTargets(targets []Target, multilib string) []Target {
return ret return ret
} }
// Return the set of Os specific common architecture targets for each Os in a list of
// targets.
func getCommonTargets(targets []Target) []Target { func getCommonTargets(targets []Target) []Target {
var ret []Target var ret []Target
set := make(map[string]bool) set := make(map[string]bool)

View file

@ -359,6 +359,9 @@ func NewConfig(srcDir, buildDir string) (Config, error) {
return Config{}, err return Config{}, err
} }
// Make the CommonOS OsType available for all products.
targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
var archConfig []archConfig var archConfig []archConfig
if Bool(config.Mega_device) { if Bool(config.Mega_device) {
archConfig = getMegaDeviceConfig() archConfig = getMegaDeviceConfig()

View file

@ -132,6 +132,9 @@ type BaseModuleContext interface {
Target() Target Target() Target
TargetPrimary() bool TargetPrimary() bool
// The additional arch specific targets (e.g. 32/64 bit) that this module variant is
// responsible for creating.
MultiTargets() []Target MultiTargets() []Target
Arch() Arch Arch() Arch
Os() OsType Os() OsType
@ -361,6 +364,10 @@ type commonProperties struct {
} }
} }
// If set to true then the archMutator will create variants for each arch specific target
// (e.g. 32/64) that the module is required to produce. If set to false then it will only
// create a variant for the architecture and will list the additional arch specific targets
// that the variant needs to produce in the CompileMultiTargets property.
UseTargetVariants bool `blueprint:"mutated"` UseTargetVariants bool `blueprint:"mutated"`
Default_multilib string `blueprint:"mutated"` Default_multilib string `blueprint:"mutated"`
@ -439,16 +446,56 @@ type commonProperties struct {
Suffix *string `android:"arch_variant"` Suffix *string `android:"arch_variant"`
} `android:"arch_variant"` } `android:"arch_variant"`
// Set by TargetMutator // The OsType of artifacts that this module variant is responsible for creating.
//
// Set by osMutator
CompileOS OsType `blueprint:"mutated"` CompileOS OsType `blueprint:"mutated"`
// The Target of artifacts that this module variant is responsible for creating.
//
// Set by archMutator
CompileTarget Target `blueprint:"mutated"` CompileTarget Target `blueprint:"mutated"`
// The additional arch specific targets (e.g. 32/64 bit) that this module variant is
// responsible for creating.
//
// By default this is nil as, where necessary, separate variants are created for the
// different multilib types supported and that information is encapsulated in the
// CompileTarget so the module variant simply needs to create artifacts for that.
//
// However, if UseTargetVariants is set to false (e.g. by
// InitAndroidMultiTargetsArchModule) then no separate variants are created for the
// multilib targets. Instead a single variant is created for the architecture and
// this contains the multilib specific targets that this variant should create.
//
// Set by archMutator
CompileMultiTargets []Target `blueprint:"mutated"` CompileMultiTargets []Target `blueprint:"mutated"`
// True if the module variant's CompileTarget is the primary target
//
// Set by archMutator
CompilePrimary bool `blueprint:"mutated"` CompilePrimary bool `blueprint:"mutated"`
// Set by InitAndroidModule // Set by InitAndroidModule
HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"` HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
ArchSpecific bool `blueprint:"mutated"` ArchSpecific bool `blueprint:"mutated"`
// If set to true then a CommonOS variant will be created which will have dependencies
// on all its OsType specific variants. Used by sdk/module_exports to create a snapshot
// that covers all os and architecture variants.
//
// The OsType specific variants can be retrieved by calling
// GetOsSpecificVariantsOfCommonOSVariant
//
// Set at module initialization time by calling InitCommonOSAndroidMultiTargetsArchModule
CreateCommonOSVariant bool `blueprint:"mutated"`
// If set to true then this variant is the CommonOS variant that has dependencies on its
// OsType specific variants.
//
// Set by osMutator.
CommonOSVariant bool `blueprint:"mutated"`
SkipInstall bool `blueprint:"mutated"` SkipInstall bool `blueprint:"mutated"`
NamespaceExportedToMake bool `blueprint:"mutated"` NamespaceExportedToMake bool `blueprint:"mutated"`
@ -581,6 +628,14 @@ func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defa
m.base().commonProperties.UseTargetVariants = false m.base().commonProperties.UseTargetVariants = false
} }
// As InitAndroidMultiTargetsArchModule except it creates an additional CommonOS variant that
// has dependencies on all the OsType specific variants.
func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidArchModule(m, hod, defaultMultilib)
m.base().commonProperties.UseTargetVariants = false
m.base().commonProperties.CreateCommonOSVariant = true
}
// A ModuleBase object contains the properties that are common to all Android // A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module // modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's // struct definition. InitAndroidModule should then be called from the module's
@ -772,6 +827,11 @@ func (m *ModuleBase) ArchSpecific() bool {
return m.commonProperties.ArchSpecific return m.commonProperties.ArchSpecific
} }
// True if the current variant is a CommonOS variant, false otherwise.
func (m *ModuleBase) IsCommonOSVariant() bool {
return m.commonProperties.CommonOSVariant
}
func (m *ModuleBase) OsClassSupported() []OsClass { func (m *ModuleBase) OsClassSupported() []OsClass {
switch m.commonProperties.HostOrDeviceSupported { switch m.commonProperties.HostOrDeviceSupported {
case HostSupported: case HostSupported:
@ -958,6 +1018,16 @@ func (m *ModuleBase) ImageVariation() blueprint.Variation {
} }
} }
func (m *ModuleBase) getVariationByMutatorName(mutator string) string {
for i, v := range m.commonProperties.DebugMutators {
if v == mutator {
return m.commonProperties.DebugVariations[i]
}
}
return ""
}
func (m *ModuleBase) InRamdisk() bool { func (m *ModuleBase) InRamdisk() bool {
return m.base().commonProperties.ImageVariation == RamdiskVariation return m.base().commonProperties.ImageVariation == RamdiskVariation
} }
@ -1136,8 +1206,11 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
blueprintCtx.GetMissingDependencies() blueprintCtx.GetMissingDependencies()
// For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and // For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and
// are enabled. // are enabled. Unless the module is a CommonOS variant which may have dependencies on disabled variants
ctx.baseModuleContext.strictVisitDeps = true // (because the dependencies are added before the modules are disabled). The
// GetOsSpecificVariantsOfCommonOSVariant(...) method will ensure that the disabled variants are
// ignored.
ctx.baseModuleContext.strictVisitDeps = !m.IsCommonOSVariant()
if ctx.config.captureBuild { if ctx.config.captureBuild {
ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams) ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)

View file

@ -1238,8 +1238,8 @@ func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string
return ret return ret
} }
func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath { func pathForNdkOrSdkInstall(ctx PathContext, prefix string, paths []string) InstallPath {
paths = append([]string{"ndk"}, paths...) paths = append([]string{prefix}, paths...)
path, err := validatePath(paths...) path, err := validatePath(paths...)
if err != nil { if err != nil {
reportPathError(ctx, err) reportPathError(ctx, err)
@ -1247,6 +1247,14 @@ func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
return InstallPath{basePath{path, ctx.Config(), ""}, ""} return InstallPath{basePath{path, ctx.Config(), ""}, ""}
} }
func PathForNdkInstall(ctx PathContext, paths ...string) InstallPath {
return pathForNdkOrSdkInstall(ctx, "ndk", paths)
}
func PathForMainlineSdksInstall(ctx PathContext, paths ...string) InstallPath {
return pathForNdkOrSdkInstall(ctx, "mainline-sdks", paths)
}
func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string { func InstallPathToOnDevicePath(ctx PathContext, path InstallPath) string {
rel := Rel(ctx, PathForOutput(ctx, "target", "product", ctx.Config().DeviceName()).String(), path.String()) rel := Rel(ctx, PathForOutput(ctx, "target", "product", ctx.Config().DeviceName()).String(), path.String())

View file

@ -50,12 +50,9 @@ type PrebuiltProperties struct {
type Prebuilt struct { type Prebuilt struct {
properties PrebuiltProperties properties PrebuiltProperties
module Module
srcs *[]string
// Metadata for single source Prebuilt modules. srcsSupplier PrebuiltSrcsSupplier
srcProps reflect.Value srcsPropertyName string
srcField reflect.StructField
} }
func (p *Prebuilt) Name(name string) string { func (p *Prebuilt) Name(name string) string {
@ -72,31 +69,26 @@ func (p *Prebuilt) ForcePrefer() {
// preference configs. We'll want to add native support for dynamic source cases if we end up having // preference configs. We'll want to add native support for dynamic source cases if we end up having
// more modules like this. // more modules like this.
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path { func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
if p.srcs != nil { if p.srcsSupplier != nil {
if len(*p.srcs) == 0 { srcs := p.srcsSupplier()
ctx.PropertyErrorf("srcs", "missing prebuilt source file")
if len(srcs) == 0 {
ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
return nil return nil
} }
if len(*p.srcs) > 1 { if len(srcs) > 1 {
ctx.PropertyErrorf("srcs", "multiple prebuilt source files") ctx.PropertyErrorf(p.srcsPropertyName, "multiple prebuilt source files")
return nil return nil
} }
// Return the singleton source after expanding any filegroup in the // Return the singleton source after expanding any filegroup in the
// sources. // sources.
return PathForModuleSrc(ctx, (*p.srcs)[0]) src := srcs[0]
} else {
if !p.srcProps.IsValid() {
ctx.ModuleErrorf("prebuilt source was not set")
}
src := p.getSingleSourceFieldValue()
if src == "" {
ctx.PropertyErrorf(proptools.FieldNameForProperty(p.srcField.Name),
"missing prebuilt source file")
return nil
}
return PathForModuleSrc(ctx, src) return PathForModuleSrc(ctx, src)
} else {
ctx.ModuleErrorf("prebuilt source was not set")
return nil
} }
} }
@ -104,18 +96,80 @@ func (p *Prebuilt) UsePrebuilt() bool {
return p.properties.UsePrebuilt return p.properties.UsePrebuilt
} }
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) { // Called to provide the srcs value for the prebuilt module.
//
// Return the src value or nil if it is not available.
type PrebuiltSrcsSupplier func() []string
// Initialize the module as a prebuilt module that uses the provided supplier to access the
// prebuilt sources of the module.
//
// The supplier will be called multiple times and must return the same values each time it
// is called. If it returns an empty array (or nil) then the prebuilt module will not be used
// as a replacement for a source module with the same name even if prefer = true.
//
// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array
// containing exactly one source file.
//
// The provided property name is used to provide helpful error messages in the event that
// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
p := module.Prebuilt() p := module.Prebuilt()
module.AddProperties(&p.properties) module.AddProperties(&p.properties)
p.srcs = srcs
if srcsSupplier == nil {
panic(fmt.Errorf("srcsSupplier must not be nil"))
}
if srcsPropertyName == "" {
panic(fmt.Errorf("srcsPropertyName must not be empty"))
}
p.srcsSupplier = srcsSupplier
p.srcsPropertyName = srcsPropertyName
}
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
if srcs == nil {
panic(fmt.Errorf("srcs must not be nil"))
}
srcsSupplier := func() []string {
return *srcs
}
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
} }
func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) { func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
p := module.Prebuilt() srcPropsValue := reflect.ValueOf(srcProps).Elem()
module.AddProperties(&p.properties) srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
p.srcProps = reflect.ValueOf(srcProps).Elem() if !srcPropsValue.IsValid() || srcStructField.Name == "" {
p.srcField, _ = p.srcProps.Type().FieldByName(srcField) panic(fmt.Errorf("invalid single source prebuilt %+v", module))
p.checkSingleSourceProperties() }
if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface {
panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps))
}
srcFieldIndex := srcStructField.Index
srcPropertyName := proptools.PropertyNameForField(srcField)
srcsSupplier := func() []string {
value := srcPropsValue.FieldByIndex(srcFieldIndex)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
if value.Kind() != reflect.String {
panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one but was %d %q", srcPropertyName, value.Kind(), value))
}
src := value.String()
if src == "" {
return nil
}
return []string{src}
}
InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName)
} }
type PrebuiltInterface interface { type PrebuiltInterface interface {
@ -152,7 +206,7 @@ func PrebuiltMutator(ctx BottomUpMutatorContext) {
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil { if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
p := m.Prebuilt() p := m.Prebuilt()
if p.srcs == nil && !p.srcProps.IsValid() { if p.srcsSupplier == nil {
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it")) panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
} }
if !p.properties.SourceExists { if !p.properties.SourceExists {
@ -191,11 +245,7 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt // usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled. // will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool { func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
if p.srcs != nil && len(*p.srcs) == 0 { if p.srcsSupplier != nil && len(p.srcsSupplier()) == 0 {
return false
}
if p.srcProps.IsValid() && p.getSingleSourceFieldValue() == "" {
return false return false
} }
@ -210,24 +260,3 @@ func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
func (p *Prebuilt) SourceExists() bool { func (p *Prebuilt) SourceExists() bool {
return p.properties.SourceExists return p.properties.SourceExists
} }
func (p *Prebuilt) checkSingleSourceProperties() {
if !p.srcProps.IsValid() || p.srcField.Name == "" {
panic(fmt.Errorf("invalid single source prebuilt %+v", p))
}
if p.srcProps.Kind() != reflect.Struct && p.srcProps.Kind() != reflect.Interface {
panic(fmt.Errorf("invalid single source prebuilt %+v", p.srcProps))
}
}
func (p *Prebuilt) getSingleSourceFieldValue() string {
value := p.srcProps.FieldByIndex(p.srcField.Index)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
if value.Kind() != reflect.String {
panic(fmt.Errorf("prebuilt src field %q should be a string or a pointer to one", p.srcField.Name))
}
return value.String()
}

View file

@ -145,10 +145,6 @@ func (s *SdkBase) RequiredSdks() SdkRefs {
return s.properties.RequiredSdks return s.properties.RequiredSdks
} }
func (s *SdkBase) BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder) {
sdkModuleContext.ModuleErrorf("module type " + sdkModuleContext.OtherModuleType(s.module) + " cannot be used in an sdk")
}
// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including // InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
// SdkBase. // SdkBase.
func InitSdkAwareModule(m SdkAware) { func InitSdkAwareModule(m SdkAware) {
@ -186,9 +182,33 @@ type SnapshotBuilder interface {
// is correctly output for both versioned and unversioned prebuilts in the // is correctly output for both versioned and unversioned prebuilts in the
// snapshot. // snapshot.
// //
// "required: true" means that the property must only contain references
// to other members of the sdk. Passing a reference to a module that is not a
// member of the sdk will result in a build error.
//
// "required: false" means that the property can contain references to modules
// that are either members or not members of the sdk. If a reference is to a
// module that is a non member then the reference is left unchanged, i.e. it
// is not transformed as references to members are.
//
// The handling of the member names is dependent on whether it is an internal or
// exported member. An exported member is one whose name is specified in one of
// the member type specific properties. An internal member is one that is added
// due to being a part of an exported (or other internal) member and is not itself
// an exported member.
//
// Member names are handled as follows:
// * When creating the unversioned form of the module the name is left unchecked
// unless the member is internal in which case it is transformed into an sdk
// specific name, i.e. by prefixing with the sdk name.
//
// * When creating the versioned form of the module the name is transformed into
// a versioned sdk specific name, i.e. by prefixing with the sdk name and
// suffixing with the version.
//
// e.g. // e.g.
// bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag()) // bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag(true))
SdkMemberReferencePropertyTag() BpPropertyTag SdkMemberReferencePropertyTag(required bool) BpPropertyTag
} }
type BpPropertyTag interface{} type BpPropertyTag interface{}
@ -295,14 +315,36 @@ type SdkMemberType interface {
// the module is not allowed in whichever sdk property it was added. // the module is not allowed in whichever sdk property it was added.
IsInstance(module Module) bool IsInstance(module Module) bool
// Build the snapshot for the SDK member // Add a prebuilt module that the sdk will populate.
// //
// The ModuleContext provided is for the SDK module, so information for // Returning nil from this will cause the sdk module type to use the deprecated BuildSnapshot
// variants in the supplied member can be accessed using the Other... methods. // method to build the snapshot. That method is deprecated because it requires the SdkMemberType
// implementation to do all the word.
// //
// The SdkMember is guaranteed to contain variants for which the // Otherwise, returning a non-nil value from this will cause the sdk module type to do the
// IsInstance(Module) method returned true. // majority of the work to generate the snapshot. The sdk module code generates the snapshot
BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) // as follows:
//
// * A properties struct of type SdkMemberProperties is created for each variant and
// populated with information from the variant by calling PopulateFromVariant(SdkAware)
// on the struct.
//
// * An additional properties struct is created into which the common properties will be
// added.
//
// * The variant property structs are analysed to find exported (capitalized) fields which
// have common values. Those fields are cleared and the common value added to the common
// properties. A field annotated with a tag of `sdk:"keep"` will be treated as if it
// was not capitalized, i.e. not optimized for common values.
//
// * The sdk module type populates the BpModule structure, creating the arch specific
// structure and calls AddToPropertySet(...) on the properties struct to add the member
// specific properties in the correct place in the structure.
//
AddPrebuiltModule(ctx SdkMemberContext, member SdkMember) BpModule
// Create a structure into which variant specific properties can be added.
CreateVariantPropertiesStruct() SdkMemberProperties
} }
// Base type for SdkMemberType implementations. // Base type for SdkMemberType implementations.
@ -389,3 +431,84 @@ func RegisterSdkMemberType(memberType SdkMemberType) {
SdkMemberTypes = SdkMemberTypes.copyAndAppend(memberType) SdkMemberTypes = SdkMemberTypes.copyAndAppend(memberType)
} }
} }
// Base structure for all implementations of SdkMemberProperties.
//
// Contains common properties that apply across many different member types. These
// are not affected by the optimization to extract common values.
type SdkMemberPropertiesBase struct {
// The number of unique os types supported by the member variants.
//
// If a member has a variant with more than one os type then it will need to differentiate
// the locations of any of their prebuilt files in the snapshot by os type to prevent them
// from colliding. See OsPrefix().
//
// This property is the same for all variants of a member and so would be optimized away
// if it was not explicitly kept.
Os_count int `sdk:"keep"`
// The os type for which these properties refer.
//
// Provided to allow a member to differentiate between os types in the locations of their
// prebuilt files when it supports more than one os type.
//
// This property is the same for all os type specific variants of a member and so would be
// optimized away if it was not explicitly kept.
Os OsType `sdk:"keep"`
// The setting to use for the compile_multilib property.
//
// This property is set after optimization so there is no point in trying to optimize it.
Compile_multilib string `sdk:"keep"`
}
// The os prefix to use for any file paths in the sdk.
//
// Is an empty string if the member only provides variants for a single os type, otherwise
// is the OsType.Name.
func (b *SdkMemberPropertiesBase) OsPrefix() string {
if b.Os_count == 1 {
return ""
} else {
return b.Os.Name
}
}
func (b *SdkMemberPropertiesBase) Base() *SdkMemberPropertiesBase {
return b
}
// Interface to be implemented on top of a structure that contains variant specific
// information.
//
// Struct fields that are capitalized are examined for common values to extract. Fields
// that are not capitalized are assumed to be arch specific.
type SdkMemberProperties interface {
// Access the base structure.
Base() *SdkMemberPropertiesBase
// Populate this structure with information from the variant.
PopulateFromVariant(ctx SdkMemberContext, variant Module)
// Add the information from this structure to the property set.
AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet)
}
// Provides access to information common to a specific member.
type SdkMemberContext interface {
// The module context of the sdk common os variant which is creating the snapshot.
SdkModuleContext() ModuleContext
// The builder of the snapshot.
SnapshotBuilder() SnapshotBuilder
// The type of the member.
MemberType() SdkMemberType
// The name of the member.
//
// Provided for use by sdk members to create a member specific location within the snapshot
// into which to copy the prebuilt files.
Name() string
}

View file

@ -410,6 +410,10 @@ func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPat
} }
func SetInMakeForTests(config Config) {
config.inMake = true
}
func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) []AndroidMkEntries { func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) []AndroidMkEntries {
var p AndroidMkEntriesProvider var p AndroidMkEntriesProvider
var ok bool var ok bool

View file

@ -61,8 +61,26 @@ var (
usesTag = dependencyTag{name: "uses"} usesTag = dependencyTag{name: "uses"}
androidAppTag = dependencyTag{name: "androidApp", payload: true} androidAppTag = dependencyTag{name: "androidApp", payload: true}
apexAvailWl = makeApexAvailableWhitelist() apexAvailWl = makeApexAvailableWhitelist()
inverseApexAvailWl = invertApexWhiteList(apexAvailWl)
) )
// Transform the map of apex -> modules to module -> apexes.
func invertApexWhiteList(m map[string][]string) map[string][]string {
r := make(map[string][]string)
for apex, modules := range m {
for _, module := range modules {
r[module] = append(r[module], apex)
}
}
return r
}
// Retrieve the while list of apexes to which the supplied module belongs.
func WhitelistedApexAvailable(moduleName string) []string {
return inverseApexAvailWl[normalizeModuleName(moduleName)]
}
// This is a map from apex to modules, which overrides the // This is a map from apex to modules, which overrides the
// apex_available setting for that particular module to make // apex_available setting for that particular module to make
// it available for the apex regardless of its setting. // it available for the apex regardless of its setting.
@ -91,7 +109,7 @@ func makeApexAvailableWhitelist() map[string][]string {
// //
// Module separator // Module separator
// //
m["com.android.art"] = []string{ artApexContents := []string{
"art_cmdlineparser_headers", "art_cmdlineparser_headers",
"art_disassembler_headers", "art_disassembler_headers",
"art_libartbase_headers", "art_libartbase_headers",
@ -152,6 +170,8 @@ func makeApexAvailableWhitelist() map[string][]string {
"libziparchive", "libziparchive",
"perfetto_trace_protos", "perfetto_trace_protos",
} }
m["com.android.art.debug"] = artApexContents
m["com.android.art.release"] = artApexContents
// //
// Module separator // Module separator
// //
@ -773,7 +793,7 @@ func makeApexAvailableWhitelist() map[string][]string {
// //
// Module separator // Module separator
// //
m["//any"] = []string{ m[android.AvailableToAnyApex] = []string{
"libatomic", "libatomic",
"libclang_rt", "libclang_rt",
"libgcc_stripped", "libgcc_stripped",
@ -1749,10 +1769,14 @@ func (c *flattenedApexContext) InstallBypassMake() bool {
return true return true
} }
// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
type payloadDepsCallback func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool
// Visit dependencies that contributes to the payload of this APEX // Visit dependencies that contributes to the payload of this APEX
func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCallback) {
do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) { ctx.WalkDeps(func(child, parent android.Module) bool {
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
am, ok := child.(android.ApexModule) am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() { if !ok || !am.CanHaveApexVariants() {
return false return false
@ -1761,22 +1785,18 @@ func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
// Check for the direct dependencies that contribute to the payload // Check for the direct dependencies that contribute to the payload
if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok { if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok {
if dt.payload { if dt.payload {
do(ctx, parent, am, false /* externalDep */) return do(ctx, parent, am, false /* externalDep */)
return true
} }
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false return false
} }
// Check for the indirect dependencies if it is considered as part of the APEX // Check for the indirect dependencies if it is considered as part of the APEX
if am.ApexName() != "" { if am.ApexName() != "" {
do(ctx, parent, am, false /* externalDep */) return do(ctx, parent, am, false /* externalDep */)
return true
} }
do(ctx, parent, am, true /* externalDep */) return do(ctx, parent, am, true /* externalDep */)
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
}) })
} }
@ -1803,24 +1823,36 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
return return
} }
a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if externalDep {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
}
apexName := ctx.ModuleName() apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from) fromName := ctx.OtherModuleName(from)
toName := ctx.OtherModuleName(to) toName := ctx.OtherModuleName(to)
if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) { if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
return return true
} }
ctx.ModuleErrorf("%q requires %q that is not available for the APEX.", fromName, toName) message := ""
for _, m := range ctx.GetWalkPath()[1:] {
message = fmt.Sprintf("%s\n -> %s", message, m.String())
}
ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, message)
// Visit this module's dependencies to check and report any issues with their availability.
return true
}) })
} }
// Collects the list of module names that directly or indirectly contributes to the payload of this APEX // Collects the list of module names that directly or indirectly contributes to the payload of this APEX
func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) { func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
a.depInfos = make(map[string]depInfo) a.depInfos = make(map[string]depInfo)
a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if from.Name() == to.Name() { if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this. // This can happen for cc.reuseObjTag. We are not interested in tracking this.
return // As soon as the dependency graph crosses the APEX boundary, don't go further.
return !externalDep
} }
if info, exists := a.depInfos[to.Name()]; exists { if info, exists := a.depInfos[to.Name()]; exists {
@ -1836,6 +1868,9 @@ func (a *apexBundle) collectDepsInfo(ctx android.ModuleContext) {
isExternal: externalDep, isExternal: externalDep,
} }
} }
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return !externalDep
}) })
} }
@ -2182,10 +2217,21 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func whitelistedApexAvailable(apex, moduleName string) bool { func whitelistedApexAvailable(apex, moduleName string) bool {
key := apex key := apex
key = strings.Replace(key, "test_", "", 1) moduleName = normalizeModuleName(moduleName)
key = strings.Replace(key, "com.android.art.debug", "com.android.art", 1)
key = strings.Replace(key, "com.android.art.release", "com.android.art", 1)
if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
return true
}
key = android.AvailableToAnyApex
if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
return true
}
return false
}
func normalizeModuleName(moduleName string) string {
// Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
// system. Trim the prefix for the check since they are confusing // system. Trim the prefix for the check since they are confusing
moduleName = strings.TrimPrefix(moduleName, "prebuilt_") moduleName = strings.TrimPrefix(moduleName, "prebuilt_")
@ -2194,17 +2240,7 @@ func whitelistedApexAvailable(apex, moduleName string) bool {
// We don't want to list them all // We don't want to list them all
moduleName = "libclang_rt" moduleName = "libclang_rt"
} }
return moduleName
if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
return true
}
key = "//any"
if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
return true
}
return false
} }
func newApexBundle() *apexBundle { func newApexBundle() *apexBundle {

View file

@ -3478,7 +3478,7 @@ func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
}`) }`)
} }
func TestApexAvailable(t *testing.T) { func TestApexAvailable_DirectDep(t *testing.T) {
// libfoo is not available to myapex, but only to otherapex // libfoo is not available to myapex, but only to otherapex
testApexError(t, "requires \"libfoo\" that is not available for the APEX", ` testApexError(t, "requires \"libfoo\" that is not available for the APEX", `
apex { apex {
@ -3511,9 +3511,17 @@ func TestApexAvailable(t *testing.T) {
system_shared_libs: [], system_shared_libs: [],
apex_available: ["otherapex"], apex_available: ["otherapex"],
}`) }`)
}
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep // libbbaz is an indirect dep
testApexError(t, "requires \"libbaz\" that is not available for the APEX", ` testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path:
.*-> libfoo.*link:shared.*
.*-> libfoo.*link:static.*
.*-> libbar.*link:shared.*
.*-> libbar.*link:static.*
.*-> libbaz.*link:shared.*
.*-> libbaz.*link:static.*`, `
apex { apex {
name: "myapex", name: "myapex",
key: "myapex.key", key: "myapex.key",
@ -3547,7 +3555,9 @@ func TestApexAvailable(t *testing.T) {
stl: "none", stl: "none",
system_shared_libs: [], system_shared_libs: [],
}`) }`)
}
func TestApexAvailable_InvalidApexName(t *testing.T) {
testApexError(t, "\"otherapex\" is not a valid module name", ` testApexError(t, "\"otherapex\" is not a valid module name", `
apex { apex {
name: "myapex", name: "myapex",
@ -3568,7 +3578,7 @@ func TestApexAvailable(t *testing.T) {
apex_available: ["otherapex"], apex_available: ["otherapex"],
}`) }`)
ctx, _ := testApex(t, ` testApex(t, `
apex { apex {
name: "myapex", name: "myapex",
key: "myapex.key", key: "myapex.key",
@ -3604,7 +3614,9 @@ func TestApexAvailable(t *testing.T) {
versions: ["10", "20", "30"], versions: ["10", "20", "30"],
}, },
}`) }`)
}
func TestApexAvailable_CreatedForPlatform(t *testing.T) {
// check that libfoo and libbar are created only for myapex, but not for the platform // check that libfoo and libbar are created only for myapex, but not for the platform
// TODO(jiyong) the checks for the platform variant are removed because we now create // TODO(jiyong) the checks for the platform variant are removed because we now create
// the platform variant regardless of the apex_availability. Instead, we will make sure that // the platform variant regardless of the apex_availability. Instead, we will make sure that
@ -3616,7 +3628,7 @@ func TestApexAvailable(t *testing.T) {
// ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex") // ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
// ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared") // ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
ctx, _ = testApex(t, ` ctx, _ := testApex(t, `
apex { apex {
name: "myapex", name: "myapex",
key: "myapex.key", key: "myapex.key",
@ -3638,8 +3650,10 @@ func TestApexAvailable(t *testing.T) {
// check that libfoo is created only for the platform // check that libfoo is created only for the platform
ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex") ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared") ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
}
ctx, _ = testApex(t, ` func TestApexAvailable_CreatedForApex(t *testing.T) {
testApex(t, `
apex { apex {
name: "myapex", name: "myapex",
key: "myapex.key", key: "myapex.key",

View file

@ -219,14 +219,18 @@ func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs,
func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs { func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs {
var noticeFiles android.Paths var noticeFiles android.Paths
a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if externalDep { if externalDep {
return // As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
} }
notice := to.NoticeFile() notice := to.NoticeFile()
if notice.Valid() { if notice.Valid() {
noticeFiles = append(noticeFiles, notice.Path()) noticeFiles = append(noticeFiles, notice.Path())
} }
return true
}) })
if len(noticeFiles) == 0 { if len(noticeFiles) == 0 {

View file

@ -16,7 +16,6 @@ package cc
import ( import (
"path/filepath" "path/filepath"
"strings"
"android/soong/android" "android/soong/android"
"github.com/google/blueprint" "github.com/google/blueprint"
@ -64,65 +63,12 @@ func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
return false return false
} }
func (mt *binarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { func (mt *binarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
info := mt.organizeVariants(member) return ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary")
buildSharedNativeBinarySnapshot(info, builder, member)
} }
// Organize the variants by architecture. func (mt *binarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
func (mt *binarySdkMemberType) organizeVariants(member android.SdkMember) *nativeBinaryInfo { return &nativeBinaryInfoProperties{}
memberName := member.Name()
info := &nativeBinaryInfo{
name: memberName,
memberType: mt,
}
for _, variant := range member.Variants() {
ccModule := variant.(*Module)
info.archVariantProperties = append(info.archVariantProperties, nativeBinaryInfoProperties{
name: memberName,
archType: ccModule.Target().Arch.ArchType.String(),
outputFile: ccModule.OutputFile().Path(),
})
}
// Initialize the unexported properties that will not be set during the
// extraction process.
info.commonProperties.name = memberName
// Extract common properties from the arch specific properties.
extractCommonProperties(&info.commonProperties, info.archVariantProperties)
return info
}
func buildSharedNativeBinarySnapshot(info *nativeBinaryInfo, builder android.SnapshotBuilder, member android.SdkMember) {
pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary")
archVariantCount := len(info.archVariantProperties)
// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
var multilib string
if archVariantCount == 2 {
multilib = "both"
} else if archVariantCount == 1 {
if strings.HasSuffix(info.archVariantProperties[0].archType, "64") {
multilib = "64"
} else {
multilib = "32"
}
}
if multilib != "" {
pbm.AddProperty("compile_multilib", multilib)
}
archProperties := pbm.AddPropertySet("arch")
for _, av := range info.archVariantProperties {
archTypeProperties := archProperties.AddPropertySet(av.archType)
archTypeProperties.AddProperty("srcs", []string{nativeBinaryPathFor(av)})
builder.CopyToSnapshot(av.outputFile, nativeBinaryPathFor(av))
}
} }
const ( const (
@ -131,7 +77,7 @@ const (
// path to the native binary. Relative to <sdk_root>/<api_dir> // path to the native binary. Relative to <sdk_root>/<api_dir>
func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string { func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
return filepath.Join(lib.archType, return filepath.Join(lib.OsPrefix(), lib.archType,
nativeBinaryDir, lib.outputFile.Base()) nativeBinaryDir, lib.outputFile.Base())
} }
@ -140,8 +86,7 @@ func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
// The exported (capitalized) fields will be examined and may be changed during common value extraction. // The exported (capitalized) fields will be examined and may be changed during common value extraction.
// The unexported fields will be left untouched. // The unexported fields will be left untouched.
type nativeBinaryInfoProperties struct { type nativeBinaryInfoProperties struct {
// The name of the library, is not exported as this must not be changed during optimization. android.SdkMemberPropertiesBase
name string
// archType is not exported as if set (to a non default value) it is always arch specific. // archType is not exported as if set (to a non default value) it is always arch specific.
// This is "" for common properties. // This is "" for common properties.
@ -149,12 +94,50 @@ type nativeBinaryInfoProperties struct {
// outputFile is not exported as it is always arch specific. // outputFile is not exported as it is always arch specific.
outputFile android.Path outputFile android.Path
// The set of shared libraries
//
// This field is exported as its contents may not be arch specific.
SharedLibs []string
// The set of system shared libraries
//
// This field is exported as its contents may not be arch specific.
SystemSharedLibs []string
} }
// nativeBinaryInfo represents a collection of arch-specific modules having the same name func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
type nativeBinaryInfo struct { ccModule := variant.(*Module)
name string
memberType *binarySdkMemberType p.archType = ccModule.Target().Arch.ArchType.String()
archVariantProperties []nativeBinaryInfoProperties p.outputFile = ccModule.OutputFile().Path()
commonProperties nativeBinaryInfoProperties
if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
p.SharedLibs = specifiedDeps.sharedLibs
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
}
func (p *nativeBinaryInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
if p.Compile_multilib != "" {
propertySet.AddProperty("compile_multilib", p.Compile_multilib)
}
builder := ctx.SnapshotBuilder()
if p.outputFile != nil {
propertySet.AddProperty("srcs", []string{nativeBinaryPathFor(*p)})
builder.CopyToSnapshot(p.outputFile, nativeBinaryPathFor(*p))
}
if len(p.SharedLibs) > 0 {
propertySet.AddPropertyWithTag("shared_libs", p.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
if len(p.SystemSharedLibs) > 0 {
propertySet.AddPropertyWithTag("system_shared_libs", p.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
}
} }

View file

@ -250,6 +250,8 @@ type BaseProperties struct {
// Used by vendor snapshot to record dependencies from snapshot modules. // Used by vendor snapshot to record dependencies from snapshot modules.
SnapshotSharedLibs []string `blueprint:"mutated"` SnapshotSharedLibs []string `blueprint:"mutated"`
SnapshotRuntimeLibs []string `blueprint:"mutated"` SnapshotRuntimeLibs []string `blueprint:"mutated"`
Installable *bool
} }
type VendorProperties struct { type VendorProperties struct {
@ -368,11 +370,21 @@ type linker interface {
nativeCoverage() bool nativeCoverage() bool
coverageOutputFilePath() android.OptionalPath coverageOutputFilePath() android.OptionalPath
// Get the deps that have been explicitly specified in the properties.
// Only updates the
linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
}
type specifiedDeps struct {
sharedLibs []string
systemSharedLibs []string
} }
type installer interface { type installer interface {
installerProps() []interface{} installerProps() []interface{}
install(ctx ModuleContext, path android.Path) install(ctx ModuleContext, path android.Path)
everInstallable() bool
inData() bool inData() bool
inSanitizerDir() bool inSanitizerDir() bool
hostToolPath() android.OptionalPath hostToolPath() android.OptionalPath
@ -1513,6 +1525,13 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
if ctx.Failed() { if ctx.Failed() {
return return
} }
} else if !proptools.BoolDefault(c.Properties.Installable, true) {
// If the module has been specifically configure to not be installed then
// skip the installation as otherwise it will break when running inside make
// as the output path to install will not be specified. Not all uninstallable
// modules can skip installation as some are needed for resolving make side
// dependencies.
c.SkipInstall()
} }
} }
@ -2705,8 +2724,18 @@ func (c *Module) AvailableFor(what string) bool {
} }
} }
// Return true if the module is ever installable.
func (c *Module) EverInstallable() bool {
return c.installer != nil &&
// Check to see whether the module is actually ever installable.
c.installer.everInstallable()
}
func (c *Module) installable() bool { func (c *Module) installable() bool {
ret := c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() ret := c.EverInstallable() &&
// Check to see whether the module has been configured to not be installed.
proptools.BoolDefault(c.Properties.Installable, true) &&
!c.Properties.PreventInstall && c.outputFile.Valid()
// The platform variant doesn't need further condition. Apex variants however might not // The platform variant doesn't need further condition. Apex variants however might not
// be installable because it will likely to be included in the APEX and won't appear // be installable because it will likely to be included in the APEX and won't appear

View file

@ -86,6 +86,11 @@ func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file) installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
} }
func (installer *baseInstaller) everInstallable() bool {
// Most cc modules are installable.
return true
}
func (installer *baseInstaller) inData() bool { func (installer *baseInstaller) inData() bool {
return installer.location == InstallInData return installer.location == InstallInData
} }

View file

@ -195,6 +195,7 @@ func LibraryFactory() android.Module {
module.sdkMemberTypes = []android.SdkMemberType{ module.sdkMemberTypes = []android.SdkMemberType{
sharedLibrarySdkMemberType, sharedLibrarySdkMemberType,
staticLibrarySdkMemberType, staticLibrarySdkMemberType,
staticAndSharedLibrarySdkMemberType,
} }
return module.Init() return module.Init()
} }
@ -817,6 +818,23 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
return deps return deps
} }
func (library *libraryDecorator) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
specifiedDeps = library.baseLinker.linkerSpecifiedDeps(specifiedDeps)
var properties StaticOrSharedProperties
if library.static() {
properties = library.StaticProperties.Static
} else if library.shared() {
properties = library.SharedProperties.Shared
}
specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, properties.Shared_libs...)
specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, properties.System_shared_libs...)
specifiedDeps.sharedLibs = android.FirstUniqueStrings(specifiedDeps.sharedLibs)
specifiedDeps.systemSharedLibs = android.FirstUniqueStrings(specifiedDeps.systemSharedLibs)
return specifiedDeps
}
func (library *libraryDecorator) linkStatic(ctx ModuleContext, func (library *libraryDecorator) linkStatic(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path { flags Flags, deps PathDeps, objs Objects) android.Path {
@ -1221,6 +1239,12 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
} }
} }
func (library *libraryDecorator) everInstallable() bool {
// Only shared and static libraries are installed. Header libraries (which are
// neither static or shared) are not installed.
return library.shared() || library.static()
}
func (library *libraryDecorator) static() bool { func (library *libraryDecorator) static() bool {
return library.MutatedProperties.VariantIsStatic return library.MutatedProperties.VariantIsStatic
} }

View file

@ -18,6 +18,18 @@ import "android/soong/android"
func init() { func init() {
RegisterLibraryHeadersBuildComponents(android.InitRegistrationContext) RegisterLibraryHeadersBuildComponents(android.InitRegistrationContext)
// Register sdk member types.
android.RegisterSdkMemberType(headersLibrarySdkMemberType)
}
var headersLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "native_header_libs",
SupportsSdk: true,
},
prebuiltModuleType: "cc_prebuilt_library_headers",
linkTypes: nil,
} }
func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) { func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) {
@ -32,6 +44,7 @@ func RegisterLibraryHeadersBuildComponents(ctx android.RegistrationContext) {
func LibraryHeaderFactory() android.Module { func LibraryHeaderFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported) module, library := NewLibrary(android.HostAndDeviceSupported)
library.HeaderOnly() library.HeaderOnly()
module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
return module.Init() return module.Init()
} }

View file

@ -16,10 +16,10 @@ package cc
import ( import (
"path/filepath" "path/filepath"
"reflect"
"android/soong/android" "android/soong/android"
"github.com/google/blueprint" "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
) )
// This file contains support for using cc library modules within an sdk. // This file contains support for using cc library modules within an sdk.
@ -42,10 +42,20 @@ var staticLibrarySdkMemberType = &librarySdkMemberType{
linkTypes: []string{"static"}, linkTypes: []string{"static"},
} }
var staticAndSharedLibrarySdkMemberType = &librarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "native_libs",
SupportsSdk: true,
},
prebuiltModuleType: "cc_prebuilt_library",
linkTypes: []string{"static", "shared"},
}
func init() { func init() {
// Register sdk member types. // Register sdk member types.
android.RegisterSdkMemberType(sharedLibrarySdkMemberType) android.RegisterSdkMemberType(sharedLibrarySdkMemberType)
android.RegisterSdkMemberType(staticLibrarySdkMemberType) android.RegisterSdkMemberType(staticLibrarySdkMemberType)
android.RegisterSdkMemberType(staticAndSharedLibrarySdkMemberType)
} }
type librarySdkMemberType struct { type librarySdkMemberType struct {
@ -65,6 +75,12 @@ func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorCont
if version == "" { if version == "" {
version = LatestStubsVersionFor(mctx.Config(), name) version = LatestStubsVersionFor(mctx.Config(), name)
} }
if mt.linkTypes == nil {
mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: android.CoreVariation},
{Mutator: "version", Variation: version},
}...), dependencyTag, name)
} else {
for _, linkType := range mt.linkTypes { for _, linkType := range mt.linkTypes {
mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: android.CoreVariation}, {Mutator: "image", Variation: android.CoreVariation},
@ -75,6 +91,7 @@ func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorCont
} }
} }
} }
}
func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
// Check the module to see if it can be used with this module type. // Check the module to see if it can be used with this module type.
@ -89,48 +106,25 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
return false return false
} }
// copy exported header files and stub *.so files func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, mt.prebuiltModuleType)
info := mt.organizeVariants(member)
buildSharedNativeLibSnapshot(sdkModuleContext, info, builder, member) ccModule := member.Variants()[0].(*Module)
sdkVersion := ccModule.SdkVersion()
if sdkVersion != "" {
pbm.AddProperty("sdk_version", sdkVersion)
} }
// Organize the variants by architecture. stl := ccModule.stl.Properties.Stl
func (mt *librarySdkMemberType) organizeVariants(member android.SdkMember) *nativeLibInfo { if stl != nil {
memberName := member.Name() pbm.AddProperty("stl", proptools.String(stl))
info := &nativeLibInfo{ }
name: memberName, return pbm
memberType: mt,
} }
for _, variant := range member.Variants() { func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
ccModule := variant.(*Module) return &nativeLibInfoProperties{memberType: mt}
// Separate out the generated include dirs (which are arch specific) from the
// include dirs (which may not be).
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
ccModule.ExportedIncludeDirs(), isGeneratedHeaderDirectory)
info.archVariantProperties = append(info.archVariantProperties, nativeLibInfoProperties{
name: memberName,
archType: ccModule.Target().Arch.ArchType.String(),
ExportedIncludeDirs: exportedIncludeDirs,
exportedGeneratedIncludeDirs: exportedGeneratedIncludeDirs,
ExportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
ExportedFlags: ccModule.ExportedFlags(),
exportedGeneratedHeaders: ccModule.ExportedGeneratedHeaders(),
outputFile: ccModule.OutputFile().Path(),
})
}
// Initialize the unexported properties that will not be set during the
// extraction process.
info.commonProperties.name = memberName
// Extract common properties from the arch specific properties.
extractCommonProperties(&info.commonProperties, info.archVariantProperties)
return info
} }
func isGeneratedHeaderDirectory(p android.Path) bool { func isGeneratedHeaderDirectory(p android.Path) bool {
@ -138,144 +132,137 @@ func isGeneratedHeaderDirectory(p android.Path) bool {
return gen return gen
} }
// Extract common properties from a slice of property structures of the same type. type includeDirsProperty struct {
// // Accessor to retrieve the paths
// All the property structures must be of the same type. pathsGetter func(libInfo *nativeLibInfoProperties) android.Paths
// commonProperties - must be a pointer to the structure into which common properties will be added.
// inputPropertiesSlice - must be a slice of input properties structures.
//
// Iterates over each exported field (capitalized name) and checks to see whether they
// have the same value (using DeepEquals) across all the input properties. If it does not then no
// change is made. Otherwise, the common value is stored in the field in the commonProperties
// and the field in each of the input properties structure is set to its default value.
func extractCommonProperties(commonProperties interface{}, inputPropertiesSlice interface{}) {
commonStructValue := reflect.ValueOf(commonProperties).Elem()
propertiesStructType := commonStructValue.Type()
// Create an empty structure from which default values for the field can be copied. // The name of the property in the prebuilt library, "" means there is no property.
emptyStructValue := reflect.New(propertiesStructType).Elem() propertyName string
for f := 0; f < propertiesStructType.NumField(); f++ { // The directory within the snapshot directory into which items should be copied.
// Check to see if all the structures have the same value for the field. The commonValue snapshotDir string
// is nil on entry to the loop and if it is nil on exit then there is no common value,
// otherwise it points to the common value.
var commonValue *reflect.Value
sliceValue := reflect.ValueOf(inputPropertiesSlice)
for i := 0; i < sliceValue.Len(); i++ { // True if the items on the path should be copied.
structValue := sliceValue.Index(i) copy bool
fieldValue := structValue.Field(f)
if !fieldValue.CanInterface() { // True if the paths represent directories, files if they represent files.
// The field is not exported so ignore it. dirs bool
continue
} }
if commonValue == nil { var includeDirProperties = []includeDirsProperty{
// Use the first value as the commonProperties value. {
commonValue = &fieldValue // ExportedIncludeDirs lists directories that contains some header files to be
} else { // copied into a directory in the snapshot. The snapshot directories must be added to
// If the value does not match the current common value then there is // the export_include_dirs property in the prebuilt module in the snapshot.
// no value in common so break out. pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedIncludeDirs },
if !reflect.DeepEqual(fieldValue.Interface(), commonValue.Interface()) { propertyName: "export_include_dirs",
commonValue = nil snapshotDir: nativeIncludeDir,
break copy: true,
} dirs: true,
} },
{
// ExportedSystemIncludeDirs lists directories that contains some system header files to
// be copied into a directory in the snapshot. The snapshot directories must be added to
// the export_system_include_dirs property in the prebuilt module in the snapshot.
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedSystemIncludeDirs },
propertyName: "export_system_include_dirs",
snapshotDir: nativeIncludeDir,
copy: true,
dirs: true,
},
{
// exportedGeneratedIncludeDirs lists directories that contains some header files
// that are explicitly listed in the exportedGeneratedHeaders property. So, the contents
// of these directories do not need to be copied, but these directories do need adding to
// the export_include_dirs property in the prebuilt module in the snapshot.
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
propertyName: "export_include_dirs",
snapshotDir: nativeGeneratedIncludeDir,
copy: false,
dirs: true,
},
{
// exportedGeneratedHeaders lists header files that are in one of the directories
// specified in exportedGeneratedIncludeDirs must be copied into the snapshot.
// As they are in a directory in exportedGeneratedIncludeDirs they do not need adding to a
// property in the prebuilt module in the snapshot.
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
propertyName: "",
snapshotDir: nativeGeneratedIncludeDir,
copy: true,
dirs: false,
},
} }
// If the fields all have a common value then store it in the common struct field // Add properties that may, or may not, be arch specific.
// and set the input struct's field to the empty value. func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
if commonValue != nil {
emptyValue := emptyStructValue.Field(f) // Copy the generated library to the snapshot and add a reference to it in the .bp module.
commonStructValue.Field(f).Set(*commonValue) if libInfo.outputFile != nil {
for i := 0; i < sliceValue.Len(); i++ { nativeLibraryPath := nativeLibraryPathFor(libInfo)
structValue := sliceValue.Index(i) builder.CopyToSnapshot(libInfo.outputFile, nativeLibraryPath)
fieldValue := structValue.Field(f) outputProperties.AddProperty("srcs", []string{nativeLibraryPath})
fieldValue.Set(emptyValue)
}
}
}
} }
func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder, member android.SdkMember) { if len(libInfo.SharedLibs) > 0 {
// a function for emitting include dirs outputProperties.AddPropertyWithTag("shared_libs", libInfo.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
addExportedDirCopyCommandsForNativeLibs := func(lib nativeLibInfoProperties) { }
// Do not include exportedGeneratedIncludeDirs in the list of directories whose
// contents are copied as they are copied from exportedGeneratedHeaders below. if len(libInfo.SystemSharedLibs) > 0 {
includeDirs := lib.ExportedIncludeDirs outputProperties.AddPropertyWithTag("system_shared_libs", libInfo.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
includeDirs = append(includeDirs, lib.ExportedSystemIncludeDirs...) }
for _, dir := range includeDirs {
// Map from property name to the include dirs to add to the prebuilt module in the snapshot.
includeDirs := make(map[string][]string)
// Iterate over each include directory property, copying files and collating property
// values where necessary.
for _, propertyInfo := range includeDirProperties {
// Calculate the base directory in the snapshot into which the files will be copied.
// lib.ArchType is "" for common properties. // lib.ArchType is "" for common properties.
targetDir := filepath.Join(lib.archType, nativeIncludeDir) targetDir := filepath.Join(libInfo.archType, propertyInfo.snapshotDir)
propertyName := propertyInfo.propertyName
// Iterate over each path in one of the include directory properties.
for _, path := range propertyInfo.pathsGetter(libInfo) {
// Copy the files/directories when necessary.
if propertyInfo.copy {
if propertyInfo.dirs {
// When copying a directory glob and copy all the headers within it.
// TODO(jiyong) copy headers having other suffixes // TODO(jiyong) copy headers having other suffixes
headers, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.h", nil) headers, _ := sdkModuleContext.GlobWithDeps(path.String()+"/**/*.h", nil)
for _, file := range headers { for _, file := range headers {
src := android.PathForSource(sdkModuleContext, file) src := android.PathForSource(sdkModuleContext, file)
dest := filepath.Join(targetDir, file) dest := filepath.Join(targetDir, file)
builder.CopyToSnapshot(src, dest) builder.CopyToSnapshot(src, dest)
} }
}
genHeaders := lib.exportedGeneratedHeaders
for _, file := range genHeaders {
// lib.ArchType is "" for common properties.
targetDir := filepath.Join(lib.archType, nativeGeneratedIncludeDir)
dest := filepath.Join(targetDir, lib.name, file.Rel())
builder.CopyToSnapshot(file, dest)
}
}
addExportedDirCopyCommandsForNativeLibs(info.commonProperties)
// for each architecture
for _, av := range info.archVariantProperties {
builder.CopyToSnapshot(av.outputFile, nativeLibraryPathFor(av))
addExportedDirCopyCommandsForNativeLibs(av)
}
info.generatePrebuiltLibrary(sdkModuleContext, builder, member)
}
func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
pbm := builder.AddPrebuiltModule(member, info.memberType.prebuiltModuleType)
addPossiblyArchSpecificProperties(info.commonProperties, pbm)
archProperties := pbm.AddPropertySet("arch")
for _, av := range info.archVariantProperties {
archTypeProperties := archProperties.AddPropertySet(av.archType)
// Add any arch specific properties inside the appropriate arch: {<arch>: {...}} block
archTypeProperties.AddProperty("srcs", []string{nativeLibraryPathFor(av)})
addPossiblyArchSpecificProperties(av, archTypeProperties)
}
pbm.AddProperty("stl", "none")
pbm.AddProperty("system_shared_libs", []string{})
}
// Add properties that may, or may not, be arch specific.
func addPossiblyArchSpecificProperties(libInfo nativeLibInfoProperties, outputProperties android.BpPropertySet) {
addExportedDirsForNativeLibs(libInfo, outputProperties, false /*systemInclude*/)
addExportedDirsForNativeLibs(libInfo, outputProperties, true /*systemInclude*/)
}
// a function for emitting include dirs
func addExportedDirsForNativeLibs(lib nativeLibInfoProperties, properties android.BpPropertySet, systemInclude bool) {
includeDirs := nativeIncludeDirPathsFor(lib, systemInclude)
if len(includeDirs) == 0 {
return
}
var propertyName string
if !systemInclude {
propertyName = "export_include_dirs"
} else { } else {
propertyName = "export_system_include_dirs" // Otherwise, just copy the files.
dest := filepath.Join(targetDir, libInfo.name, path.Rel())
builder.CopyToSnapshot(path, dest)
}
}
// Only directories are added to a property.
if propertyInfo.dirs {
var snapshotPath string
if isGeneratedHeaderDirectory(path) {
snapshotPath = filepath.Join(targetDir, libInfo.name)
} else {
snapshotPath = filepath.Join(targetDir, path.String())
}
includeDirs[propertyName] = append(includeDirs[propertyName], snapshotPath)
}
}
}
// Add the collated include dir properties to the output.
for property, dirs := range includeDirs {
outputProperties.AddProperty(property, dirs)
} }
properties.AddProperty(propertyName, includeDirs)
} }
const ( const (
@ -285,41 +272,20 @@ const (
) )
// path to the native library. Relative to <sdk_root>/<api_dir> // path to the native library. Relative to <sdk_root>/<api_dir>
func nativeLibraryPathFor(lib nativeLibInfoProperties) string { func nativeLibraryPathFor(lib *nativeLibInfoProperties) string {
return filepath.Join(lib.archType, return filepath.Join(lib.OsPrefix(), lib.archType,
nativeStubDir, lib.outputFile.Base()) nativeStubDir, lib.outputFile.Base())
} }
// paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
func nativeIncludeDirPathsFor(lib nativeLibInfoProperties, systemInclude bool) []string {
var result []string
var includeDirs []android.Path
if !systemInclude {
// Include the generated include dirs in the exported include dirs.
includeDirs = append(lib.ExportedIncludeDirs, lib.exportedGeneratedIncludeDirs...)
} else {
includeDirs = lib.ExportedSystemIncludeDirs
}
for _, dir := range includeDirs {
var path string
if isGeneratedHeaderDirectory(dir) {
path = filepath.Join(nativeGeneratedIncludeDir, lib.name)
} else {
path = filepath.Join(nativeIncludeDir, dir.String())
}
// lib.ArchType is "" for common properties.
path = filepath.Join(lib.archType, path)
result = append(result, path)
}
return result
}
// nativeLibInfoProperties represents properties of a native lib // nativeLibInfoProperties represents properties of a native lib
// //
// The exported (capitalized) fields will be examined and may be changed during common value extraction. // The exported (capitalized) fields will be examined and may be changed during common value extraction.
// The unexported fields will be left untouched. // The unexported fields will be left untouched.
type nativeLibInfoProperties struct { type nativeLibInfoProperties struct {
android.SdkMemberPropertiesBase
memberType *librarySdkMemberType
// The name of the library, is not exported as this must not be changed during optimization. // The name of the library, is not exported as this must not be changed during optimization.
name string name string
@ -352,14 +318,53 @@ type nativeLibInfoProperties struct {
// This field is exported as its contents may not be arch specific. // This field is exported as its contents may not be arch specific.
ExportedFlags []string ExportedFlags []string
// The set of shared libraries
//
// This field is exported as its contents may not be arch specific.
SharedLibs []string
// The set of system shared libraries
//
// This field is exported as its contents may not be arch specific.
SystemSharedLibs []string
// outputFile is not exported as it is always arch specific. // outputFile is not exported as it is always arch specific.
outputFile android.Path outputFile android.Path
} }
// nativeLibInfo represents a collection of arch-specific modules having the same name func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
type nativeLibInfo struct { ccModule := variant.(*Module)
name string
memberType *librarySdkMemberType // If the library has some link types then it produces an output binary file, otherwise it
archVariantProperties []nativeLibInfoProperties // is header only.
commonProperties nativeLibInfoProperties if p.memberType.linkTypes != nil {
p.outputFile = ccModule.OutputFile().Path()
}
// Separate out the generated include dirs (which are arch specific) from the
// include dirs (which may not be).
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
ccModule.ExportedIncludeDirs(), isGeneratedHeaderDirectory)
p.name = variant.Name()
p.archType = ccModule.Target().Arch.ArchType.String()
// Make sure that the include directories are unique.
p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
p.exportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
p.ExportedSystemIncludeDirs = android.FirstUniquePaths(ccModule.ExportedSystemIncludeDirs())
p.ExportedFlags = ccModule.ExportedFlags()
if ccModule.linker != nil {
specifiedDeps := specifiedDeps{}
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
p.SharedLibs = specifiedDeps.sharedLibs
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
}
func (p *nativeLibInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
addPossiblyArchSpecificProperties(ctx.SdkModuleContext(), ctx.SnapshotBuilder(), p, propertySet)
} }

View file

@ -490,6 +490,12 @@ func (linker *baseLinker) link(ctx ModuleContext,
panic(fmt.Errorf("baseLinker doesn't know how to link")) panic(fmt.Errorf("baseLinker doesn't know how to link"))
} }
func (linker *baseLinker) linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps {
specifiedDeps.sharedLibs = append(specifiedDeps.sharedLibs, linker.Properties.Shared_libs...)
specifiedDeps.systemSharedLibs = append(specifiedDeps.systemSharedLibs, linker.Properties.System_shared_libs...)
return specifiedDeps
}
// Injecting version symbols // Injecting version symbols
// Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step // Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step
// after linking that injects a constant placeholder with the current version number. // after linking that injects a constant placeholder with the current version number.

View file

@ -23,6 +23,7 @@ func init() {
} }
func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) { func RegisterPrebuiltBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory) ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory) ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory) ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
@ -96,10 +97,16 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...) p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
// TODO(ccross): verify shared library dependencies // TODO(ccross): verify shared library dependencies
if len(p.properties.Srcs) > 0 { srcs := p.prebuiltSrcs()
if len(srcs) > 0 {
builderFlags := flagsToBuilderFlags(flags) builderFlags := flagsToBuilderFlags(flags)
in := p.Prebuilt.SingleSourcePath(ctx) if len(srcs) > 1 {
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
return nil
}
in := android.PathForModuleSrc(ctx, srcs[0])
if p.shared() { if p.shared() {
p.unstrippedOutputFile = in p.unstrippedOutputFile = in
@ -123,6 +130,18 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
return nil return nil
} }
func (p *prebuiltLibraryLinker) prebuiltSrcs() []string {
srcs := p.properties.Srcs
if p.static() {
srcs = append(srcs, p.libraryDecorator.StaticProperties.Static.Srcs...)
}
if p.shared() {
srcs = append(srcs, p.libraryDecorator.SharedProperties.Shared.Srcs...)
}
return srcs
}
func (p *prebuiltLibraryLinker) shared() bool { func (p *prebuiltLibraryLinker) shared() bool {
return p.libraryDecorator.shared() return p.libraryDecorator.shared()
} }
@ -151,13 +170,28 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec
module.AddProperties(&prebuilt.properties) module.AddProperties(&prebuilt.properties)
android.InitPrebuiltModule(module, &prebuilt.properties.Srcs) srcsSupplier := func() []string {
return prebuilt.prebuiltSrcs()
}
android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
// Prebuilt libraries can be used in SDKs. // Prebuilt libraries can be used in SDKs.
android.InitSdkAwareModule(module) android.InitSdkAwareModule(module)
return module, library return module, library
} }
// cc_prebuilt_library installs a precompiled shared library that are
// listed in the srcs property in the device's directory.
func PrebuiltLibraryFactory() android.Module {
module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
// Prebuilt shared libraries can be included in APEXes
android.InitApexModule(module)
return module.Init()
}
// cc_prebuilt_library_shared installs a precompiled shared library that are // cc_prebuilt_library_shared installs a precompiled shared library that are
// listed in the srcs property in the device's directory. // listed in the srcs property in the device's directory.
func PrebuiltSharedLibraryFactory() android.Module { func PrebuiltSharedLibraryFactory() android.Module {

View file

@ -59,36 +59,38 @@ func TestPrebuilt(t *testing.T) {
name: "libe", name: "libe",
srcs: ["libe.a"], srcs: ["libe.a"],
} }
`
fs := map[string][]byte{ cc_library {
"liba.so": nil, name: "libf",
"libb.a": nil,
"libd.so": nil,
"libe.a": nil,
} }
config := TestConfig(buildDir, android.Android, nil, bp, fs) cc_prebuilt_library {
name: "libf",
static: {
srcs: ["libf.a"],
},
shared: {
srcs: ["libf.so"],
},
}
`
ctx := CreateTestContext() ctx := testPrebuilt(t, bp)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
// Verify that all the modules exist and that their dependencies were connected correctly // Verify that all the modules exist and that their dependencies were connected correctly
liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module() liba := ctx.ModuleForTests("liba", "android_arm64_armv8-a_shared").Module()
libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module() libb := ctx.ModuleForTests("libb", "android_arm64_armv8-a_static").Module()
libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module() libd := ctx.ModuleForTests("libd", "android_arm64_armv8-a_shared").Module()
libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module() libe := ctx.ModuleForTests("libe", "android_arm64_armv8-a_static").Module()
libfStatic := ctx.ModuleForTests("libf", "android_arm64_armv8-a_static").Module()
libfShared := ctx.ModuleForTests("libf", "android_arm64_armv8-a_shared").Module()
prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module() prebuiltLiba := ctx.ModuleForTests("prebuilt_liba", "android_arm64_armv8-a_shared").Module()
prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module() prebuiltLibb := ctx.ModuleForTests("prebuilt_libb", "android_arm64_armv8-a_static").Module()
prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module() prebuiltLibd := ctx.ModuleForTests("prebuilt_libd", "android_arm64_armv8-a_shared").Module()
prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module() prebuiltLibe := ctx.ModuleForTests("prebuilt_libe", "android_arm64_armv8-a_static").Module()
prebuiltLibfStatic := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_static").Module()
prebuiltLibfShared := ctx.ModuleForTests("prebuilt_libf", "android_arm64_armv8-a_shared").Module()
hasDep := func(m android.Module, wantDep android.Module) bool { hasDep := func(m android.Module, wantDep android.Module) bool {
t.Helper() t.Helper()
@ -116,4 +118,89 @@ func TestPrebuilt(t *testing.T) {
if !hasDep(libe, prebuiltLibe) { if !hasDep(libe, prebuiltLibe) {
t.Errorf("libe missing dependency on prebuilt_libe") t.Errorf("libe missing dependency on prebuilt_libe")
} }
if !hasDep(libfStatic, prebuiltLibfStatic) {
t.Errorf("libf static missing dependency on prebuilt_libf")
}
if !hasDep(libfShared, prebuiltLibfShared) {
t.Errorf("libf shared missing dependency on prebuilt_libf")
}
}
func testPrebuilt(t *testing.T, bp string) *android.TestContext {
fs := map[string][]byte{
"liba.so": nil,
"libb.a": nil,
"libd.so": nil,
"libe.a": nil,
"libf.a": nil,
"libf.so": nil,
}
config := TestConfig(buildDir, android.Android, nil, bp, fs)
ctx := CreateTestContext()
// Enable androidmk support.
// * Register the singleton
// * Configure that we are inside make
// * Add CommonOS to ensure that androidmk processing works.
android.RegisterAndroidMkBuildComponents(ctx)
android.SetInMakeForTests(config)
ctx.Register(config)
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
return ctx
}
func TestPrebuiltLibraryShared(t *testing.T) {
ctx := testPrebuilt(t, `
cc_prebuilt_library_shared {
name: "libtest",
srcs: ["libf.so"],
strip: {
none: true,
},
}
`)
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().String(), "libf.so")
}
func TestPrebuiltLibraryStatic(t *testing.T) {
ctx := testPrebuilt(t, `
cc_prebuilt_library_static {
name: "libtest",
srcs: ["libf.a"],
}
`)
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().String(), "libf.a")
}
func TestPrebuiltLibrary(t *testing.T) {
ctx := testPrebuilt(t, `
cc_prebuilt_library {
name: "libtest",
static: {
srcs: ["libf.a"],
},
shared: {
srcs: ["libf.so"],
},
strip: {
none: true,
},
}
`)
shared := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_shared").Module().(*Module)
assertString(t, shared.OutputFile().String(), "libf.so")
static := ctx.ModuleForTests("libtest", "android_arm64_armv8-a_static").Module().(*Module)
assertString(t, static.OutputFile().String(), "libf.a")
} }

View file

@ -34,7 +34,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory) ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
} }
func GatherRequiredDepsForTest(os android.OsType) string { func GatherRequiredDepsForTest(oses ...android.OsType) string {
ret := ` ret := `
toolchain_library { toolchain_library {
name: "libatomic", name: "libatomic",
@ -380,6 +380,7 @@ func GatherRequiredDepsForTest(os android.OsType) string {
} }
` `
for _, os := range oses {
if os == android.Fuchsia { if os == android.Fuchsia {
ret += ` ret += `
cc_library { cc_library {
@ -392,6 +393,22 @@ func GatherRequiredDepsForTest(os android.OsType) string {
} }
` `
} }
if os == android.Windows {
ret += `
toolchain_library {
name: "libwinpthread",
host_supported: true,
enabled: false,
target: {
windows: {
enabled: true,
},
},
src: "",
}
`
}
}
return ret return ret
} }

View file

@ -1927,18 +1927,33 @@ func (mt *droidStubsSdkMemberType) IsInstance(module android.Module) bool {
return ok return ok
} }
func (mt *droidStubsSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { func (mt *droidStubsSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
variants := member.Variants() return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_stubs_sources")
if len(variants) != 1 {
sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
} }
variant := variants[0]
d, _ := variant.(*Droidstubs)
stubsSrcJar := d.stubsSrcJar
snapshotRelativeDir := filepath.Join("java", d.Name()+"_stubs_sources") func (mt *droidStubsSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
builder.UnzipToSnapshot(stubsSrcJar, snapshotRelativeDir) return &droidStubsInfoProperties{}
}
pbm := builder.AddPrebuiltModule(member, "prebuilt_stubs_sources")
pbm.AddProperty("srcs", []string{snapshotRelativeDir}) type droidStubsInfoProperties struct {
android.SdkMemberPropertiesBase
StubsSrcJar android.Path
}
func (p *droidStubsInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
droidstubs := variant.(*Droidstubs)
p.StubsSrcJar = droidstubs.stubsSrcJar
}
func (p *droidStubsInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
if p.StubsSrcJar != nil {
builder := ctx.SnapshotBuilder()
snapshotRelativeDir := filepath.Join("java", ctx.Name()+"_stubs_sources")
builder.UnzipToSnapshot(p.StubsSrcJar, snapshotRelativeDir)
propertySet.AddProperty("srcs", []string{snapshotRelativeDir})
}
} }

View file

@ -39,11 +39,17 @@ func init() {
// Register sdk member types. // Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType) android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
android.RegisterSdkMemberType(&implLibrarySdkMemberType{ android.RegisterSdkMemberType(&librarySdkMemberType{
librarySdkMemberType{
android.SdkMemberTypeBase{ android.SdkMemberTypeBase{
PropertyName: "java_libs", PropertyName: "java_libs",
}, },
func(j *Library) android.Path {
implementationJars := j.ImplementationJars()
if len(implementationJars) != 1 {
panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
}
return implementationJars[0]
}, },
}) })
@ -1860,16 +1866,20 @@ const (
) )
// path to the jar file of a java library. Relative to <sdk_root>/<api_dir> // path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
func sdkSnapshotFilePathForJar(member android.SdkMember) string { func sdkSnapshotFilePathForJar(osPrefix, name string) string {
return sdkSnapshotFilePathForMember(member, jarFileSuffix) return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
} }
func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) string { func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string {
return filepath.Join(javaDir, member.Name()+suffix) return filepath.Join(javaDir, osPrefix, name+suffix)
} }
type librarySdkMemberType struct { type librarySdkMemberType struct {
android.SdkMemberTypeBase android.SdkMemberTypeBase
// Function to retrieve the appropriate output jar (implementation or header) from
// the library.
jarToExportGetter func(j *Library) android.Path
} }
func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
@ -1881,27 +1891,43 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
return ok return ok
} }
func (mt *librarySdkMemberType) buildSnapshot( func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
sdkModuleContext android.ModuleContext, return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_import")
builder android.SnapshotBuilder, }
member android.SdkMember,
jarToExportGetter func(j *Library) android.Path) {
variants := member.Variants() func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
if len(variants) != 1 { return &librarySdkMemberProperties{}
sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
for _, variant := range variants {
sdkModuleContext.ModuleErrorf(" %q", variant)
} }
type librarySdkMemberProperties struct {
android.SdkMemberPropertiesBase
JarToExport android.Path
AidlIncludeDirs android.Paths
} }
variant := variants[0]
func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
j := variant.(*Library) j := variant.(*Library)
exportedJar := jarToExportGetter(j) p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(j)
snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member) p.AidlIncludeDirs = j.AidlIncludeDirs()
}
func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
builder := ctx.SnapshotBuilder()
exportedJar := p.JarToExport
if exportedJar != nil {
snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
for _, dir := range j.AidlIncludeDirs() { propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
aidlIncludeDirs := p.AidlIncludeDirs
if len(aidlIncludeDirs) != 0 {
sdkModuleContext := ctx.SdkModuleContext()
for _, dir := range aidlIncludeDirs {
// TODO(jiyong): copy parcelable declarations only // TODO(jiyong): copy parcelable declarations only
aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil) aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
for _, file := range aidlFiles { for _, file := range aidlFiles {
@ -1909,47 +1935,23 @@ func (mt *librarySdkMemberType) buildSnapshot(
} }
} }
module := builder.AddPrebuiltModule(member, "java_import") // TODO(b/151933053) - add aidl include dirs property
module.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) }
} }
var javaHeaderLibsSdkMemberType android.SdkMemberType = &headerLibrarySdkMemberType{ var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
librarySdkMemberType{
android.SdkMemberTypeBase{ android.SdkMemberTypeBase{
PropertyName: "java_header_libs", PropertyName: "java_header_libs",
SupportsSdk: true, SupportsSdk: true,
}, },
}, func(j *Library) android.Path {
}
type headerLibrarySdkMemberType struct {
librarySdkMemberType
}
func (mt *headerLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
headerJars := j.HeaderJars() headerJars := j.HeaderJars()
if len(headerJars) != 1 { if len(headerJars) != 1 {
panic(fmt.Errorf("there must be only one header jar from %q", j.Name())) panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
} }
return headerJars[0] return headerJars[0]
}) },
}
type implLibrarySdkMemberType struct {
librarySdkMemberType
}
func (mt *implLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path {
implementationJars := j.ImplementationJars()
if len(implementationJars) != 1 {
panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
}
return implementationJars[0]
})
} }
// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well. // java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
@ -2100,31 +2102,50 @@ func (mt *testSdkMemberType) IsInstance(module android.Module) bool {
return ok return ok
} }
func (mt *testSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { func (mt *testSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
variants := member.Variants() return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_test_import")
if len(variants) != 1 {
sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
for _, variant := range variants {
sdkModuleContext.ModuleErrorf(" %q", variant)
} }
}
variant := variants[0]
j := variant.(*Test)
implementationJars := j.ImplementationJars() func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
return &testSdkMemberProperties{}
}
type testSdkMemberProperties struct {
android.SdkMemberPropertiesBase
JarToExport android.Path
TestConfig android.Path
}
func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
test := variant.(*Test)
implementationJars := test.ImplementationJars()
if len(implementationJars) != 1 { if len(implementationJars) != 1 {
panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name()))
} }
snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member) p.JarToExport = implementationJars[0]
builder.CopyToSnapshot(implementationJars[0], snapshotRelativeJavaLibPath) p.TestConfig = test.testConfig
}
snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(member, testConfigSuffix) func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
builder.CopyToSnapshot(j.testConfig, snapshotRelativeTestConfigPath) builder := ctx.SnapshotBuilder()
module := builder.AddPrebuiltModule(member, "java_test_import") exportedJar := p.JarToExport
module.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) if exportedJar != nil {
module.AddProperty("test_config", snapshotRelativeTestConfigPath) snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
testConfig := p.TestConfig
if testConfig != nil {
snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), ctx.Name(), testConfigSuffix)
builder.CopyToSnapshot(testConfig, snapshotRelativeTestConfigPath)
propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath)
}
} }
// java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and // java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and
@ -2327,7 +2348,7 @@ func BinaryHostFactory() android.Module {
// //
type ImportProperties struct { type ImportProperties struct {
Jars []string `android:"path"` Jars []string `android:"path,arch_variant"`
Sdk_version *string Sdk_version *string

View file

@ -451,7 +451,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiSc
mctx.CreateModule(LibraryFactory, &props) mctx.CreateModule(LibraryFactory, &props)
} }
// Creates a droiddoc module that creates stubs source files from the given full source // Creates a droidstubs module that creates stubs source files from the given full source
// files // files
func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) { func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) {
props := struct { props := struct {
@ -506,15 +506,15 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
droiddocArgs := []string{} droidstubsArgs := []string{}
if len(module.sdkLibraryProperties.Api_packages) != 0 { if len(module.sdkLibraryProperties.Api_packages) != 0 {
droiddocArgs = append(droiddocArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":")) droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":"))
} }
if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 { if len(module.sdkLibraryProperties.Hidden_api_packages) != 0 {
droiddocArgs = append(droiddocArgs, droidstubsArgs = append(droidstubsArgs,
android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package ")) android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
} }
droiddocArgs = append(droiddocArgs, module.sdkLibraryProperties.Droiddoc_options...) droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
disabledWarnings := []string{ disabledWarnings := []string{
"MissingPermission", "MissingPermission",
"BroadcastBehavior", "BroadcastBehavior",
@ -526,16 +526,16 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc
"Todo", "Todo",
"Typo", "Typo",
} }
droiddocArgs = append(droiddocArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
switch apiScope { switch apiScope {
case apiScopeSystem: case apiScopeSystem:
droiddocArgs = append(droiddocArgs, "-showAnnotation android.annotation.SystemApi") droidstubsArgs = append(droidstubsArgs, "-showAnnotation android.annotation.SystemApi")
case apiScopeTest: case apiScopeTest:
droiddocArgs = append(droiddocArgs, " -showAnnotation android.annotation.TestApi") droidstubsArgs = append(droidstubsArgs, " -showAnnotation android.annotation.TestApi")
} }
props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files
props.Args = proptools.StringPtr(strings.Join(droiddocArgs, " ")) props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " "))
// List of APIs identified from the provided source files are created. They are later // List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the // compared against to the not-yet-released (a.k.a current) list of APIs and to the

View file

@ -242,18 +242,28 @@ func (mt *systemModulesSdkMemberType) IsInstance(module android.Module) bool {
return false return false
} }
func (mt *systemModulesSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { func (mt *systemModulesSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
variants := member.Variants() return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_system_modules_import")
if len(variants) != 1 {
sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
for _, variant := range variants {
sdkModuleContext.ModuleErrorf(" %q", variant)
} }
}
variant := variants[0]
systemModule := variant.(*SystemModules)
pbm := builder.AddPrebuiltModule(member, "java_system_modules_import") type systemModulesInfoProperties struct {
// Add the references to the libraries that form the system module. android.SdkMemberPropertiesBase
pbm.AddPropertyWithTag("libs", systemModule.properties.Libs, builder.SdkMemberReferencePropertyTag())
Libs []string
}
func (mt *systemModulesSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
return &systemModulesInfoProperties{}
}
func (p *systemModulesInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
systemModule := variant.(*SystemModules)
p.Libs = systemModule.properties.Libs
}
func (p *systemModulesInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
if len(p.Libs) > 0 {
// Add the references to the libraries that form the system module.
propertySet.AddPropertyWithTag("libs", p.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
}
} }

View file

@ -35,7 +35,7 @@ func (s *bpPropertySet) init() {
func (s *bpPropertySet) AddProperty(name string, value interface{}) { func (s *bpPropertySet) AddProperty(name string, value interface{}) {
if s.properties[name] != nil { if s.properties[name] != nil {
panic("Property %q already exists in property set") panic(fmt.Sprintf("Property %q already exists in property set", name))
} }
s.properties[name] = value s.properties[name] = value
@ -48,8 +48,7 @@ func (s *bpPropertySet) AddPropertyWithTag(name string, value interface{}, tag a
} }
func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet { func (s *bpPropertySet) AddPropertySet(name string) android.BpPropertySet {
set := &bpPropertySet{} set := newPropertySet()
set.init()
s.AddProperty(name, set) s.AddProperty(name, set)
return set return set
} }
@ -62,7 +61,7 @@ func (s *bpPropertySet) getTag(name string) interface{} {
return s.tags[name] return s.tags[name]
} }
func (s *bpPropertySet) transform(transformer bpPropertyTransformer) { func (s *bpPropertySet) transformContents(transformer bpPropertyTransformer) {
var newOrder []string var newOrder []string
for _, name := range s.order { for _, name := range s.order {
value := s.properties[name] value := s.properties[name]
@ -70,7 +69,13 @@ func (s *bpPropertySet) transform(transformer bpPropertyTransformer) {
var newValue interface{} var newValue interface{}
var newTag android.BpPropertyTag var newTag android.BpPropertyTag
if propertySet, ok := value.(*bpPropertySet); ok { if propertySet, ok := value.(*bpPropertySet); ok {
newValue, newTag = transformer.transformPropertySet(name, propertySet, tag) var newPropertySet *bpPropertySet
newPropertySet, newTag = transformPropertySet(transformer, name, propertySet, tag)
if newPropertySet == nil {
newValue = nil
} else {
newValue = newPropertySet
}
} else { } else {
newValue, newTag = transformer.transformProperty(name, value, tag) newValue, newTag = transformer.transformProperty(name, value, tag)
} }
@ -88,6 +93,16 @@ func (s *bpPropertySet) transform(transformer bpPropertyTransformer) {
s.order = newOrder s.order = newOrder
} }
func transformPropertySet(transformer bpPropertyTransformer, name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
newPropertySet, newTag := transformer.transformPropertySetBeforeContents(name, propertySet, tag)
if newPropertySet != nil {
newPropertySet.transformContents(transformer)
newPropertySet, newTag = transformer.transformPropertySetAfterContents(name, newPropertySet, newTag)
}
return newPropertySet, newTag
}
func (s *bpPropertySet) setProperty(name string, value interface{}) { func (s *bpPropertySet) setProperty(name string, value interface{}) {
if s.properties[name] == nil { if s.properties[name] == nil {
s.AddProperty(name, value) s.AddProperty(name, value)
@ -136,7 +151,17 @@ type bpPropertyTransformer interface {
// The name will be "" for the top level property set. // The name will be "" for the top level property set.
// //
// Returning (nil, ...) will cause the property set to be removed. // Returning (nil, ...) will cause the property set to be removed.
transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
// Transform the property set, returning the new property set/tag to insert back into the
// parent property set (or module if this is the top level property set).
//
// This will be called after transforming the properties in the supplied set.
//
// The name will be "" for the top level property set.
//
// Returning (nil, ...) will cause the property set to be removed.
transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag)
// Transform a property, return the new value/tag to insert back into the property set. // Transform a property, return the new value/tag to insert back into the property set.
// //
@ -165,7 +190,11 @@ func (t identityTransformation) transformModule(module *bpModule) *bpModule {
return module return module
} }
func (t identityTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { func (t identityTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
return propertySet, tag
}
func (t identityTransformation) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
return propertySet, tag return propertySet, tag
} }
@ -180,12 +209,13 @@ func (m *bpModule) deepCopy() *bpModule {
func (m *bpModule) transform(transformer bpTransformer) *bpModule { func (m *bpModule) transform(transformer bpTransformer) *bpModule {
transformedModule := transformer.transformModule(m) transformedModule := transformer.transformModule(m)
// Copy the contents of the returned property set into the module and then transform that. // Copy the contents of the returned property set into the module and then transform that.
transformedModule.bpPropertySet, _ = transformer.transformPropertySet("", transformedModule.bpPropertySet, nil) transformedModule.bpPropertySet, _ = transformPropertySet(transformer, "", transformedModule.bpPropertySet, nil)
transformedModule.bpPropertySet.transform(transformer)
return transformedModule return transformedModule
} }
type deepCopyTransformation struct{} type deepCopyTransformation struct {
identityTransformation
}
func (t deepCopyTransformation) transformModule(module *bpModule) *bpModule { func (t deepCopyTransformation) transformModule(module *bpModule) *bpModule {
// Take a shallow copy of the module. Any mutable property values will be copied by the // Take a shallow copy of the module. Any mutable property values will be copied by the
@ -194,7 +224,7 @@ func (t deepCopyTransformation) transformModule(module *bpModule) *bpModule {
return &moduleCopy return &moduleCopy
} }
func (t deepCopyTransformation) transformPropertySet(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { func (t deepCopyTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
// Create a shallow copy of the properties map. Any mutable property values will be copied by the // Create a shallow copy of the properties map. Any mutable property values will be copied by the
// transformer. // transformer.
propertiesCopy := make(map[string]interface{}) propertiesCopy := make(map[string]interface{})
@ -253,10 +283,19 @@ func (f *bpFile) AddModule(module android.BpModule) {
} }
func (f *bpFile) newModule(moduleType string) *bpModule { func (f *bpFile) newModule(moduleType string) *bpModule {
return newModule(moduleType)
}
func newModule(moduleType string) *bpModule {
module := &bpModule{ module := &bpModule{
moduleType: moduleType, moduleType: moduleType,
bpPropertySet: &bpPropertySet{}, bpPropertySet: newPropertySet(),
} }
module.bpPropertySet.init()
return module return module
} }
func newPropertySet() *bpPropertySet {
set := &bpPropertySet{}
set.init()
return set
}

76
sdk/bp_test.go Normal file
View file

@ -0,0 +1,76 @@
// Copyright (C) 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 sdk
import (
"testing"
"android/soong/android"
)
type removeFredTransformation struct {
identityTransformation
}
func (t removeFredTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
if name == "fred" {
return nil, nil
}
return value, tag
}
func (t removeFredTransformation) transformPropertySetBeforeContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
if name == "fred" {
return nil, nil
}
return propertySet, tag
}
func (t removeFredTransformation) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) {
if len(propertySet.properties) == 0 {
return nil, nil
}
return propertySet, tag
}
func TestTransformRemoveProperty(t *testing.T) {
helper := &TestHelper{t}
set := newPropertySet()
set.AddProperty("name", "name")
set.AddProperty("fred", "12")
set.transformContents(removeFredTransformation{})
contents := &generatedContents{}
outputPropertySet(contents, set)
helper.AssertTrimmedStringEquals("removing property failed", "name: \"name\",\\n", contents.content.String())
}
func TestTransformRemovePropertySet(t *testing.T) {
helper := &TestHelper{t}
set := newPropertySet()
set.AddProperty("name", "name")
set.AddPropertySet("fred")
set.transformContents(removeFredTransformation{})
contents := &generatedContents{}
outputPropertySet(contents, set)
helper.AssertTrimmedStringEquals("removing property set failed", "name: \"name\",\\n", contents.content.String())
}

View file

@ -17,6 +17,7 @@ package sdk
import ( import (
"testing" "testing"
"android/soong/android"
"android/soong/cc" "android/soong/cc"
) )
@ -26,6 +27,8 @@ func testSdkWithCc(t *testing.T, bp string) *testSdkResult {
fs := map[string][]byte{ fs := map[string][]byte{
"Test.cpp": nil, "Test.cpp": nil,
"include/Test.h": nil, "include/Test.h": nil,
"include-android/AndroidTest.h": nil,
"include-host/HostTest.h": nil,
"arm64/include/Arm64Test.h": nil, "arm64/include/Arm64Test.h": nil,
"libfoo.so": nil, "libfoo.so": nil,
"aidl/foo/bar/Test.aidl": nil, "aidl/foo/bar/Test.aidl": nil,
@ -54,7 +57,7 @@ func TestSdkIsCompileMultilibBoth(t *testing.T) {
arm64Output := result.Module("sdkmember", "android_arm64_armv8-a_shared").(*cc.Module).OutputFile() arm64Output := result.Module("sdkmember", "android_arm64_armv8-a_shared").(*cc.Module).OutputFile()
var inputs []string var inputs []string
buildParams := result.Module("mysdk", "android_common").BuildParamsForTests() buildParams := result.Module("mysdk", android.CommonOS.Name).BuildParamsForTests()
for _, bp := range buildParams { for _, bp := range buildParams {
if bp.Input != nil { if bp.Input != nil {
inputs = append(inputs, bp.Input.String()) inputs = append(inputs, bp.Input.String())
@ -250,7 +253,7 @@ func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "android_common", "", result.CheckSnapshot("mysdk", "",
checkAllCopyRules(` checkAllCopyRules(`
include/Test.h -> include/include/Test.h include/Test.h -> include/include/Test.h
.intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so .intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
@ -287,13 +290,15 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "android_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared { cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current", name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
installable: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -304,13 +309,12 @@ cc_prebuilt_library_shared {
srcs: ["arm/lib/mynativelib.so"], srcs: ["arm/lib/mynativelib.so"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_shared { cc_prebuilt_library_shared {
name: "mynativelib", name: "mynativelib",
prefer: false, prefer: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -321,8 +325,6 @@ cc_prebuilt_library_shared {
srcs: ["arm/lib/mynativelib.so"], srcs: ["arm/lib/mynativelib.so"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
sdk_snapshot { sdk_snapshot {
@ -356,13 +358,14 @@ func TestSnapshotWithCcBinary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mymodule_exports", "android_common", "", result.CheckSnapshot("mymodule_exports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary { cc_prebuilt_binary {
name: "mymodule_exports_mynativebinary@current", name: "mymodule_exports_mynativebinary@current",
sdk_member_name: "mynativebinary", sdk_member_name: "mynativebinary",
installable: false,
compile_multilib: "both", compile_multilib: "both",
arch: { arch: {
arm64: { arm64: {
@ -400,6 +403,114 @@ module_exports_snapshot {
) )
} }
func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
device_supported: false,
host_supported: true,
native_binaries: ["mynativebinary"],
target: {
windows: {
enabled: true,
},
},
}
cc_binary {
name: "mynativebinary",
device_supported: false,
host_supported: true,
srcs: [
"Test.cpp",
],
compile_multilib: "both",
system_shared_libs: [],
stl: "none",
target: {
windows: {
enabled: true,
},
},
}
`)
result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
name: "myexports_mynativebinary@current",
sdk_member_name: "mynativebinary",
device_supported: false,
host_supported: true,
installable: false,
target: {
linux_glibc: {
compile_multilib: "both",
},
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/bin/mynativebinary"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
compile_multilib: "64",
},
windows_x86_64: {
srcs: ["windows/x86_64/bin/mynativebinary.exe"],
},
},
}
cc_prebuilt_binary {
name: "mynativebinary",
prefer: false,
device_supported: false,
host_supported: true,
target: {
linux_glibc: {
compile_multilib: "both",
},
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/bin/mynativebinary"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/bin/mynativebinary"],
},
windows: {
compile_multilib: "64",
},
windows_x86_64: {
srcs: ["windows/x86_64/bin/mynativebinary.exe"],
},
},
}
module_exports_snapshot {
name: "myexports@current",
device_supported: false,
host_supported: true,
native_binaries: ["myexports_mynativebinary@current"],
target: {
windows: {
compile_multilib: "64",
},
},
}
`),
checkAllCopyRules(`
.intermediates/mynativebinary/linux_glibc_x86_64/mynativebinary -> linux_glibc/x86_64/bin/mynativebinary
.intermediates/mynativebinary/linux_glibc_x86/mynativebinary -> linux_glibc/x86/bin/mynativebinary
.intermediates/mynativebinary/windows_x86_64/mynativebinary.exe -> windows/x86_64/bin/mynativebinary.exe
`),
)
}
func TestSnapshotWithCcSharedLibrary(t *testing.T) { func TestSnapshotWithCcSharedLibrary(t *testing.T) {
result := testSdkWithCc(t, ` result := testSdkWithCc(t, `
sdk { sdk {
@ -413,6 +524,7 @@ func TestSnapshotWithCcSharedLibrary(t *testing.T) {
"Test.cpp", "Test.cpp",
"aidl/foo/bar/Test.aidl", "aidl/foo/bar/Test.aidl",
], ],
apex_available: ["apex1", "apex2"],
export_include_dirs: ["include"], export_include_dirs: ["include"],
aidl: { aidl: {
export_aidl_headers: true, export_aidl_headers: true,
@ -422,13 +534,19 @@ func TestSnapshotWithCcSharedLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "android_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared { cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current", name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
apex_available: [
"apex1",
"apex2",
],
installable: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -440,13 +558,16 @@ cc_prebuilt_library_shared {
export_include_dirs: ["arm/include_gen/mynativelib"], export_include_dirs: ["arm/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_shared { cc_prebuilt_library_shared {
name: "mynativelib", name: "mynativelib",
prefer: false, prefer: false,
apex_available: [
"apex1",
"apex2",
],
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -458,8 +579,6 @@ cc_prebuilt_library_shared {
export_include_dirs: ["arm/include_gen/mynativelib"], export_include_dirs: ["arm/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
sdk_snapshot { sdk_snapshot {
@ -481,6 +600,189 @@ include/Test.h -> include/include/Test.h
) )
} }
func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
native_shared_libs: [
"mynativelib",
"myothernativelib",
"mysystemnativelib",
],
}
cc_library {
name: "mysystemnativelib",
srcs: [
"Test.cpp",
],
system_shared_libs: [],
stl: "none",
}
cc_library_shared {
name: "myothernativelib",
srcs: [
"Test.cpp",
],
system_shared_libs: [
// A reference to a library that is not an sdk member. Uses libm as that
// is in the default set of modules available to this test and so is available
// both here and also when the generated Android.bp file is tested in
// CheckSnapshot(). This ensures that the system_shared_libs property correctly
// handles references to modules that are not sdk members.
"libm",
],
stl: "none",
}
cc_library {
name: "mynativelib",
srcs: [
"Test.cpp",
],
shared_libs: [
// A reference to another sdk member.
"myothernativelib",
],
target: {
android: {
shared: {
shared_libs: [
// A reference to a library that is not an sdk member. The libc library
// is used here to check that the shared_libs property is handled correctly
// in a similar way to how libm is used to check system_shared_libs above.
"libc",
],
},
},
},
system_shared_libs: [],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
shared_libs: [
"mysdk_myothernativelib@current",
"libc",
],
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.so"],
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
},
},
}
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
stl: "none",
shared_libs: [
"myothernativelib",
"libc",
],
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.so"],
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
},
},
}
cc_prebuilt_library_shared {
name: "mysdk_myothernativelib@current",
sdk_member_name: "myothernativelib",
installable: false,
stl: "none",
system_shared_libs: ["libm"],
arch: {
arm64: {
srcs: ["arm64/lib/myothernativelib.so"],
},
arm: {
srcs: ["arm/lib/myothernativelib.so"],
},
},
}
cc_prebuilt_library_shared {
name: "myothernativelib",
prefer: false,
stl: "none",
system_shared_libs: ["libm"],
arch: {
arm64: {
srcs: ["arm64/lib/myothernativelib.so"],
},
arm: {
srcs: ["arm/lib/myothernativelib.so"],
},
},
}
cc_prebuilt_library_shared {
name: "mysdk_mysystemnativelib@current",
sdk_member_name: "mysystemnativelib",
installable: false,
stl: "none",
arch: {
arm64: {
srcs: ["arm64/lib/mysystemnativelib.so"],
},
arm: {
srcs: ["arm/lib/mysystemnativelib.so"],
},
},
}
cc_prebuilt_library_shared {
name: "mysystemnativelib",
prefer: false,
stl: "none",
arch: {
arm64: {
srcs: ["arm64/lib/mysystemnativelib.so"],
},
arm: {
srcs: ["arm/lib/mysystemnativelib.so"],
},
},
}
sdk_snapshot {
name: "mysdk@current",
native_shared_libs: [
"mysdk_mynativelib@current",
"mysdk_myothernativelib@current",
"mysdk_mysystemnativelib@current",
],
}
`),
checkAllCopyRules(`
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
.intermediates/myothernativelib/android_arm64_armv8-a_shared/myothernativelib.so -> arm64/lib/myothernativelib.so
.intermediates/myothernativelib/android_arm_armv7-a-neon_shared/myothernativelib.so -> arm/lib/myothernativelib.so
.intermediates/mysystemnativelib/android_arm64_armv8-a_shared/mysystemnativelib.so -> arm64/lib/mysystemnativelib.so
.intermediates/mysystemnativelib/android_arm_armv7-a-neon_shared/mysystemnativelib.so -> arm/lib/mysystemnativelib.so
`),
)
}
func TestHostSnapshotWithCcSharedLibrary(t *testing.T) { func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported. // b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t) SkipIfNotLinux(t)
@ -507,10 +809,11 @@ func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
}, },
system_shared_libs: [], system_shared_libs: [],
stl: "none", stl: "none",
sdk_version: "minimum",
} }
`) `)
result.CheckSnapshot("mysdk", "linux_glibc_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -519,6 +822,9 @@ cc_prebuilt_library_shared {
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
installable: false,
sdk_version: "minimum",
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -530,8 +836,6 @@ cc_prebuilt_library_shared {
export_include_dirs: ["x86/include_gen/mynativelib"], export_include_dirs: ["x86/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_shared { cc_prebuilt_library_shared {
@ -539,6 +843,8 @@ cc_prebuilt_library_shared {
prefer: false, prefer: false,
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
sdk_version: "minimum",
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -550,8 +856,6 @@ cc_prebuilt_library_shared {
export_include_dirs: ["x86/include_gen/mynativelib"], export_include_dirs: ["x86/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
sdk_snapshot { sdk_snapshot {
@ -575,6 +879,103 @@ include/Test.h -> include/include/Test.h
) )
} }
func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
device_supported: false,
host_supported: true,
native_shared_libs: ["mynativelib"],
target: {
windows: {
enabled: true,
},
},
}
cc_library_shared {
name: "mynativelib",
device_supported: false,
host_supported: true,
srcs: [
"Test.cpp",
],
system_shared_libs: [],
stl: "none",
target: {
windows: {
enabled: true,
},
},
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
name: "mysdk_mynativelib@current",
sdk_member_name: "mynativelib",
device_supported: false,
host_supported: true,
installable: false,
stl: "none",
target: {
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
windows_x86_64: {
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
},
}
cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
device_supported: false,
host_supported: true,
stl: "none",
target: {
linux_glibc_x86_64: {
srcs: ["linux_glibc/x86_64/lib/mynativelib.so"],
},
linux_glibc_x86: {
srcs: ["linux_glibc/x86/lib/mynativelib.so"],
},
windows_x86_64: {
srcs: ["windows/x86_64/lib/mynativelib.dll"],
},
},
}
sdk_snapshot {
name: "mysdk@current",
device_supported: false,
host_supported: true,
native_shared_libs: ["mysdk_mynativelib@current"],
target: {
windows: {
compile_multilib: "64",
},
},
}
`),
checkAllCopyRules(`
.intermediates/mynativelib/linux_glibc_x86_64_shared/mynativelib.so -> linux_glibc/x86_64/lib/mynativelib.so
.intermediates/mynativelib/linux_glibc_x86_shared/mynativelib.so -> linux_glibc/x86/lib/mynativelib.so
.intermediates/mynativelib/windows_x86_64_shared/mynativelib.dll -> windows/x86_64/lib/mynativelib.dll
`),
)
}
func TestSnapshotWithCcStaticLibrary(t *testing.T) { func TestSnapshotWithCcStaticLibrary(t *testing.T) {
result := testSdkWithCc(t, ` result := testSdkWithCc(t, `
module_exports { module_exports {
@ -597,13 +998,15 @@ func TestSnapshotWithCcStaticLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "android_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static { cc_prebuilt_library_static {
name: "myexports_mynativelib@current", name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
installable: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -615,13 +1018,12 @@ cc_prebuilt_library_static {
export_include_dirs: ["arm/include_gen/mynativelib"], export_include_dirs: ["arm/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_static { cc_prebuilt_library_static {
name: "mynativelib", name: "mynativelib",
prefer: false, prefer: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
arm64: { arm64: {
@ -633,8 +1035,6 @@ cc_prebuilt_library_static {
export_include_dirs: ["arm/include_gen/mynativelib"], export_include_dirs: ["arm/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
module_exports_snapshot { module_exports_snapshot {
@ -685,7 +1085,7 @@ func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "linux_glibc_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -694,6 +1094,8 @@ cc_prebuilt_library_static {
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
installable: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -705,8 +1107,6 @@ cc_prebuilt_library_static {
export_include_dirs: ["x86/include_gen/mynativelib"], export_include_dirs: ["x86/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_static { cc_prebuilt_library_static {
@ -714,6 +1114,7 @@ cc_prebuilt_library_static {
prefer: false, prefer: false,
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -725,8 +1126,6 @@ cc_prebuilt_library_static {
export_include_dirs: ["x86/include_gen/mynativelib"], export_include_dirs: ["x86/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
module_exports_snapshot { module_exports_snapshot {
@ -750,6 +1149,93 @@ include/Test.h -> include/include/Test.h
) )
} }
func TestSnapshotWithCcLibrary(t *testing.T) {
result := testSdkWithCc(t, `
module_exports {
name: "myexports",
native_libs: ["mynativelib"],
}
cc_library {
name: "mynativelib",
srcs: [
"Test.cpp",
],
export_include_dirs: ["include"],
system_shared_libs: [],
stl: "none",
}
`)
result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library {
name: "myexports_mynativelib@current",
sdk_member_name: "mynativelib",
installable: false,
stl: "none",
export_include_dirs: ["include/include"],
arch: {
arm64: {
static: {
srcs: ["arm64/lib/mynativelib.a"],
},
shared: {
srcs: ["arm64/lib/mynativelib.so"],
},
},
arm: {
static: {
srcs: ["arm/lib/mynativelib.a"],
},
shared: {
srcs: ["arm/lib/mynativelib.so"],
},
},
},
}
cc_prebuilt_library {
name: "mynativelib",
prefer: false,
stl: "none",
export_include_dirs: ["include/include"],
arch: {
arm64: {
static: {
srcs: ["arm64/lib/mynativelib.a"],
},
shared: {
srcs: ["arm64/lib/mynativelib.so"],
},
},
arm: {
static: {
srcs: ["arm/lib/mynativelib.a"],
},
shared: {
srcs: ["arm/lib/mynativelib.so"],
},
},
},
}
module_exports_snapshot {
name: "myexports@current",
native_libs: ["myexports_mynativelib@current"],
}
`),
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
.intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
)
}
func TestHostSnapshotWithMultiLib64(t *testing.T) { func TestHostSnapshotWithMultiLib64(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported. // b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t) SkipIfNotLinux(t)
@ -784,7 +1270,7 @@ func TestHostSnapshotWithMultiLib64(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "linux_glibc_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -793,6 +1279,8 @@ cc_prebuilt_library_static {
sdk_member_name: "mynativelib", sdk_member_name: "mynativelib",
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
installable: false,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -800,8 +1288,6 @@ cc_prebuilt_library_static {
export_include_dirs: ["x86_64/include_gen/mynativelib"], export_include_dirs: ["x86_64/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
cc_prebuilt_library_static { cc_prebuilt_library_static {
@ -809,6 +1295,7 @@ cc_prebuilt_library_static {
prefer: false, prefer: false,
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
stl: "none",
export_include_dirs: ["include/include"], export_include_dirs: ["include/include"],
arch: { arch: {
x86_64: { x86_64: {
@ -816,20 +1303,18 @@ cc_prebuilt_library_static {
export_include_dirs: ["x86_64/include_gen/mynativelib"], export_include_dirs: ["x86_64/include_gen/mynativelib"],
}, },
}, },
stl: "none",
system_shared_libs: [],
} }
module_exports_snapshot { module_exports_snapshot {
name: "myexports@current", name: "myexports@current",
device_supported: false, device_supported: false,
host_supported: true, host_supported: true,
native_static_libs: ["myexports_mynativelib@current"],
target: { target: {
host: { linux_glibc: {
compile_multilib: "64", compile_multilib: "64",
}, },
}, },
native_static_libs: ["myexports_mynativelib@current"],
}`), }`),
checkAllCopyRules(` checkAllCopyRules(`
include/Test.h -> include/include/Test.h include/Test.h -> include/include/Test.h
@ -840,3 +1325,182 @@ include/Test.h -> include/include/Test.h
`), `),
) )
} }
func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
native_header_libs: ["mynativeheaders"],
}
cc_library_headers {
name: "mynativeheaders",
export_include_dirs: ["include"],
system_shared_libs: [],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
stl: "none",
export_include_dirs: ["include/include"],
}
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
stl: "none",
export_include_dirs: ["include/include"],
}
sdk_snapshot {
name: "mysdk@current",
native_header_libs: ["mysdk_mynativeheaders@current"],
}
`),
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
`),
)
}
func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
device_supported: false,
host_supported: true,
native_header_libs: ["mynativeheaders"],
}
cc_library_headers {
name: "mynativeheaders",
device_supported: false,
host_supported: true,
export_include_dirs: ["include"],
system_shared_libs: [],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
device_supported: false,
host_supported: true,
stl: "none",
export_include_dirs: ["include/include"],
}
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
device_supported: false,
host_supported: true,
stl: "none",
export_include_dirs: ["include/include"],
}
sdk_snapshot {
name: "mysdk@current",
device_supported: false,
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
}
`),
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
`),
)
}
func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithCc(t, `
sdk {
name: "mysdk",
host_supported: true,
native_header_libs: ["mynativeheaders"],
}
cc_library_headers {
name: "mynativeheaders",
host_supported: true,
system_shared_libs: [],
stl: "none",
export_system_include_dirs: ["include"],
target: {
android: {
export_include_dirs: ["include-android"],
},
host: {
export_include_dirs: ["include-host"],
},
},
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
name: "mysdk_mynativeheaders@current",
sdk_member_name: "mynativeheaders",
host_supported: true,
stl: "none",
export_system_include_dirs: ["include/include"],
target: {
android: {
export_include_dirs: ["include/include-android"],
},
linux_glibc: {
export_include_dirs: ["include/include-host"],
},
},
}
cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
host_supported: true,
stl: "none",
export_system_include_dirs: ["include/include"],
target: {
android: {
export_include_dirs: ["include/include-android"],
},
linux_glibc: {
export_include_dirs: ["include/include-host"],
},
},
}
sdk_snapshot {
name: "mysdk@current",
host_supported: true,
native_header_libs: ["mysdk_mynativeheaders@current"],
}
`),
checkAllCopyRules(`
include/Test.h -> include/include/Test.h
include-android/AndroidTest.h -> include/include-android/AndroidTest.h
include-host/HostTest.h -> include/include-host/HostTest.h
`),
)
}

View file

@ -42,7 +42,7 @@ func TestModuleExportsSnapshot(t *testing.T) {
"package/Android.bp": []byte(packageBp), "package/Android.bp": []byte(packageBp),
}) })
result.CheckSnapshot("myexports", "android_common", "package", result.CheckSnapshot("myexports", "package",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.

View file

@ -141,7 +141,7 @@ func TestSnapshotWithJavaHeaderLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "android_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -196,7 +196,7 @@ func TestHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "linux_glibc_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -230,6 +230,72 @@ aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
) )
} }
func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithJava(t, `
sdk {
name: "mysdk",
host_supported: true,
java_header_libs: ["myjavalib"],
}
java_library {
name: "myjavalib",
host_supported: true,
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
compile_dex: true,
}
`)
result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
java_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
host_supported: true,
target: {
android: {
jars: ["java/android/myjavalib.jar"],
},
linux_glibc: {
jars: ["java/linux_glibc/myjavalib.jar"],
},
},
}
java_import {
name: "myjavalib",
prefer: false,
host_supported: true,
target: {
android: {
jars: ["java/android/myjavalib.jar"],
},
linux_glibc: {
jars: ["java/linux_glibc/myjavalib.jar"],
},
},
}
sdk_snapshot {
name: "mysdk@current",
host_supported: true,
java_header_libs: ["mysdk_myjavalib@current"],
}
`),
checkAllCopyRules(`
.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/android/myjavalib.jar
.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/linux_glibc/myjavalib.jar
`),
)
}
func TestSnapshotWithJavaImplLibrary(t *testing.T) { func TestSnapshotWithJavaImplLibrary(t *testing.T) {
result := testSdkWithJava(t, ` result := testSdkWithJava(t, `
module_exports { module_exports {
@ -250,7 +316,7 @@ func TestSnapshotWithJavaImplLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "android_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -305,7 +371,7 @@ func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "linux_glibc_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -356,7 +422,7 @@ func TestSnapshotWithJavaTest(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "android_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -409,7 +475,7 @@ func TestHostSnapshotWithJavaTest(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "linux_glibc_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -503,7 +569,7 @@ func TestSnapshotWithDroidstubs(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "android_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -526,7 +592,7 @@ module_exports_snapshot {
`), `),
checkAllCopyRules(""), checkAllCopyRules(""),
checkMergeZip(".intermediates/myexports/android_common/tmp/java/myjavaapistubs_stubs_sources.zip"), checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
) )
} }
@ -552,7 +618,7 @@ func TestHostSnapshotWithDroidstubs(t *testing.T) {
} }
`) `)
result.CheckSnapshot("myexports", "linux_glibc_common", "", result.CheckSnapshot("myexports", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -580,7 +646,7 @@ module_exports_snapshot {
} }
`), `),
checkAllCopyRules(""), checkAllCopyRules(""),
checkMergeZip(".intermediates/myexports/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"), checkMergeZip(".intermediates/myexports/common_os/tmp/java/myjavaapistubs_stubs_sources.zip"),
) )
} }
@ -612,7 +678,7 @@ func TestSnapshotWithJavaSystemModules(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "android_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -702,7 +768,7 @@ func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
} }
`) `)
result.CheckSnapshot("mysdk", "linux_glibc_common", "", result.CheckSnapshot("mysdk", "",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -750,3 +816,126 @@ sdk_snapshot {
checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac/system-module.jar -> java/system-module.jar"), checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac/system-module.jar -> java/system-module.jar"),
) )
} }
func TestDeviceAndHostSnapshotWithOsSpecificMembers(t *testing.T) {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
SkipIfNotLinux(t)
result := testSdkWithJava(t, `
module_exports {
name: "myexports",
host_supported: true,
java_libs: ["myjavalib"],
target: {
android: {
java_header_libs: ["androidjavalib"],
},
host: {
java_header_libs: ["hostjavalib"],
},
},
}
java_library {
name: "myjavalib",
host_supported: true,
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
java_library {
name: "androidjavalib",
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
java_library_host {
name: "hostjavalib",
srcs: ["Test.java"],
}
`)
result.CheckSnapshot("myexports", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
java_import {
name: "myexports_hostjavalib@current",
sdk_member_name: "hostjavalib",
device_supported: false,
host_supported: true,
jars: ["java/hostjavalib.jar"],
}
java_import {
name: "hostjavalib",
prefer: false,
device_supported: false,
host_supported: true,
jars: ["java/hostjavalib.jar"],
}
java_import {
name: "myexports_androidjavalib@current",
sdk_member_name: "androidjavalib",
jars: ["java/androidjavalib.jar"],
}
java_import {
name: "androidjavalib",
prefer: false,
jars: ["java/androidjavalib.jar"],
}
java_import {
name: "myexports_myjavalib@current",
sdk_member_name: "myjavalib",
host_supported: true,
target: {
android: {
jars: ["java/android/myjavalib.jar"],
},
linux_glibc: {
jars: ["java/linux_glibc/myjavalib.jar"],
},
},
}
java_import {
name: "myjavalib",
prefer: false,
host_supported: true,
target: {
android: {
jars: ["java/android/myjavalib.jar"],
},
linux_glibc: {
jars: ["java/linux_glibc/myjavalib.jar"],
},
},
}
module_exports_snapshot {
name: "myexports@current",
host_supported: true,
java_libs: ["myexports_myjavalib@current"],
target: {
android: {
java_header_libs: ["myexports_androidjavalib@current"],
},
linux_glibc: {
java_header_libs: ["myexports_hostjavalib@current"],
},
},
}
`),
checkAllCopyRules(`
.intermediates/hostjavalib/linux_glibc_common/javac/hostjavalib.jar -> java/hostjavalib.jar
.intermediates/androidjavalib/android_common/turbine-combined/androidjavalib.jar -> java/androidjavalib.jar
.intermediates/myjavalib/android_common/javac/myjavalib.jar -> java/android/myjavalib.jar
.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/linux_glibc/myjavalib.jar
`),
)
}

View file

@ -50,8 +50,17 @@ type sdk struct {
// list properties, e.g. java_libs. // list properties, e.g. java_libs.
dynamicMemberTypeListProperties interface{} dynamicMemberTypeListProperties interface{}
// The set of exported members. // Information about the OsType specific member variants associated with this variant.
exportedMembers map[string]struct{} //
// Set by OsType specific variants in the collectMembers() method and used by the
// CommonOS variant when building the snapshot. That work is all done on separate
// calls to the sdk.GenerateAndroidBuildActions method which is guaranteed to be
// called for the OsType specific variants before the CommonOS variant (because
// the latter depends on the former).
memberRefs []sdkMemberRef
// The multilib variants that are used by this sdk variant.
multilibUsages multilibUsage
properties sdkProperties properties sdkProperties
@ -143,6 +152,7 @@ func createDynamicSdkMemberTypes(sdkMemberTypes []android.SdkMemberType) *dynami
fields = append(fields, reflect.StructField{ fields = append(fields, reflect.StructField{
Name: proptools.FieldNameForProperty(p), Name: proptools.FieldNameForProperty(p),
Type: reflect.TypeOf([]string{}), Type: reflect.TypeOf([]string{}),
Tag: `android:"arch_variant"`,
}) })
// Copy the field index for use in the getter func as using the loop variable directly will // Copy the field index for use in the getter func as using the loop variable directly will
@ -201,7 +211,7 @@ func newSdkModule(moduleExports bool) *sdk {
// properties for the member type specific list properties. // properties for the member type specific list properties.
s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties() s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties) s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
android.InitAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon) android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(s) android.InitDefaultableModule(s)
android.AddLoadHook(s, func(ctx android.LoadHookContext) { android.AddLoadHook(s, func(ctx android.LoadHookContext) {
type props struct { type props struct {
@ -225,26 +235,19 @@ func (s *sdk) memberListProperties() []*sdkMemberListProperty {
} }
func (s *sdk) getExportedMembers() map[string]struct{} { func (s *sdk) getExportedMembers() map[string]struct{} {
if s.exportedMembers == nil {
// Collect all the exported members. // Collect all the exported members.
s.exportedMembers = make(map[string]struct{}) exportedMembers := make(map[string]struct{})
for _, memberListProperty := range s.memberListProperties() { for _, memberListProperty := range s.memberListProperties() {
names := memberListProperty.getter(s.dynamicMemberTypeListProperties) names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
// Every member specified explicitly in the properties is exported by the sdk. // Every member specified explicitly in the properties is exported by the sdk.
for _, name := range names { for _, name := range names {
s.exportedMembers[name] = struct{}{} exportedMembers[name] = struct{}{}
}
} }
} }
return s.exportedMembers return exportedMembers
}
func (s *sdk) isInternalMember(memberName string) bool {
_, ok := s.getExportedMembers()[memberName]
return !ok
} }
func (s *sdk) snapshot() bool { func (s *sdk) snapshot() bool {
@ -252,10 +255,31 @@ func (s *sdk) snapshot() bool {
} }
func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if !s.snapshot() { if s.snapshot() {
// We don't need to create a snapshot out of sdk_snapshot. // We don't need to create a snapshot out of sdk_snapshot.
// That doesn't make sense. We need a snapshot to create sdk_snapshot. // That doesn't make sense. We need a snapshot to create sdk_snapshot.
s.snapshotFile = android.OptionalPathForPath(s.buildSnapshot(ctx)) return
}
// This method is guaranteed to be called on OsType specific variants before it is called
// on their corresponding CommonOS variant.
if !s.IsCommonOSVariant() {
// Update the OsType specific sdk variant with information about its members.
s.collectMembers(ctx)
} else {
// Get the OsType specific variants on which the CommonOS depends.
osSpecificVariants := android.GetOsSpecificVariantsOfCommonOSVariant(ctx)
var sdkVariants []*sdk
for _, m := range osSpecificVariants {
if sdkVariant, ok := m.(*sdk); ok {
sdkVariants = append(sdkVariants, sdkVariant)
}
}
// Generate the snapshot from the member info.
p := s.buildSnapshot(ctx, sdkVariants)
s.snapshotFile = android.OptionalPathForPath(p)
ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), s.Name()+"-current.zip", p)
} }
} }
@ -320,15 +344,18 @@ func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {}
// Step 1: create dependencies from an SDK module to its members. // Step 1: create dependencies from an SDK module to its members.
func memberMutator(mctx android.BottomUpMutatorContext) { func memberMutator(mctx android.BottomUpMutatorContext) {
if s, ok := mctx.Module().(*sdk); ok { if s, ok := mctx.Module().(*sdk); ok {
if s.Enabled() { // Add dependencies from enabled and non CommonOS variants to the sdk member variants.
if s.Enabled() && !s.IsCommonOSVariant() {
for _, memberListProperty := range s.memberListProperties() { for _, memberListProperty := range s.memberListProperties() {
names := memberListProperty.getter(s.dynamicMemberTypeListProperties) names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
if len(names) > 0 {
tag := memberListProperty.dependencyTag tag := memberListProperty.dependencyTag
memberListProperty.memberType.AddDependencies(mctx, tag, names) memberListProperty.memberType.AddDependencies(mctx, tag, names)
} }
} }
} }
} }
}
// Step 2: record that dependencies of SDK modules are members of the SDK modules // Step 2: record that dependencies of SDK modules are members of the SDK modules
func memberDepsMutator(mctx android.TopDownMutatorContext) { func memberDepsMutator(mctx android.TopDownMutatorContext) {

View file

@ -16,6 +16,8 @@ package sdk
import ( import (
"testing" "testing"
"github.com/google/blueprint/proptools"
) )
// Needed in an _test.go file in this package to ensure tests run correctly, particularly in IDE. // Needed in an _test.go file in this package to ensure tests run correctly, particularly in IDE.
@ -146,7 +148,7 @@ func TestSnapshotVisibility(t *testing.T) {
"package/Android.bp": []byte(packageBp), "package/Android.bp": []byte(packageBp),
}) })
result.CheckSnapshot("mysdk", "android_common", "package", result.CheckSnapshot("mysdk", "package",
checkAndroidBpContents(` checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT. // This is auto-generated. DO NOT EDIT.
@ -206,3 +208,122 @@ sdk_snapshot {
} }
`)) `))
} }
func TestSDkInstall(t *testing.T) {
sdk := `
sdk {
name: "mysdk",
}
`
result := testSdkWithFs(t, ``,
map[string][]byte{
"Android.bp": []byte(sdk),
})
result.CheckSnapshot("mysdk", "",
checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
)
}
type EmbeddedPropertiesStruct struct {
S_Embedded_Common string
S_Embedded_Different string
}
type testPropertiesStruct struct {
private string
Public_Kept string `sdk:"keep"`
S_Common string
S_Different string
A_Common []string
A_Different []string
F_Common *bool
F_Different *bool
EmbeddedPropertiesStruct
}
func TestCommonValueOptimization(t *testing.T) {
common := &testPropertiesStruct{}
structs := []*testPropertiesStruct{
&testPropertiesStruct{
private: "common",
Public_Kept: "common",
S_Common: "common",
S_Different: "upper",
A_Common: []string{"first", "second"},
A_Different: []string{"alpha", "beta"},
F_Common: proptools.BoolPtr(false),
F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_upper",
},
},
&testPropertiesStruct{
private: "common",
Public_Kept: "common",
S_Common: "common",
S_Different: "lower",
A_Common: []string{"first", "second"},
A_Different: []string{"alpha", "delta"},
F_Common: proptools.BoolPtr(false),
F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_lower",
},
},
}
extractor := newCommonValueExtractor(common)
extractor.extractCommonProperties(common, structs)
h := TestHelper{t}
h.AssertDeepEquals("common properties not correct", common,
&testPropertiesStruct{
private: "",
Public_Kept: "",
S_Common: "common",
S_Different: "",
A_Common: []string{"first", "second"},
A_Different: []string(nil),
F_Common: proptools.BoolPtr(false),
F_Different: nil,
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "",
},
})
h.AssertDeepEquals("updated properties[0] not correct", structs[0],
&testPropertiesStruct{
private: "common",
Public_Kept: "common",
S_Common: "",
S_Different: "upper",
A_Common: nil,
A_Different: []string{"alpha", "beta"},
F_Common: nil,
F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_upper",
},
})
h.AssertDeepEquals("updated properties[1] not correct", structs[1],
&testPropertiesStruct{
private: "common",
Public_Kept: "common",
S_Common: "",
S_Different: "lower",
A_Common: nil,
A_Different: []string{"alpha", "delta"},
F_Common: nil,
F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_lower",
},
})
}

View file

@ -19,6 +19,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"strings" "strings"
"testing" "testing"
@ -40,7 +41,7 @@ func testSdkContext(bp string, fs map[string][]byte) (*android.TestContext, andr
name: "myapex.cert", name: "myapex.cert",
certificate: "myapex", certificate: "myapex",
} }
` + cc.GatherRequiredDepsForTest(android.Android) ` + cc.GatherRequiredDepsForTest(android.Android, android.Windows)
mockFS := map[string][]byte{ mockFS := map[string][]byte{
"build/make/target/product/security": nil, "build/make/target/product/security": nil,
@ -61,8 +62,24 @@ func testSdkContext(bp string, fs map[string][]byte) (*android.TestContext, andr
config := android.TestArchConfig(buildDir, nil, bp, mockFS) config := android.TestArchConfig(buildDir, nil, bp, mockFS)
// Add windows as a default disable OS to test behavior when some OS variants
// are disabled.
config.Targets[android.Windows] = []android.Target{
{android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""},
}
ctx := android.NewTestArchContext() ctx := android.NewTestArchContext()
// Enable androidmk support.
// * Register the singleton
// * Configure that we are inside make
// * Add CommonOS to ensure that androidmk processing works.
android.RegisterAndroidMkBuildComponents(ctx)
android.SetInMakeForTests(config)
config.Targets[android.CommonOS] = []android.Target{
{android.CommonOS, android.Arch{ArchType: android.Common}, android.NativeBridgeDisabled, "", ""},
}
// from android package // from android package
android.RegisterPackageBuildComponents(ctx) android.RegisterPackageBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker) ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
@ -160,6 +177,13 @@ func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string,
h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual)) h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
} }
func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
h.t.Helper()
if !reflect.DeepEqual(actual, expected) {
h.t.Errorf("%s: expected %#v, actual %#v", message, expected, actual)
}
}
// Encapsulates result of processing an SDK definition. Provides support for // Encapsulates result of processing an SDK definition. Provides support for
// checking the state of the build structures. // checking the state of the build structures.
type testSdkResult struct { type testSdkResult struct {
@ -182,15 +206,23 @@ func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
buildParams := sdk.BuildParamsForTests() buildParams := sdk.BuildParamsForTests()
copyRules := &strings.Builder{} copyRules := &strings.Builder{}
otherCopyRules := &strings.Builder{}
snapshotDirPrefix := sdk.builderForTests.snapshotDir.String() + "/"
for _, bp := range buildParams { for _, bp := range buildParams {
switch bp.Rule.String() { switch bp.Rule.String() {
case android.Cp.String(): case android.Cp.String():
// Get source relative to build directory. output := bp.Output
src := android.NormalizePathForTesting(bp.Input)
// Get destination relative to the snapshot root // Get destination relative to the snapshot root
dest := bp.Output.Rel() dest := output.Rel()
src := android.NormalizePathForTesting(bp.Input)
// We differentiate between copy rules for the snapshot, and copy rules for the install file.
if strings.HasPrefix(output.String(), snapshotDirPrefix) {
// Get source relative to build directory.
_, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest) _, _ = fmt.Fprintf(copyRules, "%s -> %s\n", src, dest)
info.snapshotContents = append(info.snapshotContents, dest) info.snapshotContents = append(info.snapshotContents, dest)
} else {
_, _ = fmt.Fprintf(otherCopyRules, "%s -> %s\n", src, dest)
}
case repackageZip.String(): case repackageZip.String():
// Add the destdir to the snapshot contents as that is effectively where // Add the destdir to the snapshot contents as that is effectively where
@ -223,6 +255,7 @@ func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
} }
info.copyRules = copyRules.String() info.copyRules = copyRules.String()
info.otherCopyRules = otherCopyRules.String()
return info return info
} }
@ -240,9 +273,12 @@ func (r *testSdkResult) ModuleForTests(name string, variant string) android.Test
// Takes a list of functions which check different facets of the snapshot build rules. // Takes a list of functions which check different facets of the snapshot build rules.
// Allows each test to customize what is checked without duplicating lots of code // Allows each test to customize what is checked without duplicating lots of code
// or proliferating check methods of different flavors. // or proliferating check methods of different flavors.
func (r *testSdkResult) CheckSnapshot(name string, variant string, dir string, checkers ...snapshotBuildInfoChecker) { func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snapshotBuildInfoChecker) {
r.t.Helper() r.t.Helper()
// The sdk CommonOS variant is always responsible for generating the snapshot.
variant := android.CommonOS.Name
sdk := r.Module(name, variant).(*sdk) sdk := r.Module(name, variant).(*sdk)
snapshotBuildInfo := r.getSdkSnapshotBuildInfo(sdk) snapshotBuildInfo := r.getSdkSnapshotBuildInfo(sdk)
@ -295,6 +331,13 @@ func checkAllCopyRules(expected string) snapshotBuildInfoChecker {
} }
} }
func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
info.r.t.Helper()
info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.otherCopyRules)
}
}
// Check that the specified path is in the list of zips to merge with the intermediate zip. // Check that the specified path is in the list of zips to merge with the intermediate zip.
func checkMergeZip(expected string) snapshotBuildInfoChecker { func checkMergeZip(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) { return func(info *snapshotBuildInfo) {
@ -321,10 +364,14 @@ type snapshotBuildInfo struct {
// snapshot. // snapshot.
snapshotContents []string snapshotContents []string
// A formatted representation of the src/dest pairs, one pair per line, of the format // A formatted representation of the src/dest pairs for a snapshot, one pair per line,
// src -> dest // of the format src -> dest
copyRules string copyRules string
// A formatted representation of the src/dest pairs for files not in a snapshot, one pair
// per line, of the format src -> dest
otherCopyRules string
// The path to the intermediate zip, which is a zip created from the source files copied // The path to the intermediate zip, which is a zip created from the source files copied
// into the snapshot directory and which will be merged with other zips to form the final output. // into the snapshot directory and which will be merged with other zips to form the final output.
// Is am empty string if there is no intermediate zip because there are no zips to merge in. // Is am empty string if there is no intermediate zip because there are no zips to merge in.

File diff suppressed because it is too large Load diff

View file

@ -115,6 +115,7 @@ func syspropJavaGenFactory() android.Module {
type syspropLibrary struct { type syspropLibrary struct {
android.ModuleBase android.ModuleBase
android.ApexModuleBase
properties syspropLibraryProperties properties syspropLibraryProperties
@ -296,6 +297,7 @@ func syspropLibraryFactory() android.Module {
&m.properties, &m.properties,
) )
android.InitAndroidModule(m) android.InitAndroidModule(m)
android.InitApexModule(m)
android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) }) android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
return m return m
} }
@ -323,6 +325,7 @@ type ccLibraryProperties struct {
Recovery_available *bool Recovery_available *bool
Vendor_available *bool Vendor_available *bool
Host_supported *bool Host_supported *bool
Apex_available []string
} }
type javaLibraryProperties struct { type javaLibraryProperties struct {
@ -411,6 +414,7 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
ccProps.Recovery_available = m.properties.Recovery_available ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available ccProps.Vendor_available = m.properties.Vendor_available
ccProps.Host_supported = m.properties.Host_supported ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
ctx.CreateModule(cc.LibraryFactory, &ccProps) ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal" scope := "internal"

View file

@ -15,6 +15,8 @@
package sysprop package sysprop
import ( import (
"reflect"
"android/soong/android" "android/soong/android"
"android/soong/cc" "android/soong/cc"
"android/soong/java" "android/soong/java"
@ -157,6 +159,7 @@ func TestSyspropLibrary(t *testing.T) {
ctx := test(t, ` ctx := test(t, `
sysprop_library { sysprop_library {
name: "sysprop-platform", name: "sysprop-platform",
apex_available: ["//apex_available:platform"],
srcs: ["android/sysprop/PlatformProperties.sysprop"], srcs: ["android/sysprop/PlatformProperties.sysprop"],
api_packages: ["android.sysprop"], api_packages: ["android.sysprop"],
property_owner: "Platform", property_owner: "Platform",
@ -305,7 +308,12 @@ func TestSyspropLibrary(t *testing.T) {
"android_arm64_armv8-a_shared", "android_arm64_armv8-a_shared",
"android_arm64_armv8-a_static", "android_arm64_armv8-a_static",
} { } {
ctx.ModuleForTests("libsysprop-platform", variant) library := ctx.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
expectedApexAvailableOnLibrary := []string{"//apex_available:platform"}
if !reflect.DeepEqual(library.ApexProperties.Apex_available, expectedApexAvailableOnLibrary) {
t.Errorf("apex available property on libsysprop-platform must be %#v, but was %#v.",
expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
}
// core variant of vendor-owned sysprop_library is for product // core variant of vendor-owned sysprop_library is for product
ctx.ModuleForTests("libsysprop-vendor", variant) ctx.ModuleForTests("libsysprop-vendor", variant)