Separate cc.go

Split cc.go into files per module type, plus files for the compiler,
linker, and installer stages.

Change-Id: Id44c03f42fcd180950ccd008d4de0c144ea3597b
diff --git a/cc/binary.go b/cc/binary.go
new file mode 100644
index 0000000..d6b086c
--- /dev/null
+++ b/cc/binary.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 cc
+
+import (
+	"github.com/google/blueprint"
+
+	"android/soong"
+	"android/soong/android"
+)
+
+type BinaryLinkerProperties struct {
+	// compile executable with -static
+	Static_executable *bool `android:"arch_variant"`
+
+	// set the name of the output
+	Stem string `android:"arch_variant"`
+
+	// append to the name of the output
+	Suffix string `android:"arch_variant"`
+
+	// if set, add an extra objcopy --prefix-symbols= step
+	Prefix_symbols string
+}
+
+func init() {
+	soong.RegisterModuleType("cc_binary", binaryFactory)
+	soong.RegisterModuleType("cc_binary_host", binaryHostFactory)
+}
+
+// Module factory for binaries
+func binaryFactory() (blueprint.Module, []interface{}) {
+	module := NewBinary(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+// Module factory for host binaries
+func binaryHostFactory() (blueprint.Module, []interface{}) {
+	module := NewBinary(android.HostSupported)
+	return module.Init()
+}
+
+//
+// Executables
+//
+
+type binaryLinker struct {
+	baseLinker
+	stripper
+
+	Properties BinaryLinkerProperties
+
+	hostToolPath android.OptionalPath
+}
+
+var _ linker = (*binaryLinker)(nil)
+
+func (binary *binaryLinker) props() []interface{} {
+	return append(binary.baseLinker.props(),
+		&binary.Properties,
+		&binary.stripper.StripProperties)
+
+}
+
+func (binary *binaryLinker) buildStatic() bool {
+	return binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) buildShared() bool {
+	return !binary.baseLinker.staticBinary()
+}
+
+func (binary *binaryLinker) getStem(ctx BaseModuleContext) string {
+	stem := ctx.ModuleName()
+	if binary.Properties.Stem != "" {
+		stem = binary.Properties.Stem
+	}
+
+	return stem + binary.Properties.Suffix
+}
+
+func (binary *binaryLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
+	deps = binary.baseLinker.deps(ctx, deps)
+	if ctx.Device() {
+		if !Bool(binary.baseLinker.Properties.Nocrt) {
+			if !ctx.sdk() {
+				if binary.buildStatic() {
+					deps.CrtBegin = "crtbegin_static"
+				} else {
+					deps.CrtBegin = "crtbegin_dynamic"
+				}
+				deps.CrtEnd = "crtend_android"
+			} else {
+				if binary.buildStatic() {
+					deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+				} else {
+					if Bool(binary.Properties.Static_executable) {
+						deps.CrtBegin = "ndk_crtbegin_static." + ctx.sdkVersion()
+					} else {
+						deps.CrtBegin = "ndk_crtbegin_dynamic." + ctx.sdkVersion()
+					}
+					deps.CrtEnd = "ndk_crtend_android." + ctx.sdkVersion()
+				}
+			}
+		}
+
+		if binary.buildStatic() {
+			if inList("libc++_static", deps.StaticLibs) {
+				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl")
+			}
+			// static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
+			// --start-group/--end-group along with libgcc.  If they are in deps.StaticLibs,
+			// move them to the beginning of deps.LateStaticLibs
+			var groupLibs []string
+			deps.StaticLibs, groupLibs = filterList(deps.StaticLibs,
+				[]string{"libc", "libc_nomalloc", "libcompiler_rt"})
+			deps.LateStaticLibs = append(groupLibs, deps.LateStaticLibs...)
+		}
+	}
+
+	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")
+	}
+	return deps
+}
+
+func (*binaryLinker) installable() bool {
+	return true
+}
+
+func (binary *binaryLinker) isDependencyRoot() bool {
+	return true
+}
+
+func NewBinary(hod android.HostOrDeviceSupported) *Module {
+	module := newModule(hod, android.MultilibFirst)
+	module.compiler = &baseCompiler{}
+	module.linker = &binaryLinker{}
+	module.installer = &baseInstaller{
+		dir: "bin",
+	}
+	return module
+}
+
+func (binary *binaryLinker) begin(ctx BaseModuleContext) {
+	binary.baseLinker.begin(ctx)
+
+	static := Bool(binary.Properties.Static_executable)
+	if ctx.Host() {
+		if ctx.Os() == android.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 static {
+		binary.dynamicProperties.VariantIsStatic = true
+		binary.dynamicProperties.VariantIsStaticBinary = true
+	}
+}
+
+func (binary *binaryLinker) flags(ctx ModuleContext, flags Flags) Flags {
+	flags = binary.baseLinker.flags(ctx, flags)
+
+	if ctx.Host() && !binary.staticBinary() {
+		flags.LdFlags = append(flags.LdFlags, "-pie")
+		if ctx.Os() == android.Windows {
+			flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup")
+		}
+	}
+
+	// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
+	// all code is position independent, and then those warnings get promoted to
+	// errors.
+	if ctx.Os() != android.Windows {
+		flags.CFlags = append(flags.CFlags, "-fpie")
+	}
+
+	if ctx.Device() {
+		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,
+			// so we add -static only if -shared is not used.
+			if !inList("-shared", flags.LdFlags) {
+				flags.LdFlags = append(flags.LdFlags, "-static")
+			}
+
+			flags.LdFlags = append(flags.LdFlags,
+				"-nostdlib",
+				"-Bstatic",
+				"-Wl,--gc-sections",
+			)
+
+		} else {
+			if flags.DynamicLinker == "" {
+				flags.DynamicLinker = "/system/bin/linker"
+				if flags.Toolchain.Is64Bit() {
+					flags.DynamicLinker += "64"
+				}
+			}
+
+			flags.LdFlags = append(flags.LdFlags,
+				"-pie",
+				"-nostdlib",
+				"-Bdynamic",
+				"-Wl,--gc-sections",
+				"-Wl,-z,nocopyreloc",
+			)
+		}
+	} 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
+}
+
+func (binary *binaryLinker) link(ctx ModuleContext,
+	flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
+
+	fileName := binary.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
+	outputFile := android.PathForModuleOut(ctx, fileName)
+	ret := outputFile
+	if ctx.Os().Class == android.Host {
+		binary.hostToolPath = android.OptionalPathForPath(outputFile)
+	}
+
+	var linkerDeps android.Paths
+
+	sharedLibs := deps.SharedLibs
+	sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
+
+	if flags.DynamicLinker != "" {
+		flags.LdFlags = append(flags.LdFlags, " -Wl,-dynamic-linker,"+flags.DynamicLinker)
+	}
+
+	builderFlags := flagsToBuilderFlags(flags)
+
+	if binary.stripper.needsStrip(ctx) {
+		strippedOutputFile := outputFile
+		outputFile = android.PathForModuleOut(ctx, "unstripped", fileName)
+		binary.stripper.strip(ctx, outputFile, strippedOutputFile, builderFlags)
+	}
+
+	if binary.Properties.Prefix_symbols != "" {
+		afterPrefixSymbols := outputFile
+		outputFile = android.PathForModuleOut(ctx, "unprefixed", fileName)
+		TransformBinaryPrefixSymbols(ctx, binary.Properties.Prefix_symbols, outputFile,
+			flagsToBuilderFlags(flags), afterPrefixSymbols)
+	}
+
+	TransformObjToDynamicBinary(ctx, objFiles, sharedLibs, deps.StaticLibs,
+		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
+		builderFlags, outputFile)
+
+	return ret
+}
+
+func (binary *binaryLinker) HostToolPath() android.OptionalPath {
+	return binary.hostToolPath
+}