Add os/target configurable selects for label list attributes.

This CL is pretty large, so I recommend starting with reading the newly
added tests for the expected behavior.

This change works in conjunction with the linked CLs in the Gerrit topic.
Those CLs add support for new platform() definitions for OS targets
specified in Soong's arch.go, which are configurable through
Android.bp's `target {}` property. It works similary to previous CLs
adding support for the `arch {}` property.

These configurable props are keyed by the OS: android, linux_bionic,
windows, and so on. They map to `select` statements in label list
attributes, which this CL enables for cc_library_headers' header_libs
and export_header_lib_headers props.

This enables //bionic/libc:libc_headers to be generated correctly, from:

    cc_library_headers {
        name: "libc_headers",
        target: {
            android: {
                header_libs: ["libc_headers_arch"],
                export_header_lib_headers: ["libc_headers_arch"],
            },
            linux_bionic: {
                header_libs: ["libc_headers_arch"],
                export_header_lib_headers: ["libc_headers_arch"],
            },
        },
        // omitted props
    }

to:

    cc_library_headers(
        name = "libc_headers",
        deps = [] + select({
            "//build/bazel/platforms/os:android": [
                ":libc_headers_arch",
            ],
            "//build/bazel/platforms/os:linux_bionic": [
                ":libc_headers_arch",
            ],
            "//conditions:default": [],
        }),
    )

Test: TH
Test: Verify generated //bionic/libc:libc_headers
Fixes: 183597786

Change-Id: I01016cc2cc9a71449f02300d747f01decebf3f6e
diff --git a/bazel/properties.go b/bazel/properties.go
index 1763f2d..250fea4 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -80,10 +80,19 @@
 }
 
 const (
-	ARCH_X86    = "x86"
-	ARCH_X86_64 = "x86_64"
+	// ArchType names in arch.go
 	ARCH_ARM    = "arm"
 	ARCH_ARM64  = "arm64"
+	ARCH_X86    = "x86"
+	ARCH_X86_64 = "x86_64"
+
+	// OsType names in arch.go
+	OS_ANDROID      = "android"
+	OS_DARWIN       = "darwin"
+	OS_FUCHSIA      = "fuchsia"
+	OS_LINUX        = "linux_glibc"
+	OS_LINUX_BIONIC = "linux_bionic"
+	OS_WINDOWS      = "windows"
 )
 
 var (
@@ -92,6 +101,36 @@
 	// android package depends on the bazel package, so a cyclic dependency
 	// prevents using that here.
 	selectableArchs = []string{ARCH_X86, ARCH_X86_64, ARCH_ARM, ARCH_ARM64}
+
+	// Likewise, this is the list of target operating systems.
+	selectableTargetOs = []string{
+		OS_ANDROID,
+		OS_DARWIN,
+		OS_FUCHSIA,
+		OS_LINUX,
+		OS_LINUX_BIONIC,
+		OS_WINDOWS,
+	}
+
+	// A map of architectures to the Bazel label of the constraint_value
+	// for the @platforms//cpu:cpu constraint_setting
+	PlatformArchMap = map[string]string{
+		ARCH_ARM:    "//build/bazel/platforms/arch:arm",
+		ARCH_ARM64:  "//build/bazel/platforms/arch:arm64",
+		ARCH_X86:    "//build/bazel/platforms/arch:x86",
+		ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
+	}
+
+	// A map of target operating systems to the Bazel label of the
+	// constraint_value for the @platforms//os:os constraint_setting
+	PlatformOsMap = map[string]string{
+		OS_ANDROID:      "//build/bazel/platforms/os:android",
+		OS_DARWIN:       "//build/bazel/platforms/os:darwin",
+		OS_FUCHSIA:      "//build/bazel/platforms/os:fuchsia",
+		OS_LINUX:        "//build/bazel/platforms/os:linux",
+		OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
+		OS_WINDOWS:      "//build/bazel/platforms/os:windows",
+	}
 )
 
 // Arch-specific label_list typed Bazel attribute values. This should correspond
@@ -101,8 +140,16 @@
 	X86_64 LabelList
 	Arm    LabelList
 	Arm64  LabelList
-	// TODO(b/181299724): this is currently missing the "common" arch, which
-	// doesn't have an equivalent platform() definition yet.
+	Common LabelList
+}
+
+type labelListOsValues struct {
+	Android     LabelList
+	Darwin      LabelList
+	Fuchsia     LabelList
+	Linux       LabelList
+	LinuxBionic LabelList
+	Windows     LabelList
 }
 
 // LabelListAttribute is used to represent a list of Bazel labels as an
@@ -115,6 +162,11 @@
 	// are generated in a select statement and appended to the non-arch specific
 	// label list Value.
 	ArchValues labelListArchValues
+
+	// The os-specific attribute label list values. Optional. If used, these
+	// are generated in a select statement and appended to the non-os specific
+	// label list Value.
+	OsValues labelListOsValues
 }
 
 // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
@@ -124,45 +176,75 @@
 
 // HasArchSpecificValues returns true if the attribute contains
 // architecture-specific label_list values.
