bp2build: add configurable attribute (select) support.

This CL adds a basic framework to support configurable string_list
attributes, selecting on the Arch variant (x86, x86_64, arm, arm64).

It offers fine-grained controls to map individual configurable
properties (arch_variant) to configurable Bazel attributes, starting
with the string_list type for the copts property for cc_object.

This design is primarily motivated to have minimal boilerplate in
bp2build mutators, allowing anyone to opt-in configurable attributes,
and modify intermediate states before passing them on into the
CreateBazelTargetModule instantiator.

Fixes: 178130668

Test: go tests
Test: build/bazel/scripts/milestone-2/demo.sh

Change-Id: Id6f04d7c560312a93e193d7ca4e1b7ceb6062260
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a4c4a0d..7fa4996 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -354,11 +354,42 @@
 		ret += makeIndent(indent)
 		ret += "]"
 	case reflect.Struct:
+		// Special cases where the bp2build sends additional information to the codegenerator
+		// by wrapping the attributes in a custom struct type.
 		if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
 			// TODO(b/165114590): convert glob syntax
 			return prettyPrint(reflect.ValueOf(labels.Includes), indent)
 		} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
 			return fmt.Sprintf("%q", label.Label), nil
+		} else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok {
+			// A Bazel string_list attribute that may contain a select statement.
+			ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
+			if err != nil {
+				return ret, err
+			}
+
+			if !stringList.HasArchSpecificValues() {
+				// Select statement not needed.
+				return ret, nil
+			}
+
+			ret += " + " + "select({\n"
+			for _, arch := range android.ArchTypeList() {
+				value := stringList.GetValueForArch(arch.Name)
+				if len(value) > 0 {
+					ret += makeIndent(indent + 1)
+					list, _ := prettyPrint(reflect.ValueOf(value), indent+1)
+					ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list)
+				}
+			}
+
+			ret += makeIndent(indent + 1)
+			list, _ := prettyPrint(reflect.ValueOf(stringList.GetValueForArch("default")), indent+1)
+			ret += fmt.Sprintf("\"%s\": %s,\n", "//conditions:default", list)
+
+			ret += makeIndent(indent)
+			ret += "})"
+			return ret, err
 		}
 
 		ret = "{\n"