make arch and variant parsing more robust

Post-process the arch and cpu variants to treat the arch name or
"generic" as an empty variant.  Filter out extra empty abis.  Ignore
empty arches.  Print a useful error message when appending properties
fails to find the target field, when an unknown architecture is used, or
when a toolchain has not been implemented for the selected
architecture.

Change-Id: I671d4cd04975f4f29aefc4267b3a624868ce6a75
diff --git a/common/arch.go b/common/arch.go
index 52c8347..21f638a 100644
--- a/common/arch.go
+++ b/common/arch.go
@@ -431,7 +431,13 @@
 func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
 	dst, src interface{}, field, srcPrefix string) {
 
-	src = reflect.ValueOf(src).FieldByName(field).Elem().Interface()
+	srcField := reflect.ValueOf(src).FieldByName(field)
+	if !srcField.IsValid() {
+		ctx.ModuleErrorf("field %q does not exist", srcPrefix)
+		return
+	}
+
+	src = srcField.Elem().Interface()
 
 	filter := func(property string,
 		dstField, srcField reflect.StructField,
@@ -647,7 +653,7 @@
 
 	hostArches := []Arch{hostArch}
 
-	if variables.HostSecondaryArch != nil {
+	if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
 		hostSecondaryArch, err := decodeArch(*variables.HostSecondaryArch, nil, nil, nil)
 		if err != nil {
 			return nil, nil, err
@@ -667,7 +673,7 @@
 
 	deviceArches := []Arch{deviceArch}
 
-	if variables.DeviceSecondaryArch != nil {
+	if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
 		deviceSecondaryArch, err := decodeArch(*variables.DeviceSecondaryArch,
 			variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
 			variables.DeviceSecondaryAbi)
@@ -696,14 +702,34 @@
 		return nil
 	}
 
-	archType := archTypeMap[arch]
+	archType, ok := archTypeMap[arch]
+	if !ok {
+		return Arch{}, fmt.Errorf("unknown arch %q", arch)
+	}
 
-	return Arch{
+	a := Arch{
 		ArchType:    archType,
 		ArchVariant: stringPtr(archVariant),
 		CpuVariant:  stringPtr(cpuVariant),
 		Abi:         slicePtr(abi),
-	}, nil
+	}
+
+	if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
+		a.ArchVariant = ""
+	}
+
+	if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
+		a.CpuVariant = ""
+	}
+
+	for i := 0; i < len(a.Abi); i++ {
+		if a.Abi[i] == "" {
+			a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
+			i--
+		}
+	}
+
+	return a, nil
 }
 
 // Use the module multilib setting to select one or more arches from an arch list