Add e.g. Target: { Android_arm: { ...} } support to LabelAttribute.

LabelListAttribute support was already added, but LabelAttribute support is needed for cc_import rules.

Test: Added unit test for version_script, which is the only supported LabelAttribute so far.

Change-Id: I4e86e7391586e0780623d06b794e7399f0ccd50e
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index b5070b9..c13e737 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -60,19 +60,67 @@
 }
 
 func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
-	var value reflect.Value
-	var archSelects selects
-
-	if label.HasConfigurableValues() {
-		archSelects = map[string]reflect.Value{}
-		for arch, selectKey := range bazel.PlatformArchMap {
-			archSelects[selectKey] = reflect.ValueOf(label.GetValueForArch(arch))
-		}
-	} else {
-		value = reflect.ValueOf(label.Value)
+	value := reflect.ValueOf(label.Value)
+	if !label.HasConfigurableValues() {
+		return value, []selects{}
 	}
 
-	return value, []selects{archSelects}
+	// Keep track of which arches and oses have been used in case we need to raise a warning
+	usedArches := make(map[string]bool)
+	usedOses := make(map[string]bool)
+
+	archSelects := map[string]reflect.Value{}
+	for arch, selectKey := range bazel.PlatformArchMap {
+		archSelects[selectKey] = reflect.ValueOf(label.GetValueForArch(arch))
+		if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
+			usedArches[arch] = true
+		}
+	}
+
+	osSelects := map[string]reflect.Value{}
+	for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
+		selectKey := bazel.PlatformOsMap[os]
+		osSelects[selectKey] = reflect.ValueOf(label.GetOsValueForTarget(os))
+		if osSelects[selectKey].IsValid() && !isZero(osSelects[selectKey]) {
+			usedOses[os] = true
+		}
+	}
+
+	osArchSelects := make([]selects, 0)
+	for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
+		archSelects := make(map[string]reflect.Value)
+		// TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (not in AllArches)
+		for _, arch := range bazel.AllArches {
+			target := os + "_" + arch
+			selectKey := bazel.PlatformTargetMap[target]
+			archSelects[selectKey] = reflect.ValueOf(label.GetOsArchValueForTarget(os, arch))
+			if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
+				if _, ok := usedArches[arch]; ok {
+					fmt.Printf("WARNING: Same arch used twice in LabelAttribute select: arch '%s'\n", arch)
+				}
+				if _, ok := usedOses[os]; ok {
+					fmt.Printf("WARNING: Same os used twice in LabelAttribute select: os '%s'\n", os)
+				}
+			}
+		}
+		osArchSelects = append(osArchSelects, archSelects)
+	}
+
+	// Because we have to return a single Label, we can only use one select statement
+	combinedSelects := map[string]reflect.Value{}
+	for k, v := range archSelects {
+		combinedSelects[k] = v
+	}
+	for k, v := range osSelects {
+		combinedSelects[k] = v
+	}
+	for _, osArchSelect := range osArchSelects {
+		for k, v := range osArchSelect {
+			combinedSelects[k] = v
+		}
+	}
+
+	return value, []selects{combinedSelects}
 }
 
 func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {