Merge "Move stub providers to droidstubs.go"
diff --git a/android/arch.go b/android/arch.go
index d7b12bc..c1b2c33 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -665,7 +665,7 @@
}
// only the primary arch in the ramdisk / vendor_ramdisk / recovery partition
- if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk()) {
+ if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) {
osTargets = []Target{osTargets[0]}
}
@@ -1014,35 +1014,19 @@
base.customizableProperties = m.GetProperties()
}
-// appendProperties squashes properties from the given field of the given src property struct
-// into the dst property struct. Returns the reflect.Value of the field in the src property
-// struct to be used for further appendProperties calls on fields of that property struct.
-func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
- dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
-
- // Step into non-nil pointers to structs in the src value.
- if src.Kind() == reflect.Ptr {
- if src.IsNil() {
- return src
- }
- src = src.Elem()
- }
-
- // Find the requested field in the src struct.
- src = src.FieldByName(field)
- if !src.IsValid() {
- ctx.ModuleErrorf("field %q does not exist", srcPrefix)
- return src
- }
-
- // Save the value of the field in the src struct to return.
- ret := src
-
+func maybeBlueprintEmbed(src reflect.Value) reflect.Value {
// If the value of the field is a struct (as opposed to a pointer to a struct) then step
// into the BlueprintEmbed field.
if src.Kind() == reflect.Struct {
- src = src.FieldByName("BlueprintEmbed")
+ return src.FieldByName("BlueprintEmbed")
+ } else {
+ return src
}
+}
+
+// Merges the property struct in srcValue into dst.
+func mergePropertyStruct(ctx BaseMutatorContext, dst interface{}, srcValue reflect.Value) {
+ src := maybeBlueprintEmbed(srcValue).Interface()
// order checks the `android:"variant_prepend"` tag to handle properties where the
// arch-specific value needs to come before the generic value, for example for lists of
@@ -1058,7 +1042,7 @@
}
// Squash the located property struct into the destination property struct.
- err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order)
+ err := proptools.ExtendMatchingProperties([]interface{}{dst}, src, nil, order)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
@@ -1066,8 +1050,29 @@
panic(err)
}
}
+}
- return ret
+// Returns the immediate child of the input property struct that corresponds to
+// the sub-property "field".
+func getChildPropertyStruct(ctx BaseMutatorContext,
+ src reflect.Value, field, userFriendlyField string) reflect.Value {
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ return src
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field in the src struct.
+ src = src.FieldByName(proptools.FieldNameForProperty(field))
+ if !src.IsValid() {
+ ctx.ModuleErrorf("field %q does not exist", userFriendlyField)
+ return src
+ }
+
+ return src
}
// Squash the appropriate OS-specific property structs into the matching top level property structs
@@ -1094,7 +1099,8 @@
if os.Class == Host {
field := "Host"
prefix := "target.host"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ hostProperties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, hostProperties)
}
// Handle target OS generalities of the form:
@@ -1106,13 +1112,15 @@
if os.Linux() {
field := "Linux"
prefix := "target.linux"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ linuxProperties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, linuxProperties)
}
if os.Bionic() {
field := "Bionic"
prefix := "target.bionic"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ bionicProperties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, bionicProperties)
}
// Handle target OS properties in the form:
@@ -1129,12 +1137,14 @@
// },
field := os.Field
prefix := "target." + os.Name
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ osProperties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, osProperties)
if os.Class == Host && os != Windows {
field := "Not_windows"
prefix := "target.not_windows"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ notWindowsProperties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, notWindowsProperties)
}
// Handle 64-bit device properties in the form:
@@ -1154,17 +1164,189 @@
if ctx.Config().Android64() {
field := "Android64"
prefix := "target.android64"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ android64Properties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, android64Properties)
} else {
field := "Android32"
prefix := "target.android32"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ android32Properties := getChildPropertyStruct(ctx, targetProp, field, prefix)
+ mergePropertyStruct(ctx, genProps, android32Properties)
}
}
}
}
}
+// Returns the struct containing the properties specific to the given
+// architecture type. These look like this in Blueprint files:
+// arch: {
+// arm64: {
+// key: value,
+// },
+// },
+// This struct will also contain sub-structs containing to the architecture/CPU
+// variants and features that themselves contain properties specific to those.
+func getArchTypeStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+ archProp := archPropValues.FieldByName("Arch").Elem()
+ prefix := "arch." + archType.Name
+ archStruct := getChildPropertyStruct(ctx, archProp, archType.Name, prefix)
+ return archStruct
+}
+
+// Returns the struct containing the properties specific to a given multilib
+// value. These look like this in the Blueprint file:
+// multilib: {
+// lib32: {
+// key: value,
+// },
+// },
+func getMultilibStruct(ctx BaseMutatorContext, archProperties interface{}, archType ArchType) reflect.Value {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+ multilibProp := archPropValues.FieldByName("Multilib").Elem()
+ multilibProperties := getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib)
+ return multilibProperties
+}
+
+// Returns the structs corresponding to the properties specific to the given
+// architecture and OS in archProperties.
+func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
+ result := make([]reflect.Value, 0)
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+
+ targetProp := archPropValues.FieldByName("Target").Elem()
+
+ archType := arch.ArchType
+
+ if arch.ArchType != Common {
+ archStruct := getArchTypeStruct(ctx, archProperties, arch.ArchType)
+ result = append(result, archStruct)
+
+ // Handle arch-variant-specific properties in the form:
+ // arch: {
+ // arm: {
+ // variant: {
+ // key: value,
+ // },
+ // },
+ // },
+ v := variantReplacer.Replace(arch.ArchVariant)
+ if v != "" {
+ prefix := "arch." + archType.Name + "." + v
+ variantProperties := getChildPropertyStruct(ctx, archStruct, v, prefix)
+ result = append(result, variantProperties)
+ }
+
+ // Handle cpu-variant-specific properties in the form:
+ // arch: {
+ // arm: {
+ // variant: {
+ // key: value,
+ // },
+ // },
+ // },
+ if arch.CpuVariant != arch.ArchVariant {
+ c := variantReplacer.Replace(arch.CpuVariant)
+ if c != "" {
+ prefix := "arch." + archType.Name + "." + c
+ cpuVariantProperties := getChildPropertyStruct(ctx, archStruct, c, prefix)
+ result = append(result, cpuVariantProperties)
+ }
+ }
+
+ // Handle arch-feature-specific properties in the form:
+ // arch: {
+ // arm: {
+ // feature: {
+ // key: value,
+ // },
+ // },
+ // },
+ for _, feature := range arch.ArchFeatures {
+ prefix := "arch." + archType.Name + "." + feature
+ featureProperties := getChildPropertyStruct(ctx, archStruct, feature, prefix)
+ result = append(result, featureProperties)
+ }
+
+ multilibProperties := getMultilibStruct(ctx, archProperties, archType)
+ result = append(result, multilibProperties)
+
+ // Handle combined OS-feature and arch specific properties in the form:
+ // target: {
+ // bionic_x86: {
+ // key: value,
+ // },
+ // }
+ if os.Linux() {
+ field := "Linux_" + arch.ArchType.Name
+ userFriendlyField := "target.linux_" + arch.ArchType.Name
+ linuxProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField)
+ result = append(result, linuxProperties)
+ }
+
+ if os.Bionic() {
+ field := "Bionic_" + archType.Name
+ userFriendlyField := "target.bionic_" + archType.Name
+ bionicProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField)
+ result = append(result, bionicProperties)
+ }
+
+ // Handle combined OS and arch specific properties in the form:
+ // target: {
+ // linux_glibc_x86: {
+ // key: value,
+ // },
+ // linux_glibc_arm: {
+ // key: value,
+ // },
+ // android_arm {
+ // key: value,
+ // },
+ // android_x86 {
+ // key: value,
+ // },
+ // },
+ field := os.Field + "_" + archType.Name
+ userFriendlyField := "target." + os.Name + "_" + archType.Name
+ osArchProperties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField)
+ result = append(result, osArchProperties)
+ }
+
+ // Handle arm on x86 properties in the form:
+ // target {
+ // arm_on_x86 {
+ // key: value,
+ // },
+ // arm_on_x86_64 {
+ // key: value,
+ // },
+ // },
+ if os.Class == Device {
+ if arch.ArchType == X86 && (hasArmAbi(arch) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android])) {
+ field := "Arm_on_x86"
+ userFriendlyField := "target.arm_on_x86"
+ armOnX86Properties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField)
+ result = append(result, armOnX86Properties)
+ }
+ if arch.ArchType == X86_64 && (hasArmAbi(arch) ||
+ hasArmAndroidArch(ctx.Config().Targets[Android])) {
+ field := "Arm_on_x86_64"
+ userFriendlyField := "target.arm_on_x86_64"
+ armOnX8664Properties := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField)
+ result = append(result, armOnX8664Properties)
+ }
+ if os == Android && nativeBridgeEnabled {
+ userFriendlyField := "Native_bridge"
+ prefix := "target.native_bridge"
+ nativeBridgeProperties := getChildPropertyStruct(ctx, targetProp, userFriendlyField, prefix)
+ result = append(result, nativeBridgeProperties)
+ }
+ }
+
+ return result
+}
+
// Squash the appropriate arch-specific property structs into the matching top level property
// structs based on the CompileTarget value that was annotated on the variant.
func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
@@ -1176,144 +1358,15 @@
if m.archProperties[i] == nil {
continue
}
- for _, archProperties := range m.archProperties[i] {
- archPropValues := reflect.ValueOf(archProperties).Elem()
- archProp := archPropValues.FieldByName("Arch").Elem()
- multilibProp := archPropValues.FieldByName("Multilib").Elem()
- targetProp := archPropValues.FieldByName("Target").Elem()
+ propStructs := make([]reflect.Value, 0)
+ for _, archProperty := range m.archProperties[i] {
+ propStructShard := getArchProperties(ctx, archProperty, arch, os, m.Target().NativeBridge == NativeBridgeEnabled)
+ propStructs = append(propStructs, propStructShard...)
+ }
- // Handle arch-specific properties in the form:
- // arch: {
- // arm64: {
- // key: value,
- // },
- // },
- t := arch.ArchType
-
- if arch.ArchType != Common {
- field := proptools.FieldNameForProperty(t.Name)
- prefix := "arch." + t.Name
- archStruct := m.appendProperties(ctx, genProps, archProp, field, prefix)
-
- // Handle arch-variant-specific properties in the form:
- // arch: {
- // variant: {
- // key: value,
- // },
- // },
- v := variantReplacer.Replace(arch.ArchVariant)
- if v != "" {
- field := proptools.FieldNameForProperty(v)
- prefix := "arch." + t.Name + "." + v
- m.appendProperties(ctx, genProps, archStruct, field, prefix)
- }
-
- // Handle cpu-variant-specific properties in the form:
- // arch: {
- // variant: {
- // key: value,
- // },
- // },
- if arch.CpuVariant != arch.ArchVariant {
- c := variantReplacer.Replace(arch.CpuVariant)
- if c != "" {
- field := proptools.FieldNameForProperty(c)
- prefix := "arch." + t.Name + "." + c
- m.appendProperties(ctx, genProps, archStruct, field, prefix)
- }
- }
-
- // Handle arch-feature-specific properties in the form:
- // arch: {
- // feature: {
- // key: value,
- // },
- // },
- for _, feature := range arch.ArchFeatures {
- field := proptools.FieldNameForProperty(feature)
- prefix := "arch." + t.Name + "." + feature
- m.appendProperties(ctx, genProps, archStruct, field, prefix)
- }
-
- // Handle multilib-specific properties in the form:
- // multilib: {
- // lib32: {
- // key: value,
- // },
- // },
- field = proptools.FieldNameForProperty(t.Multilib)
- prefix = "multilib." + t.Multilib
- m.appendProperties(ctx, genProps, multilibProp, field, prefix)
- }
-
- // Handle combined OS-feature and arch specific properties in the form:
- // target: {
- // bionic_x86: {
- // key: value,
- // },
- // }
- if os.Linux() && arch.ArchType != Common {
- field := "Linux_" + arch.ArchType.Name
- prefix := "target.linux_" + arch.ArchType.Name
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
- if os.Bionic() && arch.ArchType != Common {
- field := "Bionic_" + t.Name
- prefix := "target.bionic_" + t.Name
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
- // Handle combined OS and arch specific properties in the form:
- // target: {
- // linux_glibc_x86: {
- // key: value,
- // },
- // linux_glibc_arm: {
- // key: value,
- // },
- // android_arm {
- // key: value,
- // },
- // android_x86 {
- // key: value,
- // },
- // },
- if arch.ArchType != Common {
- field := os.Field + "_" + t.Name
- prefix := "target." + os.Name + "_" + t.Name
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
-
- // Handle arm on x86 properties in the form:
- // target {
- // arm_on_x86 {
- // key: value,
- // },
- // arm_on_x86_64 {
- // key: value,
- // },
- // },
- if os.Class == Device {
- if arch.ArchType == X86 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Android])) {
- field := "Arm_on_x86"
- prefix := "target.arm_on_x86"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
- if arch.ArchType == X86_64 && (hasArmAbi(arch) ||
- hasArmAndroidArch(ctx.Config().Targets[Android])) {
- field := "Arm_on_x86_64"
- prefix := "target.arm_on_x86_64"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
- if os == Android && m.Target().NativeBridge == NativeBridgeEnabled {
- field := "Native_bridge"
- prefix := "target.native_bridge"
- m.appendProperties(ctx, genProps, targetProp, field, prefix)
- }
- }
+ for _, propStruct := range propStructs {
+ mergePropertyStruct(ctx, genProps, propStruct)
}
}
}
@@ -1673,13 +1726,144 @@
return buildTargets, nil
}
+func (m *ModuleBase) getArchPropertySet(propertySet interface{}, archType ArchType) interface{} {
+ archString := archType.Field
+ for i := range m.archProperties {
+ if m.archProperties[i] == nil {
+ // Skip over nil properties
+ continue
+ }
+
+ // Not archProperties are usable; this function looks for properties of a very specific
+ // form, and ignores the rest.
+ for _, archProperty := range m.archProperties[i] {
+ // archPropValue is a property struct, we are looking for the form:
+ // `arch: { arm: { key: value, ... }}`
+ archPropValue := reflect.ValueOf(archProperty).Elem()
+
+ // Unwrap src so that it should looks like a pointer to `arm: { key: value, ... }`
+ src := archPropValue.FieldByName("Arch").Elem()
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ continue
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field (e.g. arm, x86) in the src struct.
+ src = src.FieldByName(archString)
+
+ // We only care about structs.
+ if !src.IsValid() || src.Kind() != reflect.Struct {
+ continue
+ }
+
+ // If the value of the field is a struct then step into the
+ // BlueprintEmbed field. The special "BlueprintEmbed" name is
+ // used by createArchPropTypeDesc to embed the arch properties
+ // in the parent struct, so the src arch prop should be in this
+ // field.
+ //
+ // See createArchPropTypeDesc for more details on how Arch-specific
+ // module properties are processed from the nested props and written
+ // into the module's archProperties.
+ src = src.FieldByName("BlueprintEmbed")
+
+ // Clone the destination prop, since we want a unique prop struct per arch.
+ propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+
+ // Copy the located property struct into the cloned destination property struct.
+ err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
+ if err != nil {
+ // This is fine, it just means the src struct doesn't match the type of propertySet.
+ continue
+ }
+
+ return propertySetClone
+ }
+ }
+ // No property set was found specific to the given arch, so return an empty
+ // property set.
+ return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+}
+
+// getMultilibPropertySet returns a property set struct matching the type of
+// `propertySet`, containing multilib-specific module properties for the given architecture.
+// If no multilib-specific properties exist for the given architecture, returns an empty property
+// set matching `propertySet`'s type.
+func (m *ModuleBase) getMultilibPropertySet(propertySet interface{}, archType ArchType) interface{} {
+ // archType.Multilib is lowercase (for example, lib32) but property struct field is
+ // capitalized, such as Lib32, so use strings.Title to capitalize it.
+ multiLibString := strings.Title(archType.Multilib)
+
+ for i := range m.archProperties {
+ if m.archProperties[i] == nil {
+ // Skip over nil properties
+ continue
+ }
+
+ // Not archProperties are usable; this function looks for properties of a very specific
+ // form, and ignores the rest.
+ for _, archProperties := range m.archProperties[i] {
+ // archPropValue is a property struct, we are looking for the form:
+ // `multilib: { lib32: { key: value, ... }}`
+ archPropValue := reflect.ValueOf(archProperties).Elem()
+
+ // Unwrap src so that it should looks like a pointer to `lib32: { key: value, ... }`
+ src := archPropValue.FieldByName("Multilib").Elem()
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ // Ignore nil pointers.
+ continue
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field (e.g. lib32) in the src struct.
+ src = src.FieldByName(multiLibString)
+
+ // We only care about valid struct pointers.
+ if !src.IsValid() || src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct {
+ continue
+ }
+
+ // Get the zero value for the requested property set.
+ propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+
+ // Copy the located property struct into the "zero" property set struct.
+ err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
+
+ if err != nil {
+ // This is fine, it just means the src struct doesn't match.
+ continue
+ }
+
+ return propertySetClone
+ }
+ }
+
+ // There were no multilib properties specifically matching the given archtype.
+ // Return zeroed value.
+ return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+}
+
// GetArchProperties returns a map of architectures to the values of the
-// properties of the 'dst' struct that are specific to that architecture.
+// properties of the 'propertySet' struct that are specific to that architecture.
//
// For example, passing a struct { Foo bool, Bar string } will return an
// interface{} that can be type asserted back into the same struct, containing
// the arch specific property value specified by the module if defined.
-func (m *ModuleBase) GetArchProperties(dst interface{}) map[ArchType]interface{} {
+//
+// Arch-specific properties may come from an arch stanza or a multilib stanza; properties
+// in these stanzas are combined.
+// For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
+// will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
+// propertyset contains `Foo []string`.
+func (m *ModuleBase) GetArchProperties(ctx BaseMutatorContext, propertySet interface{}) map[ArchType]interface{} {
// Return value of the arch types to the prop values for that arch.
archToProp := map[ArchType]interface{}{}
@@ -1688,82 +1872,47 @@
return archToProp
}
- // archProperties has the type of [][]interface{}. Looks complicated, so let's
- // explain this step by step.
- //
- // Loop over the outer index, which determines the property struct that
- // contains a matching set of properties in dst that we're interested in.
- // For example, BaseCompilerProperties or BaseLinkerProperties.
- for i := range m.archProperties {
- if m.archProperties[i] == nil {
- // Skip over nil arch props
- continue
- }
+ dstType := reflect.ValueOf(propertySet).Type()
+ var archProperties []interface{}
- // Non-nil arch prop, let's see if the props match up.
- for _, arch := range ArchTypeList() {
- // e.g X86, Arm
- field := arch.Field
-
- // If it's not nil, loop over the inner index, which determines the arch variant
- // of the prop type. In an Android.bp file, this is like looping over:
- //
- // arch: { arm: { key: value, ... }, x86: { key: value, ... } }
- for _, archProperties := range m.archProperties[i] {
- archPropValues := reflect.ValueOf(archProperties).Elem()
-
- // This is the archPropRoot struct. Traverse into the Arch nested struct.
- src := archPropValues.FieldByName("Arch").Elem()
-
- // Step into non-nil pointers to structs in the src value.
- if src.Kind() == reflect.Ptr {
- if src.IsNil() {
- // Ignore nil pointers.
- continue
- }
- src = src.Elem()
- }
-
- // Find the requested field (e.g. x86, x86_64) in the src struct.
- src = src.FieldByName(field)
- if !src.IsValid() {
- continue
- }
-
- // We only care about structs. These are not the droids you are looking for.
- if src.Kind() != reflect.Struct {
- continue
- }
-
- // If the value of the field is a struct then step into the
- // BlueprintEmbed field. The special "BlueprintEmbed" name is
- // used by createArchPropTypeDesc to embed the arch properties
- // in the parent struct, so the src arch prop should be in this
- // field.
- //
- // See createArchPropTypeDesc for more details on how Arch-specific
- // module properties are processed from the nested props and written
- // into the module's archProperties.
- src = src.FieldByName("BlueprintEmbed")
-
- // Clone the destination prop, since we want a unique prop struct per arch.
- dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface()
-
- // Copy the located property struct into the cloned destination property struct.
- err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace)
- if err != nil {
- // This is fine, it just means the src struct doesn't match.
- continue
- }
-
- // Found the prop for the arch, you have.
- archToProp[arch] = dstClone
-
- // Go to the next prop.
- break
- }
+ // First find the property set in the module that corresponds to the requested
+ // one. m.archProperties[i] corresponds to m.generalProperties[i].
+ for i, generalProp := range m.generalProperties {
+ srcType := reflect.ValueOf(generalProp).Type()
+ if srcType == dstType {
+ archProperties = m.archProperties[i]
+ break
}
}
+
+ if archProperties == nil {
+ // This module does not have the property set requested
+ return archToProp
+ }
+
+ // For each arch type (x86, arm64, etc.)
+ for _, arch := range ArchTypeList() {
+ // Arch properties are sometimes sharded (see createArchPropTypeDesc() ).
+ // Iterate over ever shard and extract a struct with the same type as the
+ // input one that contains the data specific to that arch.
+ propertyStructs := make([]reflect.Value, 0)
+ for _, archProperty := range archProperties {
+ archTypeStruct := getArchTypeStruct(ctx, archProperty, arch)
+ multilibStruct := getMultilibStruct(ctx, archProperty, arch)
+ propertyStructs = append(propertyStructs, archTypeStruct, multilibStruct)
+ }
+
+ // Create a new instance of the requested property set
+ value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+
+ // Merge all the structs together
+ for _, propertyStruct := range propertyStructs {
+ mergePropertyStruct(ctx, value, propertyStruct)
+ }
+
+ archToProp[arch] = value
+ }
+
return archToProp
}
diff --git a/android/bazel.go b/android/bazel.go
index e330681..6c476a7 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -170,71 +170,93 @@
"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
"system/libbase": Bp2BuildDefaultTrueRecursively,
"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
+ "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
+ "external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
}
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
bp2buildModuleDoNotConvertList = []string{
// Things that transitively depend on unconverted libc_* modules.
- "libc_common", // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
- "libc_common_static", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
- "libc_common_shared", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
- "libc_nomalloc", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
- "libc_nopthread", // ruperts@, cc_library_static, depends on lib_bionic_ndk, libc_syscalls, libc_tzcode, libstdc++
+ "libc_nopthread", // http://b/186821550, cc_library_static, depends on //bionic/libc:libc_bionic_ndk (http://b/186822256)
+ // also depends on //bionic/libc:libc_tzcode (http://b/186822591)
+ // also depends on //bionic/libc:libstdc++ (http://b/186822597)
+ "libc_common", // http://b/186821517, cc_library_static, depends on //bionic/libc:libc_nopthread (http://b/186821550)
+ "libc_common_static", // http://b/186824119, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
+ "libc_common_shared", // http://b/186824118, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
+ "libc_nomalloc", // http://b/186825031, cc_library_static, depends on //bionic/libc:libc_common (http://b/186821517)
- // Things that transitively depend on //system/libbase. libbase doesn't work because:
- // fmtlib: fatal error: 'cassert' file not found
- "libbase", // eakammer@, cc_library, no such target '//build/bazel/platforms/os:darwin': target 'darwin' not declared
- "libbase_ndk", // eakammer@, cc_library, no such target '//build/bazel/platforms/os:darwin': target 'darwin' not declared
- "libbionic_spawn_benchmark", // ruperts@, cc_library_static, depends on libbase, libgoogle-benchmark
- "libc_malloc_debug", // ruperts@, cc_library_static, depends on libbase
- "libc_malloc_debug_backtrace", // ruperts@, cc_library_static, depends on libbase
- "libcutils", // eakammer@, cc_library, depends on libbase, liblog
- "libcutils_sockets", // eakammer@, cc_library, depends on libbase, liblog
- "liblinker_debuggerd_stub", // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
- "liblinker_main", // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
- "liblinker_malloc", // ruperts@, cc_library_static, depends on libziparchive, libz, libbase
+ "libbionic_spawn_benchmark", // http://b/186824595, cc_library_static, depends on //external/google-benchmark (http://b/186822740)
+ // also depends on //system/logging/liblog:liblog (http://b/186822772)
- // Requires non-libc targets, but otherwise works
- "libc_jemalloc_wrapper", // ruperts@, cc_library_static, depends on //external/jemalloc_new
+ "libc_malloc_debug", // http://b/186824339, cc_library_static, depends on //system/libbase:libbase (http://b/186823646)
+ "libc_malloc_debug_backtrace", // http://b/186824112, cc_library_static, depends on //external/libcxxabi:libc++demangle (http://b/186823773)
- // Compilation error, seems to be fixable by changing the toolchain definition
- "libc_bionic_ndk", // ruperts@, cc_library_static, error: ISO C++ requires field designators...
- "libc_tzcode", // ruperts@, cc_library_static, error: expected expression
- "libm", // jingwen@, cc_library, error: "expected register here" (and many others)
+ "libcutils", // http://b/186827426, cc_library, depends on //system/core/libprocessgroup:libprocessgroup_headers (http://b/186826841)
+ "libcutils_sockets", // http://b/186826853, cc_library, depends on //system/libbase:libbase (http://b/186826479)
- // Linker error
- "libc_malloc_hooks", // jingwen@, cc_library, undefined symbol: __malloc_hook, etc.
- "libstdc++", // jingwen@, cc_library, undefined symbol: free
+ "liblinker_debuggerd_stub", // http://b/186824327, cc_library_static, depends on //external/zlib:libz (http://b/186823782)
+ // also depends on //system/libziparchive:libziparchive (http://b/186823656)
+ // also depends on //system/logging/liblog:liblog (http://b/186822772)
+ "liblinker_main", // http://b/186825989, cc_library_static, depends on //external/zlib:libz (http://b/186823782)
+ // also depends on //system/libziparchive:libziparchive (http://b/186823656)
+ // also depends on//system/logging/liblog:liblog (http://b/186822772)
+ "liblinker_malloc", // http://b/186826466, cc_library_static, depends on //external/zlib:libz (http://b/186823782)
+ // also depends on //system/libziparchive:libziparchive (http://b/186823656)
+ // also depends on //system/logging/liblog:liblog (http://b/186822772)
+ "libc_jemalloc_wrapper", // http://b/187012490, cc_library_static, depends on //external/jemalloc_new:libjemalloc5 (http://b/186828626)
+ "libc_ndk", // http://b/187013218, cc_library_static, depends on //bionic/libm:libm (http://b/183064661)
+ "libc", // http://b/183064430, cc_library, depends on //external/jemalloc_new:libjemalloc5 (http://b/186828626)
+ "libc_tzcode", // http://b/186822591, cc_library_static, localtime.c:84:46: error: expected expression
+ "libc_bionic_ndk", // http://b/186822256, cc_library_static, signal.cpp:186:52: error: ISO C++ requires field designators to be specified in declaration order
+ "libc_malloc_hooks", // http://b/187016307, cc_library, ld.lld: error: undefined symbol: __malloc_hook
+ "libm", // http://b/183064661, cc_library, math.h:25:16: error: unexpected token in argument list
- // Includes not found
- "libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'dirent.h' not found
- "liblog", // eakammer@, cc_library, 'sys/cdefs.h' file not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
- "libseccomp_policy", // jingwen@, cc_library, 'linux/filter.h' not found, missing -isystem bionic/libc/kernel/uapi/asm-arm, probably due to us not handling arch { ... { export_system_include_dirs } } correctly
- "note_memtag_heap_async", // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
- "note_memtag_heap_sync", // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+ // http://b/186823769: Needs C++ STL support, includes from unconverted standard libraries in //external/libcxx
+ // c++_static
+ "libbase_ndk", // http://b/186826477, cc_library, no such target '//build/bazel/platforms/os:darwin' when --platforms //build/bazel/platforms:android_x86 is added
+ // libcxx
+ "libBionicBenchmarksUtils", // cc_library_static, fatal error: 'map' file not found, from libcxx
+ "fmtlib", // cc_library_static, fatal error: 'cassert' file not found, from libcxx
+ "libbase", // http://b/186826479, cc_library, fatal error: 'memory' file not found, from libcxx
- // Other
- "libBionicBenchmarksUtils", // ruperts@, cc_library_static, 'map' file not found
- "libc_ndk", // ruperts@, cc_library_static, depends on libc_bionic_ndk, libc_jemalloc_wrapper, libc_tzcode, libstdc++
+ // http://b/186024507: Includes errors because of the system_shared_libs default value.
+ // Missing -isystem bionic/libc/include through the libc/libm/libdl
+ // default dependencies if system_shared_libs is unset.
+ "liblog", // http://b/186822772: cc_library, 'sys/cdefs.h' file not found
+ "libjemalloc5_jet", // cc_library, 'sys/cdefs.h' file not found
+ "libseccomp_policy", // http://b/186476753: cc_library, 'linux/filter.h' not found
+ "note_memtag_heap_async", // http://b/185127353: cc_library_static, error: feature.h not found
+ "note_memtag_heap_sync", // http://b/185127353: cc_library_static, error: feature.h not found
- "libc", // jingwen@, cc_library, depends on //external/gwp_asan
+ // Tests. Handle later.
+ "libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found
+ "libjemalloc5_integrationtest",
+ "libjemalloc5_stresstestlib",
+ "libjemalloc5_unittest",
+ }
+
+ // Per-module denylist of cc_library modules to only generate the static
+ // variant if their shared variant isn't ready or buildable by Bazel.
+ bp2buildCcLibraryStaticOnlyList = []string{
+ "libstdc++", // http://b/186822597, cc_library, ld.lld: error: undefined symbol: __errno
}
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
mixedBuildsDisabledList = []string{
- "libc_gdtoa", // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
"libc_netbsd", // lberki@, cc_library_static, version script assignment of 'LIBC_PRIVATE' to symbol 'SHA1Final' failed: symbol not defined
"libc_openbsd", // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
"libsystemproperties", // cparsons@, cc_library_static, wrong include paths
"libpropertyinfoparser", // cparsons@, cc_library_static, wrong include paths
"libarm-optimized-routines-string", // jingwen@, cc_library_static, OK for bp2build but b/186615213 (asflags not handled in bp2build), version script assignment of 'LIBC' to symbol 'memcmp' failed: symbol not defined (also for memrchr, strnlen)
+ "fmtlib_ndk", // http://b/187040371, cc_library_static, OK for bp2build but format-inl.h:11:10: fatal error: 'cassert' file not found for mixed builds
}
// Used for quicker lookups
bp2buildDoNotWriteBuildFile = map[string]bool{}
bp2buildModuleDoNotConvert = map[string]bool{}
+ bp2buildCcLibraryStaticOnly = map[string]bool{}
mixedBuildsDisabled = map[string]bool{}
)
@@ -247,11 +269,19 @@
bp2buildModuleDoNotConvert[moduleName] = true
}
+ for _, moduleName := range bp2buildCcLibraryStaticOnlyList {
+ bp2buildCcLibraryStaticOnly[moduleName] = true
+ }
+
for _, moduleName := range mixedBuildsDisabledList {
mixedBuildsDisabled[moduleName] = true
}
}
+func GenerateCcLibraryStaticOnly(ctx BazelConversionPathContext) bool {
+ return bp2buildCcLibraryStaticOnly[ctx.Module().Name()]
+}
+
func ShouldWriteBuildFileForDir(dir string) bool {
if _, ok := bp2buildDoNotWriteBuildFile[dir]; ok {
return false
@@ -269,6 +299,12 @@
if len(b.GetBazelLabel(ctx, ctx.Module())) == 0 {
return false
}
+ if GenerateCcLibraryStaticOnly(ctx) {
+ // Don't use partially-converted cc_library targets in mixed builds,
+ // since mixed builds would generally rely on both static and shared
+ // variants of a cc_library.
+ return false
+ }
return !mixedBuildsDisabled[ctx.Module().Name()]
}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 4280bc3..f4b2a7c 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -100,6 +100,10 @@
return labels
}
+func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
+ return BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes[0]
+}
+
// BazelLabelForModuleSrc expects a list of path (relative to local module directory) and module
// references (":<module>") and returns a bazel.LabelList{} containing the resolved references in
// paths, relative to the local module, or Bazel-labels (absolute if in a different package or
diff --git a/android/image.go b/android/image.go
index 1a1a423..66101be 100644
--- a/android/image.go
+++ b/android/image.go
@@ -30,6 +30,10 @@
// vendor ramdisk partition).
VendorRamdiskVariantNeeded(ctx BaseModuleContext) bool
+ // DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the
+ // debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk).
+ DebugRamdiskVariantNeeded(ctx BaseModuleContext) bool
+
// RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the
// recovery partition).
RecoveryVariantNeeded(ctx BaseModuleContext) bool
@@ -60,6 +64,9 @@
// VendorRamdiskVariation means a module to be installed to vendor ramdisk image.
VendorRamdiskVariation string = "vendor_ramdisk"
+
+ // DebugRamdiskVariation means a module to be installed to debug ramdisk image.
+ DebugRamdiskVariation string = "debug_ramdisk"
)
// imageMutator creates variants for modules that implement the ImageInterface that
@@ -83,6 +90,9 @@
if m.VendorRamdiskVariantNeeded(ctx) {
variations = append(variations, VendorRamdiskVariation)
}
+ if m.DebugRamdiskVariantNeeded(ctx) {
+ variations = append(variations, DebugRamdiskVariation)
+ }
if m.RecoveryVariantNeeded(ctx) {
variations = append(variations, RecoveryVariation)
}
diff --git a/android/module.go b/android/module.go
index fdb5290..99606d1 100644
--- a/android/module.go
+++ b/android/module.go
@@ -393,6 +393,7 @@
InstallInSanitizerDir() bool
InstallInRamdisk() bool
InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -450,6 +451,7 @@
InstallInSanitizerDir() bool
InstallInRamdisk() bool
InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -753,6 +755,9 @@
// Whether this module is installed to vendor ramdisk
Vendor_ramdisk *bool
+ // Whether this module is installed to debug ramdisk
+ Debug_ramdisk *bool
+
// Whether this module is built for non-native architectures (also known as native bridge binary)
Native_bridge_supported *bool `android:"arch_variant"`
@@ -1540,6 +1545,10 @@
return Bool(m.commonProperties.Vendor_ramdisk)
}
+func (m *ModuleBase) InstallInDebugRamdisk() bool {
+ return Bool(m.commonProperties.Debug_ramdisk)
+}
+
func (m *ModuleBase) InstallInRecovery() bool {
return Bool(m.commonProperties.Recovery)
}
@@ -1593,6 +1602,10 @@
return m.base().commonProperties.ImageVariation == VendorRamdiskVariation
}
+func (m *ModuleBase) InDebugRamdisk() bool {
+ return m.base().commonProperties.ImageVariation == DebugRamdiskVariation
+}
+
func (m *ModuleBase) InRecovery() bool {
return m.base().commonProperties.ImageVariation == RecoveryVariation
}
@@ -2576,6 +2589,10 @@
return m.module.InstallInVendorRamdisk()
}
+func (m *moduleContext) InstallInDebugRamdisk() bool {
+ return m.module.InstallInDebugRamdisk()
+}
+
func (m *moduleContext) InstallInRecovery() bool {
return m.module.InstallInRecovery()
}
diff --git a/android/paths.go b/android/paths.go
index 93c5684..b934687 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -106,6 +106,7 @@
InstallInSanitizerDir() bool
InstallInRamdisk() bool
InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
@@ -1689,6 +1690,8 @@
if !ctx.InstallInRoot() {
partition += "/system"
}
+ } else if ctx.InstallInDebugRamdisk() {
+ partition = "debug_ramdisk"
} else if ctx.InstallInRecovery() {
if ctx.InstallInRoot() {
partition = "recovery/root"
@@ -1859,6 +1862,7 @@
inSanitizerDir bool
inRamdisk bool
inVendorRamdisk bool
+ inDebugRamdisk bool
inRecovery bool
inRoot bool
forceOS *OsType
@@ -1891,6 +1895,10 @@
return m.inVendorRamdisk
}
+func (m testModuleInstallPathContext) InstallInDebugRamdisk() bool {
+ return m.inDebugRamdisk
+}
+
func (m testModuleInstallPathContext) InstallInRecovery() bool {
return m.inRecovery
}
diff --git a/android/paths_test.go b/android/paths_test.go
index 6ec75b4..f8ccc77 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -395,6 +395,19 @@
partitionDir: "target/product/test_device/vendor_ramdisk",
},
{
+ name: "debug_ramdisk binary",
+ ctx: &testModuleInstallPathContext{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inDebugRamdisk: true,
+ },
+ in: []string{"my_test"},
+ out: "target/product/test_device/debug_ramdisk/my_test",
+ partitionDir: "target/product/test_device/debug_ramdisk",
+ },
+ {
name: "system native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 06d3b54..ebf0833 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -118,10 +118,6 @@
seenDataOutPaths := make(map[string]bool)
for _, fi := range a.filesInfo {
- if ccMod, ok := fi.module.(*cc.Module); ok && ccMod.Properties.HideFromMake {
- continue
- }
-
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
moduleName := a.fullModuleName(apexBundleName, &fi)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 956b8d9..08d82e9 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6519,6 +6519,15 @@
min_sdk_version: "current",
}
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["some-art-lib"],
+ apex_available: [
+ "com.android.art.debug",
+ ],
+ }
+
apex_key {
name: "com.android.art.debug.key",
}
@@ -6651,14 +6660,14 @@
})
t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
+ err := `ArtApexJars expects this to be in apex "some-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
// Update the dexpreopt ArtApexJars directly.
preparer := prepareSetArtJars("some-updatable-apex:some-updatable-apex-lib")
testNoUpdatableJarsInBootImage(t, err, preparer)
})
t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
- err := `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
+ err := `ArtApexJars expects this to be in apex "some-non-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
// Update the dexpreopt ArtApexJars directly.
preparer := prepareSetArtJars("some-non-updatable-apex:some-non-updatable-apex-lib")
testNoUpdatableJarsInBootImage(t, err, preparer)
@@ -6688,7 +6697,7 @@
})
t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
- err := `module "some-platform-lib" is not allowed in the ART boot image`
+ err := `ArtApexJars is invalid as it requests a platform variant of "some-platform-lib"`
// Update the dexpreopt ArtApexJars directly.
preparer := prepareSetArtJars("platform:some-platform-lib")
testNoUpdatableJarsInBootImage(t, err, preparer)
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 3d39d34..e2b320c 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -94,6 +94,8 @@
bootclasspath_fragment {
name: "art-bootclasspath-fragment",
image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["baz", "quuz"],
apex_available: [
"com.android.art",
],
@@ -405,6 +407,8 @@
prebuilt_bootclasspath_fragment {
name: "mybootclasspathfragment",
image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["foo", "bar"],
apex_available: [
"com.android.art",
],
diff --git a/bazel/properties.go b/bazel/properties.go
index 037150d..a71b12b 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -227,6 +227,51 @@
HasConfigurableValues() bool
}
+// Represents an attribute whose value is a single label
+type LabelAttribute struct {
+ Value Label
+ X86 Label
+ X86_64 Label
+ Arm Label
+ Arm64 Label
+}
+
+func (attr *LabelAttribute) GetValueForArch(arch string) Label {
+ switch arch {
+ case ARCH_ARM:
+ return attr.Arm
+ case ARCH_ARM64:
+ return attr.Arm64
+ case ARCH_X86:
+ return attr.X86
+ case ARCH_X86_64:
+ return attr.X86_64
+ case CONDITIONS_DEFAULT:
+ return attr.Value
+ default:
+ panic("Invalid arch type")
+ }
+}
+
+func (attr *LabelAttribute) SetValueForArch(arch string, value Label) {
+ switch arch {
+ case ARCH_ARM:
+ attr.Arm = value
+ case ARCH_ARM64:
+ attr.Arm64 = value
+ case ARCH_X86:
+ attr.X86 = value
+ case ARCH_X86_64:
+ attr.X86_64 = value
+ default:
+ panic("Invalid arch type")
+ }
+}
+
+func (attr LabelAttribute) HasConfigurableValues() bool {
+ return attr.Arm.Label != "" || attr.Arm64.Label != "" || attr.X86.Label != "" || attr.X86_64.Label != ""
+}
+
// Arch-specific label_list typed Bazel attribute values. This should correspond
// to the types of architectures supported for compilation in arch.go.
type labelListArchValues struct {
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index f1bf648..cf6994f 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -18,7 +18,6 @@
"android/soong/android"
"fmt"
"os"
- "strings"
)
// Codegen is the backend of bp2build. The code generator is responsible for
@@ -36,18 +35,12 @@
for _, f := range filesToWrite {
p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename)
if err := writeFile(ctx, p, f.Contents); err != nil {
- fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)
+ panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err))
}
// if these generated files are modified, regenerate on next run.
generatedBuildFiles = append(generatedBuildFiles, p.String())
}
- // The MANIFEST file contains the full list of files generated by bp2build, excluding itself.
- // Its purpose is for downstream tools to understand the set of files converted by bp2build.
- manifestFile := outputDir.Join(ctx, "MANIFEST")
- writeFile(ctx, manifestFile, strings.Join(generatedBuildFiles, "\n"))
- generatedBuildFiles = append(generatedBuildFiles, manifestFile.String())
-
return metrics
}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 08790d1..bddc524 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -519,9 +519,7 @@
case reflect.Struct:
valueIsZero := true
for i := 0; i < value.NumField(); i++ {
- if value.Field(i).CanSet() {
- valueIsZero = valueIsZero && isZero(value.Field(i))
- }
+ valueIsZero = valueIsZero && isZero(value.Field(i))
}
return valueIsZero
case reflect.Ptr:
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index aa8200b..0551a18 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -277,6 +277,31 @@
static_deps_for_shared = [":b"],
)`},
},
+ {
+ description: "cc_library non-configured version script",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "a",
+ srcs: ["a.cpp"],
+ version_script: "v.map",
+ bazel_module: { bp2build_available: true },
+}
+`,
+ },
+ bp: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{`cc_library(
+ name = "a",
+ copts = ["-Ifoo/bar"],
+ srcs = ["a.cpp"],
+ version_script = "v.map",
+)`},
+ },
}
dir := "."
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index e8235d5..bff9b07 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -746,6 +746,172 @@
linkstatic = True,
)`},
},
+ {
+ description: "cc_library_static 1 multilib srcs and exclude_srcs",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{
+ "common.c": "",
+ "for-lib32.c": "",
+ "not-for-lib32.c": "",
+ },
+ bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "foo_static",
+ srcs: ["common.c", "not-for-*.c"],
+ multilib: {
+ lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
+ },
+} `,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo_static",
+ copts = ["-I."],
+ linkstatic = True,
+ srcs = ["common.c"] + select({
+ "//build/bazel/platforms/arch:arm": ["for-lib32.c"],
+ "//build/bazel/platforms/arch:x86": ["for-lib32.c"],
+ "//conditions:default": ["not-for-lib32.c"],
+ }),
+)`},
+ },
+ {
+ description: "cc_library_static 2 multilib srcs and exclude_srcs",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{
+ "common.c": "",
+ "for-lib32.c": "",
+ "for-lib64.c": "",
+ "not-for-lib32.c": "",
+ "not-for-lib64.c": "",
+ },
+ bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "foo_static2",
+ srcs: ["common.c", "not-for-*.c"],
+ multilib: {
+ lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
+ lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
+ },
+} `,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo_static2",
+ copts = ["-I."],
+ linkstatic = True,
+ srcs = ["common.c"] + select({
+ "//build/bazel/platforms/arch:arm": [
+ "for-lib32.c",
+ "not-for-lib64.c",
+ ],
+ "//build/bazel/platforms/arch:arm64": [
+ "for-lib64.c",
+ "not-for-lib32.c",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ "for-lib32.c",
+ "not-for-lib64.c",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ "for-lib64.c",
+ "not-for-lib32.c",
+ ],
+ "//conditions:default": [
+ "not-for-lib32.c",
+ "not-for-lib64.c",
+ ],
+ }),
+)`},
+ },
+ {
+ description: "cc_library_static arch and multilib srcs and exclude_srcs",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{
+ "common.c": "",
+ "for-arm.c": "",
+ "for-arm64.c": "",
+ "for-x86.c": "",
+ "for-x86_64.c": "",
+ "for-lib32.c": "",
+ "for-lib64.c": "",
+ "not-for-arm.c": "",
+ "not-for-arm64.c": "",
+ "not-for-x86.c": "",
+ "not-for-x86_64.c": "",
+ "not-for-lib32.c": "",
+ "not-for-lib64.c": "",
+ "not-for-everything.c": "",
+ },
+ bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "foo_static3",
+ srcs: ["common.c", "not-for-*.c"],
+ exclude_srcs: ["not-for-everything.c"],
+ arch: {
+ arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+ arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
+ x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
+ x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
+ },
+ multilib: {
+ lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
+ lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
+ },
+}`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo_static3",
+ copts = ["-I."],
+ linkstatic = True,
+ srcs = ["common.c"] + select({
+ "//build/bazel/platforms/arch:arm": [
+ "for-arm.c",
+ "for-lib32.c",
+ "not-for-arm64.c",
+ "not-for-lib64.c",
+ "not-for-x86.c",
+ "not-for-x86_64.c",
+ ],
+ "//build/bazel/platforms/arch:arm64": [
+ "for-arm64.c",
+ "for-lib64.c",
+ "not-for-arm.c",
+ "not-for-lib32.c",
+ "not-for-x86.c",
+ "not-for-x86_64.c",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ "for-lib32.c",
+ "for-x86.c",
+ "not-for-arm.c",
+ "not-for-arm64.c",
+ "not-for-lib64.c",
+ "not-for-x86_64.c",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ "for-lib64.c",
+ "for-x86_64.c",
+ "not-for-arm.c",
+ "not-for-arm64.c",
+ "not-for-lib32.c",
+ "not-for-x86.c",
+ ],
+ "//conditions:default": [
+ "not-for-arm.c",
+ "not-for-arm64.c",
+ "not-for-lib32.c",
+ "not-for-lib64.c",
+ "not-for-x86.c",
+ "not-for-x86_64.c",
+ ],
+ }),
+)`},
+ },
}
dir := "."
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 52afb55..95a2747 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -30,6 +30,11 @@
return value, archSelects, osSelects
}
+func getLabelValue(label bazel.LabelAttribute) (reflect.Value, selects, selects) {
+ value := reflect.ValueOf(label.Value)
+ return value, nil, nil
+}
+
func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, selects, selects) {
value := reflect.ValueOf(list.Value.Includes)
if !list.HasConfigurableValues() {
@@ -54,21 +59,30 @@
func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
var value reflect.Value
var archSelects, osSelects selects
-
+ var defaultSelectValue string
switch list := v.(type) {
case bazel.StringListAttribute:
value, archSelects, osSelects = getStringListValues(list)
+ defaultSelectValue = "[]"
case bazel.LabelListAttribute:
value, archSelects, osSelects = getLabelListValues(list)
+ defaultSelectValue = "[]"
+ case bazel.LabelAttribute:
+ value, archSelects, osSelects = getLabelValue(list)
+ defaultSelectValue = "None"
default:
return "", fmt.Errorf("Not a supported Bazel attribute type: %s", v)
}
- ret, err := prettyPrint(value, indent)
- if err != nil {
- return ret, err
- }
+ ret := ""
+ if value.Kind() != reflect.Invalid {
+ s, err := prettyPrint(value, indent)
+ if err != nil {
+ return ret, err
+ }
+ ret += s
+ }
// Convenience function to append selects components to an attribute value.
appendSelects := func(selectsData selects, defaultValue, s string) (string, error) {
selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent)
@@ -83,12 +97,12 @@
return s, nil
}
- ret, err = appendSelects(archSelects, "[]", ret)
+ ret, err := appendSelects(archSelects, defaultSelectValue, ret)
if err != nil {
return "", err
}
- ret, err = appendSelects(osSelects, "[]", ret)
+ ret, err = appendSelects(osSelects, defaultSelectValue, ret)
return ret, err
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 452f6ed..b925682 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -142,7 +142,7 @@
paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths))
- for arch, props := range m.GetArchProperties(&customProps{}) {
+ for arch, props := range m.GetArchProperties(ctx, &customProps{}) {
if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 70b5259..e58d166 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -580,20 +580,6 @@
entries.Class = "SHARED_LIBRARIES"
}
-func (c *vendorPublicLibraryStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- entries.Class = "SHARED_LIBRARIES"
- entries.SubName = vendorPublicLibrarySuffix
-
- entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- c.libraryDecorator.androidMkWriteExportedFlags(entries)
- _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
-
- entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
- entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
- })
-}
-
func (p *prebuiltLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
if p.properties.Check_elf_files != nil {
diff --git a/cc/bp2build.go b/cc/bp2build.go
index a4db79f..1433f6f 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -58,7 +58,7 @@
}
}
- for _, p := range module.GetArchProperties(&BaseLinkerProperties{}) {
+ for _, p := range module.GetArchProperties(ctx, &BaseLinkerProperties{}) {
// arch specific linker props
if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok {
allDeps = append(allDeps, baseLinkerProps.Header_libs...)
@@ -198,7 +198,7 @@
copts.Value = append(copts.Value, includeFlag("."))
}
- for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
+ for arch, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
@@ -215,7 +215,7 @@
// After going through all archs, delete the duplicate files in the arch
// values that are already in the base srcs.Value.
- for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
+ for arch, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
if _, ok := props.(*BaseCompilerProperties); ok {
srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcs.GetValueForArch(arch.Name), srcs.Value))
}
@@ -246,15 +246,17 @@
// Convenience struct to hold all attributes parsed from linker properties.
type linkerAttributes struct {
- deps bazel.LabelListAttribute
- linkopts bazel.StringListAttribute
+ deps bazel.LabelListAttribute
+ linkopts bazel.StringListAttribute
+ versionScript bazel.LabelAttribute
}
-// bp2BuildParseLinkerProps creates a label list attribute containing the header library deps of a module, including
+// bp2BuildParseLinkerProps parses the linker properties of a module, including
// configurable attribute values.
func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) linkerAttributes {
var deps bazel.LabelListAttribute
var linkopts bazel.StringListAttribute
+ var versionScript bazel.LabelAttribute
for _, linkerProps := range module.linker.linkerProps() {
if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
@@ -265,11 +267,15 @@
libs = android.SortedUniqueStrings(libs)
deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, libs))
linkopts.Value = baseLinkerProps.Ldflags
+
+ if baseLinkerProps.Version_script != nil {
+ versionScript.Value = android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)
+ }
break
}
}
- for arch, p := range module.GetArchProperties(&BaseLinkerProperties{}) {
+ for arch, p := range module.GetArchProperties(ctx, &BaseLinkerProperties{}) {
if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok {
libs := baseLinkerProps.Header_libs
libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
@@ -278,6 +284,10 @@
libs = android.SortedUniqueStrings(libs)
deps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, libs))
linkopts.SetValueForArch(arch.Name, baseLinkerProps.Ldflags)
+ if baseLinkerProps.Version_script != nil {
+ versionScript.SetValueForArch(arch.Name,
+ android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
+ }
}
}
@@ -294,8 +304,9 @@
}
return linkerAttributes{
- deps: deps,
- linkopts: linkopts,
+ deps: deps,
+ linkopts: linkopts,
+ versionScript: versionScript,
}
}
@@ -334,7 +345,7 @@
includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)
includeDirsAttribute := bazel.MakeStringListAttribute(includeDirs)
- for arch, props := range module.GetArchProperties(&FlagExporterProperties{}) {
+ for arch, props := range module.GetArchProperties(ctx, &FlagExporterProperties{}) {
if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
archIncludeDirs := flagExporterProperties.Export_system_include_dirs
archIncludeDirs = append(archIncludeDirs, flagExporterProperties.Export_include_dirs...)
diff --git a/cc/builder.go b/cc/builder.go
index ad7e1e6..0542015 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -126,15 +126,22 @@
_ = pctx.SourcePathVariable("stripPath", "build/soong/scripts/strip.sh")
_ = pctx.SourcePathVariable("xzCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/xz")
+ _ = pctx.SourcePathVariable("createMiniDebugInfo", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/create_minidebuginfo")
// Rule to invoke `strip` (to discard symbols and data from object files).
strip = pctx.AndroidStaticRule("strip",
blueprint.RuleParams{
- Depfile: "${out}.d",
- Deps: blueprint.DepsGCC,
- Command: "XZ=$xzCmd CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
- CommandDeps: []string{"$stripPath", "$xzCmd"},
- Pool: darwinStripPool,
+ Depfile: "${out}.d",
+ Deps: blueprint.DepsGCC,
+ Command: "XZ=$xzCmd CREATE_MINIDEBUGINFO=$createMiniDebugInfo CLANG_BIN=${config.ClangBin} $stripPath ${args} -i ${in} -o ${out} -d ${out}.d",
+ CommandDeps: func() []string {
+ if runtime.GOOS != "darwin" {
+ return []string{"$stripPath", "$xzCmd", "$createMiniDebugInfo"}
+ } else {
+ return []string{"$stripPath", "$xzCmd"}
+ }
+ }(),
+ Pool: darwinStripPool,
},
"args", "crossCompile")
diff --git a/cc/cc.go b/cc/cc.go
index 3ba5366..16a49d3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -447,6 +447,10 @@
// IsVNDKProduct is set if a VNDK module sets the product_available property.
IsVNDKProduct bool `blueprint:"mutated"`
+
+ // IsVendorPublicLibrary is set for the core and product variants of a library that has
+ // vendor_public_library stubs.
+ IsVendorPublicLibrary bool `blueprint:"mutated"`
}
// ModuleContextIntf is an interface (on a module context helper) consisting of functions related
@@ -475,6 +479,7 @@
isVndk() bool
isVndkSp() bool
IsVndkExt() bool
+ IsVendorPublicLibrary() bool
inProduct() bool
inVendor() bool
inRamdisk() bool
@@ -1126,6 +1131,16 @@
return lib != nil && (lib.hasLLNDKStubs() || lib.hasLLNDKHeaders())
}
+func (m *Module) NeedsVendorPublicLibraryVariants() bool {
+ lib := moduleLibraryInterface(m)
+ return lib != nil && (lib.hasVendorPublicLibrary())
+}
+
+// IsVendorPublicLibrary returns true for vendor public libraries.
+func (c *Module) IsVendorPublicLibrary() bool {
+ return c.VendorProperties.IsVendorPublicLibrary
+}
+
// isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs
// and does not set llndk.vendor_available: false.
func (c *Module) isImplementationForLLNDKPublic() bool {
@@ -1437,6 +1452,10 @@
return ctx.mod.IsVndkExt()
}
+func (ctx *moduleContextImpl) IsVendorPublicLibrary() bool {
+ return ctx.mod.IsVendorPublicLibrary()
+}
+
func (ctx *moduleContextImpl) mustUseVendorVariant() bool {
return ctx.mod.MustUseVendorVariant()
}
@@ -1599,6 +1618,8 @@
// added for product variant only when we have vendor and product variants with core
// variant. The suffix is not added for vendor-only or product-only module.
c.Properties.SubName += c.getNameSuffixWithVndkVersion(actx)
+ } else if c.IsVendorPublicLibrary() {
+ c.Properties.SubName += vendorPublicLibrarySuffix
} else if _, ok := c.linker.(*vndkPrebuiltLibraryDecorator); ok {
// .vendor suffix is added for backward compatibility with VNDK snapshot whose names with
// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
@@ -2043,8 +2064,6 @@
// The caller can then know to add the variantLibs dependencies differently from the
// nonvariantLibs
- vendorPublicLibraries := vendorPublicLibraries(actx.Config())
-
rewriteLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
variantLibs = []string{}
nonvariantLibs = []string{}
@@ -2055,16 +2074,6 @@
nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
} else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
- } else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
- vendorPublicLib := name + vendorPublicLibrarySuffix
- if actx.OtherModuleExists(vendorPublicLib) {
- nonvariantLibs = append(nonvariantLibs, vendorPublicLib)
- } else {
- // This can happen if vendor_public_library module is defined in a
- // namespace that isn't visible to the current module. In that case,
- // link to the original library.
- nonvariantLibs = append(nonvariantLibs, name)
- }
} else if ctx.useVndk() {
nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
} else {
@@ -2921,13 +2930,9 @@
}
func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableInterface, depName string) string {
-
- vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
libName := baseLibName(depName)
ccDepModule, _ := ccDep.(*Module)
isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
- isVendorPublicLib := inList(libName, *vendorPublicLibraries)
nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
if ccDepModule != nil {
@@ -2949,8 +2954,6 @@
// The vendor and product modules in Make will have been renamed to not conflict with the
// core module, so update the dependency name here accordingly.
return libName + ccDep.SubName()
- } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
- return libName + vendorPublicLibrarySuffix
} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
return libName + ramdiskSuffix
} else if ccDep.InVendorRamdisk() && !ccDep.OnlyInVendorRamdisk() {
diff --git a/cc/genrule.go b/cc/genrule.go
index ca4fda7..82d7205 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -75,6 +75,10 @@
return Bool(g.Vendor_ramdisk_available)
}
+func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
// If the build is using a snapshot, the recovery variant under AOSP directories
// is not needed.
diff --git a/cc/image.go b/cc/image.go
index 5593afc..5d41717 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -452,6 +452,17 @@
if productVndkVersion != "" {
productVariants = append(productVariants, productVndkVersion)
}
+ } else if m.NeedsVendorPublicLibraryVariants() {
+ // A vendor public library has the implementation on /vendor, with stub variants
+ // for system and product.
+ coreVariantNeeded = true
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ if platformVndkVersion != "" {
+ productVariants = append(productVariants, platformVndkVersion)
+ }
+ if productVndkVersion != "" {
+ productVariants = append(productVariants, productVndkVersion)
+ }
} else if boardVndkVersion == "" {
// If the device isn't compiling against the VNDK, we always
// use the core mode.
@@ -597,6 +608,10 @@
return c.Properties.VendorRamdiskVariantNeeded
}
+func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return c.Properties.RecoveryVariantNeeded
}
@@ -677,4 +692,9 @@
m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
squashProductSrcs(m)
}
+
+ if c.NeedsVendorPublicLibraryVariants() &&
+ (variant == android.CoreVariation || strings.HasPrefix(variant, ProductVariationPrefix)) {
+ c.VendorProperties.IsVendorPublicLibrary = true
+ }
}
diff --git a/cc/library.go b/cc/library.go
index 4cd1b09..7b631fa 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -120,6 +120,9 @@
// If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from
// the module pointed to by llndk_stubs if it is set.
Llndk llndkLibraryProperties
+
+ // If this is a vendor public library, properties to describe the vendor public library stubs.
+ Vendor_public_library vendorPublicLibraryProperties
}
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
@@ -225,6 +228,7 @@
User_link_flags bazel.StringListAttribute
Includes bazel.StringListAttribute
Static_deps_for_shared bazel.LabelListAttribute
+ Version_script bazel.LabelAttribute
}
type bazelCcLibrary struct {
@@ -255,6 +259,14 @@
return
}
+ // For some cc_library modules, their static variants are ready to be
+ // converted, but not their shared variants. For these modules, delegate to
+ // the cc_library_static bp2build converter temporarily instead.
+ if android.GenerateCcLibraryStaticOnly(ctx) {
+ ccLibraryStaticBp2BuildInternal(ctx, m)
+ return
+ }
+
sharedAttrs := bp2BuildParseSharedProps(ctx, m)
staticAttrs := bp2BuildParseStaticProps(ctx, m)
compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
@@ -270,6 +282,7 @@
Copts: compilerAttrs.copts,
Linkopts: linkerAttrs.linkopts,
Deps: linkerAttrs.deps,
+ Version_script: linkerAttrs.versionScript,
Static_deps_for_shared: sharedAttrs.staticDeps,
Includes: exportedIncludes,
}
@@ -786,6 +799,13 @@
}
return objs
}
+ if ctx.IsVendorPublicLibrary() {
+ objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Vendor_public_library.Symbol_file), "current", "")
+ if !Bool(library.Properties.Vendor_public_library.Unversioned) {
+ library.versionScriptPath = android.OptionalPathForPath(versionScript)
+ }
+ return objs
+ }
if library.buildStubs() {
symbolFile := String(library.Properties.Stubs.Symbol_file)
if symbolFile != "" && !strings.HasSuffix(symbolFile, ".map.txt") {
@@ -883,6 +903,7 @@
implementationModuleName(name string) string
hasLLNDKStubs() bool
hasLLNDKHeaders() bool
+ hasVendorPublicLibrary() bool
}
var _ libraryInterface = (*libraryDecorator)(nil)
@@ -978,6 +999,12 @@
deps.ReexportHeaderLibHeaders = append([]string(nil), library.Properties.Llndk.Export_llndk_headers...)
return deps
}
+ if ctx.IsVendorPublicLibrary() {
+ headers := library.Properties.Vendor_public_library.Export_public_headers
+ deps.HeaderLibs = append([]string(nil), headers...)
+ deps.ReexportHeaderLibHeaders = append([]string(nil), headers...)
+ return deps
+ }
if library.static() {
// Compare with nil because an empty list needs to be propagated.
@@ -1434,6 +1461,14 @@
}
}
+ if ctx.IsVendorPublicLibrary() {
+ // override the module's export_include_dirs with vendor_public_library.override_export_include_dirs
+ // if it is set.
+ if override := library.Properties.Vendor_public_library.Override_export_include_dirs; override != nil {
+ library.flagExporter.Properties.Export_include_dirs = override
+ }
+ }
+
// Linking this library consists of linking `deps.Objs` (.o files in dependencies
// of this library), together with `objs` (.o files created by compiling this
// library).
@@ -1695,6 +1730,12 @@
return Bool(library.Properties.Llndk.Llndk_headers)
}
+// hasVendorPublicLibrary returns true if this cc_library module has a variant that will build
+// vendor public library stubs.
+func (library *libraryDecorator) hasVendorPublicLibrary() bool {
+ return String(library.Properties.Vendor_public_library.Symbol_file) != ""
+}
+
func (library *libraryDecorator) implementationModuleName(name string) string {
return name
}
@@ -1994,11 +2035,12 @@
m := mctx.Module().(*Module)
isLLNDK := m.IsLlndk()
+ isVendorPublicLibrary := m.IsVendorPublicLibrary()
modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
- if variants[i] != "" || isLLNDK {
+ if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
// A stubs or LLNDK stubs variant.
c := m.(*Module)
c.sanitize = nil
@@ -2171,6 +2213,28 @@
return module
}
+func ccLibraryStaticBp2BuildInternal(ctx android.TopDownMutatorContext, module *Module) {
+ compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
+ linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
+
+ attrs := &bazelCcLibraryStaticAttributes{
+ Copts: compilerAttrs.copts,
+ Srcs: compilerAttrs.srcs,
+ Deps: linkerAttrs.deps,
+ Linkopts: linkerAttrs.linkopts,
+ Linkstatic: true,
+ Includes: exportedIncludes,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_static",
+ Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(BazelCcLibraryStaticFactory, module.Name(), props, attrs)
+}
+
func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) {
module, ok := ctx.Module().(*Module)
if !ok {
@@ -2184,24 +2248,7 @@
return
}
- compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
- linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
-
- attrs := &bazelCcLibraryStaticAttributes{
- Copts: compilerAttrs.copts,
- Srcs: compilerAttrs.srcs,
- Deps: linkerAttrs.deps,
- Linkstatic: true,
- Includes: exportedIncludes,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library_static",
- Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
- }
-
- ctx.CreateBazelTargetModule(BazelCcLibraryStaticFactory, module.Name(), props, attrs)
+ ccLibraryStaticBp2BuildInternal(ctx, module)
}
func (m *bazelCcLibraryStatic) Name() string {
diff --git a/cc/linkable.go b/cc/linkable.go
index 17526b4..40a9d8b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -109,6 +109,9 @@
// NeedsLlndkVariants returns true if this module has LLNDK stubs or provides LLNDK headers.
NeedsLlndkVariants() bool
+ // NeedsVendorPublicLibraryVariants returns true if this module has vendor public library stubs.
+ NeedsVendorPublicLibraryVariants() bool
+
UseVndk() bool
MustUseVendorVariant() bool
IsVndk() bool
diff --git a/cc/makevars.go b/cc/makevars.go
index 923472a..2b7bb9b 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -71,8 +71,6 @@
}
func makeVarsProvider(ctx android.MakeVarsContext) {
- vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}")
ctx.Strict("LLVM_PREBUILTS_VERSION", "${config.ClangVersion}")
ctx.Strict("LLVM_PREBUILTS_BASE", "${config.ClangBase}")
@@ -106,7 +104,7 @@
ctx.VisitAllModules(func(module android.Module) {
if ccModule, ok := module.(*Module); ok {
baseName := ccModule.BaseModuleName()
- if inList(baseName, *vendorPublicLibraries) && module.ExportedToMake() {
+ if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() {
if !inList(baseName, exportedVendorPublicLibraries) {
exportedVendorPublicLibraries = append(exportedVendorPublicLibraries, baseName)
}
@@ -153,6 +151,7 @@
ctx.Strict("SOONG_STRIP_PATH", "${stripPath}")
ctx.Strict("XZ", "${xzCmd}")
+ ctx.Strict("CREATE_MINIDEBUGINFO", "${createMiniDebugInfo}")
includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes}")
if err != nil {
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index c12ad79..885a0ce 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -308,6 +308,10 @@
return false
}
+func (s *snapshot) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (s *snapshot) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
diff --git a/cc/testing.go b/cc/testing.go
index ca6a0fa..15f7ebb 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -556,7 +556,6 @@
ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
- ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
RegisterVndkLibraryTxtTypes(ctx)
@@ -672,7 +671,6 @@
ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
- ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index 394e322..65a2b0c 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -14,26 +14,10 @@
package cc
-import (
- "strings"
- "sync"
-
- "android/soong/android"
-)
-
var (
vendorPublicLibrarySuffix = ".vendorpublic"
-
- vendorPublicLibrariesKey = android.NewOnceKey("vendorPublicLibraries")
- vendorPublicLibrariesLock sync.Mutex
)
-func vendorPublicLibraries(config android.Config) *[]string {
- return config.Once(vendorPublicLibrariesKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
-}
-
// Creates a stub shared library for a vendor public library. Vendor public libraries
// are vendor libraries (owned by them and installed to /vendor partition) that are
// exposed to Android apps via JNI. The libraries are made public by being listed in
@@ -64,105 +48,9 @@
// list of header libs to re-export include directories from.
Export_public_headers []string `android:"arch_variant"`
-}
-type vendorPublicLibraryStubDecorator struct {
- *libraryDecorator
-
- Properties vendorPublicLibraryProperties
-
- versionScriptPath android.ModuleGenPath
-}
-
-func (stub *vendorPublicLibraryStubDecorator) Name(name string) string {
- return name + vendorPublicLibrarySuffix
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compilerInit(ctx BaseModuleContext) {
- stub.baseCompiler.compilerInit(ctx)
-
- name := ctx.baseModuleName()
- if strings.HasSuffix(name, vendorPublicLibrarySuffix) {
- ctx.PropertyErrorf("name", "Do not append %q manually, just use the base name", vendorPublicLibrarySuffix)
- }
-
- vendorPublicLibrariesLock.Lock()
- defer vendorPublicLibrariesLock.Unlock()
- vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
- for _, lib := range *vendorPublicLibraries {
- if lib == name {
- return
- }
- }
- *vendorPublicLibraries = append(*vendorPublicLibraries, name)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
- flags = stub.baseCompiler.compilerFlags(ctx, flags, deps)
- return addStubLibraryCompilerFlags(flags)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), "current", "")
- stub.versionScriptPath = versionScript
- return objs
-}
-
-func (stub *vendorPublicLibraryStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
- headers := stub.Properties.Export_public_headers
- deps.HeaderLibs = append(deps.HeaderLibs, headers...)
- deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...)
- return deps
-}
-
-func (stub *vendorPublicLibraryStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- stub.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), vendorPublicLibrarySuffix)
- return stub.libraryDecorator.linkerFlags(ctx, flags)
-}
-
-func (stub *vendorPublicLibraryStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps,
- objs Objects) android.Path {
- if !Bool(stub.Properties.Unversioned) {
- linkerScriptFlag := "-Wl,--version-script," + stub.versionScriptPath.String()
- flags.Local.LdFlags = append(flags.Local.LdFlags, linkerScriptFlag)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, stub.versionScriptPath)
- }
- return stub.libraryDecorator.link(ctx, flags, deps, objs)
-}
-
-// vendor_public_library creates a stub shared library for a vendor public
-// library. This stub library is a build-time only artifact that provides
-// symbols that are exposed from a vendor public library. Example:
-//
-// vendor_public_library {
-// name: "libfoo",
-// symbol_file: "libfoo.map.txt",
-// export_public_headers: ["libfoo_headers"],
-// }
-func vendorPublicLibraryFactory() android.Module {
- module, library := NewLibrary(android.DeviceSupported)
- library.BuildOnlyShared()
- module.stl = nil
- module.sanitize = nil
- library.disableStripping()
-
- stub := &vendorPublicLibraryStubDecorator{
- libraryDecorator: library,
- }
- module.compiler = stub
- module.linker = stub
- module.installer = nil
-
- module.AddProperties(
- &stub.Properties,
- &module.VendorProperties,
- &library.MutatedProperties,
- &library.flagExporter.Properties)
-
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- return module
-}
-
-func init() {
- android.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
+ // list of directories relative to the Blueprints file that willbe added to the include path
+ // (using -I) for any module that links against the LLNDK variant of this module, replacing
+ // any that were listed outside the llndk clause.
+ Override_export_include_dirs []string
}
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 9f2accf..01959b4 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -26,18 +26,16 @@
product_available: true,
export_include_dirs: ["my_include"],
}
- vendor_public_library {
- name: "libvendorpublic",
- product_available: true,
- symbol_file: "",
- export_public_headers: ["libvendorpublic_headers"],
- }
cc_library {
name: "libvendorpublic",
srcs: ["foo.c"],
vendor: true,
no_libcrt: true,
nocrt: true,
+ vendor_public_library: {
+ symbol_file: "libvendorpublic.map.txt",
+ export_public_headers: ["libvendorpublic_headers"],
+ },
}
cc_library {
@@ -81,7 +79,7 @@
// test if libsystem is linked to the stub
ld := ctx.ModuleForTests("libsystem", coreVariant).Rule("ld")
libflags := ld.Args["libFlags"]
- stubPaths := getOutputPaths(ctx, coreVariant, []string{"libvendorpublic" + vendorPublicLibrarySuffix})
+ stubPaths := getOutputPaths(ctx, coreVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libsystem must contain %#v, but was %#v", stubPaths[0], libflags)
}
@@ -89,7 +87,7 @@
// test if libsystem is linked to the stub
ld = ctx.ModuleForTests("libproduct", productVariant).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = getOutputPaths(ctx, productVariant, []string{"libvendorpublic" + vendorPublicLibrarySuffix})
+ stubPaths = getOutputPaths(ctx, productVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libproduct must contain %#v, but was %#v", stubPaths[0], libflags)
}
diff --git a/cmd/run_with_timeout/Android.bp b/cmd/run_with_timeout/Android.bp
new file mode 100644
index 0000000..76262cc
--- /dev/null
+++ b/cmd/run_with_timeout/Android.bp
@@ -0,0 +1,27 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "run_with_timeout",
+ srcs: [
+ "run_with_timeout.go",
+ ],
+ testSrcs: [
+ "run_with_timeout_test.go",
+ ],
+}
diff --git a/cmd/run_with_timeout/run_with_timeout.go b/cmd/run_with_timeout/run_with_timeout.go
new file mode 100644
index 0000000..f2caaab
--- /dev/null
+++ b/cmd/run_with_timeout/run_with_timeout.go
@@ -0,0 +1,143 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// 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.
+
+// run_with_timeout is a utility that can kill a wrapped command after a configurable timeout,
+// optionally running a command to collect debugging information first.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "sync"
+ "syscall"
+ "time"
+)
+
+var (
+ timeout = flag.Duration("timeout", 0, "time after which to kill command (example: 60s)")
+ onTimeoutCmd = flag.String("on_timeout", "", "command to run with `PID=<pid> sh -c` after timeout.")
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s [--timeout N] [--on_timeout CMD] -- command [args...]\n", os.Args[0])
+ flag.PrintDefaults()
+ fmt.Fprintln(os.Stderr, "run_with_timeout is a utility that can kill a wrapped command after a configurable timeout,")
+ fmt.Fprintln(os.Stderr, "optionally running a command to collect debugging information first.")
+
+ os.Exit(2)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if flag.NArg() < 1 {
+ fmt.Fprintln(os.Stderr, "command is required")
+ usage()
+ }
+
+ err := runWithTimeout(flag.Arg(0), flag.Args()[1:], *timeout, *onTimeoutCmd,
+ os.Stdin, os.Stdout, os.Stderr)
+ if err != nil {
+ if exitErr, ok := err.(*exec.ExitError); ok {
+ fmt.Fprintln(os.Stderr, "process exited with error:", exitErr.Error())
+ } else {
+ fmt.Fprintln(os.Stderr, "error:", err.Error())
+ }
+ os.Exit(1)
+ }
+}
+
+// concurrentWriter wraps a writer to make it thread-safe to call Write.
+type concurrentWriter struct {
+ w io.Writer
+ sync.Mutex
+}
+
+// Write writes the data to the wrapped writer with a lock to allow for concurrent calls.
+func (c *concurrentWriter) Write(data []byte) (n int, err error) {
+ c.Lock()
+ defer c.Unlock()
+ if c.w == nil {
+ return 0, nil
+ }
+ return c.w.Write(data)
+}
+
+// Close ends the concurrentWriter, causing future calls to Write to be no-ops. It does not close
+// the underlying writer.
+func (c *concurrentWriter) Close() {
+ c.Lock()
+ defer c.Unlock()
+ c.w = nil
+}
+
+func runWithTimeout(command string, args []string, timeout time.Duration, onTimeoutCmdStr string,
+ stdin io.Reader, stdout, stderr io.Writer) error {
+ cmd := exec.Command(command, args...)
+
+ // Wrap the writers in a locking writer so that cmd and onTimeoutCmd don't try to write to
+ // stdout or stderr concurrently.
+ concurrentStdout := &concurrentWriter{w: stdout}
+ concurrentStderr := &concurrentWriter{w: stderr}
+ defer concurrentStdout.Close()
+ defer concurrentStderr.Close()
+
+ cmd.Stdin, cmd.Stdout, cmd.Stderr = stdin, concurrentStdout, concurrentStderr
+ err := cmd.Start()
+ if err != nil {
+ return err
+ }
+
+ // waitCh will signal the subprocess exited.
+ waitCh := make(chan error)
+ go func() {
+ waitCh <- cmd.Wait()
+ }()
+
+ // timeoutCh will signal the subprocess timed out if timeout was set.
+ var timeoutCh <-chan time.Time = make(chan time.Time)
+ if timeout > 0 {
+ timeoutCh = time.After(timeout)
+ }
+
+ select {
+ case err := <-waitCh:
+ if exitErr, ok := err.(*exec.ExitError); ok {
+ return fmt.Errorf("process exited with error: %w", exitErr)
+ }
+ return err
+ case <-timeoutCh:
+ // Continue below.
+ }
+
+ // Process timed out before exiting.
+ defer cmd.Process.Signal(syscall.SIGKILL)
+
+ if onTimeoutCmdStr != "" {
+ onTimeoutCmd := exec.Command("sh", "-c", onTimeoutCmdStr)
+ onTimeoutCmd.Stdin, onTimeoutCmd.Stdout, onTimeoutCmd.Stderr = stdin, concurrentStdout, concurrentStderr
+ onTimeoutCmd.Env = append(os.Environ(), fmt.Sprintf("PID=%d", cmd.Process.Pid))
+ err := onTimeoutCmd.Run()
+ if err != nil {
+ return fmt.Errorf("on_timeout command %q exited with error: %w", onTimeoutCmdStr, err)
+ }
+ }
+
+ return fmt.Errorf("timed out after %s", timeout.String())
+}
diff --git a/cmd/run_with_timeout/run_with_timeout_test.go b/cmd/run_with_timeout/run_with_timeout_test.go
new file mode 100644
index 0000000..aebd336
--- /dev/null
+++ b/cmd/run_with_timeout/run_with_timeout_test.go
@@ -0,0 +1,94 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// 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 main
+
+import (
+ "bytes"
+ "io"
+ "testing"
+ "time"
+)
+
+func Test_runWithTimeout(t *testing.T) {
+ type args struct {
+ command string
+ args []string
+ timeout time.Duration
+ onTimeoutCmd string
+ stdin io.Reader
+ }
+ tests := []struct {
+ name string
+ args args
+ wantStdout string
+ wantStderr string
+ wantErr bool
+ }{
+ {
+ name: "no timeout",
+ args: args{
+ command: "echo",
+ args: []string{"foo"},
+ },
+ wantStdout: "foo\n",
+ },
+ {
+ name: "timeout not reached",
+ args: args{
+ command: "echo",
+ args: []string{"foo"},
+ timeout: 1 * time.Second,
+ },
+ wantStdout: "foo\n",
+ },
+ {
+ name: "timed out",
+ args: args{
+ command: "sh",
+ args: []string{"-c", "sleep 1 && echo foo"},
+ timeout: 1 * time.Millisecond,
+ },
+ wantErr: true,
+ },
+ {
+ name: "on_timeout command",
+ args: args{
+ command: "sh",
+ args: []string{"-c", "sleep 1 && echo foo"},
+ timeout: 1 * time.Millisecond,
+ onTimeoutCmd: "echo bar",
+ },
+ wantStdout: "bar\n",
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ stdout := &bytes.Buffer{}
+ stderr := &bytes.Buffer{}
+ err := runWithTimeout(tt.args.command, tt.args.args, tt.args.timeout, tt.args.onTimeoutCmd, tt.args.stdin, stdout, stderr)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("runWithTimeout() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if gotStdout := stdout.String(); gotStdout != tt.wantStdout {
+ t.Errorf("runWithTimeout() gotStdout = %v, want %v", gotStdout, tt.wantStdout)
+ }
+ if gotStderr := stderr.String(); gotStderr != tt.wantStderr {
+ t.Errorf("runWithTimeout() gotStderr = %v, want %v", gotStderr, tt.wantStderr)
+ }
+ })
+ }
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 3848205..628197c 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -134,7 +134,8 @@
profileInstalledPath := module.DexLocation + ".prof"
if !module.ProfileIsTextListing {
- rule.Command().FlagWithOutput("touch ", profilePath)
+ rule.Command().Text("rm -f").Output(profilePath)
+ rule.Command().Text("touch").Output(profilePath)
}
cmd := rule.Command().
@@ -174,7 +175,8 @@
profileInstalledPath := module.DexLocation + ".bprof"
if !module.ProfileIsTextListing {
- rule.Command().FlagWithOutput("touch ", profilePath)
+ rule.Command().Text("rm -f").Output(profilePath)
+ rule.Command().Text("touch").Output(profilePath)
}
cmd := rule.Command().
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 6e502b7..de9dc45 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -54,6 +54,7 @@
ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
+ ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory)
}
var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
@@ -84,6 +85,9 @@
// the recovery variant instead.
Vendor_ramdisk_available *bool
+ // Make this module available when building for debug ramdisk.
+ Debug_ramdisk_available *bool
+
// Make this module available when building for recovery.
Recovery_available *bool
@@ -159,6 +163,18 @@
return p.inVendorRamdisk()
}
+func (p *PrebuiltEtc) inDebugRamdisk() bool {
+ return p.ModuleBase.InDebugRamdisk() || p.ModuleBase.InstallInDebugRamdisk()
+}
+
+func (p *PrebuiltEtc) onlyInDebugRamdisk() bool {
+ return p.ModuleBase.InstallInDebugRamdisk()
+}
+
+func (p *PrebuiltEtc) InstallInDebugRamdisk() bool {
+ return p.inDebugRamdisk()
+}
+
func (p *PrebuiltEtc) inRecovery() bool {
return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
}
@@ -177,7 +193,7 @@
func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() &&
- !p.ModuleBase.InstallInVendorRamdisk()
+ !p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk()
}
func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -188,6 +204,10 @@
return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk()
}
+func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk()
+}
+
func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
}
@@ -313,6 +333,9 @@
if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() {
nameSuffix = ".vendor_ramdisk"
}
+ if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() {
+ nameSuffix = ".debug_ramdisk"
+ }
if p.inRecovery() && !p.onlyInRecovery() {
nameSuffix = ".recovery"
}
@@ -431,3 +454,16 @@
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
}
+
+// prebuilt_rfsa installs a firmware file that will be available through Qualcomm's RFSA
+// to the <partition>/lib/rfsa directory.
+func PrebuiltRFSAFactory() android.Module {
+ module := &PrebuiltEtc{}
+ // Ideally these would go in /vendor/dsp, but the /vendor/lib/rfsa paths are hardcoded in too
+ // many places outside of the application processor. They could be moved to /vendor/dsp once
+ // that is cleaned up.
+ InitPrebuiltEtcModule(module, "lib/rfsa")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index fdb5648..354f6bb 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -312,3 +312,37 @@
})
}
}
+
+func TestPrebuiltRFSADirPath(t *testing.T) {
+ targetPath := "out/soong/target/product/test_device"
+ tests := []struct {
+ description string
+ config string
+ expectedPath string
+ }{{
+ description: "prebuilt: system rfsa",
+ config: `
+ prebuilt_rfsa {
+ name: "foo.conf",
+ src: "foo.conf",
+ }`,
+ expectedPath: filepath.Join(targetPath, "system/lib/rfsa"),
+ }, {
+ description: "prebuilt: vendor rfsa",
+ config: `
+ prebuilt_rfsa {
+ name: "foo.conf",
+ src: "foo.conf",
+ soc_specific: true,
+ sub_dir: "sub_dir",
+ }`,
+ expectedPath: filepath.Join(targetPath, "vendor/lib/rfsa/sub_dir"),
+ }}
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config)
+ p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
+ android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath)
+ })
+ }
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b426b20..77dae75 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -626,6 +626,7 @@
func (x noopImageInterface) CoreVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) RamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
+func (x noopImageInterface) DebugRamdiskVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) RecoveryVariantNeeded(android.BaseModuleContext) bool { return false }
func (x noopImageInterface) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil }
func (x noopImageInterface) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index f03a673..02833ab 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -69,13 +69,15 @@
// addDependencyOntoApexModulePair adds a dependency onto the specified APEX specific variant or the
// specified module.
//
-// If apex="platform" then this adds a dependency onto the platform variant of the module. This adds
-// dependencies onto the prebuilt and source modules with the specified name, depending on which
-// ones are available. Visiting must use isActiveModule to select the preferred module when both
-// source and prebuilt modules are available.
+// If apex="platform" or "system_ext" then this adds a dependency onto the platform variant of the
+// module. This adds dependencies onto the prebuilt and source modules with the specified name,
+// depending on which ones are available. Visiting must use isActiveModule to select the preferred
+// module when both source and prebuilt modules are available.
+//
+// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
var variations []blueprint.Variation
- if apex != "platform" {
+ if apex != "platform" && apex != "system_ext" {
// Pick the correct apex variant.
variations = []blueprint.Variation{
{Mutator: "apex", Variation: apex},
@@ -118,12 +120,28 @@
ctx.AddFarVariationDependencies(variations, nil, name)
}
+// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
+// added by addDependencyOntoApexModulePair.
+func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
+ var modules []android.Module
+ ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+ t := ctx.OtherModuleDependencyTag(module)
+ if t == tag {
+ modules = append(modules, module)
+ }
+ })
+ return modules
+}
+
// ApexVariantReference specifies a particular apex variant of a module.
type ApexVariantReference struct {
// The name of the module apex variant, i.e. the apex containing the module variant.
//
// If this is not specified then it defaults to "platform" which will cause a dependency to be
// added to the module's platform variant.
+ //
+ // A value of system_ext should be used for any module that will be part of the system_ext
+ // partition.
Apex *string
// The name of the module.
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index d7525ec..8fe362a 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -145,11 +145,6 @@
ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
}
- if len(contents) != 0 {
- // Nothing to do.
- return
- }
-
imageName := proptools.String(m.properties.Image_name)
if imageName == "art" {
// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
@@ -181,7 +176,7 @@
continue
}
if !m.AvailableFor(apex) {
- ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
+ ctx.ModuleErrorf("ArtApexJars configuration incompatible with this module, ArtApexJars expects this to be in apex %q but this is only in apexes %q",
apex, m.ApexAvailable())
continue
}
@@ -193,6 +188,11 @@
}
}
+ if len(contents) != 0 {
+ // Nothing to do.
+ return
+ }
+
// Store the jars in the Contents property so that they can be used to add dependencies.
m.properties.Contents = modules.CopyOfJars()
}
diff --git a/java/config/config.go b/java/config/config.go
index 30c6f91..273084c 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -69,6 +69,8 @@
pctx.StaticVariable("JavacHeapSize", "2048M")
pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
pctx.StaticVariable("DexFlags", "-JXX:OnError='cat hs_err_pid%p.log' -JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads")
+ // TODO(b/181095653): remove duplicated flags.
+ pctx.StaticVariable("DexJavaFlags", "-XX:OnError='cat hs_err_pid%p.log' -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads -Xmx2G")
pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
`-Xmaxerrs 9999999`,
diff --git a/java/dex.go b/java/dex.go
index 7898e9d..6bf0143 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -84,6 +84,11 @@
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
+func init() {
+ pctx.HostBinToolVariable("runWithTimeoutCmd", "run_with_timeout")
+ pctx.SourcePathVariable("jstackCmd", "${config.JavaToolchain}/jstack")
+}
+
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -117,7 +122,10 @@
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
`mkdir -p $$(dirname ${outUsage}) && ` +
- `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
+ // TODO(b/181095653): remove R8 timeout and go back to config.R8Cmd.
+ `${runWithTimeoutCmd} -timeout 30m -on_timeout '${jstackCmd} $$PID' -- ` +
+ `$r8Template${config.JavaCmd} ${config.DexJavaFlags} -cp ${config.R8Jar} ` +
+ `com.android.tools.r8.compatproguard.CompatProguard -injars $in --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
`-printusage ${outUsage} ` +
@@ -128,9 +136,10 @@
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
- "${config.R8Cmd}",
+ "${config.R8Jar}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
+ "${runWithTimeoutCmd}",
},
}, map[string]*remoteexec.REParams{
"$r8Template": &remoteexec.REParams{
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 8a6f3d1..ce5155f 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -431,9 +431,6 @@
defaultImageConfig := defaultBootImageConfig(ctx)
profile := bootImageProfileRule(ctx, defaultImageConfig)
- // Generate the updatable bootclasspath packages rule.
- updatableBcpPackagesRule(ctx, defaultImageConfig)
-
// Create the default boot image.
d.defaultBootImage = buildBootImage(ctx, defaultImageConfig, profile)
@@ -441,8 +438,6 @@
d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx), profile))
copyUpdatableBootJars(ctx)
-
- dumpOatRules(ctx, d.defaultBootImage)
}
// shouldBuildBootImages determines whether boot images should be built.
@@ -457,129 +452,79 @@
return true
}
-// Inspect this module to see if it contains a bootclasspath dex jar.
-// Note that the same jar may occur in multiple modules.
-// This logic is tested in the apex package to avoid import cycle apex <-> java.
+// A copy of isModuleInConfiguredList created to work with singleton context.
//
-// This is similar to logic in isModuleInConfiguredList() so any changes needed here are likely to
-// be needed there too.
-//
-// TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it.
-func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList,
- module android.Module, fromWhere string) (int, android.Path, *android.ApexInfo) {
-
+// TODO(b/177892522): Remove this.
+func isModuleInConfiguredListForSingleton(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
name := ctx.ModuleName(module)
- // Strip a prebuilt_ prefix so that this can access the dex jar from a prebuilt module.
+ // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
name = android.RemoveOptionalPrebuiltPrefix(name)
// Ignore any module that is not listed in the boot image configuration.
- index := bootjars.IndexOfJar(name)
+ index := configuredBootJars.IndexOfJar(name)
if index == -1 {
- return -1, nil, nil
+ return false
}
- // It is an error if a module configured in the boot image does not support accessing the dex jar.
- // This is safe because every module that has the same name has to have the same module type.
- jar, hasJar := module.(interface{ DexJarBuildPath() android.Path })
- if !hasJar {
- ctx.Errorf("module %q %sdoes not support accessing dex jar", module, fromWhere)
- return -1, nil, nil
- }
-
- // It is also an error if the module is not an ApexModule.
+ // It is an error if the module is not an ApexModule.
if _, ok := module.(android.ApexModule); !ok {
- ctx.Errorf("module %q %sdoes not support being added to an apex", module, fromWhere)
- return -1, nil, nil
+ ctx.Errorf("%s is configured in boot jars but does not support being added to an apex", ctx.ModuleName(module))
+ return false
}
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
// Now match the apex part of the boot image configuration.
- requiredApex := bootjars.Apex(index)
+ requiredApex := configuredBootJars.Apex(index)
if requiredApex == "platform" || requiredApex == "system_ext" {
if len(apexInfo.InApexes) != 0 {
// A platform variant is required but this is for an apex so ignore it.
- return -1, nil, nil
+ return false
}
} else if !apexInfo.InApexByBaseName(requiredApex) {
// An apex variant for a specific apex is required but this is the wrong apex.
- return -1, nil, nil
+ return false
}
- return index, jar.DexJarBuildPath(), &apexInfo
+ return true
}
-// Inspect this module to see if it contains a bootclasspath dex jar from a given boot image.
-func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
- fromImage := fmt.Sprintf("configured in boot image %q ", image.name)
- index, jarPath, apexInfo := getBootJar(ctx, image.modules, module, fromImage)
- if index == -1 {
- return -1, nil
- }
-
- name := ctx.ModuleName(module)
-
- // Check that this module satisfies any boot image specific constraints.
- fromUpdatableApex := apexInfo.Updatable
-
- switch image.name {
- case artBootImageName:
- inArtApex := false
- for _, n := range artApexNames {
- if apexInfo.InApexByBaseName(n) {
- inArtApex = true
- break
- }
- }
- if inArtApex {
- // ok: found the jar in the ART apex
- } else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- // exception (skip and continue): Jacoco platform variant for a coverage build
- return -1, nil
- } else if fromUpdatableApex {
- // error: this jar is part of an updatable apex other than ART
- ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apexInfo.InApexes)
- } else {
- // error: this jar is part of the platform or a non-updatable apex
- ctx.Errorf("module %q is not allowed in the ART boot image", name)
- }
-
- case frameworkBootImageName:
- if !fromUpdatableApex {
- // ok: this jar is part of the platform or a non-updatable apex
- } else {
- // error: this jar is part of an updatable apex
- ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apexInfo.InApexes)
- }
- default:
- panic("unknown boot image: " + image.name)
- }
-
- return index, jarPath
-}
-
-// Generate commands that will copy boot jars to predefined paths in the global config.
-func findAndCopyBootJars(ctx android.SingletonContext, bootjars android.ConfiguredJarList,
- jarPathsPredefined android.WritablePaths,
- getBootJar func(module android.Module) (int, android.Path)) {
+// findBootJarModules finds the boot jar module variants specified in the bootjars parameter.
+//
+// It returns a list of modules such that the module at index i corresponds to the configured jar
+// at index i.
+func findBootJarModules(ctx android.SingletonContext, bootjars android.ConfiguredJarList) []android.Module {
+ modules := make([]android.Module, bootjars.Len())
// This logic is tested in the apex package to avoid import cycle apex <-> java.
- jarPaths := make(android.Paths, bootjars.Len())
-
ctx.VisitAllModules(func(module android.Module) {
- if !isActiveModule(module) {
+ if !isActiveModule(module) || !isModuleInConfiguredListForSingleton(ctx, module, bootjars) {
return
}
- if i, j := getBootJar(module); i != -1 {
- if existing := jarPaths[i]; existing != nil {
- ctx.Errorf("Multiple dex jars found for %s:%s - %q and %q",
- bootjars.Apex(i), bootjars.Jar(i), existing, j)
- return
- }
- jarPaths[i] = j
+
+ name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module))
+ index := bootjars.IndexOfJar(name)
+ if existing := modules[index]; existing != nil {
+ ctx.Errorf("Multiple boot jar modules found for %s:%s - %q and %q",
+ bootjars.Apex(index), bootjars.Jar(index), existing, module)
+ return
}
+ modules[index] = module
})
+ return modules
+}
+
+// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to
+// predefined paths in the global config.
+func copyBootJarsToPredefinedLocations(ctx android.SingletonContext, bootModules []android.Module, bootjars android.ConfiguredJarList, jarPathsPredefined android.WritablePaths) {
+ jarPaths := make(android.Paths, bootjars.Len())
+ for i, module := range bootModules {
+ if module != nil {
+ bootDexJar := module.(interface{ DexJarBuildPath() android.Path }).DexJarBuildPath()
+ jarPaths[i] = bootDexJar
+ }
+ }
// The paths to bootclasspath DEX files need to be known at module GenerateAndroidBuildAction
// time, before the boot images are built (these paths are used in dexpreopt rule generation for
@@ -619,10 +564,8 @@
// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
func buildBootImage(ctx android.SingletonContext, image *bootImageConfig, profile android.WritablePath) *bootImageConfig {
- getBootJarFunc := func(module android.Module) (int, android.Path) {
- return getBootImageJar(ctx, image, module)
- }
- findAndCopyBootJars(ctx, image.modules, image.dexPaths, getBootJarFunc)
+ bootModules := findBootJarModules(ctx, image.modules)
+ copyBootJarsToPredefinedLocations(ctx, bootModules, image.modules, image.dexPaths)
var zipFiles android.Paths
for _, variant := range image.variants {
@@ -649,11 +592,8 @@
// Generate commands that will copy updatable boot jars to predefined paths in the global config.
func copyUpdatableBootJars(ctx android.SingletonContext) {
config := GetUpdatableBootConfig(ctx)
- getBootJarFunc := func(module android.Module) (int, android.Path) {
- index, jar, _ := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ")
- return index, jar
- }
- findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc)
+ bootModules := findBootJarModules(ctx, config.modules)
+ copyBootJarsToPredefinedLocations(ctx, bootModules, config.modules, config.dexPaths)
}
// Generate boot image build rules for a specific target.
@@ -887,32 +827,9 @@
return profile
}
-func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig) android.WritablePath {
- if ctx.Config().UnbundledBuild() {
- return nil
- }
-
- global := dexpreopt.GetGlobalConfig(ctx)
- var modules []android.Module
- updatableModules := global.UpdatableBootJars.CopyOfJars()
- ctx.VisitAllModules(func(module android.Module) {
- if !isActiveModule(module) {
- return
- }
- name := ctx.ModuleName(module)
- if i := android.IndexList(name, updatableModules); i != -1 {
- modules = append(modules, module)
- // Do not match the same library repeatedly.
- updatableModules = append(updatableModules[:i], updatableModules[i+1:]...)
- }
- })
-
- return generateUpdatableBcpPackagesRule(ctx, image, modules)
-}
-
// generateUpdatableBcpPackagesRule generates the rule to create the updatable-bcp-packages.txt file
// and returns a path to the generated file.
-func generateUpdatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig, updatableModules []android.Module) android.WritablePath {
+func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImageConfig, updatableModules []android.Module) android.WritablePath {
// Collect `permitted_packages` for updatable boot jars.
var updatablePackages []string
for _, module := range updatableModules {
@@ -921,7 +838,7 @@
if len(pp) > 0 {
updatablePackages = append(updatablePackages, pp...)
} else {
- ctx.Errorf("Missing permitted_packages for %s", ctx.ModuleName(module))
+ ctx.ModuleErrorf("Missing permitted_packages")
}
}
}
@@ -944,7 +861,7 @@
return updatableBcpPackages
}
-func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
+func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
var allPhonies android.Paths
for _, image := range image.variants {
arch := image.target.Arch.ArchType
@@ -985,7 +902,6 @@
Inputs: allPhonies,
Description: "dump-oat-boot",
})
-
}
func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 3011250..566f7e3 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -300,6 +300,8 @@
if Bool(d.properties.Annotations_enabled) {
cmd.Flag("--include-annotations")
+ cmd.FlagWithArg("--exclude-annotation ", "androidx.annotation.RequiresApi")
+
validatingNullability :=
strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
String(d.properties.Validate_nullability_from_list) != ""
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index bc3b474..a34044f 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -121,13 +121,6 @@
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
-// hiddenAPISupportingModule is the interface that is implemented by any module that supports
-// contributing to the hidden API processing.
-type hiddenAPISupportingModule interface {
- android.Module
- hiddenAPIIntf
-}
-
// Initialize the hiddenapi structure
func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationName string) {
// If hiddenapi processing is disabled treat this as inactive.
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 3cc88e6..f6af501 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -149,19 +149,9 @@
}
}
-// Export paths to Make. INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
-func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) {
- if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
- return
- }
-
- ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", h.flags.String())
-}
-
// Checks to see whether the supplied module variant is in the list of boot jars.
//
-// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed
-// there too.
+// Apart from the context this is identical to isModuleInConfiguredListForSingleton.
//
// TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it.
func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
@@ -178,7 +168,7 @@
// It is an error if the module is not an ApexModule.
if _, ok := module.(android.ApexModule); !ok {
- ctx.ModuleErrorf("is configured in boot jars but does not support being added to an apex")
+ ctx.ModuleErrorf("%s is configured in boot jars but does not support being added to an apex", ctx.OtherModuleName(module))
return false
}
@@ -186,7 +176,7 @@
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
- if requiredApex == "platform" {
+ if requiredApex == "platform" || requiredApex == "system_ext" {
if len(apexInfo.InApexes) != 0 {
// A platform variant is required but this is for an apex so ignore it.
return false
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 6503eca..3a59822 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -26,14 +26,19 @@
}
func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory)
+ ctx.RegisterSingletonModuleType("platform_bootclasspath", platformBootclasspathFactory)
}
-// The tag used for the dependency between the platform bootclasspath and any configured boot jars.
-var platformBootclasspathModuleDepTag = bootclasspathDependencyTag{name: "module"}
+// The tags used for the dependencies between the platform bootclasspath and any configured boot
+// jars.
+var (
+ platformBootclasspathArtBootJarDepTag = bootclasspathDependencyTag{name: "art-boot-jar"}
+ platformBootclasspathNonUpdatableBootJarDepTag = bootclasspathDependencyTag{name: "non-updatable-boot-jar"}
+ platformBootclasspathUpdatableBootJarDepTag = bootclasspathDependencyTag{name: "updatable-boot-jar"}
+)
type platformBootclasspathModule struct {
- android.ModuleBase
+ android.SingletonModuleBase
ClasspathFragmentBase
properties platformBootclasspathProperties
@@ -64,7 +69,7 @@
Hidden_api HiddenAPIFlagFileProperties
}
-func platformBootclasspathFactory() android.Module {
+func platformBootclasspathFactory() android.SingletonModule {
m := &platformBootclasspathModule{}
m.AddProperties(&m.properties)
// TODO(satayev): split systemserver and apex jars into separate configs.
@@ -125,41 +130,64 @@
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the modules configured in the "art" boot image.
artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
- addDependenciesOntoBootImageModules(ctx, artImageConfig.modules)
+ addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
- // Add dependencies on all the modules configured in the "boot" boot image. That does not
- // include modules configured in the "art" boot image.
+ // Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
+ // not include modules configured in the "art" boot image.
bootImageConfig := b.getImageConfig(ctx)
- addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules)
+ addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules, platformBootclasspathNonUpdatableBootJarDepTag)
// Add dependencies on all the updatable modules.
updatableModules := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars
- addDependenciesOntoBootImageModules(ctx, updatableModules)
+ addDependenciesOntoBootImageModules(ctx, updatableModules, platformBootclasspathUpdatableBootJarDepTag)
// Add dependencies on all the fragments.
b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx)
}
-func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList) {
+func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) {
for i := 0; i < modules.Len(); i++ {
apex := modules.Apex(i)
name := modules.Jar(i)
- addDependencyOntoApexModulePair(ctx, apex, name, platformBootclasspathModuleDepTag)
+ addDependencyOntoApexModulePair(ctx, apex, name, tag)
}
}
+// GenerateSingletonBuildActions does nothing and must never do anything.
+//
+// This module only implements android.SingletonModule so that it can implement
+// android.SingletonMakeVarsProvider.
+func (b *platformBootclasspathModule) GenerateSingletonBuildActions(android.SingletonContext) {
+ // Keep empty
+}
+
+func (d *platformBootclasspathModule) MakeVars(ctx android.MakeVarsContext) {
+ d.generateHiddenApiMakeVars(ctx)
+}
+
func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
b.classpathFragmentBase().generateAndroidBuildActions(ctx)
- ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
- tag := ctx.OtherModuleDependencyTag(module)
- if tag == platformBootclasspathModuleDepTag {
- b.configuredModules = append(b.configuredModules, module)
- } else if tag == bootclasspathFragmentDepTag {
- b.fragments = append(b.fragments, module)
- }
- })
+ // Gather all the dependencies from the art, updatable and non-updatable boot jars.
+ artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag)
+ nonUpdatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathNonUpdatableBootJarDepTag)
+ updatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathUpdatableBootJarDepTag)
+
+ // Concatenate them all, in order as they would appear on the bootclasspath.
+ var allModules []android.Module
+ allModules = append(allModules, artModules...)
+ allModules = append(allModules, nonUpdatableModules...)
+ allModules = append(allModules, updatableModules...)
+ b.configuredModules = allModules
+
+ // Gather all the fragments dependencies.
+ b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
+
+ // Check the configuration of the boot modules.
+ // ART modules are checked by the art-bootclasspath-fragment.
+ b.checkNonUpdatableModules(ctx, nonUpdatableModules)
+ b.checkUpdatableModules(ctx, updatableModules)
b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
@@ -168,13 +196,60 @@
return
}
- b.generateBootImageBuildActions(ctx)
+ b.generateBootImageBuildActions(ctx, updatableModules)
+}
+
+// checkNonUpdatableModules ensures that the non-updatable modules supplied are not part of an
+// updatable module.
+func (b *platformBootclasspathModule) checkNonUpdatableModules(ctx android.ModuleContext, modules []android.Module) {
+ for _, m := range modules {
+ apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ fromUpdatableApex := apexInfo.Updatable
+ if fromUpdatableApex {
+ // error: this jar is part of an updatable apex
+ ctx.ModuleErrorf("module %q from updatable apexes %q is not allowed in the framework boot image", ctx.OtherModuleName(m), apexInfo.InApexes)
+ } else {
+ // ok: this jar is part of the platform or a non-updatable apex
+ }
+ }
+}
+
+// checkUpdatableModules ensures that the updatable modules supplied are not from the platform.
+func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleContext, modules []android.Module) {
+ for _, m := range modules {
+ apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ fromUpdatableApex := apexInfo.Updatable
+ if fromUpdatableApex {
+ // ok: this jar is part of an updatable apex
+ } else {
+ name := ctx.OtherModuleName(m)
+ if apexInfo.IsForPlatform() {
+ // error: this jar is part of the platform
+ ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name)
+ } else {
+ // TODO(b/177892522): Treat this as an error.
+ // Cannot do that at the moment because framework-wifi and framework-tethering are in the
+ // PRODUCT_UPDATABLE_BOOT_JARS but not marked as updatable in AOSP.
+ }
+ }
+ }
}
func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
return defaultBootImageConfig(ctx)
}
+// hiddenAPISupportingModule encapsulates the information provided by any module that contributes to
+// the hidden API processing.
+type hiddenAPISupportingModule struct {
+ module android.Module
+
+ bootDexJar android.Path
+ flagsCSV android.Path
+ indexCSV android.Path
+ metadataCSV android.Path
+}
+
// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
@@ -197,27 +272,57 @@
return
}
+ // nilPathHandler will check the supplied path and if it is nil then it will either immediately
+ // report an error, or it will defer the error reporting until it is actually used, depending
+ // whether missing dependencies are allowed.
+ var nilPathHandler func(path android.Path, name string, module android.Module) android.Path
+ if ctx.Config().AllowMissingDependencies() {
+ nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
+ if path == nil {
+ outputPath := android.PathForModuleOut(ctx, "missing", module.Name(), name)
+ path = outputPath
+
+ // Create an error rule that pretends to create the output file but will actually fail if it
+ // is run.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: outputPath,
+ Args: map[string]string{
+ "error": fmt.Sprintf("missing hidden API file: %s for %s", name, module),
+ },
+ })
+ }
+ return path
+ }
+ } else {
+ nilPathHandler = func(path android.Path, name string, module android.Module) android.Path {
+ if path == nil {
+ ctx.ModuleErrorf("module %s does not provide a %s file", module, name)
+ }
+ return path
+ }
+ }
+
hiddenAPISupportingModules := []hiddenAPISupportingModule{}
for _, module := range modules {
- if h, ok := module.(hiddenAPISupportingModule); ok {
- if h.bootDexJar() == nil {
- ctx.ModuleErrorf("module %s does not provide a bootDexJar file", module)
- }
- if h.flagsCSV() == nil {
- ctx.ModuleErrorf("module %s does not provide a flagsCSV file", module)
- }
- if h.indexCSV() == nil {
- ctx.ModuleErrorf("module %s does not provide an indexCSV file", module)
- }
- if h.metadataCSV() == nil {
- ctx.ModuleErrorf("module %s does not provide a metadataCSV file", module)
+ if h, ok := module.(hiddenAPIIntf); ok {
+ hiddenAPISupportingModule := hiddenAPISupportingModule{
+ module: module,
+ bootDexJar: nilPathHandler(h.bootDexJar(), "bootDexJar", module),
+ flagsCSV: nilPathHandler(h.flagsCSV(), "flagsCSV", module),
+ indexCSV: nilPathHandler(h.indexCSV(), "indexCSV", module),
+ metadataCSV: nilPathHandler(h.metadataCSV(), "metadataCSV", module),
}
+ // If any errors were reported when trying to populate the hiddenAPISupportingModule struct
+ // then don't add it to the list.
if ctx.Failed() {
continue
}
- hiddenAPISupportingModules = append(hiddenAPISupportingModules, h)
+ hiddenAPISupportingModules = append(hiddenAPISupportingModules, hiddenAPISupportingModule)
+ } else if _, ok := module.(*DexImport); ok {
+ // Ignore this for the purposes of hidden API processing
} else {
ctx.ModuleErrorf("module %s of type %s does not support hidden API processing", module, ctx.OtherModuleType(module))
}
@@ -225,7 +330,7 @@
moduleSpecificFlagsPaths := android.Paths{}
for _, module := range hiddenAPISupportingModules {
- moduleSpecificFlagsPaths = append(moduleSpecificFlagsPaths, module.flagsCSV())
+ moduleSpecificFlagsPaths = append(moduleSpecificFlagsPaths, module.flagsCSV)
}
flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
@@ -251,7 +356,7 @@
func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
bootDexJars := android.Paths{}
for _, module := range modules {
- bootDexJars = append(bootDexJars, module.bootDexJar())
+ bootDexJars = append(bootDexJars, module.bootDexJar)
}
sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx)
@@ -264,7 +369,7 @@
func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
indexes := android.Paths{}
for _, module := range modules {
- indexes = append(indexes, module.indexCSV())
+ indexes = append(indexes, module.indexCSV)
}
rule := android.NewRuleBuilder(pctx, ctx)
@@ -280,7 +385,7 @@
func (b *platformBootclasspathModule) generatedHiddenAPIMetadataRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
metadataCSVFiles := android.Paths{}
for _, module := range modules {
- metadataCSVFiles = append(metadataCSVFiles, module.metadataCSV())
+ metadataCSVFiles = append(metadataCSVFiles, module.metadataCSV)
}
rule := android.NewRuleBuilder(pctx, ctx)
@@ -296,8 +401,18 @@
rule.Build("platform-bootclasspath-monolithic-hiddenapi-metadata", "monolithic hidden API metadata")
}
+// generateHiddenApiMakeVars generates make variables needed by hidden API related make rules, e.g.
+// veridex and run-appcompat.
+func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.MakeVarsContext) {
+ if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
+ return
+ }
+ // INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
+ ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
+}
+
// generateBootImageBuildActions generates ninja rules related to the boot image creation.
-func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext) {
+func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, updatableModules []android.Module) {
// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
// GenerateSingletonBuildActions method as it cannot create it for itself.
dexpreopt.GetGlobalSoongConfig(ctx)
@@ -314,4 +429,9 @@
// Generate the framework profile rule
bootFrameworkProfileRule(ctx, imageConfig)
+
+ // Generate the updatable bootclasspath packages rule.
+ generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules)
+
+ dumpOatRules(ctx, imageConfig)
}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 955e387..98d4614 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -33,7 +33,7 @@
func TestPlatformBootclasspath(t *testing.T) {
preparer := android.GroupFixturePreparers(
prepareForTestWithPlatformBootclasspath,
- FixtureConfigureBootJars("platform:foo", "platform:bar"),
+ FixtureConfigureBootJars("platform:foo", "system_ext:bar"),
android.FixtureWithRootAndroidBp(`
platform_bootclasspath {
name: "platform-bootclasspath",
@@ -45,6 +45,7 @@
system_modules: "none",
sdk_version: "none",
compile_dex: true,
+ system_ext_specific: true,
}
`),
)
@@ -132,6 +133,23 @@
"platform:bar",
})
})
+
+ t.Run("dex import", func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ preparer,
+ android.FixtureAddTextFile("deximport/Android.bp", `
+ dex_import {
+ name: "foo",
+ jars: ["a.jar"],
+ }
+ `),
+ ).RunTest(t)
+
+ CheckPlatformBootclasspathModules(t, result, "platform-bootclasspath", []string{
+ "platform:prebuilt_foo",
+ "platform:bar",
+ })
+ })
}
func TestPlatformBootclasspath_Fragments(t *testing.T) {
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 5f89d73..ea45ebd 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -91,7 +91,6 @@
if binary.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
}
-
ret.Class = "EXECUTABLES"
}
@@ -201,3 +200,36 @@
entries.SetString("LOCAL_MODULE_STEM", stem)
})
}
+
+func (fuzz *fuzzDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+ ctx.SubAndroidMk(entries, fuzz.binaryDecorator)
+
+ var fuzzFiles []string
+ for _, d := range fuzz.corpus {
+ fuzzFiles = append(fuzzFiles,
+ filepath.Dir(fuzz.corpusIntermediateDir.String())+":corpus/"+d.Base())
+ }
+
+ for _, d := range fuzz.data {
+ fuzzFiles = append(fuzzFiles,
+ filepath.Dir(fuzz.dataIntermediateDir.String())+":data/"+d.Rel())
+ }
+
+ if fuzz.dictionary != nil {
+ fuzzFiles = append(fuzzFiles,
+ filepath.Dir(fuzz.dictionary.String())+":"+fuzz.dictionary.Base())
+ }
+
+ if fuzz.config != nil {
+ fuzzFiles = append(fuzzFiles,
+ filepath.Dir(fuzz.config.String())+":config.json")
+ }
+
+ entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
+ entries *android.AndroidMkEntries) {
+ entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
+ if len(fuzzFiles) > 0 {
+ entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
+ }
+ })
+}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index d699971..7e1c55a 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -15,6 +15,10 @@
package rust
import (
+ "path/filepath"
+ "sort"
+ "strings"
+
"android/soong/android"
"android/soong/cc"
"android/soong/rust/config"
@@ -22,6 +26,7 @@
func init() {
android.RegisterModuleType("rust_fuzz", RustFuzzFactory)
+ android.RegisterSingletonType("rust_fuzz_packaging", rustFuzzPackagingFactory)
}
type fuzzDecorator struct {
@@ -93,3 +98,204 @@
func (fuzzer *fuzzDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
return rlibAutoDep
}
+
+// Responsible for generating GNU Make rules that package fuzz targets into
+// their architecture & target/host specific zip file.
+type rustFuzzPackager struct {
+ packages android.Paths
+ fuzzTargets map[string]bool
+}
+
+func rustFuzzPackagingFactory() android.Singleton {
+ return &rustFuzzPackager{}
+}
+
+type fileToZip struct {
+ SourceFilePath android.Path
+ DestinationPathPrefix string
+}
+
+type archOs struct {
+ hostOrTarget string
+ arch string
+ dir string
+}
+
+func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+
+ // Map between each architecture + host/device combination.
+ archDirs := make(map[archOs][]fileToZip)
+
+ // List of individual fuzz targets.
+ s.fuzzTargets = make(map[string]bool)
+
+ ctx.VisitAllModules(func(module android.Module) {
+ // Discard non-fuzz targets.
+ rustModule, ok := module.(*Module)
+ if !ok {
+ return
+ }
+
+ fuzzModule, ok := rustModule.compiler.(*fuzzDecorator)
+ if !ok {
+ return
+ }
+
+ // Discard ramdisk + vendor_ramdisk + recovery modules, they're duplicates of
+ // fuzz targets we're going to package anyway.
+ if !rustModule.Enabled() || rustModule.Properties.PreventInstall ||
+ rustModule.InRamdisk() || rustModule.InVendorRamdisk() || rustModule.InRecovery() {
+ return
+ }
+
+ // Discard modules that are in an unavailable namespace.
+ if !rustModule.ExportedToMake() {
+ return
+ }
+
+ hostOrTargetString := "target"
+ if rustModule.Host() {
+ hostOrTargetString = "host"
+ }
+
+ archString := rustModule.Arch().ArchType.String()
+ archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+ archOs := archOs{hostOrTarget: hostOrTargetString, arch: archString, dir: archDir.String()}
+
+ var files []fileToZip
+ builder := android.NewRuleBuilder(pctx, ctx)
+
+ // Package the corpora into a zipfile.
+ if fuzzModule.corpus != nil {
+ corpusZip := archDir.Join(ctx, module.Name()+"_seed_corpus.zip")
+ command := builder.Command().BuiltTool("soong_zip").
+ Flag("-j").
+ FlagWithOutput("-o ", corpusZip)
+ rspFile := corpusZip.ReplaceExtension(ctx, "rsp")
+ command.FlagWithRspFileInputList("-r ", rspFile, fuzzModule.corpus)
+ files = append(files, fileToZip{corpusZip, ""})
+ }
+
+ // Package the data into a zipfile.
+ if fuzzModule.data != nil {
+ dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
+ command := builder.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", dataZip)
+ for _, f := range fuzzModule.data {
+ intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
+ command.FlagWithArg("-C ", intermediateDir)
+ command.FlagWithInput("-f ", f)
+ }
+ files = append(files, fileToZip{dataZip, ""})
+ }
+
+ // The executable.
+ files = append(files, fileToZip{rustModule.unstrippedOutputFile.Path(), ""})
+
+ // The dictionary.
+ if fuzzModule.dictionary != nil {
+ files = append(files, fileToZip{fuzzModule.dictionary, ""})
+ }
+
+ // Additional fuzz config.
+ if fuzzModule.config != nil {
+ files = append(files, fileToZip{fuzzModule.config, ""})
+ }
+
+ fuzzZip := archDir.Join(ctx, module.Name()+".zip")
+
+ command := builder.Command().BuiltTool("soong_zip").
+ Flag("-j").
+ FlagWithOutput("-o ", fuzzZip)
+
+ for _, file := range files {
+ if file.DestinationPathPrefix != "" {
+ command.FlagWithArg("-P ", file.DestinationPathPrefix)
+ } else {
+ command.Flag("-P ''")
+ }
+ command.FlagWithInput("-f ", file.SourceFilePath)
+ }
+
+ builder.Build("create-"+fuzzZip.String(),
+ "Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
+
+ // Don't add modules to 'make haiku-rust' that are set to not be
+ // exported to the fuzzing infrastructure.
+ if config := fuzzModule.Properties.Fuzz_config; config != nil {
+ if rustModule.Host() && !BoolDefault(config.Fuzz_on_haiku_host, true) {
+ return
+ } else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
+ return
+ }
+ }
+
+ s.fuzzTargets[module.Name()] = true
+ archDirs[archOs] = append(archDirs[archOs], fileToZip{fuzzZip, ""})
+ })
+
+ var archOsList []archOs
+ for archOs := range archDirs {
+ archOsList = append(archOsList, archOs)
+ }
+ sort.Slice(archOsList, func(i, j int) bool { return archOsList[i].dir < archOsList[j].dir })
+
+ for _, archOs := range archOsList {
+ filesToZip := archDirs[archOs]
+ arch := archOs.arch
+ hostOrTarget := archOs.hostOrTarget
+ builder := android.NewRuleBuilder(pctx, ctx)
+ outputFile := android.PathForOutput(ctx, "fuzz-rust-"+hostOrTarget+"-"+arch+".zip")
+ s.packages = append(s.packages, outputFile)
+
+ command := builder.Command().BuiltTool("soong_zip").
+ Flag("-j").
+ FlagWithOutput("-o ", outputFile).
+ Flag("-L 0") // No need to try and re-compress the zipfiles.
+
+ for _, fileToZip := range filesToZip {
+ if fileToZip.DestinationPathPrefix != "" {
+ command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
+ } else {
+ command.Flag("-P ''")
+ }
+ command.FlagWithInput("-f ", fileToZip.SourceFilePath)
+ }
+ builder.Build("create-fuzz-package-"+arch+"-"+hostOrTarget,
+ "Create fuzz target packages for "+arch+"-"+hostOrTarget)
+ }
+
+}
+
+func (s *rustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+ packages := s.packages.Strings()
+ sort.Strings(packages)
+
+ ctx.Strict("SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+
+ // Preallocate the slice of fuzz targets to minimise memory allocations.
+ fuzzTargets := make([]string, 0, len(s.fuzzTargets))
+ for target, _ := range s.fuzzTargets {
+ fuzzTargets = append(fuzzTargets, target)
+ }
+ sort.Strings(fuzzTargets)
+ ctx.Strict("ALL_RUST_FUZZ_TARGETS", strings.Join(fuzzTargets, " "))
+}
+
+func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
+ fuzz.binaryDecorator.baseCompiler.dir = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzz.binaryDecorator.baseCompiler.dir64 = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzz.binaryDecorator.baseCompiler.install(ctx)
+
+ if fuzz.Properties.Corpus != nil {
+ fuzz.corpus = android.PathsForModuleSrc(ctx, fuzz.Properties.Corpus)
+ }
+ if fuzz.Properties.Data != nil {
+ fuzz.data = android.PathsForModuleSrc(ctx, fuzz.Properties.Data)
+ }
+ if fuzz.Properties.Dictionary != nil {
+ fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
+ }
+}
diff --git a/rust/image.go b/rust/image.go
index 7eb49d9..900842e 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -97,6 +97,10 @@
return mod.InRamdisk()
}
+func (mod *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool {
return mod.InRecovery()
}
diff --git a/rust/rust.go b/rust/rust.go
index 3dcd459..bb97142 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -270,6 +270,10 @@
return false
}
+func (m *Module) NeedsVendorPublicLibraryVariants() bool {
+ return false
+}
+
func (mod *Module) SdkVersion() string {
return ""
}
diff --git a/scripts/strip.sh b/scripts/strip.sh
index e3e5273..d09c187 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -71,7 +71,7 @@
"${CLANG_BIN}/llvm-objcopy" -w "${infile}" "${outfile}.tmp" ${KEEP_SYMBOLS}
}
-do_strip_keep_mini_debug_info() {
+do_strip_keep_mini_debug_info_darwin() {
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
local fail=
"${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
@@ -92,6 +92,32 @@
fi
}
+do_strip_keep_mini_debug_info_linux() {
+ rm -f "${outfile}.mini_debuginfo.xz"
+ local fail=
+ "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
+
+ if [ -z $fail ]; then
+ "${CREATE_MINIDEBUGINFO}" "${infile}" "${outfile}.mini_debuginfo.xz"
+ "${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
+ rm -f "${outfile}.mini_debuginfo.xz"
+ else
+ cp -f "${infile}" "${outfile}.tmp"
+ fi
+}
+
+do_strip_keep_mini_debug_info() {
+ case $(uname) in
+ Linux)
+ do_strip_keep_mini_debug_info_linux
+ ;;
+ Darwin)
+ do_strip_keep_mini_debug_info_darwin
+ ;;
+ *) echo "unknown OS:" $(uname) >&2 && exit 1;;
+ esac
+}
+
do_add_gnu_debuglink() {
"${CLANG_BIN}/llvm-objcopy" --add-gnu-debuglink="${infile}" "${outfile}.tmp"
}
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 2827567..0f2fd54 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -68,6 +68,7 @@
bootclasspath_fragment {
name: "mybootclasspathfragment",
image_name: "art",
+ contents: ["mybootlib"],
apex_available: ["com.android.art"],
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 6623381..42d5680 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -210,6 +210,10 @@
return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.ModuleBase.InstallInVendorRamdisk()
}
+func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery()
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 6ba497c..19b5690 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -144,7 +144,8 @@
productOut("odm"),
productOut("odm_dlkm"),
productOut("sysloader"),
- productOut("testcases"))
+ productOut("testcases"),
+ productOut("symbols"))
}
// Since products and build variants (unfortunately) shared the same