Add support for building on Darwin hosts

Add toolchain and build rules for building on Darwin.

Change-Id: I78e21f4051b2941182121b28c9ddfa24396ada41
diff --git a/Blueprints b/Blueprints
index 0a66b43..c9480c7 100644
--- a/Blueprints
+++ b/Blueprints
@@ -111,6 +111,7 @@
         "cc/arm_device.go",
         "cc/arm64_device.go",
 
+        "cc/x86_darwin_host.go",
         "cc/x86_linux_host.go",
     ],
 }
diff --git a/build.ninja.in b/build.ninja.in
index aac0cc6..50ee810 100644
--- a/build.ninja.in
+++ b/build.ninja.in
@@ -53,7 +53,7 @@
 # Variant:
 # Type:    bootstrap_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule
-# Defined: build/soong/Blueprints:185:1
+# Defined: build/soong/Blueprints:186:1
 
 build .bootstrap/androidbp/obj/androidbp.a: g.bootstrap.gc $
         ${g.bootstrap.srcDir}/build/soong/androidbp/cmd/androidbp.go $
@@ -77,7 +77,7 @@
 # Variant:
 # Type:    bootstrap_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule
-# Defined: build/soong/Blueprints:161:1
+# Defined: build/soong/Blueprints:162:1
 
 build .bootstrap/androidmk/obj/androidmk.a: g.bootstrap.gc $
         ${g.bootstrap.srcDir}/build/soong/androidmk/cmd/androidmk/android.go $
@@ -103,7 +103,7 @@
 # Variant:
 # Type:    bootstrap_go_package
 # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule
-# Defined: build/soong/Blueprints:174:1
+# Defined: build/soong/Blueprints:175:1
 
 build .bootstrap/androidmk-parser/pkg/android/soong/androidmk/parser.a: $
         g.bootstrap.gc $
@@ -345,6 +345,7 @@
         ${g.bootstrap.srcDir}/build/soong/cc/util.go $
         ${g.bootstrap.srcDir}/build/soong/cc/arm_device.go $
         ${g.bootstrap.srcDir}/build/soong/cc/arm64_device.go $
+        ${g.bootstrap.srcDir}/build/soong/cc/x86_darwin_host.go $
         ${g.bootstrap.srcDir}/build/soong/cc/x86_linux_host.go | $
         ${g.bootstrap.gcCmd} $
         .bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
@@ -408,7 +409,7 @@
 # Variant:
 # Type:    bootstrap_go_package
 # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule
-# Defined: build/soong/Blueprints:118:1
+# Defined: build/soong/Blueprints:119:1
 
 build .bootstrap/soong-genrule/pkg/android/soong/genrule.a: g.bootstrap.gc $
         ${g.bootstrap.srcDir}/build/soong/genrule/genrule.go | $
@@ -446,7 +447,7 @@
 # Variant:
 # Type:    bootstrap_go_package
 # Factory: github.com/google/blueprint/bootstrap.newGoPackageModule
-# Defined: build/soong/Blueprints:138:1
+# Defined: build/soong/Blueprints:139:1
 
 build .bootstrap/soong-java/pkg/android/soong/java.a: g.bootstrap.gc $
         ${g.bootstrap.srcDir}/build/soong/java/app_builder.go $
@@ -559,7 +560,7 @@
 # Variant:
 # Type:    bootstrap_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModule
-# Defined: build/soong/Blueprints:131:1
+# Defined: build/soong/Blueprints:132:1
 
 build .bootstrap/soong_jar/obj/soong_jar.a: g.bootstrap.gc $
         ${g.bootstrap.srcDir}/build/soong/cmd/soong_jar/soong_jar.go | $
diff --git a/cc/builder.go b/cc/builder.go
index e7c08b7..218c73b 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -20,6 +20,9 @@
 
 import (
 	"android/soong/common"
+	"fmt"
+	"runtime"
+	"strconv"
 
 	"path/filepath"
 	"strings"
@@ -72,6 +75,20 @@
 		},
 		"arCmd", "arFlags")
 
+	darwinAr = pctx.StaticRule("darwinAr",
+		blueprint.RuleParams{
+			Command:     "rm -f ${out} && $arCmd $arFlags $out $in",
+			Description: "ar $out",
+		},
+		"arCmd", "arFlags")
+
+	darwinAppendAr = pctx.StaticRule("darwinAppendAr",
+		blueprint.RuleParams{
+			Command:     "cp -f ${inAr} ${out}.tmp && $arCmd $arFlags ${out}.tmp $in && mv ${out}.tmp ${out}",
+			Description: "ar $out",
+		},
+		"arCmd", "arFlags", "inAr")
+
 	prefixSymbols = pctx.StaticRule("prefixSymbols",
 		blueprint.RuleParams{
 			Command:     "$objcopyCmd --prefix-symbols=${prefix} ${in} ${out}",
@@ -207,6 +224,56 @@
 	})
 }
 
+// Generate a rule for compiling multiple .o files to a static library (.a) on
+// darwin.  The darwin ar tool doesn't support @file for list files, and has a
+// very small command line length limit, so we have to split the ar into multiple
+// steps, each appending to the previous one.
+func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
+	flags builderFlags, outputFile string) {
+
+	arCmd := "ar"
+	arFlags := "cqs"
+
+	// ARG_MAX on darwin is 262144, use half that to be safe
+	objFilesLists, err := splitListForSize(objFiles, 131072)
+	if err != nil {
+		ctx.ModuleErrorf("%s", err.Error())
+	}
+
+	var in, out string
+	for i, l := range objFilesLists {
+		in = out
+		out = outputFile
+		if i != len(objFilesLists)-1 {
+			out += "." + strconv.Itoa(i)
+		}
+
+		if in == "" {
+			ctx.Build(pctx, blueprint.BuildParams{
+				Rule:    darwinAr,
+				Outputs: []string{out},
+				Inputs:  l,
+				Args: map[string]string{
+					"arFlags": arFlags,
+					"arCmd":   arCmd,
+				},
+			})
+		} else {
+			ctx.Build(pctx, blueprint.BuildParams{
+				Rule:      darwinAppendAr,
+				Outputs:   []string{out},
+				Inputs:    l,
+				Implicits: []string{in},
+				Args: map[string]string{
+					"arFlags": arFlags,
+					"arCmd":   arCmd,
+					"inAr":    in,
+				},
+			})
+		}
+	}
+}
+
 // Generate a rule for compiling multiple .o files, plus static libraries, whole static libraries,
 // and shared libraires, to a shared library (.so) or dynamic executable
 func TransformObjToDynamicBinary(ctx common.AndroidModuleContext,
@@ -224,9 +291,13 @@
 	var libFlagsList []string
 
 	if len(wholeStaticLibs) > 0 {
-		libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
-		libFlagsList = append(libFlagsList, wholeStaticLibs...)
-		libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
+		if ctx.Host() && runtime.GOOS == "darwin" {
+			libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs, "-force_load "))
+		} else {
+			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
+			libFlagsList = append(libFlagsList, wholeStaticLibs...)
+			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
+		}
 	}
 
 	libFlagsList = append(libFlagsList, staticLibs...)
@@ -244,11 +315,11 @@
 		ldDirs = append(ldDirs, dir)
 	}
 
-	if groupLate {
+	if groupLate && len(lateStaticLibs) > 0 {
 		libFlagsList = append(libFlagsList, "-Wl,--start-group")
 	}
 	libFlagsList = append(libFlagsList, lateStaticLibs...)
-	if groupLate {
+	if groupLate && len(lateStaticLibs) > 0 {
 		libFlagsList = append(libFlagsList, "-Wl,--end-group")
 	}
 
@@ -335,3 +406,33 @@
 func gccCmd(toolchain Toolchain, cmd string) string {
 	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
 }
+
+func splitListForSize(list []string, limit int) (lists [][]string, err error) {
+	var i int
+
+	start := 0
+	bytes := 0
+	for i = range list {
+		l := len(list[i])
+		if l > limit {
+			return nil, fmt.Errorf("list element greater than size limit (%d)", limit)
+		}
+		if bytes+l > limit {
+			lists = append(lists, list[start:i])
+			start = i
+			bytes = 0
+		}
+		bytes += l + 1 // count a space between each list element
+	}
+
+	lists = append(lists, list[start:])
+
+	totalLen := 0
+	for _, l := range lists {
+		totalLen += len(l)
+	}
+	if totalLen != len(list) {
+		panic(fmt.Errorf("Failed breaking up list, %d != %d", len(list), totalLen))
+	}
+	return lists, nil
+}
diff --git a/cc/cc.go b/cc/cc.go
index 3ab8a47..8032fe3 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -21,6 +21,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"runtime"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -456,16 +457,6 @@
 		flags.CFlags = append(flags.CFlags, target, gccPrefix)
 		flags.AsFlags = append(flags.AsFlags, target, gccPrefix)
 		flags.LdFlags = append(flags.LdFlags, target, gccPrefix)
-
-		if ctx.Host() {
-			gccToolchain := "--gcc-toolchain=" + toolchain.GccRoot()
-			sysroot := "--sysroot=" + filepath.Join(toolchain.GccRoot(), "sysroot")
-
-			// TODO: also need more -B, -L flags to make host builds hermetic
-			flags.CFlags = append(flags.CFlags, gccToolchain, sysroot)
-			flags.AsFlags = append(flags.AsFlags, gccToolchain, sysroot)
-			flags.LdFlags = append(flags.LdFlags, gccToolchain, sysroot)
-		}
 	}
 
 	if !c.Properties.No_default_compiler_flags {
@@ -744,10 +735,17 @@
 	}
 }
 
