Fix Static_executable, implement BUILD_HOST_static from Make

Static_executable was still using ModifyProperties, and was otherwise
missing things. Fix all of that up, and implement HostStaticBinaries,
which is the equivalent of BUILD_HOST_static in Make. That will default
host binaries to be static, which is useful for building SDK tools to
run with incompatible C libraries.

Change-Id: I2a62181b5d854b310edc8ae7a6bcbd30b89e7463
diff --git a/cc/cc.go b/cc/cc.go
index 0c47c79..cf4f974 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1797,11 +1797,11 @@
 }
 
 func (binary *binaryLinker) buildStatic() bool {
-	return Bool(binary.Properties.Static_executable)
+	return binary.baseLinker.staticBinary()
 }
 
 func (binary *binaryLinker) buildShared() bool {
-	return !Bool(binary.Properties.Static_executable)
+	return !binary.baseLinker.staticBinary()
 }
 
 func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
@@ -1817,14 +1817,14 @@
 	deps = binary.baseLinker.deps(ctx, deps)
 	if ctx.Device() {
 		if !ctx.sdk() {
-			if Bool(binary.Properties.Static_executable) {
+			if binary.buildStatic() {
 				deps.CrtBegin = "crtbegin_static"
 			} else {
 				deps.CrtBegin = "crtbegin_dynamic"
 			}
 			deps.CrtEnd = "crtend_android"
 		} else {
-			if Bool(binary.Properties.Static_executable) {
+			if binary.buildStatic() {
 				deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
 			} else {
 				deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
@@ -1832,7 +1832,7 @@
 			deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
 		}
 
-		if Bool(binary.Properties.Static_executable) {
+		if binary.buildStatic() {
 			if inList("libc++_static", deps.StaticLibs) {
 				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
 			}
@@ -1846,7 +1846,7 @@
 		}
 	}
 
-	if !Bool(binary.Properties.Static_executable) && inList("libc", deps.StaticLibs) {
+	if binary.buildShared() && inList("libc", deps.StaticLibs) {
 		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
 			"from static libs or set static_executable: true")
 	}
@@ -1876,11 +1876,22 @@
 	return module.Init()
 }
 
-func (binary *binaryLinker) ModifyProperties(ctx ModuleContext) {
-	if ctx.Darwin() {
-		binary.Properties.Static_executable = proptools.BoolPtr(false)
+func (binary *binaryLinker) begin(ctx BaseModuleContext) {
+	binary.baseLinker.begin(ctx)
+
+	static := Bool(binary.Properties.Static_executable)
+	if ctx.Host() {
+		if ctx.HostType() == common.Linux {
+			if binary.Properties.Static_executable == nil && Bool(ctx.AConfig().ProductVariables.HostStaticBinaries) {
+				static = true
+			}
+		} else {
+			// Static executables are not supported on Darwin or Windows
+			static = false
+		}
 	}
-	if Bool(binary.Properties.Static_executable) {
+	if static {
+		binary.dynamicProperties.VariantIsStatic = true
 		binary.dynamicProperties.VariantIsStaticBinary = true
 	}
 }
@@ -1888,7 +1899,7 @@
 func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
 	flags = binary.baseLinker.flags(ctx, flags)
 
-	if ctx.Host() {
+	if ctx.Host() && !binary.staticBinary() {
 		flags.LdFlags = append(flags.LdFlags, "-pie")
 		if ctx.HostType() == common.Windows {
 			flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
@@ -1903,7 +1914,7 @@
 	}
 
 	if ctx.Device() {
-		if Bool(binary.Properties.Static_executable) {
+		if binary.buildStatic() {
 			// Clang driver needs -static to create static executable.
 			// However, bionic/linker uses -shared to overwrite.
 			// Linker for x86 targets does not allow coexistance of -static and -shared,
@@ -1934,8 +1945,13 @@
 				"-Wl,-z,nocopyreloc",
 			)
 		}
-	} else if ctx.Darwin() {
-		flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
+	} else {
+		if binary.staticBinary() {
+			flags.LdFlags = append(flags.LdFlags, "-static")
+		}
+		if ctx.Darwin() {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-headerpad_max_install_names")
+		}
 	}
 
 	return flags
diff --git a/cc/makevars.go b/cc/makevars.go
index 48698bf..b0d371f 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -72,15 +72,20 @@
 
 	toolchain := toolchainFactories[hod][ht][arch.ArchType](arch)
 
-	globalCflags := fmt.Sprintf("${commonGlobalCflags} ${%sGlobalCflags}", hod)
-
+	var productExtraCflags string
+	var productExtraLdflags string
 	if hod.Device() && Bool(ctx.Config().ProductVariables.Brillo) {
-		globalCflags += " -D__BRILLO__"
+		productExtraCflags += "-D__BRILLO__"
+	}
+	if hod.Host() && Bool(ctx.Config().ProductVariables.HostStaticBinaries) {
+		productExtraLdflags += "-static"
 	}
 
 	ctx.StrictSorted(makePrefix+"GLOBAL_CFLAGS", strings.Join([]string{
 		toolchain.ToolchainCflags(),
-		globalCflags,
+		"${commonGlobalCflags}",
+		fmt.Sprintf("${%sGlobalCflags}", hod),
+		productExtraCflags,
 		toolchain.Cflags(),
 	}, " "))
 	ctx.StrictSorted(makePrefix+"GLOBAL_CONLYFLAGS", "")
@@ -90,6 +95,7 @@
 	}, " "))
 	ctx.StrictSorted(makePrefix+"GLOBAL_LDFLAGS", strings.Join([]string{
 		toolchain.ToolchainLdflags(),
+		productExtraLdflags,
 		toolchain.Ldflags(),
 	}, " "))
 
@@ -100,15 +106,12 @@
 			clangExtras += " -B" + filepath.Join(toolchain.GccRoot(), toolchain.GccTriple(), "bin")
 		}
 
-		globalClangCflags := fmt.Sprintf("${commonClangGlobalCflags} ${clangExtraCflags} ${%sClangGlobalCflags}", hod)
-
-		if hod.Device() && Bool(ctx.Config().ProductVariables.Brillo) {
-			globalClangCflags += " -D__BRILLO__"
-		}
-
 		ctx.StrictSorted(clangPrefix+"GLOBAL_CFLAGS", strings.Join([]string{
 			toolchain.ToolchainClangCflags(),
-			globalClangCflags,
+			"${commonClangGlobalCflags}",
+			"${clangExtraCflags}",
+			fmt.Sprintf("${%sClangGlobalCflags}", hod),
+			productExtraCflags,
 			toolchain.ClangCflags(),
 			clangExtras,
 		}, " "))
@@ -119,6 +122,7 @@
 		}, " "))
 		ctx.StrictSorted(clangPrefix+"GLOBAL_LDFLAGS", strings.Join([]string{
 			toolchain.ToolchainClangLdflags(),
+			productExtraLdflags,
 			toolchain.ClangLdflags(),
 			clangExtras,
 		}, " "))