Reland "Split the x86 host toolchain into glibc and musl variants"

Split the x86 host toolchain into glibc and musl variants

Create new musl toolchains that are based on the existing glibc
toolchains, and add the necessary flags for musl compiles.

This relands Ifc02f9e5afa61ff758be98b0c962f3a4b53d0546 with changes
for I46672e3a096b6ea94ff4c10e1c31e8fd010a163c.

Bug: 190084016
Change-Id: Iaa9f7a50ff601155ecd73acc5701a2c226be66dc
Test: TestArchMutator
diff --git a/android/arch.go b/android/arch.go
index 583793e..7ca7336 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -255,7 +255,7 @@
 // Linux returns true if the OS uses the Linux kernel, i.e. if the OS is Android or is Linux
 // with or without the Bionic libc runtime.
 func (os OsType) Linux() bool {
-	return os == Android || os == Linux || os == LinuxBionic
+	return os == Android || os == Linux || os == LinuxBionic || os == LinuxMusl
 }
 
 // newOsType constructs an OsType and adds it to the global lists.
@@ -305,6 +305,8 @@
 	NoOsType OsType
 	// Linux is the OS for the Linux kernel plus the glibc runtime.
 	Linux = newOsType("linux_glibc", Host, false, X86, X86_64)
+	// LinuxMusl is the OS for the Linux kernel plus the musl runtime.
+	LinuxMusl = newOsType("linux_musl", Host, false, X86, X86_64)
 	// Darwin is the OS for MacOS/Darwin host machines.
 	Darwin = newOsType("darwin", Host, false, X86_64)
 	// LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the
@@ -863,6 +865,8 @@
 			"Android64",
 			"Android32",
 			"Bionic",
+			"Glibc",
+			"Musl",
 			"Linux",
 			"Not_windows",
 			"Arm_on_x86",
@@ -1108,6 +1112,30 @@
 				}
 			}
 
+			if os == Linux {
+				field := "Glibc"
+				prefix := "target.glibc"
+				if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
+					mergePropertyStruct(ctx, genProps, bionicProperties)
+				}
+			}
+
+			if os == LinuxMusl {
+				field := "Musl"
+				prefix := "target.musl"
+				if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
+					mergePropertyStruct(ctx, genProps, bionicProperties)
+				}
+
+				// Special case:  to ease the transition from glibc to musl, apply linux_glibc
+				// properties (which has historically mean host linux) to musl variants.
+				field = "Linux_glibc"
+				prefix = "target.linux_glibc"
+				if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
+					mergePropertyStruct(ctx, genProps, bionicProperties)
+				}
+			}
+
 			// Handle target OS properties in the form:
 			// target: {
 			//     linux_glibc: {
@@ -1310,6 +1338,16 @@
 		if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
 			result = append(result, osArchProperties)
 		}
+
+		if os == LinuxMusl {
+			// Special case:  to ease the transition from glibc to musl, apply linux_glibc
+			// properties (which has historically mean host linux) to musl variants.
+			field := "Linux_glibc_" + archType.Name
+			userFriendlyField := "target.linux_glibc_" + archType.Name
+			if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
+				result = append(result, osArchProperties)
+			}
+		}
 	}
 
 	// Handle arm on x86 properties in the form:
@@ -1375,11 +1413,14 @@
 }
 
 // determineBuildOS stores the OS and architecture used for host targets used during the build into
-// config based on the runtime OS and architecture determined by Go.
+// config based on the runtime OS and architecture determined by Go and the product configuration.
 func determineBuildOS(config *config) {
 	config.BuildOS = func() OsType {
 		switch runtime.GOOS {
 		case "linux":
+			if Bool(config.productVariables.HostMusl) {
+				return LinuxMusl
+			}
 			return Linux
 		case "darwin":
 			return Darwin