Refactor snapshot module creation
Generalize the processing of arch specific properties to reduce duplication in snapshot module creation and simplify addition of support for handling multiple os types. Supporting multiple os types with the current method for building snapshot modules would require every affected module type to add support for it. Rather than duplicate multiple os type handling code across those module types this work generalizes the process cc modules use for handling arch types as it can be used as a basis for handling multiple os types. Migrating module types over to this new process will insulate them from having to handle multiple os types. OB SdkMemberType changes: * BuildSnapshot is deprecated in favour of the new AddPrebuiltModule() method. * Additional methods, CreateVariantPropertiesStruct() and FinalizeModule() are added. * A new interface SdkMemberProperties, is defined that handles extracting information from the variant (prior to common value optimization) and adding properties to a property set. The sdk module type uses these new methods and types to delegate the member type specific processing to the relevant member types while handling the behavior that is common across all members types, e.g. extracting common values across multiple architectures. A future change will leverage this processing to add support for multiple os types. This change also refactors the cc module processing to use the new process. Bug: 150451422 Test: m nothing Change-Id: If6ab2498407b17f50391d062cd9afc01b5e01af4
This commit is contained in:
parent
8f20563514
commit
88f2fbe92e
|
@ -302,7 +302,46 @@ type SdkMemberType interface {
|
|||
//
|
||||
// The SdkMember is guaranteed to contain variants for which the
|
||||
// IsInstance(Module) method returned true.
|
||||
//
|
||||
// deprecated Use AddPrebuiltModule() instead.
|
||||
BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember)
|
||||
|
||||
// Add a prebuilt module that the sdk will populate.
|
||||
//
|
||||
// Returning nil from this will cause the sdk module type to use the deprecated BuildSnapshot
|
||||
// method to build the snapshot. That method is deprecated because it requires the SdkMemberType
|
||||
// implementation to do all the word.
|
||||
//
|
||||
// Otherwise, returning a non-nil value from this will cause the sdk module type to do the
|
||||
// majority of the work to generate the snapshot. The sdk module code generates the snapshot
|
||||
// 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.
|
||||
//
|
||||
// * 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.
|
||||
//
|
||||
// * Finally, the FinalizeModule(...) method is called to add any additional properties.
|
||||
// This was created to allow the property ordering in existing tests to be maintained so
|
||||
// as to avoid having to change tests while refactoring.
|
||||
//
|
||||
AddPrebuiltModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) BpModule
|
||||
|
||||
// Add any additional properties to the end of the module.
|
||||
FinalizeModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember, bpModule BpModule)
|
||||
|
||||
// Create a structure into which variant specific properties can be added.
|
||||
CreateVariantPropertiesStruct() SdkMemberProperties
|
||||
}
|
||||
|
||||
// Base type for SdkMemberType implementations.
|
||||
|
@ -324,6 +363,23 @@ func (b *SdkMemberTypeBase) HasTransitiveSdkMembers() bool {
|
|||
return b.TransitiveSdkMembers
|
||||
}
|
||||
|
||||
func (b *SdkMemberTypeBase) BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) {
|
||||
panic("override AddPrebuiltModule")
|
||||
}
|
||||
|
||||
func (b *SdkMemberTypeBase) AddPrebuiltModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) BpModule {
|
||||
// Returning nil causes the legacy BuildSnapshot method to be used.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *SdkMemberTypeBase) FinalizeModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember, module BpModule) {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
func (b *SdkMemberTypeBase) CreateVariantPropertiesStruct() SdkMemberProperties {
|
||||
panic("override me")
|
||||
}
|
||||
|
||||
// Encapsulates the information about registered SdkMemberTypes.
|
||||
type SdkMemberTypesRegistry struct {
|
||||
// The list of types sorted by property name.
|
||||
|
@ -389,3 +445,31 @@ func RegisterSdkMemberType(memberType SdkMemberType) {
|
|||
SdkMemberTypes = SdkMemberTypes.copyAndAppend(memberType)
|
||||
}
|
||||
}
|
||||
|
||||
// Base structure for all implementations of SdkMemberProperties.
|
||||
//
|
||||
// Contains common properties that apply across many different member types.
|
||||
type SdkMemberPropertiesBase struct {
|
||||
// The setting to use for the compile_multilib property.
|
||||
Compile_multilib string
|
||||
}
|
||||
|
||||
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 the structure with information from the variant.
|
||||
PopulateFromVariant(variant SdkAware)
|
||||
|
||||
// Add the information from the structure to the property set.
|
||||
AddToPropertySet(sdkModuleContext ModuleContext, builder SnapshotBuilder, propertySet BpPropertySet)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package cc
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
|
@ -64,65 +63,13 @@ func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (mt *binarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
|
||||
info := mt.organizeVariants(member)
|
||||
buildSharedNativeBinarySnapshot(info, builder, member)
|
||||
}
|
||||
|
||||
// Organize the variants by architecture.
|
||||
func (mt *binarySdkMemberType) organizeVariants(member android.SdkMember) *nativeBinaryInfo {
|
||||
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) {
|
||||
func (mt *binarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule {
|
||||
pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary")
|
||||
archVariantCount := len(info.archVariantProperties)
|
||||
return pbm
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
func (mt *binarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
|
||||
return &nativeBinaryInfoProperties{}
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -140,8 +87,7 @@ func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
|
|||
// The exported (capitalized) fields will be examined and may be changed during common value extraction.
|
||||
// The unexported fields will be left untouched.
|
||||
type nativeBinaryInfoProperties struct {
|
||||
// The name of the library, is not exported as this must not be changed during optimization.
|
||||
name string
|
||||
android.SdkMemberPropertiesBase
|
||||
|
||||
// archType is not exported as if set (to a non default value) it is always arch specific.
|
||||
// This is "" for common properties.
|
||||
|
@ -151,10 +97,21 @@ type nativeBinaryInfoProperties struct {
|
|||
outputFile android.Path
|
||||
}
|
||||
|
||||
// nativeBinaryInfo represents a collection of arch-specific modules having the same name
|
||||
type nativeBinaryInfo struct {
|
||||
name string
|
||||
memberType *binarySdkMemberType
|
||||
archVariantProperties []nativeBinaryInfoProperties
|
||||
commonProperties nativeBinaryInfoProperties
|
||||
func (p *nativeBinaryInfoProperties) PopulateFromVariant(variant android.SdkAware) {
|
||||
ccModule := variant.(*Module)
|
||||
|
||||
p.archType = ccModule.Target().Arch.ArchType.String()
|
||||
p.outputFile = ccModule.OutputFile().Path()
|
||||
}
|
||||
|
||||
func (p *nativeBinaryInfoProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) {
|
||||
if p.Compile_multilib != "" {
|
||||
propertySet.AddProperty("compile_multilib", p.Compile_multilib)
|
||||
}
|
||||
|
||||
if p.outputFile != nil {
|
||||
propertySet.AddProperty("srcs", []string{nativeBinaryPathFor(*p)})
|
||||
|
||||
builder.CopyToSnapshot(p.outputFile, nativeBinaryPathFor(*p))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package cc
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
"android/soong/android"
|
||||
"github.com/google/blueprint"
|
||||
|
@ -96,48 +95,18 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// copy exported header files and stub *.so files
|
||||
func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
|
||||
info := mt.organizeVariants(member)
|
||||
info.generatePrebuiltLibrary(sdkModuleContext, builder, member)
|
||||
func (mt *librarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule {
|
||||
pbm := builder.AddPrebuiltModule(member, mt.prebuiltModuleType)
|
||||
return pbm
|
||||
}
|
||||
|
||||
// Organize the variants by architecture.
|
||||
func (mt *librarySdkMemberType) organizeVariants(member android.SdkMember) *nativeLibInfo {
|
||||
memberName := member.Name()
|
||||
info := &nativeLibInfo{
|
||||
name: memberName,
|
||||
memberType: mt,
|
||||
}
|
||||
func (mt *librarySdkMemberType) FinalizeModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember, bpModule android.BpModule) {
|
||||
bpModule.AddProperty("stl", "none")
|
||||
bpModule.AddProperty("system_shared_libs", []string{})
|
||||
}
|
||||
|
||||
for _, variant := range member.Variants() {
|
||||
ccModule := variant.(*Module)
|
||||
|
||||
// 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 (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
|
||||
return &nativeLibInfoProperties{memberType: mt}
|
||||
}
|
||||
|
||||
func isGeneratedHeaderDirectory(p android.Path) bool {
|
||||
|
@ -145,94 +114,9 @@ func isGeneratedHeaderDirectory(p android.Path) bool {
|
|||
return gen
|
||||
}
|
||||
|
||||
// Extract common properties from a slice of property structures of the same type.
|
||||
//
|
||||
// All the property structures must be of the same type.
|
||||
// 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.
|
||||
emptyStructValue := reflect.New(propertiesStructType).Elem()
|
||||
|
||||
for f := 0; f < propertiesStructType.NumField(); f++ {
|
||||
// Check to see if all the structures have the same value for the field. The commonValue
|
||||
// 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++ {
|
||||
structValue := sliceValue.Index(i)
|
||||
fieldValue := structValue.Field(f)
|
||||
if !fieldValue.CanInterface() {
|
||||
// The field is not exported so ignore it.
|
||||
continue
|
||||
}
|
||||
|
||||
if commonValue == nil {
|
||||
// Use the first value as the commonProperties value.
|
||||
commonValue = &fieldValue
|
||||
} else {
|
||||
// If the value does not match the current common value then there is
|
||||
// no value in common so break out.
|
||||
if !reflect.DeepEqual(fieldValue.Interface(), commonValue.Interface()) {
|
||||
commonValue = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the fields all have a common value then store it in the common struct field
|
||||
// and set the input struct's field to the empty value.
|
||||
if commonValue != nil {
|
||||
emptyValue := emptyStructValue.Field(f)
|
||||
commonStructValue.Field(f).Set(*commonValue)
|
||||
for i := 0; i < sliceValue.Len(); i++ {
|
||||
structValue := sliceValue.Index(i)
|
||||
fieldValue := structValue.Field(f)
|
||||
fieldValue.Set(emptyValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
|
||||
|
||||
pbm := builder.AddPrebuiltModule(member, info.memberType.prebuiltModuleType)
|
||||
|
||||
addPossiblyArchSpecificProperties(sdkModuleContext, builder, info.commonProperties, pbm)
|
||||
|
||||
archProperties := pbm.AddPropertySet("arch")
|
||||
for _, av := range info.archVariantProperties {
|
||||
archTypeProperties := archProperties.AddPropertySet(av.archType)
|
||||
|
||||
// If the library has some link types then it produces an output binary file, otherwise it
|
||||
// is header only.
|
||||
if info.memberType.linkTypes != nil {
|
||||
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
|
||||
nativeLibraryPath := nativeLibraryPathFor(av)
|
||||
builder.CopyToSnapshot(av.outputFile, nativeLibraryPath)
|
||||
archTypeProperties.AddProperty("srcs", []string{nativeLibraryPath})
|
||||
}
|
||||
|
||||
// Add any arch specific properties inside the appropriate arch: {<arch>: {...}} block
|
||||
addPossiblyArchSpecificProperties(sdkModuleContext, builder, av, archTypeProperties)
|
||||
}
|
||||
pbm.AddProperty("stl", "none")
|
||||
pbm.AddProperty("system_shared_libs", []string{})
|
||||
}
|
||||
|
||||
type includeDirsProperty struct {
|
||||
// Accessor to retrieve the paths
|
||||
pathsGetter func(libInfo nativeLibInfoProperties) android.Paths
|
||||
pathsGetter func(libInfo *nativeLibInfoProperties) android.Paths
|
||||
|
||||
// The name of the property in the prebuilt library, "" means there is no property.
|
||||
propertyName string
|
||||
|
@ -252,7 +136,7 @@ var includeDirProperties = []includeDirsProperty{
|
|||
// ExportedIncludeDirs lists directories that contains some header files to be
|
||||
// copied into a directory in the snapshot. The snapshot directories must be added to
|
||||
// the export_include_dirs property in the prebuilt module in the snapshot.
|
||||
pathsGetter: func(libInfo nativeLibInfoProperties) android.Paths { return libInfo.ExportedIncludeDirs },
|
||||
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedIncludeDirs },
|
||||
propertyName: "export_include_dirs",
|
||||
snapshotDir: nativeIncludeDir,
|
||||
copy: true,
|
||||
|
@ -262,7 +146,7 @@ var includeDirProperties = []includeDirsProperty{
|
|||
// 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 },
|
||||
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedSystemIncludeDirs },
|
||||
propertyName: "export_system_include_dirs",
|
||||
snapshotDir: nativeIncludeDir,
|
||||
copy: true,
|
||||
|
@ -273,7 +157,7 @@ var includeDirProperties = []includeDirsProperty{
|
|||
// 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 },
|
||||
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
|
||||
propertyName: "export_include_dirs",
|
||||
snapshotDir: nativeGeneratedIncludeDir,
|
||||
copy: false,
|
||||
|
@ -284,7 +168,7 @@ var includeDirProperties = []includeDirsProperty{
|
|||
// 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 },
|
||||
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
|
||||
propertyName: "",
|
||||
snapshotDir: nativeGeneratedIncludeDir,
|
||||
copy: true,
|
||||
|
@ -293,7 +177,14 @@ var includeDirProperties = []includeDirsProperty{
|
|||
}
|
||||
|
||||
// Add properties that may, or may not, be arch specific.
|
||||
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo nativeLibInfoProperties, outputProperties android.BpPropertySet) {
|
||||
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
|
||||
|
||||
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
|
||||
if libInfo.outputFile != nil {
|
||||
nativeLibraryPath := nativeLibraryPathFor(libInfo)
|
||||
builder.CopyToSnapshot(libInfo.outputFile, nativeLibraryPath)
|
||||
outputProperties.AddProperty("srcs", []string{nativeLibraryPath})
|
||||
}
|
||||
|
||||
// Map from property name to the include dirs to add to the prebuilt module in the snapshot.
|
||||
includeDirs := make(map[string][]string)
|
||||
|
@ -355,7 +246,7 @@ const (
|
|||
)
|
||||
|
||||
// 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,
|
||||
nativeStubDir, lib.outputFile.Base())
|
||||
}
|
||||
|
@ -365,6 +256,10 @@ func nativeLibraryPathFor(lib nativeLibInfoProperties) string {
|
|||
// The exported (capitalized) fields will be examined and may be changed during common value extraction.
|
||||
// The unexported fields will be left untouched.
|
||||
type nativeLibInfoProperties struct {
|
||||
android.SdkMemberPropertiesBase
|
||||
|
||||
memberType *librarySdkMemberType
|
||||
|
||||
// The name of the library, is not exported as this must not be changed during optimization.
|
||||
name string
|
||||
|
||||
|
@ -401,10 +296,29 @@ type nativeLibInfoProperties struct {
|
|||
outputFile android.Path
|
||||
}
|
||||
|
||||
// nativeLibInfo represents a collection of arch-specific modules having the same name
|
||||
type nativeLibInfo struct {
|
||||
name string
|
||||
memberType *librarySdkMemberType
|
||||
archVariantProperties []nativeLibInfoProperties
|
||||
commonProperties nativeLibInfoProperties
|
||||
func (p *nativeLibInfoProperties) PopulateFromVariant(variant android.SdkAware) {
|
||||
ccModule := variant.(*Module)
|
||||
|
||||
// If the library has some link types then it produces an output binary file, otherwise it
|
||||
// is header only.
|
||||
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()
|
||||
p.ExportedIncludeDirs = exportedIncludeDirs
|
||||
p.exportedGeneratedIncludeDirs = exportedGeneratedIncludeDirs
|
||||
p.ExportedSystemIncludeDirs = ccModule.ExportedSystemIncludeDirs()
|
||||
p.ExportedFlags = ccModule.ExportedFlags()
|
||||
p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders()
|
||||
}
|
||||
|
||||
func (p *nativeLibInfoProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) {
|
||||
addPossiblyArchSpecificProperties(sdkModuleContext, builder, p, propertySet)
|
||||
}
|
||||
|
|
143
sdk/update.go
143
sdk/update.go
|
@ -251,7 +251,14 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro
|
|||
|
||||
members, multilib := s.organizeMembers(ctx, memberRefs)
|
||||
for _, member := range members {
|
||||
member.memberType.BuildSnapshot(ctx, builder, member)
|
||||
memberType := member.memberType
|
||||
prebuiltModule := memberType.AddPrebuiltModule(ctx, builder, member)
|
||||
if prebuiltModule == nil {
|
||||
// Fall back to legacy method of building a snapshot
|
||||
memberType.BuildSnapshot(ctx, builder, member)
|
||||
} else {
|
||||
s.createMemberSnapshot(ctx, builder, member, prebuiltModule)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a transformer that will transform an unversioned module into a versioned module.
|
||||
|
@ -643,3 +650,137 @@ func (m *sdkMember) Name() string {
|
|||
func (m *sdkMember) Variants() []android.SdkAware {
|
||||
return m.variants
|
||||
}
|
||||
|
||||
type baseInfo struct {
|
||||
Properties android.SdkMemberProperties
|
||||
}
|
||||
|
||||
type osTypeSpecificInfo struct {
|
||||
baseInfo
|
||||
|
||||
// The list of arch type specific info for this os type.
|
||||
archTypes []*archTypeSpecificInfo
|
||||
}
|
||||
|
||||
type archTypeSpecificInfo struct {
|
||||
baseInfo
|
||||
|
||||
archType android.ArchType
|
||||
}
|
||||
|
||||
func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, builder *snapshotBuilder, member *sdkMember, bpModule android.BpModule) {
|
||||
|
||||
memberType := member.memberType
|
||||
|
||||
// Group the properties for each variant by arch type.
|
||||
osInfo := &osTypeSpecificInfo{}
|
||||
osInfo.Properties = memberType.CreateVariantPropertiesStruct()
|
||||
variants := member.Variants()
|
||||
for _, variant := range variants {
|
||||
var properties android.SdkMemberProperties
|
||||
|
||||
// Get the info associated with the arch type inside the os info.
|
||||
archType := variant.Target().Arch.ArchType
|
||||
|
||||
archInfo := &archTypeSpecificInfo{archType: archType}
|
||||
properties = memberType.CreateVariantPropertiesStruct()
|
||||
archInfo.Properties = properties
|
||||
|
||||
osInfo.archTypes = append(osInfo.archTypes, archInfo)
|
||||
|
||||
properties.PopulateFromVariant(variant)
|
||||
}
|
||||
|
||||
var archProperties []android.SdkMemberProperties
|
||||
for _, archInfo := range osInfo.archTypes {
|
||||
archProperties = append(archProperties, archInfo.Properties)
|
||||
}
|
||||
|
||||
extractCommonProperties(osInfo.Properties, archProperties)
|
||||
|
||||
// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
|
||||
var multilib string
|
||||
archVariantCount := len(osInfo.archTypes)
|
||||
if archVariantCount == 2 {
|
||||
multilib = "both"
|
||||
} else if archVariantCount == 1 {
|
||||
if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") {
|
||||
multilib = "64"
|
||||
} else {
|
||||
multilib = "32"
|
||||
}
|
||||
}
|
||||
|
||||
osInfo.Properties.Base().Compile_multilib = multilib
|
||||
|
||||
osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, bpModule)
|
||||
|
||||
archPropertySet := bpModule.AddPropertySet("arch")
|
||||
for _, av := range osInfo.archTypes {
|
||||
archTypePropertySet := archPropertySet.AddPropertySet(av.archType.Name)
|
||||
|
||||
av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet)
|
||||
}
|
||||
|
||||
memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule)
|
||||
}
|
||||
|
||||
// Extract common properties from a slice of property structures of the same type.
|
||||
//
|
||||
// All the property structures must be of the same type.
|
||||
// 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{}) {
|
||||
commonPropertiesValue := reflect.ValueOf(commonProperties)
|
||||
commonStructValue := commonPropertiesValue.Elem()
|
||||
propertiesStructType := commonStructValue.Type()
|
||||
|
||||
// Create an empty structure from which default values for the field can be copied.
|
||||
emptyStructValue := reflect.New(propertiesStructType).Elem()
|
||||
|
||||
for f := 0; f < propertiesStructType.NumField(); f++ {
|
||||
// Check to see if all the structures have the same value for the field. The commonValue
|
||||
// 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++ {
|
||||
structValue := sliceValue.Index(i).Elem().Elem()
|
||||
fieldValue := structValue.Field(f)
|
||||
if !fieldValue.CanInterface() {
|
||||
// The field is not exported so ignore it.
|
||||
continue
|
||||
}
|
||||
|
||||
if commonValue == nil {
|
||||
// Use the first value as the commonProperties value.
|
||||
commonValue = &fieldValue
|
||||
} else {
|
||||
// If the value does not match the current common value then there is
|
||||
// no value in common so break out.
|
||||
if !reflect.DeepEqual(fieldValue.Interface(), commonValue.Interface()) {
|
||||
commonValue = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the fields all have a common value then store it in the common struct field
|
||||
// and set the input struct's field to the empty value.
|
||||
if commonValue != nil {
|
||||
emptyValue := emptyStructValue.Field(f)
|
||||
commonStructValue.Field(f).Set(*commonValue)
|
||||
for i := 0; i < sliceValue.Len(); i++ {
|
||||
structValue := sliceValue.Index(i).Elem().Elem()
|
||||
fieldValue := structValue.Field(f)
|
||||
fieldValue.Set(emptyValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue