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)
+}