Add soong_build primary builder

Initial build logic for building android with soong.  It can build
a variety of C and C++ files for arm/arm64 and host.

Change-Id: I10eb37c2c2a50be6af1bb5fd568c0962b9476bf0
diff --git a/cc/builder.go b/cc/builder.go
new file mode 100644
index 0000000..b61d672
--- /dev/null
+++ b/cc/builder.go
@@ -0,0 +1,285 @@
+// 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 cc
+
+// This file generates the final rules for compiling all C/C++.  All properties related to
+// compiling should have been translated into builderFlags or another argument to the Transform*
+// functions.
+
+import (
+	"android/soong/common"
+
+	"blueprint"
+	"blueprint/pathtools"
+	"path/filepath"
+	"strings"
+)
+
+const (
+	sharedLibraryExtension = ".so"
+	staticLibraryExtension = ".a"
+)
+
+var (
+	pctx = blueprint.NewPackageContext("android/soong/cc")
+
+	cc = pctx.StaticRule("cc",
+		blueprint.RuleParams{
+			Depfile:     "${out}.d",
+			Deps:        blueprint.DepsGCC,
+			Command:     "$ccCmd $incFlags -c $cFlags -MD -MF ${out}.d -o $out $in",
+			Description: "cc $out",
+		},
+		"ccCmd", "incFlags", "cFlags")
+
+	ld = pctx.StaticRule("ld",
+		blueprint.RuleParams{
+			Command: "$ldCmd ${ldDirFlags} ${crtBegin} ${in} " +
+				"${libFlags} ${crtEnd} -o ${out} ${ldFlags} ${ldLibs}",
+			Description: "ld $out",
+		},
+		"ldCmd", "ldDirFlags", "crtBegin", "libFlags", "crtEnd", "ldFlags", "ldLibs")
+
+	partialLd = pctx.StaticRule("partialLd",
+		blueprint.RuleParams{
+			Command:     "$ldCmd -r ${in} -o ${out}",
+			Description: "partialLd $out",
+		},
+		"ldCmd")
+
+	ar = pctx.StaticRule("ar",
+		blueprint.RuleParams{
+			Command:     "rm -f ${out} && $arCmd $arFlags $out $in",
+			Description: "ar $out",
+		},
+		"arCmd", "arFlags")
+
+	copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
+
+	copyGccLib = pctx.StaticRule("copyGccLib",
+		blueprint.RuleParams{
+			Depfile:     "${out}.d",
+			Deps:        blueprint.DepsGCC,
+			Command:     "$copyGccLibPath $out $ccCmd $cFlags -print-file-name=${libName}",
+			Description: "copy gcc $out",
+		},
+		"ccCmd", "cFlags", "libName")
+)
+
+type builderFlags struct {
+	globalFlags string
+	asFlags     string
+	cFlags      string
+	conlyFlags  string
+	cppFlags    string
+	ldFlags     string
+	ldLibs      string
+	incFlags    string
+	nocrt       bool
+	toolchain   toolchain
+	clang       bool
+}
+
+// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
+func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles []string,
+	flags builderFlags) (objFiles []string) {
+
+	objFiles = make([]string, len(srcFiles))
+	objDir := common.ModuleObjDir(ctx)
+	if subdir != "" {
+		objDir = filepath.Join(objDir, subdir)
+	}
+
+	cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
+	cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
+	asflags := flags.globalFlags + " " + flags.asFlags
+
+	for i, srcFile := range srcFiles {
+		objFile := strings.TrimPrefix(srcFile, common.ModuleSrcDir(ctx))
+		objFile = filepath.Join(objDir, objFile)
+		objFile = pathtools.ReplaceExtension(objFile, "o")
+
+		objFiles[i] = objFile
+
+		var moduleCflags string
+		var ccCmd string
+
+		switch filepath.Ext(srcFile) {
+		case ".S", ".s":
+			ccCmd = "gcc"
+			moduleCflags = asflags
+		case ".c":
+			ccCmd = "gcc"
+			moduleCflags = cflags
+		case ".cpp", ".cc":
+			ccCmd = "g++"
+			moduleCflags = cppflags
+		default:
+			ctx.ModuleErrorf("File %s has unknown extension", srcFile)
+			continue
+		}
+
+		if flags.clang {
+			switch ccCmd {
+			case "gcc":
+				ccCmd = "clang"
+			case "g++":
+				ccCmd = "clang++"
+			default:
+				panic("unrecoginzied ccCmd")
+			}
+
+			ccCmd = "${clangPath}" + ccCmd
+		} else {
+			ccCmd = gccCmd(flags.toolchain, ccCmd)
+		}
+
+		ctx.Build(pctx, blueprint.BuildParams{
+			Rule:      cc,
+			Outputs:   []string{objFile},
+			Inputs:    []string{srcFile},
+			Implicits: []string{ccCmd},
+			Args: map[string]string{
+				"cFlags":   moduleCflags,
+				"incFlags": flags.incFlags,
+				"ccCmd":    ccCmd,
+			},
+		})
+	}
+
+	return objFiles
+}
+
+// Generate a rule for compiling multiple .o files to a static library (.a)
+func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
+	flags builderFlags, outputFile string) {
+
+	arCmd := gccCmd(flags.toolchain, "ar")
+	arFlags := "crsPD"
+
+	ctx.Build(pctx, blueprint.BuildParams{
+		Rule:      ar,
+		Outputs:   []string{outputFile},
+		Inputs:    objFiles,
+		Implicits: []string{arCmd},
+		Args: map[string]string{
+			"arFlags": arFlags,
+			"arCmd":   arCmd,
+		},
+	})
+}
+
+// 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,
+	objFiles, sharedLibs, staticLibs, wholeStaticLibs []string, crtBegin, crtEnd string,
+	flags builderFlags, outputFile string) {
+
+	var ldCmd string
+	if flags.clang {
+		ldCmd = "${clangPath}clang++"
+	} else {
+		ldCmd = gccCmd(flags.toolchain, "g++")
+	}
+
+	var ldDirs []string
+	var libFlagsList []string
+
+	if len(wholeStaticLibs) > 0 {
+		libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
+		libFlagsList = append(libFlagsList, wholeStaticLibs...)
+		libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
+	}
+
+	libFlagsList = append(libFlagsList, staticLibs...)
+
+	for _, lib := range sharedLibs {
+		dir, file := filepath.Split(lib)
+		if !strings.HasPrefix(file, "lib") {
+			panic("shared library " + lib + " does not start with lib")
+		}
+		if !strings.HasSuffix(file, sharedLibraryExtension) {
+			panic("shared library " + lib + " does not end with " + sharedLibraryExtension)
+		}
+		libFlagsList = append(libFlagsList,
+			"-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension))
+		ldDirs = append(ldDirs, dir)
+	}
+
+	deps := []string{ldCmd}
+	deps = append(deps, sharedLibs...)
+	deps = append(deps, staticLibs...)
+	deps = append(deps, wholeStaticLibs...)
+	if crtBegin != "" {
+		deps = append(deps, crtBegin, crtEnd)
+	}
+
+	ctx.Build(pctx, blueprint.BuildParams{
+		Rule:      ld,
+		Outputs:   []string{outputFile},
+		Inputs:    objFiles,
+		Implicits: deps,
+		Args: map[string]string{
+			"ldCmd":      ldCmd,
+			"ldDirFlags": ldDirsToFlags(ldDirs),
+			"crtBegin":   crtBegin,
+			"libFlags":   strings.Join(libFlagsList, " "),
+			"ldFlags":    flags.ldFlags,
+			"crtEnd":     crtEnd,
+			"ldLibs":     flags.ldLibs,
+		},
+	})
+}
+
+// Generate a rule for compiling multiple .o files to a .o using ld partial linking
+func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles []string,
+	flags builderFlags, outputFile string) {
+
+	ldCmd := gccCmd(flags.toolchain, "ld")
+
+	deps := []string{ldCmd}
+
+	ctx.Build(pctx, blueprint.BuildParams{
+		Rule:      partialLd,
+		Outputs:   []string{outputFile},
+		Inputs:    objFiles,
+		Implicits: deps,
+		Args: map[string]string{
+			"ldCmd": ldCmd,
+		},
+	})
+}
+
+func CopyGccLib(ctx common.AndroidModuleContext, libName string,
+	flags builderFlags, outputFile string) {
+
+	ctx.Build(pctx, blueprint.BuildParams{
+		Rule:    copyGccLib,
+		Outputs: []string{outputFile},
+		Implicits: []string{
+			"$copyGccLibPath",
+			gccCmd(flags.toolchain, "gcc"),
+		},
+		Args: map[string]string{
+			"ccCmd":   gccCmd(flags.toolchain, "gcc"),
+			"cFlags":  flags.globalFlags,
+			"libName": libName,
+		},
+	})
+}
+
+func gccCmd(toolchain toolchain, cmd string) string {
+	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
+}