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.

Bug: 190084016
Test: TestArchMutator
Change-Id: Ifc02f9e5afa61ff758be98b0c962f3a4b53d0546
diff --git a/cc/binary.go b/cc/binary.go
index c6d61ab..763d2b9 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -335,7 +335,7 @@
 
 	if flags.DynamicLinker != "" {
 		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-dynamic-linker,"+flags.DynamicLinker)
-	} else if ctx.toolchain().Bionic() && !binary.static() {
+	} else if (ctx.toolchain().Bionic() || ctx.toolchain().Musl()) && !binary.static() {
 		flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-dynamic-linker")
 	}
 
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index ff556f1..20384a8 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -118,6 +118,8 @@
 	DefaultSharedLibraries() []string
 
 	Bionic() bool
+	Glibc() bool
+	Musl() bool
 }
 
 type toolchainBase struct {
@@ -194,6 +196,14 @@
 	return false
 }
 
+func (toolchainBase) Glibc() bool {
+	return false
+}
+
+func (toolchainBase) Musl() bool {
+	return false
+}
+
 func (t toolchainBase) ToolPath() string {
 	return ""
 }
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 85d95d8..1d66cb7 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -36,10 +36,18 @@
 		"-D__STDC_CONSTANT_MACROS",
 
 		"--gcc-toolchain=${LinuxGccRoot}",
-		"--sysroot ${LinuxGccRoot}/sysroot",
 		"-fstack-protector-strong",
 	}
 
+	linuxGlibcCflags = []string{
+		"--sysroot ${LinuxGccRoot}/sysroot",
+	}
+
+	linuxMuslCflags = []string{
+		"-D_LIBCPP_HAS_MUSL_LIBC",
+		"-nostdlibinc",
+	}
+
 	linuxLdflags = []string{
 		"-Wl,-z,noexecstack",
 		"-Wl,-z,relro",
@@ -47,9 +55,17 @@
 		"-Wl,--no-undefined-version",
 
 		"--gcc-toolchain=${LinuxGccRoot}",
+	}
+
+	linuxGlibcLdflags = []string{
 		"--sysroot ${LinuxGccRoot}/sysroot",
 	}
 
+	linuxMuslLdflags = []string{
+		"-nostdlib",
+		"-lgcc", "-lgcc_eh",
+	}
+
 	// Extended cflags
 	linuxX86Cflags = []string{
 		"-msse3",
@@ -89,6 +105,12 @@
 		"rt",
 		"util",
 	}, "-l")
+
+	muslCrtBeginStaticBinary, muslCrtEndStaticBinary   = []string{"libc_musl_crtbegin_static"}, []string{"crtend_android"}
+	muslCrtBeginSharedBinary, muslCrtEndSharedBinary   = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}, []string{"libc_musl_crtend"}
+	muslCrtBeginSharedLibrary, muslCrtEndSharedLibrary = []string{"libc_musl_crtbegin_so"}, []string{"libc_musl_crtend_so"}
+
+	muslDefaultSharedLibraries = []string{"libjemalloc5", "libc_musl"}
 )
 
 const (
@@ -124,6 +146,13 @@
 	// Yasm flags
 	pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86")
 	pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64")
+
+	pctx.StaticVariable("LinuxGlibcCflags", strings.Join(linuxGlibcCflags, " "))
+	pctx.StaticVariable("LinuxGlibcLdflags", strings.Join(linuxGlibcLdflags, " "))
+	pctx.StaticVariable("LinuxGlibcLldflags", strings.Join(linuxGlibcLdflags, " "))
+	pctx.StaticVariable("LinuxMuslCflags", strings.Join(linuxMuslCflags, " "))
+	pctx.StaticVariable("LinuxMuslLdflags", strings.Join(linuxMuslLdflags, " "))
+	pctx.StaticVariable("LinuxMuslLldflags", strings.Join(linuxMuslLdflags, " "))
 }
 
 type toolchainLinux struct {
@@ -224,18 +253,146 @@
 	return linuxAvailableLibraries
 }
 
-var toolchainLinuxX86Singleton Toolchain = &toolchainLinuxX86{}
-var toolchainLinuxX8664Singleton Toolchain = &toolchainLinuxX8664{}
+// glibc specialization of the linux toolchain
 