-var (
-	hostDynamicGccLibs = []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"}
-	hostStaticGccLibs  = []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"}
-)
+var hostDynamicGccLibs, hostStaticGccLibs []string
+
+func init() {
+	if runtime.GOOS == "darwin" {
+		hostDynamicGccLibs = []string{"-lc", "-lSystem"}
+		hostStaticGccLibs = []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"}
+	} else {
+		hostDynamicGccLibs = []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"}
+		hostStaticGccLibs = []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"}
+	}
+}
 
 func (c *CCLinked) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags {
 	stl := c.stl(ctx)
@@ -1058,11 +1056,20 @@
 			flags.LdFlags = append(flags.LdFlags, "-nostdlib")
 		}
 
-		flags.LdFlags = append(flags.LdFlags,
-			"-Wl,--gc-sections",
-			sharedFlag,
-			"-Wl,-soname,"+libName+sharedLibraryExtension,
-		)
+		if ctx.Darwin() {
+			flags.LdFlags = append(flags.LdFlags,
+				"-dynamiclib",
+				"-single_module",
+				//"-read_only_relocs suppress",
+				"-install_name @rpath/"+libName+sharedLibraryExtension,
+			)
+		} else {
+			flags.LdFlags = append(flags.LdFlags,
+				"-Wl,--gc-sections",
+				sharedFlag,
+				"-Wl,-soname,"+libName+sharedLibraryExtension,
+			)
+		}
 	}
 
 	return flags
@@ -1080,7 +1087,11 @@
 
 	outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+staticLibraryExtension)
 
-	TransformObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
+	if ctx.Darwin() {
+		TransformDarwinObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
+	} else {
+		TransformObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
+	}
 
 	c.objFiles = objFiles
 	c.out = outputFile
@@ -1302,6 +1313,9 @@
 }
 
 func (c *CCBinary) ModifyProperties(ctx common.AndroidBaseContext) {
+	if ctx.Darwin() {
+		c.BinaryProperties.Static_executable = false
+	}
 	if c.BinaryProperties.Static_executable {
 		c.dynamicProperties.VariantIsStaticBinary = true
 	}
@@ -1342,6 +1356,8 @@
 				"-Wl,-z,nocopyreloc",
 			)
 		}
+	} else if ctx.Darwin() {
+		flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
 	}
 
 	return flags
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3bf0c65..ec7da90 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -54,3 +54,101 @@
 		}
 	}
 }
