Merge "Revert "Revert "Revert "Add integration test for testing generat...""
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 63495bc..17db472 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -218,6 +218,7 @@
"hardware/interfaces": Bp2BuildDefaultTrue,
"hardware/interfaces/audio/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl/common": Bp2BuildDefaultTrue,
"hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/common/fmq/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
diff --git a/android/config.go b/android/config.go
index b37d5c8..979f1ca 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1759,6 +1759,10 @@
return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
}
+func (c *deviceConfig) BuildBrokenUsesSoongPython2Modules() bool {
+ return c.config.productVariables.BuildBrokenUsesSoongPython2Modules
+}
+
func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool {
return c.config.productVariables.BuildDebugfsRestrictionsEnabled
}
@@ -1837,3 +1841,14 @@
c.mixedBuildDisabledModules[moduleName] = struct{}{}
}
}
+
+// ApiSurfaces directory returns the source path inside the api_surfaces repo
+// (relative to workspace root).
+func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
+ return filepath.Join(
+ "build",
+ "bazel",
+ "api_surfaces",
+ s.String(),
+ version)
+}
diff --git a/android/defaults.go b/android/defaults.go
index a821b28..31d6014 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -15,8 +15,6 @@
package android
import (
- "bytes"
- "fmt"
"reflect"
"github.com/google/blueprint"
@@ -69,11 +67,9 @@
// Set the property structures into which defaults will be added.
setProperties(props []interface{}, variableProperties interface{})
- // Apply defaults from the supplied DefaultsModule to the property structures supplied to
+ // Apply defaults from the supplied Defaults to the property structures supplied to
// setProperties(...).
- applyDefaults(TopDownMutatorContext, []DefaultsModule)
-
- applySingleDefaultsWithTracker(EarlyModuleContext, DefaultsModule, defaultsTrackerFunc)
+ applyDefaults(TopDownMutatorContext, []Defaults)
// Set the hook to be called after any defaults have been applied.
//
@@ -119,23 +115,9 @@
Defaults_visibility []string
}
-// AdditionalDefaultsProperties contains properties of defaults modules which
-// can have other defaults applied.
-type AdditionalDefaultsProperties struct {
-
- // The list of properties set by the default whose values must not be changed by any module that
- // applies these defaults. It is an error if a property is not supported by the defaults module or
- // has not been set to a non-zero value. If this contains "*" then that must be the only entry in
- // which case all properties that are set on this defaults will be protected (except the
- // protected_properties and visibility.
- Protected_properties []string
-}
-
type DefaultsModuleBase struct {
DefaultableModuleBase
- defaultsProperties AdditionalDefaultsProperties
-
// Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
// target. This is primarily useful for modules that were architecture specific and instead are
// handled in Bazel as a select().
@@ -169,18 +151,6 @@
// DefaultsModuleBase will type-assert to the Defaults interface.
isDefaults() bool
- // additionalDefaultableProperties returns additional properties provided by the defaults which
- // can themselves have defaults applied.
- additionalDefaultableProperties() []interface{}
-
- // protectedProperties returns the names of the properties whose values cannot be changed by a
- // module that applies these defaults.
- protectedProperties() []string
-
- // setProtectedProperties sets the names of the properties whose values cannot be changed by a
- // module that applies these defaults.
- setProtectedProperties(protectedProperties []string)
-
// Get the structures containing the properties for which defaults can be provided.
properties() []interface{}
@@ -197,18 +167,6 @@
Bazelable
}
-func (d *DefaultsModuleBase) additionalDefaultableProperties() []interface{} {
- return []interface{}{&d.defaultsProperties}
-}
-
-func (d *DefaultsModuleBase) protectedProperties() []string {
- return d.defaultsProperties.Protected_properties
-}
-
-func (d *DefaultsModuleBase) setProtectedProperties(protectedProperties []string) {
- d.defaultsProperties.Protected_properties = protectedProperties
-}
-
func (d *DefaultsModuleBase) properties() []interface{} {
return d.defaultableProperties
}
@@ -232,10 +190,6 @@
&ApexProperties{},
&distProperties{})
- // Additional properties of defaults modules that can themselves have
- // defaults applied.
- module.AddProperties(module.additionalDefaultableProperties()...)
-
// Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
InitBazelModule(module)
initAndroidModuleBase(module)
@@ -263,58 +217,6 @@
// The applicable licenses property for defaults is 'licenses'.
setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
-
- AddLoadHook(module, func(ctx LoadHookContext) {
-
- protectedProperties := module.protectedProperties()
- if len(protectedProperties) == 0 {
- return
- }
-
- propertiesAvailable := map[string]struct{}{}
- propertiesSet := map[string]struct{}{}
-
- // A defaults tracker which will keep track of which properties have been set on this module.
- collector := func(defaults DefaultsModule, property string, dstValue interface{}, srcValue interface{}) bool {
- value := reflect.ValueOf(dstValue)
- propertiesAvailable[property] = struct{}{}
- if !value.IsZero() {
- propertiesSet[property] = struct{}{}
- }
- // Skip all the properties so that there are no changes to the defaults.
- return false
- }
-
- // Try and apply this module's defaults to itself, so that the properties can be collected but
- // skip all the properties so it doesn't actually do anything.
- module.applySingleDefaultsWithTracker(ctx, module, collector)
-
- if InList("*", protectedProperties) {
- if len(protectedProperties) != 1 {
- ctx.PropertyErrorf("protected_properties", `if specified then "*" must be the only property listed`)
- return
- }
-
- // Do not automatically protect the protected_properties property.
- delete(propertiesSet, "protected_properties")
-
- // Or the visibility property.
- delete(propertiesSet, "visibility")
-
- // Replace the "*" with the names of all the properties that have been set.
- protectedProperties = SortedKeys(propertiesSet)
- module.setProtectedProperties(protectedProperties)
- } else {
- for _, property := range protectedProperties {
- if _, ok := propertiesAvailable[property]; !ok {
- ctx.PropertyErrorf(property, "property is not supported by this module type %q",
- ctx.ModuleType())
- } else if _, ok := propertiesSet[property]; !ok {
- ctx.PropertyErrorf(property, "is not set; protected properties must be explicitly set")
- }
- }
- }
- })
}
var _ Defaults = (*DefaultsModuleBase)(nil)
@@ -366,204 +268,35 @@
b.setNamespacedVariableProps(dst)
}
-// defaultValueInfo contains information about each default value that applies to a protected
-// property.
-type defaultValueInfo struct {
- // The DefaultsModule providing the value, which may be defined on that module or applied as a
- // default from other modules.
- module Module
-
- // The default value, as returned by getComparableValue
- defaultValue reflect.Value
-}
-
-// protectedPropertyInfo contains information about each property that has to be protected when
-// applying defaults.
-type protectedPropertyInfo struct {
- // True if the property was set on the module to which defaults are applied, this is an error.
- propertySet bool
-
- // The original value of the property on the module, as returned by getComparableValue.
- originalValue reflect.Value
-
- // A list of defaults for the property that are being applied.
- defaultValues []defaultValueInfo
-}
-
-// getComparableValue takes a reflect.Value that may be a pointer to another value and returns a
-// reflect.Value to the underlying data or the original if was not a pointer or was nil. The
-// returned values can then be compared for equality.
-func getComparableValue(value reflect.Value) reflect.Value {
- if value.IsZero() {
- return value
- }
- for value.Kind() == reflect.Ptr {
- value = value.Elem()
- }
- return value
-}
-
func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
- defaultsList []DefaultsModule) {
-
- // Collate information on all the properties protected by each of the default modules applied
- // to this module.
- allProtectedProperties := map[string]*protectedPropertyInfo{}
- for _, defaults := range defaultsList {
- for _, property := range defaults.protectedProperties() {
- info := allProtectedProperties[property]
- if info == nil {
- info = &protectedPropertyInfo{}
- allProtectedProperties[property] = info
- }
- }
- }
-
- // If there are any protected properties then collate information about attempts to change them.
- var protectedPropertyInfoCollector defaultsTrackerFunc
- if len(allProtectedProperties) > 0 {
- protectedPropertyInfoCollector = func(defaults DefaultsModule, property string,
- dstValue interface{}, srcValue interface{}) bool {
-
- // If the property is not protected then return immediately.
- info := allProtectedProperties[property]
- if info == nil {
- return true
- }
-
- currentValue := reflect.ValueOf(dstValue)
- if info.defaultValues == nil {
- info.propertySet = !currentValue.IsZero()
- info.originalValue = getComparableValue(currentValue)
- }
-
- defaultValue := reflect.ValueOf(srcValue)
- if !defaultValue.IsZero() {
- info.defaultValues = append(info.defaultValues,
- defaultValueInfo{defaults, getComparableValue(defaultValue)})
- }
-
- return true
- }
- }
+ defaultsList []Defaults) {
for _, defaults := range defaultsList {
if ctx.Config().BuildMode == Bp2build {
applyNamespacedVariableDefaults(defaults, ctx)
}
-
- defaultable.applySingleDefaultsWithTracker(ctx, defaults, protectedPropertyInfoCollector)
- }
-
- // Check the status of any protected properties.
- for property, info := range allProtectedProperties {
- if len(info.defaultValues) == 0 {
- // No defaults were applied to the protected properties. Possibly because this module type
- // does not support any of them.
- continue
- }
-
- // Check to make sure that there are no conflicts between the defaults.
- conflictingDefaults := false
- previousDefaultValue := reflect.ValueOf(false)
- for _, defaultInfo := range info.defaultValues {
- defaultValue := defaultInfo.defaultValue
- if previousDefaultValue.IsZero() {
- previousDefaultValue = defaultValue
- } else if !reflect.DeepEqual(previousDefaultValue.Interface(), defaultValue.Interface()) {
- conflictingDefaults = true
- break
- }
- }
-
- if conflictingDefaults {
- var buf bytes.Buffer
- for _, defaultInfo := range info.defaultValues {
- buf.WriteString(fmt.Sprintf("\n defaults module %q provides value %#v",
- ctx.OtherModuleName(defaultInfo.module), defaultInfo.defaultValue))
- }
- result := buf.String()
- ctx.ModuleErrorf("has conflicting default values for protected property %q:%s", property, result)
- continue
- }
-
- // Now check to see whether there the current module tried to override/append to the defaults.
- if info.propertySet {
- originalValue := info.originalValue
- // Just compare against the first defaults.
- defaultValue := info.defaultValues[0].defaultValue
- defaults := info.defaultValues[0].module
-
- if originalValue.Kind() == reflect.Slice {
- ctx.ModuleErrorf("attempts to append %q to protected property %q's value of %q defined in module %q",
- originalValue,
- property,
- defaultValue,
- ctx.OtherModuleName(defaults))
+ for _, prop := range defaultable.defaultableProperties {
+ if prop == defaultable.defaultableVariableProperties {
+ defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
} else {
- same := reflect.DeepEqual(originalValue.Interface(), defaultValue.Interface())
- message := ""
- if same {
- message = fmt.Sprintf(" with a matching value (%#v) so this property can simply be removed.", originalValue)
- } else {
- message = fmt.Sprintf(" with a different value (override %#v with %#v) so removing the property may necessitate other changes.", defaultValue, originalValue)
- }
- ctx.ModuleErrorf("attempts to override protected property %q defined in module %q%s",
- property,
- ctx.OtherModuleName(defaults), message)
+ defaultable.applyDefaultProperties(ctx, defaults, prop)
}
}
}
}
-func (defaultable *DefaultableModuleBase) applySingleDefaultsWithTracker(ctx EarlyModuleContext, defaults DefaultsModule, tracker defaultsTrackerFunc) {
- for _, prop := range defaultable.defaultableProperties {
- var err error
- if prop == defaultable.defaultableVariableProperties {
- err = defaultable.applyDefaultVariableProperties(defaults, prop, tracker)
- } else {
- err = defaultable.applyDefaultProperties(defaults, prop, tracker)
- }
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
- }
-}
-
-// defaultsTrackerFunc is the type of a function that can be used to track how defaults are applied.
-type defaultsTrackerFunc func(defaults DefaultsModule, property string,
- dstValue interface{}, srcValue interface{}) bool
-
-// filterForTracker wraps a defaultsTrackerFunc in a proptools.ExtendPropertyFilterFunc
-func filterForTracker(defaults DefaultsModule, tracker defaultsTrackerFunc) proptools.ExtendPropertyFilterFunc {
- if tracker == nil {
- return nil
- }
- return func(property string,
- dstField, srcField reflect.StructField,
- dstValue, srcValue interface{}) (bool, error) {
-
- apply := tracker(defaults, property, dstValue, srcValue)
- return apply, nil
- }
-}
-
// Product variable properties need special handling, the type of the filtered product variable
// property struct may not be identical between the defaults module and the defaultable module.
// Use PrependMatchingProperties to apply whichever properties match.
-func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(defaults DefaultsModule,
- defaultableProp interface{}, tracker defaultsTrackerFunc) error {
+func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
if defaultableProp == nil {
- return nil
+ return
}
defaultsProp := defaults.productVariableProperties()
if defaultsProp == nil {
- return nil
+ return
}
dst := []interface{}{
@@ -573,26 +306,31 @@
proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
}
- filter := filterForTracker(defaults, tracker)
-
- return proptools.PrependMatchingProperties(dst, defaultsProp, filter)
+ err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
+ }
}
-func (defaultable *DefaultableModuleBase) applyDefaultProperties(defaults DefaultsModule,
- defaultableProp interface{}, checker defaultsTrackerFunc) error {
-
- filter := filterForTracker(defaults, checker)
+func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
for _, def := range defaults.properties() {
if proptools.TypeEqual(defaultableProp, def) {
- err := proptools.PrependProperties(defaultableProp, def, filter)
+ err := proptools.PrependProperties(defaultableProp, def, nil)
if err != nil {
- return err
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
}
}
}
-
- return nil
}
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
@@ -609,12 +347,12 @@
func defaultsMutator(ctx TopDownMutatorContext) {
if defaultable, ok := ctx.Module().(Defaultable); ok {
if len(defaultable.defaults().Defaults) > 0 {
- var defaultsList []DefaultsModule
+ var defaultsList []Defaults
seen := make(map[Defaults]bool)
ctx.WalkDeps(func(module, parent Module) bool {
if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
- if defaults, ok := module.(DefaultsModule); ok {
+ if defaults, ok := module.(Defaults); ok {
if !seen[defaults] {
seen[defaults] = true
defaultsList = append(defaultsList, defaults)
diff --git a/android/defaults_test.go b/android/defaults_test.go
index d80f40c..a7542ab 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -19,14 +19,7 @@
)
type defaultsTestProperties struct {
- Foo []string
- Bar []string
- Nested struct {
- Fizz *bool
- }
- Other struct {
- Buzz *string
- }
+ Foo []string
}
type defaultsTestModule struct {
@@ -137,167 +130,3 @@
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
}
-
-func TestProtectedProperties_ProtectedPropertyNotSet(t *testing.T) {
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["foo"],
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- "module \"transitive\": foo: is not set; protected properties must be explicitly set")).
- RunTest(t)
-}
-
-func TestProtectedProperties_ProtectedPropertyNotLeaf(t *testing.T) {
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["nested"],
- nested: {
- fizz: true,
- },
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qmodule "transitive": nested: property is not supported by this module type "defaults"\E`)).
- RunTest(t)
-}
-
-// TestProtectedProperties_ApplyDefaults makes sure that the protected_properties property has
-// defaults applied.
-func TestProtectedProperties_HasDefaultsApplied(t *testing.T) {
-
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["foo"],
- foo: ["transitive"],
- }
-
- defaults {
- name: "defaults",
- defaults: ["transitive"],
- protected_properties: ["bar"],
- bar: ["defaults"],
- }
- `
-
- result := GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- defaults := result.Module("defaults", "").(DefaultsModule)
- AssertDeepEquals(t, "defaults protected properties", []string{"foo", "bar"}, defaults.protectedProperties())
-}
-
-// TestProtectedProperties_ProtectAllProperties makes sure that protected_properties: ["*"] protects
-// all properties.
-func TestProtectedProperties_ProtectAllProperties(t *testing.T) {
-
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "transitive",
- },
- }
-
- defaults {
- name: "defaults",
- defaults: ["transitive"],
- visibility: ["//visibility:private"],
- protected_properties: ["*"],
- foo: ["other"],
- bar: ["defaults"],
- nested: {
- fizz: true,
- }
- }
- `
-
- result := GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- defaults := result.Module("defaults", "").(DefaultsModule)
- AssertDeepEquals(t, "defaults protected properties", []string{"other.buzz", "bar", "foo", "nested.fizz"},
- defaults.protectedProperties())
-}
-
-func TestProtectedProperties_DetectedOverride(t *testing.T) {
- bp := `
- defaults {
- name: "defaults",
- protected_properties: ["foo", "nested.fizz"],
- foo: ["defaults"],
- nested: {
- fizz: true,
- },
- }
-
- test {
- name: "foo",
- defaults: ["defaults"],
- foo: ["module"],
- nested: {
- fizz: false,
- },
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(
- []string{
- `\Qmodule "foo": attempts to append ["module"] to protected property "foo"'s value of ["defaults"] defined in module "defaults"\E`,
- `\Qmodule "foo": attempts to override protected property "nested.fizz" defined in module "defaults" with a different value (override true with false) so removing the property may necessitate other changes.\E`,
- })).RunTest(t)
-}
-
-func TestProtectedProperties_DefaultsConflict(t *testing.T) {
- bp := `
- defaults {
- name: "defaults1",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "value",
- },
- }
-
- defaults {
- name: "defaults2",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "another",
- },
- }
-
- test {
- name: "foo",
- defaults: ["defaults1", "defaults2"],
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qmodule "foo": has conflicting default values for protected property "other.buzz":
- defaults module "defaults1" provides value "value"
- defaults module "defaults2" provides value "another"\E`,
- )).RunTest(t)
-}
diff --git a/android/filegroup.go b/android/filegroup.go
index 7d929bc..0f6e00e 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -78,6 +78,12 @@
Strip_import_prefix *string
}
+// api srcs can be contained in filegroups.
+// this should be generated in api_bp2build workspace as well.
+func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
+ fg.ConvertWithBp2build(ctx)
+}
+
// ConvertWithBp2build performs bp2build conversion of filegroup
func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
srcs := bazel.MakeLabelListAttribute(
diff --git a/android/module.go b/android/module.go
index 58c5464..773d77b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1334,7 +1334,7 @@
// Check product variables for `enabled: true` flag override.
// Returns a list of the constraint_value targets who enable this override.
func productVariableConfigEnableLabels(ctx *topDownMutatorContext) []bazel.Label {
- productVariableProps := ProductVariableProperties(ctx)
+ productVariableProps := ProductVariableProperties(ctx, ctx.Module())
productConfigEnablingTargets := []bazel.Label{}
const propName = "Enabled"
if productConfigProps, exists := productVariableProps[propName]; exists {
diff --git a/android/mutator.go b/android/mutator.go
index 4dacb8d..676f8a5 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -268,6 +268,11 @@
// platforms, as dictated by a given bool attribute: the target will not be buildable in
// any platform for which this bool attribute is false.
CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
+
+ // CreateBazelTargetAliasInDir creates an alias definition in `dir` directory.
+ // This function can be used to create alias definitions in a directory that is different
+ // from the directory of the visited Soong module.
+ CreateBazelTargetAliasInDir(dir string, name string, actual bazel.Label)
}
type topDownMutatorContext struct {
@@ -705,6 +710,34 @@
t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
}
+var (
+ bazelAliasModuleProperties = bazel.BazelTargetModuleProperties{
+ Rule_class: "alias",
+ }
+)
+
+type bazelAliasAttributes struct {
+ Actual *bazel.LabelAttribute
+}
+
+func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
+ dir string,
+ name string,
+ actual bazel.Label) {
+ mod := t.Module()
+ attrs := &bazelAliasAttributes{
+ Actual: bazel.MakeLabelAttribute(actual.Label),
+ }
+ info := bp2buildInfo{
+ Dir: dir,
+ BazelProps: bazelAliasModuleProperties,
+ CommonAttrs: CommonAttributes{Name: name},
+ ConstraintAttrs: constraintAttributes{},
+ Attrs: attrs,
+ }
+ mod.base().addBp2buildInfo(info)
+}
+
// ApexAvailableTags converts the apex_available property value of an ApexModule
// module and returns it as a list of keyed tags.
func ApexAvailableTags(mod Module) bazel.StringListAttribute {
diff --git a/android/variable.go b/android/variable.go
index f7ac7d6..8c5c0bc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -442,6 +442,7 @@
BuildBrokenDepfile *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
+ BuildBrokenUsesSoongPython2Modules bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
BuildBrokenInputDirModules []string `json:",omitempty"`
@@ -663,9 +664,8 @@
type ProductConfigProperties map[string]map[ProductConfigProperty]interface{}
// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
-// have been set for the module in the given context.
-func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProperties {
- module := ctx.Module()
+// have been set for the given module.
+func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductConfigProperties {
moduleBase := module.base()
productConfigProperties := ProductConfigProperties{}
diff --git a/apex/apex.go b/apex/apex.go
index 88eb72f..f506876 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -50,7 +50,7 @@
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_test", TestApexBundleFactory)
ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- ctx.RegisterModuleType("apex_defaults", defaultsFactory)
+ ctx.RegisterModuleType("apex_defaults", DefaultsFactory)
ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
ctx.RegisterModuleType("override_apex", OverrideApexFactory)
ctx.RegisterModuleType("apex_set", apexSetFactory)
@@ -2728,14 +2728,9 @@
}
// apex_defaults provides defaultable properties to other apex modules.
-func defaultsFactory() android.Module {
- return DefaultsFactory()
-}
-
-func DefaultsFactory(props ...interface{}) android.Module {
+func DefaultsFactory() android.Module {
module := &Defaults{}
- module.AddProperties(props...)
module.AddProperties(
&apexBundleProperties{},
&apexTargetBundleProperties{},
@@ -3538,7 +3533,7 @@
fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts))
}
- productVariableProps := android.ProductVariableProperties(ctx)
+ productVariableProps := android.ProductVariableProperties(ctx, a)
// TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
// given it's coming via config, we probably don't want to put it in here.
var minSdkVersion bazel.StringAttribute
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 1c0e563..73c889f 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -61,7 +61,10 @@
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("apex", apex.BundleFactory)
+ ctx.RegisterModuleType("apex_defaults", apex.DefaultsFactory)
ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
+ ctx.RegisterModuleType("soong_config_module_type", android.SoongConfigModuleTypeFactory)
+ ctx.RegisterModuleType("soong_config_string_variable", android.SoongConfigStringVariableDummyFactory)
}
func TestApexBundleSimple(t *testing.T) {
@@ -1359,3 +1362,87 @@
}),
}})
}
+
+func TestApexBundle_overridePlusProductVars(t *testing.T) {
+ // Reproduction of b/271424349
+ // Tests that overriding an apex that uses product variables correctly copies the product var
+ // selects over to the override.
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - overriding a module that uses product vars",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Blueprint: `
+soong_config_string_variable {
+ name: "library_linking_strategy",
+ values: [
+ "prefer_static",
+ ],
+}
+
+soong_config_module_type {
+ name: "library_linking_strategy_apex_defaults",
+ module_type: "apex_defaults",
+ config_namespace: "ANDROID",
+ variables: ["library_linking_strategy"],
+ properties: [
+ "manifest",
+ "min_sdk_version",
+ ],
+}
+
+library_linking_strategy_apex_defaults {
+ name: "higher_min_sdk_when_prefer_static",
+ soong_config_variables: {
+ library_linking_strategy: {
+ // Use the R min_sdk_version
+ prefer_static: {},
+ // Override the R min_sdk_version to min_sdk_version that supports dcla
+ conditions_default: {
+ min_sdk_version: "31",
+ },
+ },
+ },
+}
+
+filegroup {
+ name: "foo-file_contexts",
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "foo",
+ defaults: ["higher_min_sdk_when_prefer_static"],
+ min_sdk_version: "30",
+ package_name: "pkg_name",
+ file_contexts: ":foo-file_contexts",
+}
+override_apex {
+ name: "override_foo",
+ base: ":foo",
+ package_name: "override_pkg_name",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "foo", AttrNameToString{
+ "file_contexts": `":foo-file_contexts"`,
+ "manifest": `"apex_manifest.json"`,
+ "min_sdk_version": `select({
+ "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": "30",
+ "//conditions:default": "31",
+ })`,
+ "package_name": `"pkg_name"`,
+ }), MakeBazelTarget("apex", "override_foo", AttrNameToString{
+ "base_apex_name": `"foo"`,
+ "file_contexts": `":foo-file_contexts"`,
+ "manifest": `"apex_manifest.json"`,
+ "min_sdk_version": `select({
+ "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": "30",
+ "//conditions:default": "31",
+ })`,
+ "package_name": `"override_pkg_name"`,
+ }),
+ }})
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ced779c..fde9b69 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -60,6 +60,15 @@
}
}
+// PackageName returns the package of the Bazel target.
+// Defaults to root of tree.
+func (t BazelTarget) PackageName() string {
+ if t.packageName == "" {
+ return "."
+ }
+ return t.packageName
+}
+
// BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget
@@ -337,7 +346,10 @@
return
}
- buildFileToTargets[dir] = append(buildFileToTargets[dir], targets...)
+ for _, target := range targets {
+ targetDir := target.PackageName()
+ buildFileToTargets[targetDir] = append(buildFileToTargets[targetDir], target)
+ }
})
if len(errs) > 0 {
@@ -454,7 +466,8 @@
targetName := targetNameWithVariant(ctx, m)
return BazelTarget{
- name: targetName,
+ name: targetName,
+ packageName: ctx.ModuleDir(m),
content: fmt.Sprintf(
soongModuleTargetTemplate,
targetName,
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 0784f4b..f1d6398 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -755,3 +755,29 @@
},
})
}
+
+func TestJavaLibraryArchVariantSrcsWithExcludes(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with arch variant libs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java"],
+ target: {
+ android: {
+ exclude_srcs: ["a.java"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+ "srcs": `["b.java"] + select({
+ "//build/bazel/platforms/os:android": [],
+ "//conditions:default": ["a.java"],
+ })`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+ },
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 43baf98..a737ea1 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -21,6 +21,7 @@
import (
"fmt"
+ "sort"
"strings"
"testing"
@@ -263,6 +264,12 @@
t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
description, expectedCount, expectedContents, actualCount, actualTargets)
} else {
+ sort.SliceStable(actualTargets, func(i, j int) bool {
+ return actualTargets[i].name < actualTargets[j].name
+ })
+ sort.SliceStable(expectedContents, func(i, j int) bool {
+ return getTargetName(expectedContents[i]) < getTargetName(expectedContents[j])
+ })
for i, actualTarget := range actualTargets {
if w, g := expectedContents[i], actualTarget.content; w != g {
t.Errorf(
@@ -454,7 +461,7 @@
}
}
}
- productVariableProps := android.ProductVariableProperties(ctx)
+ productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
if props, ok := productVariableProps["String_literal_prop"]; ok {
for c, p := range props {
if val, ok := p.(*string); ok {
@@ -637,3 +644,13 @@
"exports": `[":` + name + `"]`,
})
}
+
+func getTargetName(targetContent string) string {
+ data := strings.Split(targetContent, "name = \"")
+ if len(data) < 2 {
+ return ""
+ } else {
+ endIndex := strings.Index(data[1], "\"")
+ return data[1][:endIndex]
+ }
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 1ea8bda..8644bf6 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -766,7 +766,7 @@
nativeCoverage = BoolPtr(false)
}
- productVariableProps := android.ProductVariableProperties(ctx)
+ productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
(&compilerAttrs).convertProductVariables(ctx, productVariableProps)
(&linkerAttrs).convertProductVariables(ctx, productVariableProps)
diff --git a/cc/config/global.go b/cc/config/global.go
index 05dc773..488af45 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -193,6 +193,7 @@
noOverrideGlobalCflags = []string{
"-Werror=bool-operation",
+ "-Werror=format-insufficient-args",
"-Werror=implicit-int-float-conversion",
"-Werror=int-in-bool-context",
"-Werror=int-to-pointer-cast",
@@ -247,6 +248,8 @@
noOverride64GlobalCflags = []string{}
noOverrideExternalGlobalCflags = []string{
+ // http://b/191699019
+ "-Wno-format-insufficient-args",
"-Wno-sizeof-array-div",
"-Wno-unused-but-set-variable",
"-Wno-unused-but-set-parameter",
@@ -284,9 +287,6 @@
// http://b/239661264
"-Wno-deprecated-non-prototype",
-
- // http://b/191699019
- "-Wno-format-insufficient-args",
}
llvmNextExtraCommonGlobalCflags = []string{
diff --git a/cc/library.go b/cc/library.go
index e73af81..27f0623 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -464,6 +464,21 @@
ctx.CreateBazelTargetModule(stubSuitesProps,
android.CommonAttributes{Name: m.Name() + "_stub_libs"},
stubSuitesAttrs)
+
+ // Add alias for the stub shared_library in @api_surfaces repository
+ currentModuleLibApiDir := ctx.Config().ApiSurfacesDir(android.ModuleLibApi, "current")
+ actualLabelInMainWorkspace := bazel.Label{
+ Label: fmt.Sprintf("@//%s:%s_stub_libs_current", ctx.ModuleDir(), m.Name()),
+ }
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, m.Name(), actualLabelInMainWorkspace)
+
+ // Add alias for headers exported by the stub library
+ headerLabelInMainWorkspace := bazel.Label{
+ // This label is generated from cc_stub_suite macro
+ Label: fmt.Sprintf("@//%s:%s_stub_libs_%s_headers", ctx.ModuleDir(), m.Name(), android.ModuleLibApi.String()),
+ }
+ headerAlias := m.Name() + "_headers"
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, headerAlias, headerLabelInMainWorkspace)
}
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 5c187f6..9b51160 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -136,7 +136,7 @@
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView, topDir)
- err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir))
+ err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir), false)
maybeQuit(err, "")
touch(shared.JoinPath(topDir, queryviewMarker))
}
@@ -174,7 +174,28 @@
// Run codegen to generate BUILD files
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build, topDir)
absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
- err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir)
+ // Always generate bp2build_all_srcs filegroups in api_bp2build.
+ // This is necessary to force each Android.bp file to create an equivalent BUILD file
+ // and prevent package boundray issues.
+ // e.g.
+ // Source
+ // f/b/Android.bp
+ // java_library{
+ // name: "foo",
+ // api: "api/current.txt",
+ // }
+ //
+ // f/b/api/Android.bp <- will cause package boundary issues
+ //
+ // Gen
+ // f/b/BUILD
+ // java_contribution{
+ // name: "foo.contribution",
+ // api: "//f/b/api:current.txt",
+ // }
+ //
+ // If we don't generate f/b/api/BUILD, foo.contribution will be unbuildable.
+ err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir, true)
maybeQuit(err, "")
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 35ae009..ce32184 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -25,11 +25,11 @@
)
// A helper function to generate a Read-only Bazel workspace in outDir
-func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string) error {
+func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string, generateFilegroups bool) error {
os.RemoveAll(outDir)
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
- res, err := bp2build.GenerateBazelTargets(ctx, false)
+ res, err := bp2build.GenerateBazelTargets(ctx, generateFilegroups)
if err != nil {
panic(err)
}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index b0660df..dcd7fdc 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -717,7 +717,7 @@
}
}
- for propName, productConfigProps := range android.ProductVariableProperties(ctx) {
+ for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) {
for configProp, propVal := range productConfigProps {
if propName == "Src" {
props, ok := propVal.(*string)
diff --git a/java/java.go b/java/java.go
index 63c4416..e8f78ba 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2660,6 +2660,7 @@
}
}
}
+ srcs.ResolveExcludes()
javaSrcPartition := "java"
protoSrcPartition := "proto"
@@ -2843,12 +2844,12 @@
if !bp2BuildInfo.hasKotlin {
props = bazel.BazelTargetModuleProperties{
Rule_class: "java_library",
- Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
}
} else {
props = bazel.BazelTargetModuleProperties{
Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl",
+ Bzl_load_location: "//build/bazel/rules/kotlin:rules.bzl",
}
}
@@ -2928,7 +2929,8 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_binary",
+ Rule_class: "java_binary",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
}
attrs := &javaBinaryHostAttributes{
Runtime_deps: runtimeDeps,
@@ -2943,7 +2945,7 @@
ktName := m.Name() + "_kt"
ktProps := bazel.BazelTargetModuleProperties{
Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl",
+ Bzl_load_location: "//build/bazel/rules/kotlin:rules.bzl",
}
ktAttrs := &javaLibraryAttributes{
@@ -2980,7 +2982,10 @@
attrs := &bazelJavaImportAttributes{
Jars: jars,
}
- props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_import",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
+ }
name := android.RemoveOptionalPrebuiltPrefix(i.Name())
@@ -2991,7 +2996,13 @@
Neverlink: bazel.BoolAttribute{Value: &neverlink},
Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
}
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs)
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "java_library",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
+ },
+ android.CommonAttributes{Name: name + "-neverlink"},
+ neverlinkAttrs)
}
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 061f4d0..1bb4996 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -40,6 +40,13 @@
# NewApi checks will continue to be enforced for apex deps since
# lint.strict_updatability_linting will be true for those Soong modules
--disable_check NewApi
+# Disable ChromeOS specific checks
+--disable_check PermissionImpliesUnsupportedChromeOsHardware
+# Disable UnsafeImplicitIntentLaunch until it can avoid false positives/crash
+# TODO(265425607)
+--disable_check UnsafeImplicitIntentLaunch
+# InvalidId will give errors on ids defined like android:id="@androidprv:id/contentPanel"
+--disable_check InvalidId
# Downgrade existing errors to warnings
--warning_check AppCompatResource # 55 occurences in 10 modules
diff --git a/python/python.go b/python/python.go
index 0ae7b36..c7c523d 100644
--- a/python/python.go
+++ b/python/python.go
@@ -263,6 +263,12 @@
versionProps = append(versionProps, props.Version.Py3)
}
if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
+ if !mctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() &&
+ mctx.ModuleName() != "par_test" &&
+ mctx.ModuleName() != "py2-cmd" &&
+ mctx.ModuleName() != "py2-stdlib" {
+ mctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration")
+ }
versionNames = append(versionNames, pyVersion2)
versionProps = append(versionProps, props.Version.Py2)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 5dd45cd..ddbba74 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -191,6 +191,17 @@
],
}
+python_test_host {
+ name: "conv_linker_config_test",
+ main: "conv_linker_config_test.py",
+ srcs: [
+ "conv_linker_config_test.py",
+ "conv_linker_config.py",
+ ],
+ libs: ["linker_config_proto"],
+ test_suites: ["general-tests"],
+}
+
python_binary_host {
name: "get_clang_version",
main: "get_clang_version.py",
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 2ce0ee2..3ac1b7e 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -19,6 +19,7 @@
import collections
import json
import os
+import sys
import linker_config_pb2 #pylint: disable=import-error
from google.protobuf.descriptor import FieldDescriptor
@@ -26,17 +27,41 @@
from google.protobuf.text_format import MessageToString
+def LoadJsonMessage(path):
+ """
+ Loads a message from a .json file with `//` comments strippedfor convenience.
+ """
+ json_content = ''
+ with open(path) as f:
+ for line in f:
+ if not line.lstrip().startswith('//'):
+ json_content += line
+ obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
+ return ParseDict(obj, linker_config_pb2.LinkerConfig())
+
+
def Proto(args):
+ """
+ Merges input json files (--source) into a protobuf message (--output).
+ Fails if the output file exists. Set --force or --append to deal with the existing
+ output file.
+ --force to overwrite the output file with the input (.json files).
+ --append to append the input to the output file.
+ """
pb = linker_config_pb2.LinkerConfig()
+ if os.path.isfile(args.output):
+ if args.force:
+ pass
+ elif args.append:
+ with open(args.output, 'rb') as f:
+ pb.ParseFromString(f.read())
+ else:
+ sys.stderr.write(f'Error: {args.output} exists. Use --force or --append.\n')
+ sys.exit(1)
+
if args.source:
for input in args.source.split(':'):
- json_content = ''
- with open(input) as f:
- for line in f:
- if not line.lstrip().startswith('//'):
- json_content += line
- obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
- ParseDict(obj, pb)
+ pb.MergeFrom(LoadJsonMessage(input))
with open(args.output, 'wb') as f:
f.write(pb.SerializeToString())
@@ -114,6 +139,17 @@
required=True,
type=str,
help='Target path to create protobuf file.')
+ option_for_existing_output = parser_proto.add_mutually_exclusive_group()
+ option_for_existing_output.add_argument(
+ '-f',
+ '--force',
+ action='store_true',
+ help='Overwrite if the output file exists.')
+ option_for_existing_output.add_argument(
+ '-a',
+ '--append',
+ action='store_true',
+ help='Append the input to the output file if the output file exists.')
parser_proto.set_defaults(func=Proto)
print_proto = subparsers.add_parser(
@@ -195,8 +231,12 @@
def main():
- args = GetArgParser().parse_args()
- args.func(args)
+ parser = GetArgParser()
+ args = parser.parse_args()
+ if 'func' in args:
+ args.func(args)
+ else:
+ parser.print_help()
if __name__ == '__main__':
diff --git a/scripts/conv_linker_config_test.py b/scripts/conv_linker_config_test.py
new file mode 100644
index 0000000..d19a47b
--- /dev/null
+++ b/scripts/conv_linker_config_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for conv_linker_config.py."""
+
+import io
+import os
+import shutil
+import tempfile
+import unittest
+
+import conv_linker_config
+from contextlib import redirect_stderr
+from linker_config_pb2 import LinkerConfig
+
+class FileArgs:
+ def __init__(self, files, sep = ':'):
+ self.files = files
+ self.sep = sep
+
+
+class FileArg:
+ def __init__(self, file):
+ self.file = file
+
+
+class TempDirTest(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+
+ def write(self, name, contents):
+ with open(os.path.join(self.tempdir, name), 'wb') as f:
+ f.write(contents)
+
+
+ def read(self, name):
+ with open(os.path.join(self.tempdir, name), 'rb') as f:
+ return f.read()
+
+
+ def resolve_paths(self, args):
+ for i in range(len(args)):
+ if isinstance(args[i], FileArgs):
+ args[i] = args[i].sep.join(os.path.join(self.tempdir, f.file) for f in args[i].files)
+ elif isinstance(args[i], FileArg):
+ args[i] = os.path.join(self.tempdir, args[i].file)
+ return args
+
+
+class ConvLinkerConfigTest(TempDirTest):
+ """Unit tests for conv_linker_config."""
+
+
+ def test_Proto_empty_input(self):
+ self.command(['proto', '-s', '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertEqual(pb, LinkerConfig())
+
+
+ def test_Proto_single_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.command(['proto', '-s', FileArg('foo.json'), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSequenceEqual(pb.provideLibs, ['libfoo.so'])
+
+
+ def test_Proto_with_multiple_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArgs([FileArg('foo.json'), FileArg('bar.json')]), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_existing_output(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ buf = io.StringIO()
+ with self.assertRaises(SystemExit) as err:
+ with redirect_stderr(buf):
+ self.command(['proto', '-o', FileArg('out.pb')])
+ self.assertEqual(err.exception.code, 1)
+ self.assertRegex(buf.getvalue(), r'.*out\.pb exists')
+
+
+ def test_Proto_with_append(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-a'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_force(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-f'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libbar.so']))
+
+
+ def command(self, args):
+ parser = conv_linker_config.GetArgParser()
+ parsed_args = parser.parse_args(self.resolve_paths(args))
+ parsed_args.func(parsed_args)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 1ff1b5b..68d7f8d 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -343,4 +343,29 @@
run_bazel build --config=android --config=api_bp2build //:empty
}
+# Verify that an *_api_contribution target can refer to an api file from
+# another Bazel package.
+function test_api_export_from_another_bazel_package() {
+ setup
+ # Parent dir Android.bp
+ mkdir -p foo
+ cat > foo/Android.bp << 'EOF'
+cc_library {
+ name: "libfoo",
+ stubs: {
+ symbol_file: "api/libfoo.map.txt",
+ },
+}
+EOF
+ # Child dir Android.bp
+ mkdir -p foo/api
+ cat > foo/api/Android.bp << 'EOF'
+package{}
+EOF
+ touch foo/api/libfoo.map.txt
+ # Run test
+ run_soong api_bp2build
+ run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
+}
+
scan_and_run_tests
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index b3a027e..cbdeb27 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -135,8 +135,8 @@
e := t.peek()
e.procResInfo = append(e.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
Name: proto.String(name),
- UserTimeMicros: proto.Uint64(uint64(rusage.Utime.Usec)),
- SystemTimeMicros: proto.Uint64(uint64(rusage.Stime.Usec)),
+ UserTimeMicros: proto.Uint64(uint64(state.UserTime().Microseconds())),
+ SystemTimeMicros: proto.Uint64(uint64(state.SystemTime().Microseconds())),
MinorPageFaults: proto.Uint64(uint64(rusage.Minflt)),
MajorPageFaults: proto.Uint64(uint64(rusage.Majflt)),
// ru_inblock and ru_oublock are measured in blocks of 512 bytes.