-func linuxX86ToolchainFactory(arch android.Arch) Toolchain {
-	return toolchainLinuxX86Singleton
+type toolchainGlibc struct {
 }
 
-func linuxX8664ToolchainFactory(arch android.Arch) Toolchain {
-	return toolchainLinuxX8664Singleton
+func (toolchainGlibc) Glibc() bool { return true }
+
+func (toolchainGlibc) Cflags() string {
+	return "${config.LinuxGlibcCflags}"
+}
+
+func (toolchainGlibc) Ldflags() string {
+	return "${config.LinuxGlibcLdflags}"
+}
+
+func (toolchainGlibc) Lldflags() string {
+	return "${config.LinuxGlibcLldflags}"
+}
+
+type toolchainLinuxGlibcX86 struct {
+	toolchainLinuxX86
+	toolchainGlibc
+}
+
+type toolchainLinuxGlibcX8664 struct {
+	toolchainLinuxX8664
+	toolchainGlibc
+}
+
+func (t *toolchainLinuxGlibcX86) Cflags() string {
+	return t.toolchainLinuxX86.Cflags() + " " + t.toolchainGlibc.Cflags()
+}
+
+func (t *toolchainLinuxGlibcX86) Ldflags() string {
+	return t.toolchainLinuxX86.Ldflags() + " " + t.toolchainGlibc.Ldflags()
+}
+
+func (t *toolchainLinuxGlibcX86) Lldflags() string {
+	return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainGlibc.Lldflags()
+}
+
+func (t *toolchainLinuxGlibcX8664) Cflags() string {
+	return t.toolchainLinuxX8664.Cflags() + " " + t.toolchainGlibc.Cflags()
+}
+
+func (t *toolchainLinuxGlibcX8664) Ldflags() string {
+	return t.toolchainLinuxX8664.Ldflags() + " " + t.toolchainGlibc.Ldflags()
+}
+
+func (t *toolchainLinuxGlibcX8664) Lldflags() string {
+	return t.toolchainLinuxX8664.Lldflags() + " " + t.toolchainGlibc.Lldflags()
+}
+
+var toolchainLinuxGlibcX86Singleton Toolchain = &toolchainLinuxGlibcX86{}
+var toolchainLinuxGlibcX8664Singleton Toolchain = &toolchainLinuxGlibcX8664{}
+
+func linuxGlibcX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxGlibcX86Singleton
+}
+
+func linuxGlibcX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxGlibcX8664Singleton
+}
+
+// musl specialization of the linux toolchain
+
+type toolchainMusl struct {
+}
+
+func (toolchainMusl) Musl() bool { return true }
+
+func (toolchainMusl) CrtBeginStaticBinary() []string  { return muslCrtBeginStaticBinary }
+func (toolchainMusl) CrtBeginSharedBinary() []string  { return muslCrtBeginSharedBinary }
+func (toolchainMusl) CrtBeginSharedLibrary() []string { return muslCrtBeginSharedLibrary }
+func (toolchainMusl) CrtEndStaticBinary() []string    { return muslCrtEndStaticBinary }
+func (toolchainMusl) CrtEndSharedBinary() []string    { return muslCrtEndSharedBinary }
+func (toolchainMusl) CrtEndSharedLibrary() []string   { return muslCrtEndSharedLibrary }
+
+func (toolchainMusl) DefaultSharedLibraries() []string { return muslDefaultSharedLibraries }
+
+func (toolchainMusl) Cflags() string {
+	return "${config.LinuxMuslCflags}"
+}
+
+func (toolchainMusl) Ldflags() string {
+	return "${config.LinuxMuslLdflags}"
+}
+
+func (toolchainMusl) Lldflags() string {
+	return "${config.LinuxMuslLldflags}"
+}
+
+type toolchainLinuxMuslX86 struct {
+	toolchainLinuxX86
+	toolchainMusl
+}
+
+type toolchainLinuxMuslX8664 struct {
+	toolchainLinuxX8664
+	toolchainMusl
+}
+
+func (t *toolchainLinuxMuslX86) Cflags() string {
+	return t.toolchainLinuxX86.Cflags() + " " + t.toolchainMusl.Cflags()
+}
+
+func (t *toolchainLinuxMuslX86) Ldflags() string {
+	return t.toolchainLinuxX86.Ldflags() + " " + t.toolchainMusl.Ldflags()
+}
+
+func (t *toolchainLinuxMuslX86) Lldflags() string {
+	return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainMusl.Lldflags()
+}
+
+func (t *toolchainLinuxMuslX8664) Cflags() string {
+	return t.toolchainLinuxX8664.Cflags() + " " + t.toolchainMusl.Cflags()
+}
+
+func (t *toolchainLinuxMuslX8664) Ldflags() string {
+	return t.toolchainLinuxX8664.Ldflags() + " " + t.toolchainMusl.Ldflags()
+}
+
+func (t *toolchainLinuxMuslX8664) Lldflags() string {
+	return t.toolchainLinuxX8664.Lldflags() + " " + t.toolchainMusl.Lldflags()
+}
+
+var toolchainLinuxMuslX86Singleton Toolchain = &toolchainLinuxMuslX86{}
+var toolchainLinuxMuslX8664Singleton Toolchain = &toolchainLinuxMuslX8664{}
+
+func linuxMuslX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxMuslX86Singleton
+}
+
+func linuxMuslX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxMuslX8664Singleton
 }
 
 func init() {
-	registerToolchainFactory(android.Linux, android.X86, linuxX86ToolchainFactory)
-	registerToolchainFactory(android.Linux, android.X86_64, linuxX8664ToolchainFactory)
+	registerToolchainFactory(android.Linux, android.X86, linuxGlibcX86ToolchainFactory)
+	registerToolchainFactory(android.Linux, android.X86_64, linuxGlibcX8664ToolchainFactory)
+	registerToolchainFactory(android.LinuxMusl, android.X86, linuxMuslX86ToolchainFactory)
+	registerToolchainFactory(android.LinuxMusl, android.X86_64, linuxMuslX8664ToolchainFactory)
 }