-func (attrs *LabelListAttribute) HasArchSpecificValues() bool {
+func (attrs *LabelListAttribute) HasConfigurableValues() bool {
 	for _, arch := range selectableArchs {
-		if len(attrs.GetValueForArch(arch).Includes) > 0 || len(attrs.GetValueForArch(arch).Excludes) > 0 {
+		if len(attrs.GetValueForArch(arch).Includes) > 0 {
+			return true
+		}
+	}
+
+	for _, os := range selectableTargetOs {
+		if len(attrs.GetValueForOS(os).Includes) > 0 {
 			return true
 		}
 	}
 	return false
 }
 
+func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
+	return map[string]*LabelList{
+		ARCH_X86:    &attrs.ArchValues.X86,
+		ARCH_X86_64: &attrs.ArchValues.X86_64,
+		ARCH_ARM:    &attrs.ArchValues.Arm,
+		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+	}
+}
+
 // GetValueForArch returns the label_list attribute value for an architecture.
 func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
-	switch arch {
-	case ARCH_X86:
-		return attrs.ArchValues.X86
-	case ARCH_X86_64:
-		return attrs.ArchValues.X86_64
-	case ARCH_ARM:
-		return attrs.ArchValues.Arm
-	case ARCH_ARM64:
-		return attrs.ArchValues.Arm64
-	default:
+	var v *LabelList
+	if v = attrs.archValuePtrs()[arch]; v == nil {
 		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
+	return *v
 }
 
 // SetValueForArch sets the label_list attribute value for an architecture.
 func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) {
-	switch arch {
-	case "x86":
-		attrs.ArchValues.X86 = value
-	case "x86_64":
-		attrs.ArchValues.X86_64 = value
-	case "arm":
-		attrs.ArchValues.Arm = value
-	case "arm64":
-		attrs.ArchValues.Arm64 = value
-	default:
+	var v *LabelList
+	if v = attrs.archValuePtrs()[arch]; v == nil {
 		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
+	*v = value
+}
+
+func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
+	return map[string]*LabelList{
+		OS_ANDROID:      &attrs.OsValues.Android,
+		OS_DARWIN:       &attrs.OsValues.Darwin,
+		OS_FUCHSIA:      &attrs.OsValues.Fuchsia,
+		OS_LINUX:        &attrs.OsValues.Linux,
+		OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
+		OS_WINDOWS:      &attrs.OsValues.Windows,
+	}
+}
+
+// GetValueForOS returns the label_list attribute value for an OS target.
+func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList {
+	var v *LabelList
+	if v = attrs.osValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	return *v
+}
+
+// SetValueForArch sets the label_list attribute value for an OS target.
+func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) {
+	var v *LabelList
+	if v = attrs.osValuePtrs()[os]; v == nil {
+		panic(fmt.Errorf("Unknown os: %s", os))
+	}
+	*v = value
 }
 
 // StringListAttribute corresponds to the string_list Bazel attribute type with
@@ -182,13 +264,12 @@
 	X86_64 []string
 	Arm    []string
 	Arm64  []string
-	// TODO(b/181299724): this is currently missing the "common" arch, which
-	// doesn't have an equivalent platform() definition yet.
+	Common []string
 }
 
-// HasArchSpecificValues returns true if the attribute contains
+// HasConfigurableValues returns true if the attribute contains
 // architecture-specific string_list values.
-func (attrs *StringListAttribute) HasArchSpecificValues() bool {
+func (attrs *StringListAttribute) HasConfigurableValues() bool {
 	for _, arch := range selectableArchs {
 		if len(attrs.GetValueForArch(arch)) > 0 {
 			return true
@@ -197,36 +278,31 @@
 	return false
 }
 
+func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
+	return map[string]*[]string{
+		ARCH_X86:    &attrs.ArchValues.X86,
+		ARCH_X86_64: &attrs.ArchValues.X86_64,
+		ARCH_ARM:    &attrs.ArchValues.Arm,
+		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+	}
+}
+
 // GetValueForArch returns the string_list attribute value for an architecture.
 func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
-	switch arch {
-	case ARCH_X86:
-		return attrs.ArchValues.X86
-	case ARCH_X86_64:
-		return attrs.ArchValues.X86_64
-	case ARCH_ARM:
-		return attrs.ArchValues.Arm
-	case ARCH_ARM64:
-		return attrs.ArchValues.Arm64
-	default:
+	var v *[]string
+	if v = attrs.archValuePtrs()[arch]; v == nil {
 		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
+	return *v
 }
 
 // SetValueForArch sets the string_list attribute value for an architecture.
 func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
-	switch arch {
-	case ARCH_X86:
-		attrs.ArchValues.X86 = value
-	case ARCH_X86_64:
-		attrs.ArchValues.X86_64 = value
-	case ARCH_ARM:
-		attrs.ArchValues.Arm = value
-	case ARCH_ARM64:
-		attrs.ArchValues.Arm64 = value
-	default:
+	var v *[]string
+	if v = attrs.archValuePtrs()[arch]; v == nil {
 		panic(fmt.Errorf("Unknown arch: %s", arch))
 	}
+	*v = value
 }
 
 // TryVariableSubstitution, replace string substitution formatting within each string in slice with