Loading android/mutator.go +6 −1 Original line number Diff line number Diff line Loading @@ -539,7 +539,7 @@ func (t *topDownMutatorContext) CreateBazelTargetModule( Name: &name, } b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule) b := t.createModuleWithoutInheritance(factory, &nameProp, attrs).(BazelTargetModule) b.SetBazelTargetModuleProperties(bazelProps) return b } Loading Loading @@ -608,6 +608,11 @@ func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...int return module } func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module { module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), props...).(Module) return module } func (b *bottomUpMutatorContext) MutatorName() string { return b.bp.MutatorName() } Loading android/variable.go +57 −0 Original line number Diff line number Diff line Loading @@ -448,6 +448,63 @@ func (v *productVariables) SetDefaultConfig() { } } // ProductConfigContext requires the access to the Module to get product config properties. type ProductConfigContext interface { Module() Module } // ProductConfigProperty contains the information for a single property (may be a struct) paired // with the appropriate ProductConfigVariable. type ProductConfigProperty struct { ProductConfigVariable string Property interface{} } // ProductConfigProperties is a map of property name to a slice of ProductConfigProperty such that // all it all product variable-specific versions of a property are easily accessed together type ProductConfigProperties map[string][]ProductConfigProperty // ProductVariableProperties returns a ProductConfigProperties containing only the properties which // have been set for the module in the given context. func ProductVariableProperties(ctx ProductConfigContext) ProductConfigProperties { module := ctx.Module() moduleBase := module.base() productConfigProperties := ProductConfigProperties{} if moduleBase.variableProperties == nil { return productConfigProperties } variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName("Product_variables") for i := 0; i < variableValues.NumField(); i++ { variableValue := variableValues.Field(i) // Check if any properties were set for the module if variableValue.IsZero() { continue } // e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc. productVariableName := variableValues.Type().Field(i).Name for j := 0; j < variableValue.NumField(); j++ { property := variableValue.Field(j) // If the property wasn't set, no need to pass it along if property.IsZero() { continue } // e.g. Asflags, Cflags, Enabled, etc. propertyName := variableValue.Type().Field(j).Name productConfigProperties[propertyName] = append(productConfigProperties[propertyName], ProductConfigProperty{ ProductConfigVariable: productVariableName, Property: property.Interface(), }) } } return productConfigProperties } func VariableMutator(mctx BottomUpMutatorContext) { var module Module var ok bool Loading bazel/properties.go +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package bazel import ( "fmt" "regexp" "sort" ) Loading @@ -31,6 +32,8 @@ type BazelTargetModuleProperties struct { const BazelTargetModuleNamePrefix = "__bp2build__" var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)") // Label is used to represent a Bazel compatible Label. Also stores the original bp text to support // string replacement. type Label struct { Loading Loading @@ -225,3 +228,23 @@ func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) { panic(fmt.Errorf("Unknown arch: %s", arch)) } } // TryVariableSubstitution, replace string substitution formatting within each string in slice with // Starlark string.format compatible tag for productVariable. func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) { ret := make([]string, 0, len(slice)) changesMade := false for _, s := range slice { newS, changed := TryVariableSubstitution(s, productVariable) ret = append(ret, newS) changesMade = changesMade || changed } return ret, changesMade } // TryVariableSubstitution, replace string substitution formatting within s with Starlark // string.format compatible tag for productVariable. func TryVariableSubstitution(s string, productVariable string) (string, bool) { sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}") return sub, s != sub } bp2build/cc_object_conversion_test.go +28 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,34 @@ cc_object { srcs = [ "a/b/c.c", ], )`, }, }, { description: "cc_object with product variable", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", include_build_directory: false, product_variables: { platform_sdk_version: { asflags: ["-DPLATFORM_SDK_VERSION=%d"], }, }, bazel_module: { bp2build_available: true }, } `, expectedBazelTargets: []string{`cc_object( name = "foo", asflags = [ "-DPLATFORM_SDK_VERSION={Platform_sdk_version}", ], copts = [ "-fno-addrsig", ], )`, }, }, Loading cc/object.go +20 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ type bazelObjectAttributes struct { Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute Copts bazel.StringListAttribute Asflags []string Local_include_dirs []string } Loading Loading @@ -158,6 +159,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { var copts bazel.StringListAttribute var srcs bazel.LabelListAttribute var localIncludeDirs []string var asFlags []string for _, props := range m.compiler.compilerProps() { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { copts.Value = baseCompilerProps.Cflags Loading @@ -183,6 +185,23 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { } } productVariableProps := android.ProductVariableProperties(ctx) if props, exists := productVariableProps["Asflags"]; exists { // TODO(b/183595873): consider deduplicating handling of product variable properties for _, prop := range props { flags, ok := prop.Property.([]string) if !ok { ctx.ModuleErrorf("Could not convert product variable asflag property") return } // TODO(b/183595873) handle other product variable usages -- as selects? if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed { asFlags = append(asFlags, newFlags...) } } } // TODO(b/183595872) warn/error if we're not handling product variables for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) { if cProps, ok := p.(*BaseCompilerProperties); ok { srcs.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcExcludes(ctx, cProps.Srcs, cProps.Exclude_srcs)) Loading @@ -194,6 +213,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { Srcs: srcs, Deps: deps, Copts: copts, Asflags: asFlags, Local_include_dirs: localIncludeDirs, } Loading Loading
android/mutator.go +6 −1 Original line number Diff line number Diff line Loading @@ -539,7 +539,7 @@ func (t *topDownMutatorContext) CreateBazelTargetModule( Name: &name, } b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule) b := t.createModuleWithoutInheritance(factory, &nameProp, attrs).(BazelTargetModule) b.SetBazelTargetModuleProperties(bazelProps) return b } Loading Loading @@ -608,6 +608,11 @@ func (t *topDownMutatorContext) CreateModule(factory ModuleFactory, props ...int return module } func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module { module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), props...).(Module) return module } func (b *bottomUpMutatorContext) MutatorName() string { return b.bp.MutatorName() } Loading
android/variable.go +57 −0 Original line number Diff line number Diff line Loading @@ -448,6 +448,63 @@ func (v *productVariables) SetDefaultConfig() { } } // ProductConfigContext requires the access to the Module to get product config properties. type ProductConfigContext interface { Module() Module } // ProductConfigProperty contains the information for a single property (may be a struct) paired // with the appropriate ProductConfigVariable. type ProductConfigProperty struct { ProductConfigVariable string Property interface{} } // ProductConfigProperties is a map of property name to a slice of ProductConfigProperty such that // all it all product variable-specific versions of a property are easily accessed together type ProductConfigProperties map[string][]ProductConfigProperty // ProductVariableProperties returns a ProductConfigProperties containing only the properties which // have been set for the module in the given context. func ProductVariableProperties(ctx ProductConfigContext) ProductConfigProperties { module := ctx.Module() moduleBase := module.base() productConfigProperties := ProductConfigProperties{} if moduleBase.variableProperties == nil { return productConfigProperties } variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName("Product_variables") for i := 0; i < variableValues.NumField(); i++ { variableValue := variableValues.Field(i) // Check if any properties were set for the module if variableValue.IsZero() { continue } // e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc. productVariableName := variableValues.Type().Field(i).Name for j := 0; j < variableValue.NumField(); j++ { property := variableValue.Field(j) // If the property wasn't set, no need to pass it along if property.IsZero() { continue } // e.g. Asflags, Cflags, Enabled, etc. propertyName := variableValue.Type().Field(j).Name productConfigProperties[propertyName] = append(productConfigProperties[propertyName], ProductConfigProperty{ ProductConfigVariable: productVariableName, Property: property.Interface(), }) } } return productConfigProperties } func VariableMutator(mctx BottomUpMutatorContext) { var module Module var ok bool Loading
bazel/properties.go +23 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package bazel import ( "fmt" "regexp" "sort" ) Loading @@ -31,6 +32,8 @@ type BazelTargetModuleProperties struct { const BazelTargetModuleNamePrefix = "__bp2build__" var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)") // Label is used to represent a Bazel compatible Label. Also stores the original bp text to support // string replacement. type Label struct { Loading Loading @@ -225,3 +228,23 @@ func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) { panic(fmt.Errorf("Unknown arch: %s", arch)) } } // TryVariableSubstitution, replace string substitution formatting within each string in slice with // Starlark string.format compatible tag for productVariable. func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) { ret := make([]string, 0, len(slice)) changesMade := false for _, s := range slice { newS, changed := TryVariableSubstitution(s, productVariable) ret = append(ret, newS) changesMade = changesMade || changed } return ret, changesMade } // TryVariableSubstitution, replace string substitution formatting within s with Starlark // string.format compatible tag for productVariable. func TryVariableSubstitution(s string, productVariable string) (string, bool) { sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}") return sub, s != sub }
bp2build/cc_object_conversion_test.go +28 −0 Original line number Diff line number Diff line Loading @@ -206,6 +206,34 @@ cc_object { srcs = [ "a/b/c.c", ], )`, }, }, { description: "cc_object with product variable", moduleTypeUnderTest: "cc_object", moduleTypeUnderTestFactory: cc.ObjectFactory, moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build, blueprint: `cc_object { name: "foo", include_build_directory: false, product_variables: { platform_sdk_version: { asflags: ["-DPLATFORM_SDK_VERSION=%d"], }, }, bazel_module: { bp2build_available: true }, } `, expectedBazelTargets: []string{`cc_object( name = "foo", asflags = [ "-DPLATFORM_SDK_VERSION={Platform_sdk_version}", ], copts = [ "-fno-addrsig", ], )`, }, }, Loading
cc/object.go +20 −0 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ type bazelObjectAttributes struct { Srcs bazel.LabelListAttribute Deps bazel.LabelListAttribute Copts bazel.StringListAttribute Asflags []string Local_include_dirs []string } Loading Loading @@ -158,6 +159,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { var copts bazel.StringListAttribute var srcs bazel.LabelListAttribute var localIncludeDirs []string var asFlags []string for _, props := range m.compiler.compilerProps() { if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok { copts.Value = baseCompilerProps.Cflags Loading @@ -183,6 +185,23 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { } } productVariableProps := android.ProductVariableProperties(ctx) if props, exists := productVariableProps["Asflags"]; exists { // TODO(b/183595873): consider deduplicating handling of product variable properties for _, prop := range props { flags, ok := prop.Property.([]string) if !ok { ctx.ModuleErrorf("Could not convert product variable asflag property") return } // TODO(b/183595873) handle other product variable usages -- as selects? if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed { asFlags = append(asFlags, newFlags...) } } } // TODO(b/183595872) warn/error if we're not handling product variables for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) { if cProps, ok := p.(*BaseCompilerProperties); ok { srcs.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcExcludes(ctx, cProps.Srcs, cProps.Exclude_srcs)) Loading @@ -194,6 +213,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) { Srcs: srcs, Deps: deps, Copts: copts, Asflags: asFlags, Local_include_dirs: localIncludeDirs, } Loading