diff --git a/cc/linker.go b/cc/linker.go
index 82449a6..c8fc431 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -385,6 +385,10 @@
 			indexList("libdl", deps.SystemSharedLibs) < indexList("libc", deps.SystemSharedLibs) {
 			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
 		}
+	} else if ctx.toolchain().Musl() {
+		if !Bool(linker.Properties.No_libcrt) && !ctx.header() {
+			deps.LateStaticLibs = append(deps.LateStaticLibs, config.BuiltinsRuntimeLibrary(ctx.toolchain()))
+		}
 	}
 
 	deps.LateSharedLibs = append(deps.LateSharedLibs, deps.SystemSharedLibs...)
@@ -472,7 +476,7 @@
 		flags.Global.LdFlags = append(flags.Global.LdFlags, toolchain.Ldflags())
 	}
 
-	if !ctx.toolchain().Bionic() {
+	if !ctx.toolchain().Bionic() && ctx.Os() != android.LinuxMusl {
 		CheckBadHostLdlibs(ctx, "host_ldlibs", linker.Properties.Host_ldlibs)
 
 		flags.Local.LdFlags = append(flags.Local.LdFlags, linker.Properties.Host_ldlibs...)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 3911f48..b244394 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -472,8 +472,8 @@
 		s.Diag.Cfi = nil
 	}
 
-	// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
-	if !ctx.Os().Linux() {
+	// Disable sanitizers that depend on the UBSan runtime for windows/darwin/musl builds.
+	if !ctx.Os().Linux() || ctx.Os() == android.LinuxMusl {
 		s.Cfi = nil
 		s.Diag.Cfi = nil
 		s.Misc_undefined = nil
diff --git a/cc/testing.go b/cc/testing.go
index 19513e3..1795d63 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -450,6 +450,25 @@
 		cc_library_static {
 			name: "note_memtag_heap_sync",
 		}
+
+
+		cc_library {
+			name: "libjemalloc5",
+			host_supported: true,
+			no_libcrt: true,
+			nocrt: true,
+			default_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "libc_musl",
+			host_supported: true,
+			no_libcrt: true,
+			nocrt: true,
+			default_shared_libs: [],
+			stl: "none",
+		}
 	`
 }