Move toolchain and global variables into separate package

Move all of the configuration into a cc/config package

Change-Id: If56fc7242062ed1ce3cb297f78a1e0ef7537373c
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
new file mode 100644
index 0000000..9d425c1
--- /dev/null
+++ b/cc/config/arm64_device.go
@@ -0,0 +1,204 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"fmt"
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	arm64Cflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-fno-strict-aliasing",
+		"-fstack-protector-strong",
+		"-ffunction-sections",
+		"-fdata-sections",
+		"-funwind-tables",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-fno-short-enums",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		// Help catch common 32/64-bit errors.
+		"-Werror=pointer-to-int-cast",
+		"-Werror=int-to-pointer-cast",
+		"-Werror=implicit-function-declaration",
+
+		"-fno-strict-volatile-bitfields",
+
+		// TARGET_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-O2 -g",
+		"-Wstrict-aliasing=2",
+		"-fgcse-after-reload",
+		"-frerun-cse-after-loop",
+		"-frename-registers",
+	}
+
+	arm64Ldflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,-maarch64linux",
+		"-Wl,--hash-style=gnu",
+		"-Wl,--fix-cortex-a53-843419",
+		"-fuse-ld=gold",
+		"-Wl,--icf=safe",
+		"-Wl,--no-undefined-version",
+
+		// Disable transitive dependency library symbol resolving.
+		"-Wl,--allow-shlib-undefined",
+	}
+
+	arm64Cppflags = []string{
+		"-fvisibility-inlines-hidden",
+	}
+
+	arm64CpuVariantCflags = map[string][]string{
+		"cortex-a53": []string{
+			"-mcpu=cortex-a53",
+		},
+	}
+
+	arm64ClangCpuVariantCflags = copyVariantFlags(arm64CpuVariantCflags)
+)
+
+const (
+	arm64GccVersion = "4.9"
+)
+
+func init() {
+	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
+
+	pctx.SourcePathVariable("Arm64GccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
+
+	pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
+	pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
+	pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
+	pctx.StaticVariable("Arm64IncludeFlags", bionicHeaders("arm64", "arm64"))
+
+	pctx.StaticVariable("Arm64ClangCflags", strings.Join(ClangFilterUnknownCflags(arm64Cflags), " "))
+	pctx.StaticVariable("Arm64ClangLdflags", strings.Join(ClangFilterUnknownCflags(arm64Ldflags), " "))
+	pctx.StaticVariable("Arm64ClangCppflags", strings.Join(ClangFilterUnknownCflags(arm64Cppflags), " "))
+
+	pctx.StaticVariable("Arm64CortexA53Cflags",
+		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
+	pctx.StaticVariable("Arm64ClangCortexA53Cflags",
+		strings.Join(arm64ClangCpuVariantCflags["cortex-a53"], " "))
+}
+
+var (
+	arm64CpuVariantCflagsVar = map[string]string{
+		"":           "",
+		"cortex-a53": "${config.Arm64CortexA53Cflags}",
+	}
+
+	arm64ClangCpuVariantCflagsVar = map[string]string{
+		"":           "",
+		"cortex-a53": "${config.Arm64ClangCortexA53Cflags}",
+	}
+)
+
+type toolchainArm64 struct {
+	toolchain64Bit
+
+	toolchainCflags      string
+	toolchainClangCflags string
+}
+
+func (t *toolchainArm64) Name() string {
+	return "arm64"
+}
+
+func (t *toolchainArm64) GccRoot() string {
+	return "${config.Arm64GccRoot}"
+}
+
+func (t *toolchainArm64) GccTriple() string {
+	return "aarch64-linux-android"
+}
+
+func (t *toolchainArm64) GccVersion() string {
+	return arm64GccVersion
+}
+
+func (t *toolchainArm64) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainArm64) Cflags() string {
+	return "${config.Arm64Cflags}"
+}
+
+func (t *toolchainArm64) Cppflags() string {
+	return "${config.Arm64Cppflags}"
+}
+
+func (t *toolchainArm64) Ldflags() string {
+	return "${config.Arm64Ldflags}"
+}
+
+func (t *toolchainArm64) IncludeFlags() string {
+	return "${config.Arm64IncludeFlags}"
+}
+
+func (t *toolchainArm64) ClangTriple() string {
+	return t.GccTriple()
+}
+
+func (t *toolchainArm64) ClangCflags() string {
+	return "${config.Arm64ClangCflags}"
+}
+
+func (t *toolchainArm64) ClangCppflags() string {
+	return "${config.Arm64ClangCppflags}"
+}
+
+func (t *toolchainArm64) ClangLdflags() string {
+	return "${config.Arm64Ldflags}"
+}
+
+func (t *toolchainArm64) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (toolchainArm64) AddressSanitizerRuntimeLibrary() string {
+	return "libclang_rt.asan-aarch64-android.so"
+}
+
+func arm64ToolchainFactory(arch android.Arch) Toolchain {
+	if arch.ArchVariant != "armv8-a" {
+		panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
+	}
+
+	return &toolchainArm64{
+		toolchainCflags:      variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant),
+		toolchainClangCflags: variantOrDefault(arm64ClangCpuVariantCflagsVar, arch.CpuVariant),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm64, arm64ToolchainFactory)
+}
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
new file mode 100644
index 0000000..f15d8da
--- /dev/null
+++ b/cc/config/arm_device.go
@@ -0,0 +1,387 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"fmt"
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	armToolchainCflags = []string{
+		"-mthumb-interwork",
+		"-msoft-float",
+	}
+
+	armCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-ffunction-sections",
+		"-fdata-sections",
+		"-funwind-tables",
+		"-fstack-protector-strong",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-fno-short-enums",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		"-fno-builtin-sin",
+		"-fno-strict-volatile-bitfields",
+
+		// TARGET_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-g",
+		"-Wstrict-aliasing=2",
+		"-fgcse-after-reload",
+		"-frerun-cse-after-loop",
+		"-frename-registers",
+	}
+
+	armCppflags = []string{
+		"-fvisibility-inlines-hidden",
+	}
+
+	armLdflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,--icf=safe",
+		"-Wl,--hash-style=gnu",
+		"-Wl,--no-undefined-version",
+	}
+
+	armArmCflags = []string{
+		"-O2",
+		"-fomit-frame-pointer",
+		"-fstrict-aliasing",
+		"-funswitch-loops",
+	}
+
+	armThumbCflags = []string{
+		"-mthumb",
+		"-Os",
+		"-fomit-frame-pointer",
+		"-fno-strict-aliasing",
+	}
+
+	armArchVariantCflags = map[string][]string{
+		"armv5te": []string{
+			"-march=armv5te",
+			"-mtune=xscale",
+			"-D__ARM_ARCH_5__",
+			"-D__ARM_ARCH_5T__",
+			"-D__ARM_ARCH_5E__",
+			"-D__ARM_ARCH_5TE__",
+		},
+		"armv7-a": []string{
+			"-march=armv7-a",
+			"-mfloat-abi=softfp",
+			"-mfpu=vfpv3-d16",
+		},
+		"armv7-a-neon": []string{
+			"-mfloat-abi=softfp",
+			"-mfpu=neon",
+		},
+	}
+
+	armCpuVariantCflags = map[string][]string{
+		"": []string{
+			"-march=armv7-a",
+		},
+		"cortex-a7": []string{
+			"-mcpu=cortex-a7",
+			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// don't advertise.
+			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
+			// better solution comes around. See Bug 27340895
+			"-D__ARM_FEATURE_LPAE=1",
+		},
+		"cortex-a8": []string{
+			"-mcpu=cortex-a8",
+		},
+		"cortex-a15": []string{
+			"-mcpu=cortex-a15",
+			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// don't advertise.
+			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
+			// better solution comes around. See Bug 27340895
+			"-D__ARM_FEATURE_LPAE=1",
+		},
+		"krait": []string{
+			"-mcpu=cortex-a15",
+			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// don't advertise.
+			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
+			// better solution comes around. See Bug 27340895
+			"-D__ARM_FEATURE_LPAE=1",
+		},
+	}
+
+	armClangCpuVariantCflags  = copyVariantFlags(armCpuVariantCflags)
+	armClangArchVariantCflags = copyVariantFlags(armArchVariantCflags)
+)
+
+const (
+	armGccVersion = "4.9"
+)
+
+func init() {
+	replaceFirst := func(slice []string, from, to string) {
+		if slice[0] != from {
+			panic(fmt.Errorf("Expected %q, found %q", from, to))
+		}
+
+		slice[0] = to
+	}
+
+	replaceFirst(armClangCpuVariantCflags["krait"], "-mcpu=cortex-a15", "-mcpu=krait")
+	armClangCpuVariantCflags["krait"] = append(armClangCpuVariantCflags["krait"], "-mfpu=neon-vfpv4")
+
+	pctx.StaticVariable("armGccVersion", armGccVersion)
+
+	pctx.SourcePathVariable("ArmGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
+
+	pctx.StaticVariable("ArmToolchainCflags", strings.Join(armToolchainCflags, " "))
+	pctx.StaticVariable("ArmCflags", strings.Join(armCflags, " "))
+	pctx.StaticVariable("ArmLdflags", strings.Join(armLdflags, " "))
+	pctx.StaticVariable("ArmCppflags", strings.Join(armCppflags, " "))
+	pctx.StaticVariable("ArmIncludeFlags", bionicHeaders("arm", "arm"))
+
+	// Extended cflags
+
+	// ARM vs. Thumb instruction set flags
+	pctx.StaticVariable("ArmArmCflags", strings.Join(armArmCflags, " "))
+	pctx.StaticVariable("ArmThumbCflags", strings.Join(armThumbCflags, " "))
+
+	// Architecture variant cflags
+	pctx.StaticVariable("ArmArmv5TECflags", strings.Join(armArchVariantCflags["armv5te"], " "))
+	pctx.StaticVariable("ArmArmv7ACflags", strings.Join(armArchVariantCflags["armv7-a"], " "))
+	pctx.StaticVariable("ArmArmv7ANeonCflags", strings.Join(armArchVariantCflags["armv7-a-neon"], " "))
+
+	// Cpu variant cflags
+	pctx.StaticVariable("ArmGenericCflags", strings.Join(armCpuVariantCflags[""], " "))
+	pctx.StaticVariable("ArmCortexA7Cflags", strings.Join(armCpuVariantCflags["cortex-a7"], " "))
+	pctx.StaticVariable("ArmCortexA8Cflags", strings.Join(armCpuVariantCflags["cortex-a8"], " "))
+	pctx.StaticVariable("ArmCortexA15Cflags", strings.Join(armCpuVariantCflags["cortex-a15"], " "))
+	pctx.StaticVariable("ArmKraitCflags", strings.Join(armCpuVariantCflags["krait"], " "))
+
+	// Clang cflags
+	pctx.StaticVariable("ArmToolchainClangCflags", strings.Join(ClangFilterUnknownCflags(armToolchainCflags), " "))
+	pctx.StaticVariable("ArmClangCflags", strings.Join(ClangFilterUnknownCflags(armCflags), " "))
+	pctx.StaticVariable("ArmClangLdflags", strings.Join(ClangFilterUnknownCflags(armLdflags), " "))
+	pctx.StaticVariable("ArmClangCppflags", strings.Join(ClangFilterUnknownCflags(armCppflags), " "))
+
+	// Clang ARM vs. Thumb instruction set cflags
+	pctx.StaticVariable("ArmClangArmCflags", strings.Join(ClangFilterUnknownCflags(armArmCflags), " "))
+	pctx.StaticVariable("ArmClangThumbCflags", strings.Join(ClangFilterUnknownCflags(armThumbCflags), " "))
+
+	// Clang arch variant cflags
+	pctx.StaticVariable("ArmClangArmv5TECflags",
+		strings.Join(armClangArchVariantCflags["armv5te"], " "))
+	pctx.StaticVariable("ArmClangArmv7ACflags",
+		strings.Join(armClangArchVariantCflags["armv7-a"], " "))
+	pctx.StaticVariable("ArmClangArmv7ANeonCflags",
+		strings.Join(armClangArchVariantCflags["armv7-a-neon"], " "))
+
+	// Clang cpu variant cflags
+	pctx.StaticVariable("ArmClangGenericCflags",
+		strings.Join(armClangCpuVariantCflags[""], " "))
+	pctx.StaticVariable("ArmClangCortexA7Cflags",
+		strings.Join(armClangCpuVariantCflags["cortex-a7"], " "))
+	pctx.StaticVariable("ArmClangCortexA8Cflags",
+		strings.Join(armClangCpuVariantCflags["cortex-a8"], " "))
+	pctx.StaticVariable("ArmClangCortexA15Cflags",
+		strings.Join(armClangCpuVariantCflags["cortex-a15"], " "))
+	pctx.StaticVariable("ArmClangKraitCflags",
+		strings.Join(armClangCpuVariantCflags["krait"], " "))
+}
+
+var (
+	armArchVariantCflagsVar = map[string]string{
+		"armv5te":      "${config.ArmArmv5TECflags}",
+		"armv7-a":      "${config.ArmArmv7ACflags}",
+		"armv7-a-neon": "${config.ArmArmv7ANeonCflags}",
+	}
+
+	armCpuVariantCflagsVar = map[string]string{
+		"":               "${config.ArmGenericCflags}",
+		"cortex-a7":      "${config.ArmCortexA7Cflags}",
+		"cortex-a8":      "${config.ArmCortexA8Cflags}",
+		"cortex-a15":     "${config.ArmCortexA15Cflags}",
+		"cortex-a53":     "${config.ArmCortexA7Cflags}",
+		"cortex-a53.a57": "${config.ArmCortexA7Cflags}",
+		"krait":          "${config.ArmKraitCflags}",
+		"denver":         "${config.ArmCortexA15Cflags}",
+	}
+
+	armClangArchVariantCflagsVar = map[string]string{
+		"armv5te":      "${config.ArmClangArmv5TECflags}",
+		"armv7-a":      "${config.ArmClangArmv7ACflags}",
+		"armv7-a-neon": "${config.ArmClangArmv7ANeonCflags}",
+	}
+
+	armClangCpuVariantCflagsVar = map[string]string{
+		"":               "${config.ArmClangGenericCflags}",
+		"cortex-a7":      "${config.ArmClangCortexA7Cflags}",
+		"cortex-a8":      "${config.ArmClangCortexA8Cflags}",
+		"cortex-a15":     "${config.ArmClangCortexA15Cflags}",
+		"cortex-a53":     "${config.ArmClangCortexA7Cflags}",
+		"cortex-a53.a57": "${config.ArmClangCortexA7Cflags}",
+		"krait":          "${config.ArmClangKraitCflags}",
+		"denver":         "${config.ArmClangCortexA15Cflags}",
+	}
+)
+
+type toolchainArm struct {
+	toolchain32Bit
+	ldflags                               string
+	toolchainCflags, toolchainClangCflags string
+}
+
+func (t *toolchainArm) Name() string {
+	return "arm"
+}
+
+func (t *toolchainArm) GccRoot() string {
+	return "${config.ArmGccRoot}"
+}
+
+func (t *toolchainArm) GccTriple() string {
+	return "arm-linux-androideabi"
+}
+
+func (t *toolchainArm) GccVersion() string {
+	return armGccVersion
+}
+
+func (t *toolchainArm) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainArm) Cflags() string {
+	return "${config.ArmCflags}"
+}
+
+func (t *toolchainArm) Cppflags() string {
+	return "${config.ArmCppflags}"
+}
+
+func (t *toolchainArm) Ldflags() string {
+	return t.ldflags
+}
+
+func (t *toolchainArm) IncludeFlags() string {
+	return "${config.ArmIncludeFlags}"
+}
+
+func (t *toolchainArm) InstructionSetFlags(isa string) (string, error) {
+	switch isa {
+	case "arm":
+		return "${config.ArmArmCflags}", nil
+	case "thumb", "":
+		return "${config.ArmThumbCflags}", nil
+	default:
+		return t.toolchainBase.InstructionSetFlags(isa)
+	}
+}
+
+func (t *toolchainArm) ClangTriple() string {
+	return t.GccTriple()
+}
+
+func (t *toolchainArm) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (t *toolchainArm) ClangCflags() string {
+	return "${config.ArmClangCflags}"
+}
+
+func (t *toolchainArm) ClangCppflags() string {
+	return "${config.ArmClangCppflags}"
+}
+
+func (t *toolchainArm) ClangLdflags() string {
+	return t.ldflags
+}
+
+func (t *toolchainArm) ClangInstructionSetFlags(isa string) (string, error) {
+	switch isa {
+	case "arm":
+		return "${config.ArmClangArmCflags}", nil
+	case "thumb", "":
+		return "${config.ArmClangThumbCflags}", nil
+	default:
+		return t.toolchainBase.ClangInstructionSetFlags(isa)
+	}
+}
+
+func (toolchainArm) AddressSanitizerRuntimeLibrary() string {
+	return "libclang_rt.asan-arm-android.so"
+}
+
+func armToolchainFactory(arch android.Arch) Toolchain {
+	var fixCortexA8 string
+	toolchainCflags := make([]string, 2, 3)
+	toolchainClangCflags := make([]string, 2, 3)
+
+	toolchainCflags[0] = "${config.ArmToolchainCflags}"
+	toolchainCflags[1] = armArchVariantCflagsVar[arch.ArchVariant]
+	toolchainClangCflags[0] = "${config.ArmToolchainClangCflags}"
+	toolchainClangCflags[1] = armClangArchVariantCflagsVar[arch.ArchVariant]
+
+	switch arch.ArchVariant {
+	case "armv7-a-neon":
+		switch arch.CpuVariant {
+		case "cortex-a8", "":
+			// Generic ARM might be a Cortex A8 -- better safe than sorry
+			fixCortexA8 = "-Wl,--fix-cortex-a8"
+		default:
+			fixCortexA8 = "-Wl,--no-fix-cortex-a8"
+		}
+
+		toolchainCflags = append(toolchainCflags,
+			variantOrDefault(armCpuVariantCflagsVar, arch.CpuVariant))
+		toolchainClangCflags = append(toolchainClangCflags,
+			variantOrDefault(armClangCpuVariantCflagsVar, arch.CpuVariant))
+	case "armv7-a":
+		fixCortexA8 = "-Wl,--fix-cortex-a8"
+	case "armv5te":
+		// Nothing extra for armv5te
+	default:
+		panic(fmt.Sprintf("Unknown ARM architecture version: %q", arch.ArchVariant))
+	}
+
+	return &toolchainArm{
+		toolchainCflags: strings.Join(toolchainCflags, " "),
+		ldflags: strings.Join([]string{
+			"${config.ArmLdflags}",
+			fixCortexA8,
+		}, " "),
+		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm, armToolchainFactory)
+}
diff --git a/cc/config/clang.go b/cc/config/clang.go
new file mode 100644
index 0000000..13a7e66
--- /dev/null
+++ b/cc/config/clang.go
@@ -0,0 +1,149 @@
+package config
+
+import (
+	"sort"
+	"strings"
+)
+
+// Cflags that should be filtered out when compiling with clang
+var ClangUnknownCflags = sorted([]string{
+	"-finline-functions",
+	"-finline-limit=64",
+	"-fno-canonical-system-headers",
+	"-Wno-clobbered",
+	"-fno-devirtualize",
+	"-fno-tree-sra",
+	"-fprefetch-loop-arrays",
+	"-funswitch-loops",
+	"-Werror=unused-but-set-parameter",
+	"-Werror=unused-but-set-variable",
+	"-Wmaybe-uninitialized",
+	"-Wno-error=clobbered",
+	"-Wno-error=maybe-uninitialized",
+	"-Wno-error=unused-but-set-parameter",
+	"-Wno-error=unused-but-set-variable",
+	"-Wno-free-nonheap-object",
+	"-Wno-literal-suffix",
+	"-Wno-maybe-uninitialized",
+	"-Wno-old-style-declaration",
+	"-Wno-psabi",
+	"-Wno-unused-but-set-parameter",
+	"-Wno-unused-but-set-variable",
+	"-Wno-unused-local-typedefs",
+	"-Wunused-but-set-parameter",
+	"-Wunused-but-set-variable",
+	"-fdiagnostics-color",
+
+	// arm + arm64 + mips + mips64
+	"-fgcse-after-reload",
+	"-frerun-cse-after-loop",
+	"-frename-registers",
+	"-fno-strict-volatile-bitfields",
+
+	// arm + arm64
+	"-fno-align-jumps",
+
+	// arm
+	"-mthumb-interwork",
+	"-fno-builtin-sin",
+	"-fno-caller-saves",
+	"-fno-early-inlining",
+	"-fno-move-loop-invariants",
+	"-fno-partial-inlining",
+	"-fno-tree-copy-prop",
+	"-fno-tree-loop-optimize",
+
+	// mips + mips64
+	"-msynci",
+	"-mno-synci",
+	"-mno-fused-madd",
+
+	// x86 + x86_64
+	"-finline-limit=300",
+	"-fno-inline-functions-called-once",
+	"-mfpmath=sse",
+	"-mbionic",
+})
+
+func init() {
+	pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{
+		"-D__compiler_offsetof=__builtin_offsetof",
+
+		// Help catch common 32/64-bit errors.
+		"-Werror=int-conversion",
+
+		// Disable overly aggressive warning for macros defined with a leading underscore
+		// This happens in AndroidConfig.h, which is included nearly everywhere.
+		// TODO: can we remove this now?
+		"-Wno-reserved-id-macro",
+
+		// Disable overly aggressive warning for format strings.
+		// Bug: 20148343
+		"-Wno-format-pedantic",
+
+		// Workaround for ccache with clang.
+		// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
+		"-Wno-unused-command-line-argument",
+
+		// Force clang to always output color diagnostics. Ninja will strip the ANSI
+		// color codes if it is not running in a terminal.
+		"-fcolor-diagnostics",
+
+		// http://b/29823425 Disable -Wexpansion-to-defined for Clang update to r271374
+		"-Wno-expansion-to-defined",
+	}, " "))
+
+	pctx.StaticVariable("ClangExtraConlyflags", strings.Join([]string{
+		"-std=gnu99",
+	}, " "))
+
+	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
+		// Disable -Winconsistent-missing-override until we can clean up the existing
+		// codebase for it.
+		"-Wno-inconsistent-missing-override",
+
+		// Bug: http://b/29823425 Disable -Wnull-dereference until the
+		// new instances detected by this warning are fixed.
+		"-Wno-null-dereference",
+	}, " "))
+
+	pctx.StaticVariable("ClangExtraTargetCflags", strings.Join([]string{
+		"-nostdlibinc",
+	}, " "))
+
+	pctx.StaticVariable("ClangExtraNoOverrideCflags", strings.Join([]string{
+		"-Werror=address-of-temporary",
+		// Bug: http://b/29823425 Disable -Wnull-dereference until the
+		// new cases detected by this warning in Clang r271374 are
+		// fixed.
+		//"-Werror=null-dereference",
+		"-Werror=return-type",
+	}, " "))
+}
+
+func ClangFilterUnknownCflags(cflags []string) []string {
+	ret := make([]string, 0, len(cflags))
+	for _, f := range cflags {
+		if !inListSorted(f, ClangUnknownCflags) {
+			ret = append(ret, f)
+		}
+	}
+
+	return ret
+}
+
+func inListSorted(s string, list []string) bool {
+	for _, l := range list {
+		if s == l {
+			return true
+		} else if s < l {
+			return false
+		}
+	}
+	return false
+}
+
+func sorted(list []string) []string {
+	sort.Strings(list)
+	return list
+}
diff --git a/cc/config/global.go b/cc/config/global.go
new file mode 100644
index 0000000..cdb68ff
--- /dev/null
+++ b/cc/config/global.go
@@ -0,0 +1,142 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+// Flags used by lots of devices.  Putting them in package static variables will save bytes in
+// build.ninja so they aren't repeated for every file
+var (
+	commonGlobalCflags = []string{
+		"-DANDROID",
+		"-fmessage-length=0",
+		"-W",
+		"-Wall",
+		"-Wno-unused",
+		"-Winit-self",
+		"-Wpointer-arith",
+
+		// COMMON_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-UDEBUG",
+	}
+
+	deviceGlobalCflags = []string{
+		"-fdiagnostics-color",
+
+		// TARGET_ERROR_FLAGS
+		"-Werror=return-type",
+		"-Werror=non-virtual-dtor",
+		"-Werror=address",
+		"-Werror=sequence-point",
+		"-Werror=date-time",
+	}
+
+	hostGlobalCflags = []string{}
+
+	commonGlobalCppflags = []string{
+		"-Wsign-promo",
+	}
+
+	noOverrideGlobalCflags = []string{
+		"-Werror=int-to-pointer-cast",
+		"-Werror=pointer-to-int-cast",
+	}
+
+	IllegalFlags = []string{
+		"-w",
+	}
+)
+
+var pctx = android.NewPackageContext("android/soong/cc/config")
+
+func init() {
+	if android.BuildOs == android.Linux {
+		commonGlobalCflags = append(commonGlobalCflags, "-fdebug-prefix-map=/proc/self/cwd=")
+	}
+
+	pctx.StaticVariable("CommonGlobalCflags", strings.Join(commonGlobalCflags, " "))
+	pctx.StaticVariable("DeviceGlobalCflags", strings.Join(deviceGlobalCflags, " "))
+	pctx.StaticVariable("HostGlobalCflags", strings.Join(hostGlobalCflags, " "))
+	pctx.StaticVariable("NoOverrideGlobalCflags", strings.Join(noOverrideGlobalCflags, " "))
+
+	pctx.StaticVariable("CommonGlobalCppflags", strings.Join(commonGlobalCppflags, " "))
+
+	pctx.StaticVariable("CommonClangGlobalCflags",
+		strings.Join(append(ClangFilterUnknownCflags(commonGlobalCflags), "${ClangExtraCflags}"), " "))
+	pctx.StaticVariable("DeviceClangGlobalCflags",
+		strings.Join(append(ClangFilterUnknownCflags(deviceGlobalCflags), "${ClangExtraTargetCflags}"), " "))
+	pctx.StaticVariable("HostClangGlobalCflags",
+		strings.Join(ClangFilterUnknownCflags(hostGlobalCflags), " "))
+	pctx.StaticVariable("NoOverrideClangGlobalCflags",
+		strings.Join(append(ClangFilterUnknownCflags(noOverrideGlobalCflags), "${ClangExtraNoOverrideCflags}"), " "))
+
+	pctx.StaticVariable("CommonClangGlobalCppflags",
+		strings.Join(append(ClangFilterUnknownCflags(commonGlobalCppflags), "${ClangExtraCppflags}"), " "))
+
+	// Everything in this list is a crime against abstraction and dependency tracking.
+	// Do not add anything to this list.
+	pctx.PrefixedPathsForOptionalSourceVariable("CommonGlobalIncludes", "-isystem ",
+		[]string{
+			"system/core/include",
+			"system/media/audio/include",
+			"hardware/libhardware/include",
+			"hardware/libhardware_legacy/include",
+			"hardware/ril/include",
+			"libnativehelper/include",
+			"frameworks/native/include",
+			"frameworks/native/opengl/include",
+			"frameworks/av/include",
+			"frameworks/base/include",
+		})
+	// This is used by non-NDK modules to get jni.h. export_include_dirs doesn't help
+	// with this, since there is no associated library.
+	pctx.PrefixedPathsForOptionalSourceVariable("CommonNativehelperInclude", "-I",
+		[]string{"libnativehelper/include/nativehelper"})
+
+	pctx.SourcePathVariable("ClangDefaultBase", "prebuilts/clang/host")
+	pctx.VariableFunc("ClangBase", func(config interface{}) (string, error) {
+		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_BASE"); override != "" {
+			return override, nil
+		}
+		return "${ClangDefaultBase}", nil
+	})
+	pctx.VariableFunc("ClangVersion", func(config interface{}) (string, error) {
+		if override := config.(android.Config).Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
+			return override, nil
+		}
+		return "clang-3016494", nil
+	})
+	pctx.StaticVariable("ClangPath", "${ClangBase}/${HostPrebuiltTag}/${ClangVersion}")
+	pctx.StaticVariable("ClangBin", "${ClangPath}/bin")
+
+	pctx.StaticVariable("ClangAsanLibDir", "${ClangPath}/lib64/clang/3.8/lib/linux")
+}
+
+var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+
+func bionicHeaders(bionicArch, kernelArch string) string {
+	return strings.Join([]string{
+		"-isystem bionic/libc/arch-" + bionicArch + "/include",
+		"-isystem bionic/libc/include",
+		"-isystem bionic/libc/kernel/uapi",
+		"-isystem bionic/libc/kernel/uapi/asm-" + kernelArch,
+		"-isystem bionic/libc/kernel/android/uapi",
+	}, " ")
+}
diff --git a/cc/config/mips64_device.go b/cc/config/mips64_device.go
new file mode 100644
index 0000000..f6132dc
--- /dev/null
+++ b/cc/config/mips64_device.go
@@ -0,0 +1,195 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	mips64Cflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-O2",
+		"-fomit-frame-pointer",
+		"-fno-strict-aliasing",
+		"-funswitch-loops",
+		"-U__unix",
+		"-U__unix__",
+		"-Umips",
+		"-ffunction-sections",
+		"-fdata-sections",
+		"-funwind-tables",
+		"-fstack-protector-strong",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		// Help catch common 32/64-bit errors.
+		"-Werror=pointer-to-int-cast",
+		"-Werror=int-to-pointer-cast",
+		"-Werror=implicit-function-declaration",
+
+		// TARGET_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-g",
+		"-Wstrict-aliasing=2",
+		"-fgcse-after-reload",
+		"-frerun-cse-after-loop",
+		"-frename-registers",
+	}
+
+	mips64Cppflags = []string{
+		"-fvisibility-inlines-hidden",
+	}
+
+	mips64Ldflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,--allow-shlib-undefined",
+		"-Wl,--no-undefined-version",
+	}
+
+	mips64ArchVariantCflags = map[string][]string{
+		"mips64r2": []string{
+			"-mips64r2",
+			"-msynci",
+		},
+		"mips64r6": []string{
+			"-mips64r6",
+			"-msynci",
+		},
+	}
+)
+
+const (
+	mips64GccVersion = "4.9"
+)
+
+func init() {
+	android.RegisterArchFeatures(android.Mips64, "mips64r6",
+		"rev6")
+
+	pctx.StaticVariable("mips64GccVersion", mips64GccVersion)
+
+	pctx.SourcePathVariable("Mips64GccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
+
+	pctx.StaticVariable("Mips64Cflags", strings.Join(mips64Cflags, " "))
+	pctx.StaticVariable("Mips64Ldflags", strings.Join(mips64Ldflags, " "))
+	pctx.StaticVariable("Mips64Cppflags", strings.Join(mips64Cppflags, " "))
+	pctx.StaticVariable("Mips64IncludeFlags", bionicHeaders("mips64", "mips"))
+
+	// Clang cflags
+	pctx.StaticVariable("Mips64ClangCflags", strings.Join(ClangFilterUnknownCflags(mips64Cflags), " "))
+	pctx.StaticVariable("Mips64ClangLdflags", strings.Join(ClangFilterUnknownCflags(mips64Ldflags), " "))
+	pctx.StaticVariable("Mips64ClangCppflags", strings.Join(ClangFilterUnknownCflags(mips64Cppflags), " "))
+
+	// Extended cflags
+
+	// Architecture variant cflags
+	for variant, cflags := range mips64ArchVariantCflags {
+		pctx.StaticVariable("Mips64"+variant+"VariantCflags", strings.Join(cflags, " "))
+		pctx.StaticVariable("Mips64"+variant+"VariantClangCflags",
+			strings.Join(ClangFilterUnknownCflags(cflags), " "))
+	}
+}
+
+type toolchainMips64 struct {
+	toolchain64Bit
+	cflags, clangCflags                   string
+	toolchainCflags, toolchainClangCflags string
+}
+
+func (t *toolchainMips64) Name() string {
+	return "mips64"
+}
+
+func (t *toolchainMips64) GccRoot() string {
+	return "${config.Mips64GccRoot}"
+}
+
+func (t *toolchainMips64) GccTriple() string {
+	return "mips64el-linux-android"
+}
+
+func (t *toolchainMips64) GccVersion() string {
+	return mips64GccVersion
+}
+
+func (t *toolchainMips64) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainMips64) Cflags() string {
+	return t.cflags
+}
+
+func (t *toolchainMips64) Cppflags() string {
+	return "${config.Mips64Cppflags}"
+}
+
+func (t *toolchainMips64) Ldflags() string {
+	return "${config.Mips64Ldflags}"
+}
+
+func (t *toolchainMips64) IncludeFlags() string {
+	return "${config.Mips64IncludeFlags}"
+}
+
+func (t *toolchainMips64) ClangTriple() string {
+	return t.GccTriple()
+}
+
+func (t *toolchainMips64) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (t *toolchainMips64) ClangCflags() string {
+	return t.clangCflags
+}
+
+func (t *toolchainMips64) ClangCppflags() string {
+	return "${config.Mips64ClangCppflags}"
+}
+
+func (t *toolchainMips64) ClangLdflags() string {
+	return "${config.Mips64ClangLdflags}"
+}
+
+func (toolchainMips64) AddressSanitizerRuntimeLibrary() string {
+	return "libclang_rt.asan-mips64-android.so"
+}
+
+func mips64ToolchainFactory(arch android.Arch) Toolchain {
+	return &toolchainMips64{
+		cflags:               "${config.Mips64Cflags}",
+		clangCflags:          "${config.Mips64ClangCflags}",
+		toolchainCflags:      "${config.Mips64" + arch.ArchVariant + "VariantCflags}",
+		toolchainClangCflags: "${config.Mips64" + arch.ArchVariant + "VariantClangCflags}",
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Mips64, mips64ToolchainFactory)
+}
diff --git a/cc/config/mips_device.go b/cc/config/mips_device.go
new file mode 100644
index 0000000..3c77a48
--- /dev/null
+++ b/cc/config/mips_device.go
@@ -0,0 +1,244 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	mipsCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-O2",
+		"-fomit-frame-pointer",
+		"-fno-strict-aliasing",
+		"-funswitch-loops",
+		"-U__unix",
+		"-U__unix__",
+		"-Umips",
+		"-ffunction-sections",
+		"-fdata-sections",
+		"-funwind-tables",
+		"-fstack-protector-strong",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		// TARGET_RELEASE_CFLAGS
+		"-DNDEBUG",
+		"-g",
+		"-Wstrict-aliasing=2",
+		"-fgcse-after-reload",
+		"-frerun-cse-after-loop",
+		"-frename-registers",
+	}
+
+	mipsClangCflags = append(mipsCflags, []string{
+		"-fPIC",
+		"-fno-integrated-as",
+	}...)
+
+	mipsCppflags = []string{
+		"-fvisibility-inlines-hidden",
+	}
+
+	mipsLdflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,--allow-shlib-undefined",
+		"-Wl,--no-undefined-version",
+	}
+
+	mipsToolchainLdflags = []string{
+		"-Wl,-melf32ltsmip",
+	}
+
+	mipsArchVariantCflags = map[string][]string{
+		"mips32-fp": []string{
+			"-mips32",
+			"-mfp32",
+			"-modd-spreg",
+			"-mno-synci",
+		},
+		"mips32r2-fp": []string{
+			"-mips32r2",
+			"-mfp32",
+			"-modd-spreg",
+			"-msynci",
+		},
+		"mips32r2-fp-xburst": []string{
+			"-mips32r2",
+			"-mfp32",
+			"-modd-spreg",
+			"-mno-fused-madd",
+			"-Wa,-mmxu",
+			"-mno-synci",
+		},
+		"mips32r2dsp-fp": []string{
+			"-mips32r2",
+			"-mfp32",
+			"-modd-spreg",
+			"-mdsp",
+			"-msynci",
+		},
+		"mips32r2dspr2-fp": []string{
+			"-mips32r2",
+			"-mfp32",
+			"-modd-spreg",
+			"-mdspr2",
+			"-msynci",
+		},
+		"mips32r6": []string{
+			"-mips32r6",
+			"-mfp64",
+			"-mno-odd-spreg",
+			"-msynci",
+		},
+	}
+)
+
+const (
+	mipsGccVersion = "4.9"
+)
+
+func init() {
+	android.RegisterArchFeatures(android.Mips, "mips32r6",
+		"rev6")
+
+	pctx.StaticVariable("mipsGccVersion", mipsGccVersion)
+
+	pctx.SourcePathVariable("MipsGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
+
+	pctx.StaticVariable("MipsToolchainLdflags", strings.Join(mipsToolchainLdflags, " "))
+	pctx.StaticVariable("MipsCflags", strings.Join(mipsCflags, " "))
+	pctx.StaticVariable("MipsLdflags", strings.Join(mipsLdflags, " "))
+	pctx.StaticVariable("MipsCppflags", strings.Join(mipsCppflags, " "))
+	pctx.StaticVariable("MipsIncludeFlags", bionicHeaders("mips", "mips"))
+
+	// Clang cflags
+	pctx.StaticVariable("MipsClangCflags", strings.Join(ClangFilterUnknownCflags(mipsClangCflags), " "))
+	pctx.StaticVariable("MipsClangLdflags", strings.Join(ClangFilterUnknownCflags(mipsLdflags), " "))
+	pctx.StaticVariable("MipsClangCppflags", strings.Join(ClangFilterUnknownCflags(mipsCppflags), " "))
+
+	// Extended cflags
+
+	// Architecture variant cflags
+	for variant, cflags := range mipsArchVariantCflags {
+		pctx.StaticVariable("Mips"+variant+"VariantCflags", strings.Join(cflags, " "))
+		pctx.StaticVariable("Mips"+variant+"VariantClangCflags",
+			strings.Join(ClangFilterUnknownCflags(cflags), " "))
+	}
+}
+
+type toolchainMips struct {
+	toolchain32Bit
+	cflags, clangCflags                   string
+	toolchainCflags, toolchainClangCflags string
+}
+
+func (t *toolchainMips) Name() string {
+	return "mips"
+}
+
+func (t *toolchainMips) GccRoot() string {
+	return "${config.MipsGccRoot}"
+}
+
+func (t *toolchainMips) GccTriple() string {
+	return "mips64el-linux-android"
+}
+
+func (t *toolchainMips) GccVersion() string {
+	return mipsGccVersion
+}
+
+func (t *toolchainMips) ToolchainLdflags() string {
+	return "${config.MipsToolchainLdflags}"
+}
+
+func (t *toolchainMips) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainMips) Cflags() string {
+	return t.cflags
+}
+
+func (t *toolchainMips) Cppflags() string {
+	return "${config.MipsCppflags}"
+}
+
+func (t *toolchainMips) Ldflags() string {
+	return "${config.MipsLdflags}"
+}
+
+func (t *toolchainMips) IncludeFlags() string {
+	return "${config.MipsIncludeFlags}"
+}
+
+func (t *toolchainMips) ClangTriple() string {
+	return "mipsel-linux-android"
+}
+
+func (t *toolchainMips) ToolchainClangLdflags() string {
+	return "${config.MipsToolchainLdflags}"
+}
+
+func (t *toolchainMips) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (t *toolchainMips) ClangAsflags() string {
+	return "-fPIC -fno-integrated-as"
+}
+
+func (t *toolchainMips) ClangCflags() string {
+	return t.clangCflags
+}
+
+func (t *toolchainMips) ClangCppflags() string {
+	return "${config.MipsClangCppflags}"
+}
+
+func (t *toolchainMips) ClangLdflags() string {
+	return "${config.MipsClangLdflags}"
+}
+
+func (toolchainMips) AddressSanitizerRuntimeLibrary() string {
+	return "libclang_rt.asan-mips-android.so"
+}
+
+func mipsToolchainFactory(arch android.Arch) Toolchain {
+	return &toolchainMips{
+		cflags:               "${config.MipsCflags}",
+		clangCflags:          "${config.MipsClangCflags}",
+		toolchainCflags:      "${config.Mips" + arch.ArchVariant + "VariantCflags}",
+		toolchainClangCflags: "${config.Mips" + arch.ArchVariant + "VariantClangCflags}",
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Mips, mipsToolchainFactory)
+}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
new file mode 100644
index 0000000..c286a9a
--- /dev/null
+++ b/cc/config/toolchain.go
@@ -0,0 +1,190 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"fmt"
+
+	"android/soong/android"
+)
+
+type toolchainFactory func(arch android.Arch) Toolchain
+
+var toolchainFactories = make(map[android.OsType]map[android.ArchType]toolchainFactory)
+
+func registerToolchainFactory(os android.OsType, arch android.ArchType, factory toolchainFactory) {
+	if toolchainFactories[os] == nil {
+		toolchainFactories[os] = make(map[android.ArchType]toolchainFactory)
+	}
+	toolchainFactories[os][arch] = factory
+}
+
+func FindToolchain(os android.OsType, arch android.Arch) Toolchain {
+	factory := toolchainFactories[os][arch.ArchType]
+	if factory == nil {
+		panic(fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String()))
+		return nil
+	}
+	return factory(arch)
+}
+
+type Toolchain interface {
+	Name() string
+
+	GccRoot() string
+	GccTriple() string
+	// GccVersion should return a real value, not a ninja reference
+	GccVersion() string
+
+	ToolchainCflags() string
+	ToolchainLdflags() string
+	Cflags() string
+	Cppflags() string
+	Ldflags() string
+	IncludeFlags() string
+	InstructionSetFlags(string) (string, error)
+
+	ClangSupported() bool
+	ClangTriple() string
+	ToolchainClangCflags() string
+	ToolchainClangLdflags() string
+	ClangAsflags() string
+	ClangCflags() string
+	ClangCppflags() string
+	ClangLdflags() string
+	ClangInstructionSetFlags(string) (string, error)
+
+	Is64Bit() bool
+
+	ShlibSuffix() string
+	ExecutableSuffix() string
+
+	AddressSanitizerRuntimeLibrary() string
+
+	AvailableLibraries() []string
+}
+
+type toolchainBase struct {
+}
+
+func (toolchainBase) InstructionSetFlags(s string) (string, error) {
+	if s != "" {
+		return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
+	}
+	return "", nil
+}
+
+func (toolchainBase) ClangInstructionSetFlags(s string) (string, error) {
+	if s != "" {
+		return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
+	}
+	return "", nil
+}
+
+func (toolchainBase) ToolchainCflags() string {
+	return ""
+}
+
+func (toolchainBase) ToolchainLdflags() string {
+	return ""
+}
+
+func (toolchainBase) ToolchainClangCflags() string {
+	return ""
+}
+
+func (toolchainBase) ToolchainClangLdflags() string {
+	return ""
+}
+
+func (toolchainBase) ClangSupported() bool {
+	return true
+}
+
+func (toolchainBase) ShlibSuffix() string {
+	return ".so"
+}
+
+func (toolchainBase) ExecutableSuffix() string {
+	return ""
+}
+
+func (toolchainBase) ClangAsflags() string {
+	return ""
+}
+
+func (toolchainBase) AddressSanitizerRuntimeLibrary() string {
+	return ""
+}
+
+func (toolchainBase) AvailableLibraries() []string {
+	return []string{}
+}
+
+type toolchain64Bit struct {
+	toolchainBase
+}
+
+func (toolchain64Bit) Is64Bit() bool {
+	return true
+}
+
+type toolchain32Bit struct {
+	toolchainBase
+}
+
+func (toolchain32Bit) Is64Bit() bool {
+	return false
+}
+
+func copyVariantFlags(m map[string][]string) map[string][]string {
+	ret := make(map[string][]string, len(m))
+	for k, v := range m {
+		l := make([]string, len(m[k]))
+		for i := range m[k] {
+			l[i] = v[i]
+		}
+		ret[k] = l
+	}
+	return ret
+}
+
+func variantOrDefault(variants map[string]string, choice string) string {
+	if ret, ok := variants[choice]; ok {
+		return ret
+	}
+	return variants[""]
+}
+
+func addPrefix(list []string, prefix string) []string {
+	for i := range list {
+		list[i] = prefix + list[i]
+	}
+	return list
+}
+
+func indexList(s string, list []string) int {
+	for i, l := range list {
+		if l == s {
+			return i
+		}
+	}
+
+	return -1
+}
+
+func inList(s string, list []string) bool {
+	return indexList(s, list) != -1
+}
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
new file mode 100644
index 0000000..ec02bed
--- /dev/null
+++ b/cc/config/x86_64_device.go
@@ -0,0 +1,259 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	x86_64Cflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-O2",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-Wstrict-aliasing=2",
+		"-ffunction-sections",
+		"-finline-functions",
+		"-finline-limit=300",
+		"-fno-short-enums",
+		"-fstrict-aliasing",
+		"-funswitch-loops",
+		"-funwind-tables",
+		"-fstack-protector-strong",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		// Help catch common 32/64-bit errors.
+		"-Werror=pointer-to-int-cast",
+		"-Werror=int-to-pointer-cast",
+		"-Werror=implicit-function-declaration",
+
+		// TARGET_RELEASE_CFLAGS from build/core/combo/select.mk
+		"-O2",
+		"-g",
+		"-fno-strict-aliasing",
+	}
+
+	x86_64Cppflags = []string{}
+
+	x86_64Ldflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,--gc-sections",
+		"-Wl,--hash-style=gnu",
+		"-Wl,--no-undefined-version",
+	}
+
+	x86_64ArchVariantCflags = map[string][]string{
+		"": []string{
+			"-march=x86-64",
+		},
+		"haswell": []string{
+			"-march=core-avx2",
+		},
+		"ivybridge": []string{
+			"-march=core-avx-i",
+		},
+		"sandybridge": []string{
+			"-march=corei7",
+		},
+		"silvermont": []string{
+			"-march=slm",
+		},
+	}
+
+	x86_64ArchFeatureCflags = map[string][]string{
+		"ssse3":  []string{"-DUSE_SSSE3", "-mssse3"},
+		"sse4":   []string{"-msse4"},
+		"sse4_1": []string{"-msse4.1"},
+		"sse4_2": []string{"-msse4.2"},
+		"popcnt": []string{"-mpopcnt"},
+		"avx":    []string{"-mavx"},
+		"aes_ni": []string{"-maes"},
+	}
+)
+
+const (
+	x86_64GccVersion = "4.9"
+)
+
+func init() {
+	android.RegisterArchFeatures(android.X86_64, "",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86_64, "haswell",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"avx",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86_64, "ivybridge",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"avx",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86_64, "sandybridge",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86_64, "silvermont",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"popcnt")
+
+	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
+
+	pctx.SourcePathVariable("X86_64GccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
+
+	pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
+	pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
+
+	pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
+	pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
+	pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
+	pctx.StaticVariable("X86_64IncludeFlags", bionicHeaders("x86_64", "x86"))
+
+	// Clang cflags
+	pctx.StaticVariable("X86_64ClangCflags", strings.Join(ClangFilterUnknownCflags(x86_64Cflags), " "))
+	pctx.StaticVariable("X86_64ClangLdflags", strings.Join(ClangFilterUnknownCflags(x86_64Ldflags), " "))
+	pctx.StaticVariable("X86_64ClangCppflags", strings.Join(ClangFilterUnknownCflags(x86_64Cppflags), " "))
+
+	// Extended cflags
+
+	// Architecture variant cflags
+	for variant, cflags := range x86_64ArchVariantCflags {
+		pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
+		pctx.StaticVariable("X86_64"+variant+"VariantClangCflags",
+			strings.Join(ClangFilterUnknownCflags(cflags), " "))
+	}
+}
+
+type toolchainX86_64 struct {
+	toolchain64Bit
+	toolchainCflags, toolchainClangCflags string
+}
+
+func (t *toolchainX86_64) Name() string {
+	return "x86_64"
+}
+
+func (t *toolchainX86_64) GccRoot() string {
+	return "${config.X86_64GccRoot}"
+}
+
+func (t *toolchainX86_64) GccTriple() string {
+	return "x86_64-linux-android"
+}
+
+func (t *toolchainX86_64) GccVersion() string {
+	return x86_64GccVersion
+}
+
+func (t *toolchainX86_64) ToolchainLdflags() string {
+	return "${config.X86_64ToolchainLdflags}"
+}
+
+func (t *toolchainX86_64) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainX86_64) Cflags() string {
+	return "${config.X86_64Cflags}"
+}
+
+func (t *toolchainX86_64) Cppflags() string {
+	return "${config.X86_64Cppflags}"
+}
+
+func (t *toolchainX86_64) Ldflags() string {
+	return "${config.X86_64Ldflags}"
+}
+
+func (t *toolchainX86_64) IncludeFlags() string {
+	return "${config.X86_64IncludeFlags}"
+}
+
+func (t *toolchainX86_64) ClangTriple() string {
+	return t.GccTriple()
+}
+
+func (t *toolchainX86_64) ToolchainClangLdflags() string {
+	return "${config.X86_64ToolchainLdflags}"
+}
+
+func (t *toolchainX86_64) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (t *toolchainX86_64) ClangCflags() string {
+	return "${config.X86_64ClangCflags}"
+}
+
+func (t *toolchainX86_64) ClangCppflags() string {
+	return "${config.X86_64ClangCppflags}"
+}
+
+func (t *toolchainX86_64) ClangLdflags() string {
+	return "${config.X86_64Ldflags}"
+}
+
+func x86_64ToolchainFactory(arch android.Arch) Toolchain {
+	toolchainCflags := []string{
+		"${config.X86_64ToolchainCflags}",
+		"${config.X86_64" + arch.ArchVariant + "VariantCflags}",
+	}
+
+	toolchainClangCflags := []string{
+		"${config.X86_64ToolchainCflags}",
+		"${config.X86_64" + arch.ArchVariant + "VariantClangCflags}",
+	}
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainCflags = append(toolchainCflags, x86_64ArchFeatureCflags[feature]...)
+		toolchainClangCflags = append(toolchainClangCflags, x86_64ArchFeatureCflags[feature]...)
+	}
+
+	return &toolchainX86_64{
+		toolchainCflags:      strings.Join(toolchainCflags, " "),
+		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.X86_64, x86_64ToolchainFactory)
+}
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
new file mode 100644
index 0000000..e89fc9c
--- /dev/null
+++ b/cc/config/x86_darwin_host.go
@@ -0,0 +1,282 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"fmt"
+	"os/exec"
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	darwinCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+
+		"-fdiagnostics-color",
+
+		"-fPIC",
+		"-funwind-tables",
+
+		// Workaround differences in inttypes.h between host and target.
+		//See bug 12708004.
+		"-D__STDC_FORMAT_MACROS",
+		"-D__STDC_CONSTANT_MACROS",
+
+		// HOST_RELEASE_CFLAGS
+		"-O2", // from build/core/combo/select.mk
+		"-g",  // from build/core/combo/select.mk
+		"-fno-strict-aliasing", // from build/core/combo/select.mk
+		"-isysroot ${macSdkRoot}",
+		"-mmacosx-version-min=${macSdkVersion}",
+		"-DMACOSX_DEPLOYMENT_TARGET=${macSdkVersion}",
+	}
+
+	darwinLdflags = []string{
+		"-isysroot ${macSdkRoot}",
+		"-Wl,-syslibroot,${macSdkRoot}",
+		"-mmacosx-version-min=${macSdkVersion}",
+	}
+
+	// Extended cflags
+	darwinX86Cflags = []string{
+		"-m32",
+	}
+
+	darwinX8664Cflags = []string{
+		"-m64",
+	}
+
+	darwinX86Ldflags = []string{
+		"-m32",
+	}
+
+	darwinX8664Ldflags = []string{
+		"-m64",
+	}
+
+	darwinClangCflags = append(ClangFilterUnknownCflags(darwinCflags), []string{
+		"-integrated-as",
+		"-fstack-protector-strong",
+	}...)
+
+	darwinX86ClangCflags = append(ClangFilterUnknownCflags(darwinX86Cflags), []string{
+		"-msse3",
+	}...)
+
+	darwinClangLdflags = ClangFilterUnknownCflags(darwinLdflags)
+
+	darwinX86ClangLdflags = ClangFilterUnknownCflags(darwinX86Ldflags)
+
+	darwinX8664ClangLdflags = ClangFilterUnknownCflags(darwinX8664Ldflags)
+
+	darwinSupportedSdkVersions = []string{
+		"10.8",
+		"10.9",
+		"10.10",
+		"10.11",
+	}
+
+	darwinAvailableLibraries = addPrefix([]string{
+		"c",
+		"dl",
+		"m",
+		"ncurses",
+		"pthread",
+		"z",
+	}, "-l")
+)
+
+const (
+	darwinGccVersion = "4.2.1"
+)
+
+func init() {
+	pctx.VariableFunc("macSdkPath", func(config interface{}) (string, error) {
+		bytes, err := exec.Command("xcode-select", "--print-path").Output()
+		return strings.TrimSpace(string(bytes)), err
+	})
+	pctx.VariableFunc("macSdkRoot", func(config interface{}) (string, error) {
+		return xcrunSdk(config.(android.Config), "--show-sdk-path")
+	})
+	pctx.StaticVariable("macSdkVersion", darwinSupportedSdkVersions[0])
+	pctx.VariableFunc("MacArPath", func(config interface{}) (string, error) {
+		bytes, err := exec.Command("xcrun", "--find", "ar").Output()
+		return strings.TrimSpace(string(bytes)), err
+	})
+
+	pctx.VariableFunc("MacStripPath", func(config interface{}) (string, error) {
+		bytes, err := exec.Command("xcrun", "--find", "strip").Output()
+		return strings.TrimSpace(string(bytes)), err
+	})
+
+	pctx.StaticVariable("DarwinGccVersion", darwinGccVersion)
+	pctx.SourcePathVariable("DarwinGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${DarwinGccVersion}")
+
+	pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
+
+	pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
+	pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
+
+	pctx.StaticVariable("DarwinClangCflags", strings.Join(darwinClangCflags, " "))
+	pctx.StaticVariable("DarwinClangLdflags", strings.Join(darwinClangLdflags, " "))
+
+	// Extended cflags
+	pctx.StaticVariable("DarwinX86Cflags", strings.Join(darwinX86Cflags, " "))
+	pctx.StaticVariable("DarwinX8664Cflags", strings.Join(darwinX8664Cflags, " "))
+	pctx.StaticVariable("DarwinX86Ldflags", strings.Join(darwinX86Ldflags, " "))
+	pctx.StaticVariable("DarwinX8664Ldflags", strings.Join(darwinX8664Ldflags, " "))
+
+	pctx.StaticVariable("DarwinX86ClangCflags", strings.Join(darwinX86ClangCflags, " "))
+	pctx.StaticVariable("DarwinX8664ClangCflags",
+		strings.Join(ClangFilterUnknownCflags(darwinX8664Cflags), " "))
+	pctx.StaticVariable("DarwinX86ClangLdflags", strings.Join(darwinX86ClangLdflags, " "))
+	pctx.StaticVariable("DarwinX8664ClangLdflags", strings.Join(darwinX8664ClangLdflags, " "))
+}
+
+func xcrunSdk(config android.Config, arg string) (string, error) {
+	if selected := config.Getenv("MAC_SDK_VERSION"); selected != "" {
+		if !inList(selected, darwinSupportedSdkVersions) {
+			return "", fmt.Errorf("MAC_SDK_VERSION %s isn't supported: %q", selected, darwinSupportedSdkVersions)
+		}
+
+		bytes, err := exec.Command("xcrun", "--sdk", "macosx"+selected, arg).Output()
+		if err == nil {
+			return strings.TrimSpace(string(bytes)), err
+		}
+		return "", fmt.Errorf("MAC_SDK_VERSION %s is not installed", selected)
+	}
+
+	for _, sdk := range darwinSupportedSdkVersions {
+		bytes, err := exec.Command("xcrun", "--sdk", "macosx"+sdk, arg).Output()
+		if err == nil {
+			return strings.TrimSpace(string(bytes)), err
+		}
+	}
+	return "", fmt.Errorf("Could not find a supported mac sdk: %q", darwinSupportedSdkVersions)
+}
+
+type toolchainDarwin struct {
+	cFlags, ldFlags string
+}
+
+type toolchainDarwinX86 struct {
+	toolchain32Bit
+	toolchainDarwin
+}
+
+type toolchainDarwinX8664 struct {
+	toolchain64Bit
+	toolchainDarwin
+}
+
+func (t *toolchainDarwinX86) Name() string {
+	return "x86"
+}
+
+func (t *toolchainDarwinX8664) Name() string {
+	return "x86_64"
+}
+
+func (t *toolchainDarwin) GccRoot() string {
+	return "${config.DarwinGccRoot}"
+}
+
+func (t *toolchainDarwin) GccTriple() string {
+	return "${config.DarwinGccTriple}"
+}
+
+func (t *toolchainDarwin) GccVersion() string {
+	return darwinGccVersion
+}
+
+func (t *toolchainDarwin) Cflags() string {
+	return "${config.DarwinCflags} ${config.DarwinX86Cflags}"
+}
+
+func (t *toolchainDarwinX8664) Cflags() string {
+	return "${config.DarwinCflags} ${config.DarwinX8664Cflags}"
+}
+
+func (t *toolchainDarwin) Cppflags() string {
+	return ""
+}
+
+func (t *toolchainDarwinX86) Ldflags() string {
+	return "${config.DarwinLdflags} ${config.DarwinX86Ldflags}"
+}
+
+func (t *toolchainDarwinX8664) Ldflags() string {
+	return "${config.DarwinLdflags} ${config.DarwinX8664Ldflags}"
+}
+
+func (t *toolchainDarwin) IncludeFlags() string {
+	return ""
+}
+
+func (t *toolchainDarwinX86) ClangTriple() string {
+	return "i686-apple-darwin"
+}
+
+func (t *toolchainDarwinX86) ClangCflags() string {
+	return "${config.DarwinClangCflags} ${config.DarwinX86ClangCflags}"
+}
+
+func (t *toolchainDarwinX8664) ClangTriple() string {
+	return "x86_64-apple-darwin"
+}
+
+func (t *toolchainDarwinX8664) ClangCflags() string {
+	return "${config.DarwinClangCflags} ${config.DarwinX8664ClangCflags}"
+}
+
+func (t *toolchainDarwin) ClangCppflags() string {
+	return ""
+}
+
+func (t *toolchainDarwinX86) ClangLdflags() string {
+	return "${config.DarwinClangLdflags} ${config.DarwinX86ClangLdflags}"
+}
+
+func (t *toolchainDarwinX8664) ClangLdflags() string {
+	return "${config.DarwinClangLdflags} ${config.DarwinX8664ClangLdflags}"
+}
+
+func (t *toolchainDarwin) ShlibSuffix() string {
+	return ".dylib"
+}
+
+func (t *toolchainDarwin) AvailableLibraries() []string {
+	return darwinAvailableLibraries
+}
+
+var toolchainDarwinX86Singleton Toolchain = &toolchainDarwinX86{}
+var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{}
+
+func darwinX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainDarwinX86Singleton
+}
+
+func darwinX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainDarwinX8664Singleton
+}
+
+func init() {
+	registerToolchainFactory(android.Darwin, android.X86, darwinX86ToolchainFactory)
+	registerToolchainFactory(android.Darwin, android.X86_64, darwinX8664ToolchainFactory)
+}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
new file mode 100644
index 0000000..032b1f0
--- /dev/null
+++ b/cc/config/x86_device.go
@@ -0,0 +1,282 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	x86Cflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+		"-O2",
+		"-Wa,--noexecstack",
+		"-Werror=format-security",
+		"-D_FORTIFY_SOURCE=2",
+		"-Wstrict-aliasing=2",
+		"-ffunction-sections",
+		"-finline-functions",
+		"-finline-limit=300",
+		"-fno-short-enums",
+		"-fstrict-aliasing",
+		"-funswitch-loops",
+		"-funwind-tables",
+		"-fstack-protector-strong",
+		"-no-canonical-prefixes",
+		"-fno-canonical-system-headers",
+
+		// TARGET_RELEASE_CFLAGS from build/core/combo/select.mk
+		"-O2",
+		"-g",
+		"-fno-strict-aliasing",
+	}
+
+	x86ClangCflags = append(x86Cflags, []string{
+		"-msse3",
+
+		// -mstackrealign is needed to realign stack in native code
+		// that could be called from JNI, so that movaps instruction
+		// will work on assumed stack aligned local variables.
+		"-mstackrealign",
+	}...)
+
+	x86Cppflags = []string{}
+
+	x86Ldflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+		"-Wl,--gc-sections",
+		"-Wl,--hash-style=gnu",
+		"-Wl,--no-undefined-version",
+	}
+
+	x86ArchVariantCflags = map[string][]string{
+		"": []string{
+			"-march=prescott",
+		},
+		"x86_64": []string{
+			"-march=prescott",
+		},
+		"atom": []string{
+			"-march=atom",
+			"-mfpmath=sse",
+		},
+		"haswell": []string{
+			"-march=core-avx2",
+			"-mfpmath=sse",
+		},
+		"ivybridge": []string{
+			"-march=core-avx-i",
+			"-mfpmath=sse",
+		},
+		"sandybridge": []string{
+			"-march=corei7",
+			"-mfpmath=sse",
+		},
+		"silvermont": []string{
+			"-march=slm",
+			"-mfpmath=sse",
+		},
+	}
+
+	x86ArchFeatureCflags = map[string][]string{
+		"ssse3":  []string{"-DUSE_SSSE3", "-mssse3"},
+		"sse4":   []string{"-msse4"},
+		"sse4_1": []string{"-msse4.1"},
+		"sse4_2": []string{"-msse4.2"},
+		"avx":    []string{"-mavx"},
+		"aes_ni": []string{"-maes"},
+	}
+)
+
+const (
+	x86GccVersion = "4.9"
+)
+
+func init() {
+	android.RegisterArchFeatures(android.X86, "x86_64",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86, "atom",
+		"ssse3",
+		"movbe")
+	android.RegisterArchFeatures(android.X86, "haswell",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"avx",
+		"popcnt",
+		"movbe")
+	android.RegisterArchFeatures(android.X86, "ivybridge",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"avx",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86, "sandybridge",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"popcnt")
+	android.RegisterArchFeatures(android.X86, "silvermont",
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"aes_ni",
+		"popcnt",
+		"movbe")
+
+	pctx.StaticVariable("x86GccVersion", x86GccVersion)
+
+	pctx.SourcePathVariable("X86GccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
+
+	pctx.StaticVariable("X86ToolchainCflags", "-m32")
+	pctx.StaticVariable("X86ToolchainLdflags", "-m32")
+
+	pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
+	pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
+	pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
+	pctx.StaticVariable("X86IncludeFlags", bionicHeaders("x86", "x86"))
+
+	// Clang cflags
+	pctx.StaticVariable("X86ClangCflags", strings.Join(ClangFilterUnknownCflags(x86ClangCflags), " "))
+	pctx.StaticVariable("X86ClangLdflags", strings.Join(ClangFilterUnknownCflags(x86Ldflags), " "))
+	pctx.StaticVariable("X86ClangCppflags", strings.Join(ClangFilterUnknownCflags(x86Cppflags), " "))
+
+	// Extended cflags
+
+	// Architecture variant cflags
+	for variant, cflags := range x86ArchVariantCflags {
+		pctx.StaticVariable("X86"+variant+"VariantCflags", strings.Join(cflags, " "))
+		pctx.StaticVariable("X86"+variant+"VariantClangCflags",
+			strings.Join(ClangFilterUnknownCflags(cflags), " "))
+	}
+}
+
+type toolchainX86 struct {
+	toolchain32Bit
+	toolchainCflags, toolchainClangCflags string
+}
+
+func (t *toolchainX86) Name() string {
+	return "x86"
+}
+
+func (t *toolchainX86) GccRoot() string {
+	return "${config.X86GccRoot}"
+}
+
+func (t *toolchainX86) GccTriple() string {
+	return "x86_64-linux-android"
+}
+
+func (t *toolchainX86) GccVersion() string {
+	return x86GccVersion
+}
+
+func (t *toolchainX86) ToolchainLdflags() string {
+	return "${config.X86ToolchainLdflags}"
+}
+
+func (t *toolchainX86) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (t *toolchainX86) Cflags() string {
+	return "${config.X86Cflags}"
+}
+
+func (t *toolchainX86) Cppflags() string {
+	return "${config.X86Cppflags}"
+}
+
+func (t *toolchainX86) Ldflags() string {
+	return "${config.X86Ldflags}"
+}
+
+func (t *toolchainX86) IncludeFlags() string {
+	return "${config.X86IncludeFlags}"
+}
+
+func (t *toolchainX86) ClangTriple() string {
+	return "i686-linux-android"
+}
+
+func (t *toolchainX86) ToolchainClangLdflags() string {
+	return "${config.X86ToolchainLdflags}"
+}
+
+func (t *toolchainX86) ToolchainClangCflags() string {
+	return t.toolchainClangCflags
+}
+
+func (t *toolchainX86) ClangCflags() string {
+	return "${config.X86ClangCflags}"
+}
+
+func (t *toolchainX86) ClangCppflags() string {
+	return "${config.X86ClangCppflags}"
+}
+
+func (t *toolchainX86) ClangLdflags() string {
+	return "${config.X86Ldflags}"
+}
+
+func (toolchainX86) AddressSanitizerRuntimeLibrary() string {
+	return "libclang_rt.asan-i686-android.so"
+}
+
+func x86ToolchainFactory(arch android.Arch) Toolchain {
+	toolchainCflags := []string{
+		"${config.X86ToolchainCflags}",
+		"${config.X86" + arch.ArchVariant + "VariantCflags}",
+	}
+
+	toolchainClangCflags := []string{
+		"${config.X86ToolchainCflags}",
+		"${config.X86" + arch.ArchVariant + "VariantClangCflags}",
+	}
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainCflags = append(toolchainCflags, x86ArchFeatureCflags[feature]...)
+		toolchainClangCflags = append(toolchainClangCflags, x86ArchFeatureCflags[feature]...)
+	}
+
+	return &toolchainX86{
+		toolchainCflags:      strings.Join(toolchainCflags, " "),
+		toolchainClangCflags: strings.Join(toolchainClangCflags, " "),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.X86, x86ToolchainFactory)
+}
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
new file mode 100644
index 0000000..676ea5c
--- /dev/null
+++ b/cc/config/x86_linux_host.go
@@ -0,0 +1,273 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	linuxCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+
+		"-fdiagnostics-color",
+
+		"-Wa,--noexecstack",
+
+		"-fPIC",
+		"-no-canonical-prefixes",
+
+		"-U_FORTIFY_SOURCE",
+		"-D_FORTIFY_SOURCE=2",
+		"-fstack-protector",
+
+		// Workaround differences in inttypes.h between host and target.
+		//See bug 12708004.
+		"-D__STDC_FORMAT_MACROS",
+		"-D__STDC_CONSTANT_MACROS",
+
+		// HOST_RELEASE_CFLAGS
+		"-O2", // from build/core/combo/select.mk
+		"-g",  // from build/core/combo/select.mk
+		"-fno-strict-aliasing", // from build/core/combo/select.mk
+	}
+
+	linuxLdflags = []string{
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--no-undefined-version",
+	}
+
+	// Extended cflags
+	linuxX86Cflags = []string{
+		"-msse3",
+		"-mfpmath=sse",
+		"-m32",
+		"-march=prescott",
+		"-D_FILE_OFFSET_BITS=64",
+		"-D_LARGEFILE_SOURCE=1",
+	}
+
+	linuxX8664Cflags = []string{
+		"-m64",
+	}
+
+	linuxX86Ldflags = []string{
+		"-m32",
+	}
+
+	linuxX8664Ldflags = []string{
+		"-m64",
+	}
+
+	linuxClangCflags = append(ClangFilterUnknownCflags(linuxCflags), []string{
+		"--gcc-toolchain=${LinuxGccRoot}",
+		"--sysroot ${LinuxGccRoot}/sysroot",
+		"-fstack-protector-strong",
+	}...)
+
+	linuxClangLdflags = append(ClangFilterUnknownCflags(linuxLdflags), []string{
+		"--gcc-toolchain=${LinuxGccRoot}",
+		"--sysroot ${LinuxGccRoot}/sysroot",
+	}...)
+
+	linuxX86ClangLdflags = append(ClangFilterUnknownCflags(linuxX86Ldflags), []string{
+		"-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32",
+		"-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}/32",
+		"-L${LinuxGccRoot}/${LinuxGccTriple}/lib32",
+	}...)
+
+	linuxX8664ClangLdflags = append(ClangFilterUnknownCflags(linuxX8664Ldflags), []string{
+		"-B${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}",
+		"-L${LinuxGccRoot}/lib/gcc/${LinuxGccTriple}/${LinuxGccVersion}",
+		"-L${LinuxGccRoot}/${LinuxGccTriple}/lib64",
+	}...)
+
+	linuxClangCppflags = []string{
+		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}",
+		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}/backward",
+	}
+
+	linuxX86ClangCppflags = []string{
+		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}/${LinuxGccTriple}/32",
+	}
+
+	linuxX8664ClangCppflags = []string{
+		"-isystem ${LinuxGccRoot}/${LinuxGccTriple}/include/c++/${LinuxGccVersion}/${LinuxGccTriple}",
+	}
+
+	linuxAvailableLibraries = addPrefix([]string{
+		"c",
+		"dl",
+		"gcc",
+		"gcc_s",
+		"m",
+		"ncurses",
+		"pthread",
+		"resolv",
+		"rt",
+		"util",
+		"z",
+	}, "-l")
+)
+
+const (
+	linuxGccVersion = "4.8"
+)
+
+func init() {
+	pctx.StaticVariable("LinuxGccVersion", linuxGccVersion)
+
+	pctx.SourcePathVariable("LinuxGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${LinuxGccVersion}")
+
+	pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
+
+	pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
+	pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
+
+	pctx.StaticVariable("LinuxClangCflags", strings.Join(linuxClangCflags, " "))
+	pctx.StaticVariable("LinuxClangLdflags", strings.Join(linuxClangLdflags, " "))
+	pctx.StaticVariable("LinuxClangCppflags", strings.Join(linuxClangCppflags, " "))
+
+	// Extended cflags
+	pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
+	pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
+	pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
+	pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
+
+	pctx.StaticVariable("LinuxX86ClangCflags",
+		strings.Join(ClangFilterUnknownCflags(linuxX86Cflags), " "))
+	pctx.StaticVariable("LinuxX8664ClangCflags",
+		strings.Join(ClangFilterUnknownCflags(linuxX8664Cflags), " "))
+	pctx.StaticVariable("LinuxX86ClangLdflags", strings.Join(linuxX86ClangLdflags, " "))
+	pctx.StaticVariable("LinuxX8664ClangLdflags", strings.Join(linuxX8664ClangLdflags, " "))
+	pctx.StaticVariable("LinuxX86ClangCppflags", strings.Join(linuxX86ClangCppflags, " "))
+	pctx.StaticVariable("LinuxX8664ClangCppflags", strings.Join(linuxX8664ClangCppflags, " "))
+}
+
+type toolchainLinux struct {
+	cFlags, ldFlags string
+}
+
+type toolchainLinuxX86 struct {
+	toolchain32Bit
+	toolchainLinux
+}
+
+type toolchainLinuxX8664 struct {
+	toolchain64Bit
+	toolchainLinux
+}
+
+func (t *toolchainLinuxX86) Name() string {
+	return "x86"
+}
+
+func (t *toolchainLinuxX8664) Name() string {
+	return "x86_64"
+}
+
+func (t *toolchainLinux) GccRoot() string {
+	return "${config.LinuxGccRoot}"
+}
+
+func (t *toolchainLinux) GccTriple() string {
+	return "${config.LinuxGccTriple}"
+}
+
+func (t *toolchainLinux) GccVersion() string {
+	return linuxGccVersion
+}
+
+func (t *toolchainLinuxX86) Cflags() string {
+	return "${config.LinuxCflags} ${config.LinuxX86Cflags}"
+}
+
+func (t *toolchainLinuxX8664) Cflags() string {
+	return "${config.LinuxCflags} ${config.LinuxX8664Cflags}"
+}
+
+func (t *toolchainLinux) Cppflags() string {
+	return ""
+}
+
+func (t *toolchainLinuxX86) Ldflags() string {
+	return "${config.LinuxLdflags} ${config.LinuxX86Ldflags}"
+}
+
+func (t *toolchainLinuxX8664) Ldflags() string {
+	return "${config.LinuxLdflags} ${config.LinuxX8664Ldflags}"
+}
+
+func (t *toolchainLinux) IncludeFlags() string {
+	return ""
+}
+
+func (t *toolchainLinuxX86) ClangTriple() string {
+	return "i686-linux-gnu"
+}
+
+func (t *toolchainLinuxX86) ClangCflags() string {
+	return "${config.LinuxClangCflags} ${config.LinuxX86ClangCflags}"
+}
+
+func (t *toolchainLinuxX86) ClangCppflags() string {
+	return "${config.LinuxClangCppflags} ${config.LinuxX86ClangCppflags}"
+}
+
+func (t *toolchainLinuxX8664) ClangTriple() string {
+	return "x86_64-linux-gnu"
+}
+
+func (t *toolchainLinuxX8664) ClangCflags() string {
+	return "${config.LinuxClangCflags} ${config.LinuxX8664ClangCflags}"
+}
+
+func (t *toolchainLinuxX8664) ClangCppflags() string {
+	return "${config.LinuxClangCppflags} ${config.LinuxX8664ClangCppflags}"
+}
+
+func (t *toolchainLinuxX86) ClangLdflags() string {
+	return "${config.LinuxClangLdflags} ${config.LinuxX86ClangLdflags}"
+}
+
+func (t *toolchainLinuxX8664) ClangLdflags() string {
+	return "${config.LinuxClangLdflags} ${config.LinuxX8664ClangLdflags}"
+}
+
+func (t *toolchainLinux) AvailableLibraries() []string {
+	return linuxAvailableLibraries
+}
+
+var toolchainLinuxX86Singleton Toolchain = &toolchainLinuxX86{}
+var toolchainLinuxX8664Singleton Toolchain = &toolchainLinuxX8664{}
+
+func linuxX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxX86Singleton
+}
+
+func linuxX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainLinuxX8664Singleton
+}
+
+func init() {
+	registerToolchainFactory(android.Linux, android.X86, linuxX86ToolchainFactory)
+	registerToolchainFactory(android.Linux, android.X86_64, linuxX8664ToolchainFactory)
+}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
new file mode 100644
index 0000000..125d02d
--- /dev/null
+++ b/cc/config/x86_windows_host.go
@@ -0,0 +1,218 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	windowsCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+
+		"-DUSE_MINGW",
+		"-DWIN32_LEAN_AND_MEAN",
+		"-Wno-unused-parameter",
+
+		// Workaround differences in inttypes.h between host and target.
+		//See bug 12708004.
+		"-D__STDC_FORMAT_MACROS",
+		"-D__STDC_CONSTANT_MACROS",
+
+		// Use C99-compliant printf functions (%zd).
+		"-D__USE_MINGW_ANSI_STDIO=1",
+		// Admit to using >= Vista. Both are needed because of <_mingw.h>.
+		"-D_WIN32_WINNT=0x0600",
+		"-DWINVER=0x0600",
+		// Get 64-bit off_t and related functions.
+		"-D_FILE_OFFSET_BITS=64",
+
+		"--sysroot ${WindowsGccRoot}/${WindowsGccTriple}",
+
+		// HOST_RELEASE_CFLAGS
+		"-O2", // from build/core/combo/select.mk
+		"-g",  // from build/core/combo/select.mk
+		"-fno-strict-aliasing", // from build/core/combo/select.mk
+	}
+
+	windowsIncludeFlags = []string{
+		"-isystem ${WindowsGccRoot}/${WindowsGccTriple}/include",
+		"-isystem ${WindowsGccRoot}/lib/gcc/${WindowsGccTriple}/4.8.3/include",
+	}
+
+	windowsLdflags = []string{
+		"--enable-stdcall-fixup",
+	}
+
+	windowsX86Cflags = []string{
+		"-m32",
+	}
+
+	windowsX8664Cflags = []string{
+		"-m64",
+	}
+
+	windowsX86Ldflags = []string{
+		"-m32",
+		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib32",
+	}
+
+	windowsX8664Ldflags = []string{
+		"-m64",
+		"-L${WindowsGccRoot}/${WindowsGccTriple}/lib64",
+	}
+
+	windowsAvailableLibraries = addPrefix([]string{
+		"gdi32",
+		"imagehlp",
+		"ole32",
+		"psapi",
+		"userenv",
+		"uuid",
+		"ws2_32",
+	}, "-l")
+)
+
+const (
+	windowsGccVersion = "4.8"
+)
+
+func init() {
+	pctx.StaticVariable("WindowsGccVersion", windowsGccVersion)
+
+	pctx.SourcePathVariable("WindowsGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${WindowsGccVersion}")
+
+	pctx.StaticVariable("WindowsGccTriple", "x86_64-w64-mingw32")
+
+	pctx.StaticVariable("WindowsCflags", strings.Join(windowsCflags, " "))
+	pctx.StaticVariable("WindowsLdflags", strings.Join(windowsLdflags, " "))
+
+	pctx.StaticVariable("WindowsX86Cflags", strings.Join(windowsX86Cflags, " "))
+	pctx.StaticVariable("WindowsX8664Cflags", strings.Join(windowsX8664Cflags, " "))
+	pctx.StaticVariable("WindowsX86Ldflags", strings.Join(windowsX86Ldflags, " "))
+	pctx.StaticVariable("WindowsX8664Ldflags", strings.Join(windowsX8664Ldflags, " "))
+
+	pctx.StaticVariable("WindowsIncludeFlags", strings.Join(windowsIncludeFlags, " "))
+}
+
+type toolchainWindows struct {
+	cFlags, ldFlags string
+}
+
+type toolchainWindowsX86 struct {
+	toolchain32Bit
+	toolchainWindows
+}
+
+type toolchainWindowsX8664 struct {
+	toolchain64Bit
+	toolchainWindows
+}
+
+func (t *toolchainWindowsX86) Name() string {
+	return "x86"
+}
+
+func (t *toolchainWindowsX8664) Name() string {
+	return "x86_64"
+}
+
+func (t *toolchainWindows) GccRoot() string {
+	return "${config.WindowsGccRoot}"
+}
+
+func (t *toolchainWindows) GccTriple() string {
+	return "${config.WindowsGccTriple}"
+}
+
+func (t *toolchainWindows) GccVersion() string {
+	return windowsGccVersion
+}
+
+func (t *toolchainWindowsX86) Cflags() string {
+	return "${config.WindowsCflags} ${config.WindowsX86Cflags}"
+}
+
+func (t *toolchainWindowsX8664) Cflags() string {
+	return "${config.WindowsCflags} ${config.WindowsX8664Cflags}"
+}
+
+func (t *toolchainWindows) Cppflags() string {
+	return ""
+}
+
+func (t *toolchainWindowsX86) Ldflags() string {
+	return "${config.WindowsLdflags} ${config.WindowsX86Ldflags}"
+}
+
+func (t *toolchainWindowsX8664) Ldflags() string {
+	return "${config.WindowsLdflags} ${config.WindowsX8664Ldflags}"
+}
+
+func (t *toolchainWindows) IncludeFlags() string {
+	return "${config.WindowsIncludeFlags}"
+}
+
+func (t *toolchainWindows) ClangSupported() bool {
+	return false
+}
+
+func (t *toolchainWindows) ClangTriple() string {
+	panic("Clang is not supported under mingw")
+}
+
+func (t *toolchainWindows) ClangCflags() string {
+	panic("Clang is not supported under mingw")
+}
+
+func (t *toolchainWindows) ClangCppflags() string {
+	panic("Clang is not supported under mingw")
+}
+
+func (t *toolchainWindows) ClangLdflags() string {
+	panic("Clang is not supported under mingw")
+}
+
+func (t *toolchainWindows) ShlibSuffix() string {
+	return ".dll"
+}
+
+func (t *toolchainWindows) ExecutableSuffix() string {
+	return ".exe"
+}
+
+func (t *toolchainWindows) AvailableLibraries() []string {
+	return windowsAvailableLibraries
+}
+
+var toolchainWindowsX86Singleton Toolchain = &toolchainWindowsX86{}
+var toolchainWindowsX8664Singleton Toolchain = &toolchainWindowsX8664{}
+
+func windowsX86ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainWindowsX86Singleton
+}
+
+func windowsX8664ToolchainFactory(arch android.Arch) Toolchain {
+	return toolchainWindowsX8664Singleton
+}
+
+func init() {
+	registerToolchainFactory(android.Windows, android.X86, windowsX86ToolchainFactory)
+	registerToolchainFactory(android.Windows, android.X86_64, windowsX8664ToolchainFactory)
+}