Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a060c452 authored by Liz Kammer's avatar Liz Kammer
Browse files

Handle product_variable asflag for cc_object.

cc_object crtbrand sets product_variable.platform_sdk_version.asflag
and will not compile correctly within mixed builds without it.

Only handles product_variables that expand product variables.

Bug: 181794963
Test: ~/aosp/build/bazel/scripts/milestone-2/demo.sh full
Change-Id: I293fcb18032aa51f63bb7b3de94abd6d1ec38180
parent dca349a7
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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
}
@@ -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()
}
+57 −0
Original line number Diff line number Diff line
@@ -446,6 +446,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
+23 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ package bazel

import (
	"fmt"
	"regexp"
	"sort"
)

@@ -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 {
@@ -144,3 +147,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
}
+28 −0
Original line number Diff line number Diff line
@@ -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",
    ],
)`,
			},
		},
+20 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ type bazelObjectAttributes struct {
	Srcs               bazel.LabelList
	Deps               bazel.LabelList
	Copts              bazel.StringListAttribute
	Asflags            []string
	Local_include_dirs []string
}

@@ -150,6 +151,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) {
	var srcs []string
	var excludeSrcs []string
	var localIncludeDirs []string
	var asFlags []string
	for _, props := range m.compiler.compilerProps() {
		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
			copts.Value = baseCompilerProps.Cflags
@@ -171,6 +173,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 {
			copts.SetValueForArch(arch.Name, cProps.Cflags)
@@ -182,6 +201,7 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) {
		Srcs:               android.BazelLabelForModuleSrcExcludes(ctx, srcs, excludeSrcs),
		Deps:               deps,
		Copts:              copts,
		Asflags:            asFlags,
		Local_include_dirs: localIncludeDirs,
	}