Merge "DO NOT MERGE: Remove AppSearch from Android R."
diff --git a/android/arch.go b/android/arch.go
index 922548e..e440486 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -596,7 +596,7 @@
}()
var (
- osTypeList []OsType
+ OsTypeList []OsType
commonTargetMap = make(map[string]Target)
NoOsType OsType
@@ -672,7 +672,7 @@
DefaultDisabled: defDisabled,
}
- osTypeList = append(osTypeList, os)
+ OsTypeList = append(OsTypeList, os)
if _, found := commonTargetMap[name]; found {
panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
@@ -684,7 +684,7 @@
}
func osByName(name string) OsType {
- for _, os := range osTypeList {
+ for _, os := range OsTypeList {
if os.Name == name {
return os
}
@@ -750,7 +750,7 @@
var moduleOSList []OsType
- for _, os := range osTypeList {
+ for _, os := range OsTypeList {
supportedClass := false
for _, osClass := range osClasses {
if os.Class == osClass {
@@ -1071,7 +1071,7 @@
"Arm_on_x86",
"Arm_on_x86_64",
}
- for _, os := range osTypeList {
+ for _, os := range OsTypeList {
targets = append(targets, os.Field)
for _, archType := range osArchTypeMap[os] {
diff --git a/android/sdk.go b/android/sdk.go
index d13ad7d..969e21a 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -302,7 +302,46 @@
//
// 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 @@
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,50 @@
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 setting to use for the compile_multilib property.
+ Compile_multilib string
+
+ // The number of unique os types supported by the member variants.
+ Os_count int
+
+ // The os type for which these properties refer.
+ Os OsType
+}
+
+// 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 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)
+}
diff --git a/apex/apex.go b/apex/apex.go
index 736ce85..cb1f263 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1993,7 +1993,7 @@
if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, to) {
return
}
- ctx.ModuleErrorf("requires %q that is not available for the APEX.", to.Name())
+ ctx.ModuleErrorf("%q requires %q that is not available for the APEX.", from.Name(), to.Name())
})
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2b13197..7b842da 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3345,7 +3345,7 @@
func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
// libfoo's apex_available comes from cc_defaults
- testApexError(t, `"myapex" .*: requires "libfoo" that is not available for the APEX`, `
+ testApexError(t, `"myapex" .*: "myapex" requires "libfoo" that is not available for the APEX`, `
apex {
name: "myapex",
key: "myapex.key",
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 58d6ad0..fc9b89e 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "strings"
"android/soong/android"
"github.com/google/blueprint"
@@ -64,65 +63,13 @@
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 (
@@ -131,7 +78,7 @@
// path to the native binary. Relative to <sdk_root>/<api_dir>
func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
- return filepath.Join(lib.archType,
+ return filepath.Join(lib.OsPrefix(), lib.archType,
nativeBinaryDir, lib.outputFile.Base())
}
@@ -140,8 +87,7 @@
// 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 @@
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))
+ }
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index a36917e..656df69 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "reflect"
"android/soong/android"
"github.com/google/blueprint"
@@ -96,48 +95,25 @@
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)
+
+ ccModule := member.Variants()[0].(*Module)
+
+ sdkVersion := ccModule.SdkVersion()
+ if sdkVersion != "" {
+ pbm.AddProperty("sdk_version", sdkVersion)
+ }
+ 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 +121,9 @@
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 +143,7 @@
// 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 +153,7 @@
// 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 +164,7 @@
// 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 +175,7 @@
// 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 +184,14 @@
}
// 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,8 +253,8 @@
)
// path to the native library. Relative to <sdk_root>/<api_dir>
-func nativeLibraryPathFor(lib nativeLibInfoProperties) string {
- return filepath.Join(lib.archType,
+func nativeLibraryPathFor(lib *nativeLibInfoProperties) string {
+ return filepath.Join(lib.OsPrefix(), lib.archType,
nativeStubDir, lib.outputFile.Base())
}
@@ -365,6 +263,10 @@
// 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 +303,29 @@
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)
}
diff --git a/cc/testing.go b/cc/testing.go
index a22763a..b8a7eab 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -34,7 +34,7 @@
ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
}
-func GatherRequiredDepsForTest(os android.OsType) string {
+func GatherRequiredDepsForTest(oses ...android.OsType) string {
ret := `
toolchain_library {
name: "libatomic",
@@ -341,8 +341,9 @@
}
`
- if os == android.Fuchsia {
- ret += `
+ for _, os := range oses {
+ if os == android.Fuchsia {
+ ret += `
cc_library {
name: "libbioniccompat",
stl: "none",
@@ -352,6 +353,22 @@
stl: "none",
}
`
+ }
+ if os == android.Windows {
+ ret += `
+ toolchain_library {
+ name: "libwinpthread",
+ host_supported: true,
+ enabled: false,
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+ src: "",
+ }
+ `
+ }
}
return ret
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index d7adb40..6ec919c 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -379,6 +379,7 @@
FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch]).
FlagWithArg("--android-root=", global.EmptyDirectory).
FlagWithArg("--no-inline-from=", "core-oj.jar").
+ Flag("--force-determinism").
Flag("--abort-on-hard-verifier-error")
if global.BootFlags != "" {
diff --git a/java/java.go b/java/java.go
index 135ae51..d0b5adf 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1879,12 +1879,12 @@
)
// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
-func sdkSnapshotFilePathForJar(member android.SdkMember) string {
- return sdkSnapshotFilePathForMember(member, jarFileSuffix)
+func sdkSnapshotFilePathForJar(osPrefix, name string) string {
+ return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
}
-func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) string {
- return filepath.Join(javaDir, member.Name()+suffix)
+func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string {
+ return filepath.Join(javaDir, osPrefix, name+suffix)
}
type librarySdkMemberType struct {
@@ -1904,32 +1904,46 @@
return ok
}
-func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+func (mt *librarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule {
+ return builder.AddPrebuiltModule(member, "java_import")
+}
- variants := member.Variants()
- 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]
+func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ return &librarySdkMemberProperties{memberType: mt}
+}
+
+type librarySdkMemberProperties struct {
+ android.SdkMemberPropertiesBase
+
+ memberType *librarySdkMemberType
+
+ library *Library
+ jarToExport android.Path
+}
+
+func (p *librarySdkMemberProperties) PopulateFromVariant(variant android.SdkAware) {
j := variant.(*Library)
- exportedJar := mt.jarToExportGetter(j)
- snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member)
- builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
+ p.library = j
+ p.jarToExport = p.memberType.jarToExportGetter(j)
+}
- for _, dir := range j.AidlIncludeDirs() {
- // TODO(jiyong): copy parcelable declarations only
- aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
- for _, file := range aidlFiles {
- builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
+func (p *librarySdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) {
+ if p.jarToExport != nil {
+ exportedJar := p.jarToExport
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.library.Name())
+ builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
+
+ for _, dir := range p.library.AidlIncludeDirs() {
+ // TODO(jiyong): copy parcelable declarations only
+ aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
+ for _, file := range aidlFiles {
+ builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
+ }
}
- }
- module := builder.AddPrebuiltModule(member, "java_import")
- module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
+ propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
+ }
}
var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
@@ -2094,31 +2108,44 @@
return ok
}
-func (mt *testSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
- variants := member.Variants()
- 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)
+func (mt *testSdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule {
+ return builder.AddPrebuiltModule(member, "java_test_import")
+}
- implementationJars := j.ImplementationJars()
+func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ return &testSdkMemberProperties{}
+}
+
+type testSdkMemberProperties struct {
+ android.SdkMemberPropertiesBase
+
+ test *Test
+ jarToExport android.Path
+}
+
+func (p *testSdkMemberProperties) PopulateFromVariant(variant android.SdkAware) {
+ test := variant.(*Test)
+
+ implementationJars := test.ImplementationJars()
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)
- builder.CopyToSnapshot(implementationJars[0], snapshotRelativeJavaLibPath)
+ p.test = test
+ p.jarToExport = implementationJars[0]
+}
- snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(member, testConfigSuffix)
- builder.CopyToSnapshot(j.testConfig, snapshotRelativeTestConfigPath)
+func (p *testSdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) {
+ if p.jarToExport != nil {
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.test.Name())
+ builder.CopyToSnapshot(p.jarToExport, snapshotRelativeJavaLibPath)
- module := builder.AddPrebuiltModule(member, "java_test_import")
- module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
- module.AddProperty("test_config", snapshotRelativeTestConfigPath)
+ snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), p.test.Name(), testConfigSuffix)
+ builder.CopyToSnapshot(p.test.testConfig, snapshotRelativeTestConfigPath)
+
+ propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
+ 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
@@ -2321,7 +2348,7 @@
//
type ImportProperties struct {
- Jars []string `android:"path"`
+ Jars []string `android:"path,arch_variant"`
Sdk_version *string
diff --git a/java/sdk.go b/java/sdk.go
index 1e60d67..d230ccd 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -283,6 +283,28 @@
}
}
+func (s sdkSpec) validateSystemSdk(ctx android.EarlyModuleContext) bool {
+ // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
+ // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
+ // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
+ if s.kind != sdkSystem || !s.version.isNumbered() {
+ return true
+ }
+ allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
+ if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
+ systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
+ if len(systemSdkVersions) > 0 {
+ allowedVersions = systemSdkVersions
+ }
+ }
+ if len(allowedVersions) > 0 && !android.InList(s.version.String(), allowedVersions) {
+ ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
+ s.raw, allowedVersions)
+ return false
+ }
+ return true
+}
+
func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep {
sdkVersion := sdkContext.sdkVersion()
if !sdkVersion.valid() {
@@ -293,6 +315,9 @@
if ctx.Config().IsPdkBuild() {
sdkVersion = sdkVersion.forPdkBuild(ctx)
}
+ if !sdkVersion.validateSystemSdk(ctx) {
+ return sdkDep{}
+ }
if sdkVersion.usePrebuilt(ctx) {
dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), sdkVersion.kind.String())
@@ -340,21 +365,6 @@
}
}
- // Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
- // or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
- if sdkVersion.kind == sdkSystem && sdkVersion.version.isNumbered() {
- allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
- if ctx.DeviceSpecific() || ctx.SocSpecific() {
- if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
- allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
- }
- }
- if len(allowed_versions) > 0 && !android.InList(sdkVersion.version.String(), allowed_versions) {
- ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
- sdkVersion.raw, allowed_versions)
- }
- }
-
switch sdkVersion.kind {
case sdkPrivate:
return sdkDep{
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 076b3f5..9e97a60 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -1 +1,2 @@
per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com
+per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
new file mode 100755
index 0000000..79e40dd
--- /dev/null
+++ b/scripts/build-mainline-modules.sh
@@ -0,0 +1,63 @@
+#!/bin/bash -ex
+
+# Non exhaustive list of modules where we want prebuilts. More can be added as
+# needed.
+MAINLINE_MODULES=(
+ com.android.art.debug
+ com.android.art.release
+ com.android.art.testing
+ com.android.conscrypt
+ com.android.runtime
+ com.android.tzdata
+ com.android.i18n
+)
+
+# List of SDKs and module exports we know of.
+MODULES_SDK_AND_EXPORTS=(
+ art-module-sdk
+ art-module-test-exports
+ conscrypt-module-sdk
+ conscrypt-module-test-exports
+)
+
+# We want to create apex modules for all supported architectures.
+PRODUCTS=(
+ aosp_arm
+ aosp_arm64
+ aosp_x86
+ aosp_x86_64
+)
+
+if [ ! -e "build/make/core/Makefile" ]; then
+ echo "$0 must be run from the top of the tree"
+ exit 1
+fi
+
+OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
+DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
+
+for product in "${PRODUCTS[@]}"; do
+ build/soong/soong_ui.bash --make-mode $@ \
+ TARGET_PRODUCT=${product} \
+ ${MAINLINE_MODULES[@]}
+
+ PRODUCT_OUT=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT=${product} get_build_var PRODUCT_OUT)
+ TARGET_ARCH=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT=${product} get_build_var TARGET_ARCH)
+ rm -rf ${DIST_DIR}/${TARGET_ARCH}/
+ mkdir -p ${DIST_DIR}/${TARGET_ARCH}/
+ for module in "${MAINLINE_MODULES[@]}"; do
+ cp ${PWD}/${PRODUCT_OUT}/system/apex/${module}.apex ${DIST_DIR}/${TARGET_ARCH}/
+ done
+done
+
+
+# Create multi-archs SDKs in a different out directory. The multi-arch script
+# uses soong directly and therefore needs its own directory that doesn't clash
+# with make.
+export OUT_DIR=${OUT_DIR}/aml/
+for sdk in "${MODULES_SDK_AND_EXPORTS[@]}"; do
+ build/soong/scripts/build-aml-prebuilts.sh ${sdk}
+done
+
+rm -rf ${DIST_DIR}/mainline-sdks
+cp -R ${OUT_DIR}/soong/mainline-sdks ${DIST_DIR}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index a14890e..11bc902 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -25,11 +25,13 @@
t.Helper()
fs := map[string][]byte{
- "Test.cpp": nil,
- "include/Test.h": nil,
- "arm64/include/Arm64Test.h": nil,
- "libfoo.so": nil,
- "aidl/foo/bar/Test.aidl": nil,
+ "Test.cpp": nil,
+ "include/Test.h": nil,
+ "include-android/AndroidTest.h": nil,
+ "include-host/HostTest.h": nil,
+ "arm64/include/Arm64Test.h": nil,
+ "libfoo.so": nil,
+ "aidl/foo/bar/Test.aidl": nil,
}
return testSdkWithFs(t, bp, fs)
}
@@ -401,6 +403,108 @@
)
}
+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,
+ 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"],
+}
+`),
+ 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) {
result := testSdkWithCc(t, `
sdk {
@@ -517,6 +621,7 @@
},
system_shared_libs: [],
stl: "none",
+ sdk_version: "minimum",
}
`)
@@ -529,6 +634,7 @@
sdk_member_name: "mynativelib",
device_supported: false,
host_supported: true,
+ sdk_version: "minimum",
export_include_dirs: ["include/include"],
arch: {
x86_64: {
@@ -549,6 +655,7 @@
prefer: false,
device_supported: false,
host_supported: true,
+ sdk_version: "minimum",
export_include_dirs: ["include/include"],
arch: {
x86_64: {
@@ -585,6 +692,99 @@
)
}
+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,
+ 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"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+cc_prebuilt_library_shared {
+ name: "mynativelib",
+ prefer: false,
+ device_supported: false,
+ host_supported: true,
+ 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"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ device_supported: false,
+ host_supported: true,
+ native_shared_libs: ["mysdk_mynativelib@current"],
+}
+`),
+ 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) {
result := testSdkWithCc(t, `
module_exports {
@@ -955,3 +1155,83 @@
`),
)
}
+
+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,
+ export_system_include_dirs: ["include/include"],
+ target: {
+ android: {
+ export_include_dirs: ["include/include-android"],
+ },
+ linux_glibc: {
+ export_include_dirs: ["include/include-host"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+cc_prebuilt_library_headers {
+ name: "mynativeheaders",
+ prefer: false,
+ host_supported: true,
+ export_system_include_dirs: ["include/include"],
+ target: {
+ android: {
+ export_include_dirs: ["include/include-android"],
+ },
+ linux_glibc: {
+ export_include_dirs: ["include/include-host"],
+ },
+ },
+ stl: "none",
+ system_shared_libs: [],
+}
+
+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
+`),
+ )
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 9046eec..45da1f9 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -230,6 +230,72 @@
)
}
+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) {
result := testSdkWithJava(t, `
module_exports {
diff --git a/sdk/testing.go b/sdk/testing.go
index 41333cd..464c3ca 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -40,7 +40,7 @@
name: "myapex.cert",
certificate: "myapex",
}
- ` + cc.GatherRequiredDepsForTest(android.Android)
+ ` + cc.GatherRequiredDepsForTest(android.Android, android.Windows)
mockFS := map[string][]byte{
"build/make/target/product/security": nil,
diff --git a/sdk/update.go b/sdk/update.go
index b335777..282a7a4 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "sort"
"strings"
"github.com/google/blueprint"
@@ -251,7 +252,14 @@
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 +651,285 @@
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
+
+ // True if the member has common arch variants for this os type.
+ commonArch bool
+}
+
+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 variants by os type.
+ variantsByOsType := make(map[android.OsType][]android.SdkAware)
+ variants := member.Variants()
+ for _, variant := range variants {
+ osType := variant.Target().Os
+ variantsByOsType[osType] = append(variantsByOsType[osType], variant)
+ }
+
+ osCount := len(variantsByOsType)
+ createVariantPropertiesStruct := func(os android.OsType) android.SdkMemberProperties {
+ properties := memberType.CreateVariantPropertiesStruct()
+ base := properties.Base()
+ base.Os_count = osCount
+ base.Os = os
+ return properties
+ }
+
+ osTypeToInfo := make(map[android.OsType]*osTypeSpecificInfo)
+
+ // The set of properties that are common across all architectures and os types.
+ commonProperties := createVariantPropertiesStruct(android.CommonOS)
+
+ // The list of property structures which are os type specific but common across
+ // architectures within that os type.
+ var osSpecificPropertiesList []android.SdkMemberProperties
+
+ for osType, osTypeVariants := range variantsByOsType {
+ // Group the properties for each variant by arch type within the os.
+ osInfo := &osTypeSpecificInfo{}
+ osTypeToInfo[osType] = osInfo
+
+ // Create a structure into which properties common across the architectures in
+ // this os type will be stored. Add it to the list of os type specific yet
+ // architecture independent properties structs.
+ osInfo.Properties = createVariantPropertiesStruct(osType)
+ osSpecificPropertiesList = append(osSpecificPropertiesList, osInfo.Properties)
+
+ commonArch := false
+ for _, variant := range osTypeVariants {
+ var properties android.SdkMemberProperties
+
+ // Get the info associated with the arch type inside the os info.
+ archType := variant.Target().Arch.ArchType
+
+ if archType.Name == "common" {
+ // The arch type is common so populate the common properties directly.
+ properties = osInfo.Properties
+
+ commonArch = true
+ } else {
+ archInfo := &archTypeSpecificInfo{archType: archType}
+ properties = createVariantPropertiesStruct(osType)
+ archInfo.Properties = properties
+
+ osInfo.archTypes = append(osInfo.archTypes, archInfo)
+ }
+
+ properties.PopulateFromVariant(variant)
+ }
+
+ if commonArch {
+ if len(osTypeVariants) != 1 {
+ panic("Expected to only have 1 variant when arch type is common but found " + string(len(variants)))
+ }
+ } else {
+ var archPropertiesList []android.SdkMemberProperties
+ for _, archInfo := range osInfo.archTypes {
+ archPropertiesList = append(archPropertiesList, archInfo.Properties)
+ }
+
+ extractCommonProperties(osInfo.Properties, archPropertiesList)
+
+ // 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.commonArch = commonArch
+ osInfo.Properties.Base().Compile_multilib = multilib
+ }
+ }
+
+ // Extract properties which are common across all architectures and os types.
+ extractCommonProperties(commonProperties, osSpecificPropertiesList)
+
+ // Add the common properties to the module.
+ commonProperties.AddToPropertySet(sdkModuleContext, builder, bpModule)
+
+ // Create a target property set into which target specific properties can be
+ // added.
+ targetPropertySet := bpModule.AddPropertySet("target")
+
+ // Iterate over the os types in a fixed order.
+ for _, osType := range s.getPossibleOsTypes() {
+ osInfo := osTypeToInfo[osType]
+ if osInfo == nil {
+ continue
+ }
+
+ var osPropertySet android.BpPropertySet
+ var archOsPrefix string
+ if len(osTypeToInfo) == 1 {
+ // There is only one os type present in the variants sp don't bother
+ // with adding target specific properties.
+
+ // Create a structure that looks like:
+ // module_type {
+ // name: "...",
+ // ...
+ // <common properties>
+ // ...
+ // <single os type specific properties>
+ //
+ // arch: {
+ // <arch specific sections>
+ // }
+ //
+ osPropertySet = bpModule
+
+ // Arch specific properties need to be added to an arch specific section
+ // within arch.
+ archOsPrefix = ""
+ } else {
+ // Create a structure that looks like:
+ // module_type {
+ // name: "...",
+ // ...
+ // <common properties>
+ // ...
+ // target: {
+ // <arch independent os specific sections, e.g. android>
+ // ...
+ // <arch and os specific sections, e.g. android_x86>
+ // }
+ //
+ osPropertySet = targetPropertySet.AddPropertySet(osType.Name)
+
+ // Arch specific properties need to be added to an os and arch specific
+ // section prefixed with <os>_.
+ archOsPrefix = osType.Name + "_"
+ }
+
+ osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, osPropertySet)
+ if !osInfo.commonArch {
+ // Either add the arch specific sections into the target or arch sections
+ // depending on whether they will also be os specific.
+ var archPropertySet android.BpPropertySet
+ if archOsPrefix == "" {
+ archPropertySet = osPropertySet.AddPropertySet("arch")
+ } else {
+ archPropertySet = targetPropertySet
+ }
+
+ // Add arch (and possibly os) specific sections for each set of
+ // arch (and possibly os) specific properties.
+ for _, av := range osInfo.archTypes {
+ archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + av.archType.Name)
+
+ av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet)
+ }
+ }
+ }
+
+ memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule)
+}
+
+// Compute the list of possible os types that this sdk could support.
+func (s *sdk) getPossibleOsTypes() []android.OsType {
+ var osTypes []android.OsType
+ for _, osType := range android.OsTypeList {
+ if s.DeviceSupported() {
+ if osType.Class == android.Device && osType != android.Fuchsia {
+ osTypes = append(osTypes, osType)
+ }
+ }
+ if s.HostSupported() {
+ if osType.Class == android.Host || osType.Class == android.HostCross {
+ osTypes = append(osTypes, osType)
+ }
+ }
+ }
+ sort.SliceStable(osTypes, func(i, j int) bool { return osTypes[i].Name < osTypes[j].Name })
+ return osTypes
+}
+
+// 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)
+
+ field := propertiesStructType.Field(f)
+ if field.Name == "SdkMemberPropertiesBase" {
+ continue
+ }
+
+ 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)
+ }
+ }
+ }
+}