+
+var (
+	str11 = "01234567891"
+	str10 = str11[:10]
+	str9  = str11[:9]
+	str5  = str11[:5]
+	str4  = str11[:4]
+)
+
+var splitListForSizeTestCases = []struct {
+	in   []string
+	out  [][]string
+	size int
+}{
+	{
+		in:   []string{str10},
+		out:  [][]string{{str10}},
+		size: 10,
+	},
+	{
+		in:   []string{str9},
+		out:  [][]string{{str9}},
+		size: 10,
+	},
+	{
+		in:   []string{str5},
+		out:  [][]string{{str5}},
+		size: 10,
+	},
+	{
+		in:   []string{str11},
+		out:  nil,
+		size: 10,
+	},
+	{
+		in:   []string{str10, str10},
+		out:  [][]string{{str10}, {str10}},
+		size: 10,
+	},
+	{
+		in:   []string{str9, str10},
+		out:  [][]string{{str9}, {str10}},
+		size: 10,
+	},
+	{
+		in:   []string{str10, str9},
+		out:  [][]string{{str10}, {str9}},
+		size: 10,
+	},
+	{
+		in:   []string{str5, str4},
+		out:  [][]string{{str5, str4}},
+		size: 10,
+	},
+	{
+		in:   []string{str5, str4, str5},
+		out:  [][]string{{str5, str4}, {str5}},
+		size: 10,
+	},
+	{
+		in:   []string{str5, str4, str5, str4},
+		out:  [][]string{{str5, str4}, {str5, str4}},
+		size: 10,
+	},
+	{
+		in:   []string{str5, str4, str5, str5},
+		out:  [][]string{{str5, str4}, {str5}, {str5}},
+		size: 10,
+	},
+	{
+		in:   []string{str5, str5, str5, str4},
+		out:  [][]string{{str5}, {str5}, {str5, str4}},
+		size: 10,
+	},
+	{
+		in:   []string{str9, str11},
+		out:  nil,
+		size: 10,
+	},
+	{
+		in:   []string{str11, str9},
+		out:  nil,
+		size: 10,
+	},
+}
+
+func TestSplitListForSize(t *testing.T) {
+	for _, testCase := range splitListForSizeTestCases {
+		out, _ := splitListForSize(testCase.in, testCase.size)
+		if !reflect.DeepEqual(out, testCase.out) {
+			t.Errorf("incorrect output:")
+			t.Errorf("     input: %#v", testCase.in)
+			t.Errorf("      size: %d", testCase.size)
+			t.Errorf("  expected: %#v", testCase.out)
+			t.Errorf("       got: %#v", out)
+		}
+	}
+}
diff --git a/cc/x86_darwin_host.go b/cc/x86_darwin_host.go
new file mode 100644
index 0000000..bed977d
--- /dev/null
+++ b/cc/x86_darwin_host.go
@@ -0,0 +1,213 @@
+package cc
+
+import (
+	"runtime"
+	"strings"
+
+	"android/soong/common"
+)
+
+var (
+	darwinCflags = []string{
+		"-fno-exceptions", // from build/core/combo/select.mk
+		"-Wno-multichar",  // from build/core/combo/select.mk
+
+		"-fPIC",
+		"-funwind-tables",
+		"-include ${SrcDir}/build/core/combo/include/arch/darwin-x86/AndroidConfig.h",
+
+		// 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=10.9",
+		"-DMACOSX_DEPLOYMENT_TARGET=10.9",
+	}
+
+	darwinCppflags = []string{
+		"-isystem ${macSdkPath}/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
+	}
+
+	darwinLdflags = []string{
+		"-isysroot ${macSdkRoot}",
+		"-Wl,-syslibroot,${macSdkRoot}",
+		"-mmacosx-version-min=10.9",
+	}
+
+	// Extended cflags
+	darwinX86Cflags = []string{
+		"-m32",
+	}
+
+	darwinX8664Cflags = []string{
+		"-m64",
+	}
+
+	darwinX86Ldflags = []string{
+		"-m32",
+		"-Wl,-rpath,@loader_path/../lib",
+	}
+
+	darwinX8664Ldflags = []string{
+		"-m64",
+		"-Wl,-rpath,@loader_path/../lib64",
+	}
+
+	darwinClangCflags = append([]string{
+		"-integrated-as",
+	}, clangFilterUnknownCflags(darwinCflags)...)
+
+	darwinClangLdflags = clangFilterUnknownCflags(darwinLdflags)
+
+	darwinX86ClangLdflags = clangFilterUnknownCflags(darwinX86Ldflags)
+
+	darwinX8664ClangLdflags = clangFilterUnknownCflags(darwinX8664Ldflags)
+
+	darwinClangCppflags = clangFilterUnknownCflags(darwinCppflags)
+)
+
+func init() {
+	pctx.StaticVariable("macSdkPath", "/Applications/Xcode.app/Contents/Developer")
+	pctx.StaticVariable("macSdkRoot", "${macSdkPath}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk")
+
+	pctx.StaticVariable("darwinGccVersion", "4.2.1")
+	pctx.StaticVariable("darwinGccRoot",
+		"${SrcDir}/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("darwinCppflags", strings.Join(darwinCppflags, " "))
+
+	pctx.StaticVariable("darwinClangCflags", strings.Join(darwinClangCflags, " "))
+	pctx.StaticVariable("darwinClangLdflags", strings.Join(darwinClangLdflags, " "))
+	pctx.StaticVariable("darwinClangCppflags", strings.Join(darwinClangCppflags, " "))
+
+	// 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(clangFilterUnknownCflags(darwinX86Cflags), " "))
+	pctx.StaticVariable("darwinX8664ClangCflags",
+		strings.Join(clangFilterUnknownCflags(darwinX8664Cflags), " "))
+	pctx.StaticVariable("darwinX86ClangLdflags", strings.Join(darwinX86ClangLdflags, " "))
+	pctx.StaticVariable("darwinX8664ClangLdflags", strings.Join(darwinX8664ClangLdflags, " "))
+}
+
+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 "${darwinGccRoot}"
+}
+
+func (t *toolchainDarwin) GccTriple() string {
+	return "${darwinGccTriple}"
+}
+
+func (t *toolchainDarwin) GccVersion() string {
+	return "${darwinGccVersion}"
+}
+
+func (t *toolchainDarwin) Cflags() string {
+	return "${darwinCflags} ${darwinX86Cflags}"
+}
+
+func (t *toolchainDarwinX8664) Cflags() string {
+	return "${darwinCflags} ${darwinX8664Cflags}"
+}
+
+func (t *toolchainDarwin) Cppflags() string {
+	return "${darwinCppflags}"
+}
+
+func (t *toolchainDarwinX86) Ldflags() string {
+	return "${darwinLdflags} ${darwinX86Ldflags}"
+}
+
+func (t *toolchainDarwinX8664) Ldflags() string {
+	return "${darwinLdflags} ${darwinX8664Ldflags}"
+}
+
+func (t *toolchainDarwin) IncludeFlags() string {
+	return ""
+}
+
+func (t *toolchainDarwinX86) ClangTriple() string {
+	return "i686-darwin-gnu"
+}
+
+func (t *toolchainDarwinX86) ClangCflags() string {
+	return "${darwinClangCflags} ${darwinX86ClangCflags}"
+}
+
+func (t *toolchainDarwinX86) ClangCppflags() string {
+	return "${darwinClangCppflags}"
+}
+
+func (t *toolchainDarwinX8664) ClangTriple() string {
+	return "x86_64-darwin-gnu"
+}
+
+func (t *toolchainDarwinX8664) ClangCflags() string {
+	return "${darwinClangCflags} ${darwinX8664ClangCflags}"
+}
+
+func (t *toolchainDarwinX8664) ClangCppflags() string {
+	return "${darwinClangCppflags}"
+}
+
+func (t *toolchainDarwinX86) ClangLdflags() string {
+	return "${darwinClangLdflags} ${darwinX86ClangLdflags}"
+}
+
+func (t *toolchainDarwinX8664) ClangLdflags() string {
+	return "${darwinClangLdflags} ${darwinX8664ClangLdflags}"
+}
+
+var toolchainDarwinX86Singleton Toolchain = &toolchainDarwinX86{}
+var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{}
+
+func darwinX86ToolchainFactory(archVariant string, cpuVariant string) Toolchain {
+	return toolchainDarwinX86Singleton
+}
+
+func darwinX8664ToolchainFactory(archVariant string, cpuVariant string) Toolchain {
+	return toolchainDarwinX8664Singleton
+}
+
+func init() {
+	if runtime.GOOS == "darwin" {
+		registerToolchainFactory(common.Host, common.X86, darwinX86ToolchainFactory)
+		registerToolchainFactory(common.Host, common.X86_64, darwinX8664ToolchainFactory)
+	}
+}
diff --git a/common/module.go b/common/module.go
index bafb583..d933788 100644
--- a/common/module.go
+++ b/common/module.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"runtime"
 
 	"github.com/google/blueprint"
 )
@@ -33,6 +34,7 @@
 	Arch() Arch
 	Host() bool
 	Device() bool
+	Darwin() bool
 	Debug() bool
 	AConfig() Config
 }
@@ -372,6 +374,10 @@
 	return a.arch.HostOrDevice.Device()
 }
 
+func (a *androidBaseContextImpl) Darwin() bool {
+	return a.arch.HostOrDevice.Host() && runtime.GOOS == "darwin"
+}
+
 func (a *androidBaseContextImpl) Debug() bool {
 	return a.debug
 }