Use `Path` instead of string for file paths

This centralizes verification and common operations, like converting the
path to a source file to the path for a built object.

It also embeds the configuration knowledge into the path, so that we can
remove "${SrcDir}/path" from the ninja file. When SrcDir is '.', that
leads to paths like './path' instead of just 'path' like make is doing,
causing differences in compiled binaries.

Change-Id: Ib4e8910a6e867ce1b7b420d927c04f1142a7589e
diff --git a/cc/builder.go b/cc/builder.go
index 64437d2..f5fc9ee 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -28,7 +28,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 )
 
 const (
@@ -37,7 +36,7 @@
 )
 
 var (
-	pctx = blueprint.NewPackageContext("android/soong/cc")
+	pctx = common.NewPackageContext("android/soong/cc")
 
 	cc = pctx.StaticRule("cc",
 		blueprint.RuleParams{
@@ -102,7 +101,7 @@
 		},
 		"objcopyCmd", "prefix")
 
-	copyGccLibPath = pctx.StaticVariable("copyGccLibPath", "${SrcDir}/build/soong/copygcclib.sh")
+	copyGccLibPath = pctx.SourcePathVariable("copyGccLibPath", "build/soong/copygcclib.sh")
 
 	copyGccLib = pctx.StaticRule("copyGccLib",
 		blueprint.RuleParams{
@@ -141,45 +140,24 @@
 }
 
 // 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, deps []string) (objFiles []string) {
+func TransformSourceToObj(ctx common.AndroidModuleContext, subdir string, srcFiles common.Paths,
+	flags builderFlags, deps common.Paths) (objFiles common.Paths) {
 
-	srcRoot := ctx.AConfig().SrcDir()
-	intermediatesRoot := ctx.AConfig().IntermediatesDir()
-
-	objFiles = make([]string, len(srcFiles))
-	objDir := common.ModuleObjDir(ctx)
-	if subdir != "" {
-		objDir = filepath.Join(objDir, subdir)
-	}
+	objFiles = make(common.Paths, len(srcFiles))
 
 	cflags := flags.globalFlags + " " + flags.cFlags + " " + flags.conlyFlags
 	cppflags := flags.globalFlags + " " + flags.cFlags + " " + flags.cppFlags
 	asflags := flags.globalFlags + " " + flags.asFlags
 
 	for i, srcFile := range srcFiles {
-		var objFile string
-		if strings.HasPrefix(srcFile, intermediatesRoot) {
-			objFile = strings.TrimPrefix(srcFile, intermediatesRoot)
-			objFile = filepath.Join(objDir, "gen", objFile)
-		} else if strings.HasPrefix(srcFile, srcRoot) {
-			srcFile, _ = filepath.Rel(srcRoot, srcFile)
-			objFile = filepath.Join(objDir, srcFile)
-		} else if srcRoot == "." && srcFile[0] != '/' {
-			objFile = filepath.Join(objDir, srcFile)
-		} else {
-			ctx.ModuleErrorf("source file %q is not in source directory %q", srcFile, srcRoot)
-			continue
-		}
-
-		objFile = pathtools.ReplaceExtension(objFile, "o")
+		objFile := common.ObjPathWithExt(ctx, srcFile, subdir, "o")
 
 		objFiles[i] = objFile
 
 		var moduleCflags string
 		var ccCmd string
 
-		switch filepath.Ext(srcFile) {
+		switch srcFile.Ext() {
 		case ".S", ".s":
 			ccCmd = "gcc"
 			moduleCflags = asflags
@@ -204,15 +182,15 @@
 				panic("unrecoginzied ccCmd")
 			}
 
-			ccCmd = "${clangPath}" + ccCmd
+			ccCmd = "${clangPath}/" + ccCmd
 		} else {
 			ccCmd = gccCmd(flags.toolchain, ccCmd)
 		}
 
-		ctx.Build(pctx, blueprint.BuildParams{
+		ctx.ModuleBuild(pctx, common.ModuleBuildParams{
 			Rule:      cc,
-			Outputs:   []string{objFile},
-			Inputs:    []string{srcFile},
+			Output:    objFile,
+			Input:     srcFile,
 			Implicits: deps,
 			Args: map[string]string{
 				"cFlags": moduleCflags,
@@ -225,16 +203,16 @@
 }
 
 // Generate a rule for compiling multiple .o files to a static library (.a)
-func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles []string,
-	flags builderFlags, outputFile string) {
+func TransformObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
+	flags builderFlags, outputFile common.ModuleOutPath) {
 
 	arCmd := gccCmd(flags.toolchain, "ar")
 	arFlags := "crsPD"
 
-	ctx.Build(pctx, blueprint.BuildParams{
-		Rule:    ar,
-		Outputs: []string{outputFile},
-		Inputs:  objFiles,
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
+		Rule:   ar,
+		Output: outputFile,
+		Inputs: objFiles,
 		Args: map[string]string{
 			"arFlags": arFlags,
 			"arCmd":   arCmd,
@@ -246,18 +224,20 @@
 // 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) {
+func TransformDarwinObjToStaticLib(ctx common.AndroidModuleContext, objFiles common.Paths,
+	flags builderFlags, outputPath common.ModuleOutPath) {
 
 	arCmd := "ar"
 	arFlags := "cqs"
 
 	// ARG_MAX on darwin is 262144, use half that to be safe
-	objFilesLists, err := splitListForSize(objFiles, 131072)
+	objFilesLists, err := splitListForSize(objFiles.Strings(), 131072)
 	if err != nil {
 		ctx.ModuleErrorf("%s", err.Error())
 	}
 
+	outputFile := outputPath.String()
+
 	var in, out string
 	for i, l := range objFilesLists {
 		in = out
@@ -295,12 +275,12 @@
 // 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, lateStaticLibs, wholeStaticLibs, deps []string,
-	crtBegin, crtEnd string, groupLate bool, flags builderFlags, outputFile string) {
+	objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps common.Paths,
+	crtBegin, crtEnd common.OptionalPath, groupLate bool, flags builderFlags, outputFile common.WritablePath) {
 
 	var ldCmd string
 	if flags.clang {
-		ldCmd = "${clangPath}clang++"
+		ldCmd = "${clangPath}/clang++"
 	} else {
 		ldCmd = gccCmd(flags.toolchain, "g++")
 	}
@@ -310,31 +290,31 @@
 
 	if len(wholeStaticLibs) > 0 {
 		if ctx.Host() && ctx.Darwin() {
-			libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs, "-force_load "))
+			libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs.Strings(), "-force_load "))
 		} else {
 			libFlagsList = append(libFlagsList, "-Wl,--whole-archive ")
-			libFlagsList = append(libFlagsList, wholeStaticLibs...)
+			libFlagsList = append(libFlagsList, wholeStaticLibs.Strings()...)
 			libFlagsList = append(libFlagsList, "-Wl,--no-whole-archive ")
 		}
 	}
 
-	libFlagsList = append(libFlagsList, staticLibs...)
+	libFlagsList = append(libFlagsList, staticLibs.Strings()...)
 
 	if groupLate && len(lateStaticLibs) > 0 {
 		libFlagsList = append(libFlagsList, "-Wl,--start-group")
 	}
-	libFlagsList = append(libFlagsList, lateStaticLibs...)
+	libFlagsList = append(libFlagsList, lateStaticLibs.Strings()...)
 	if groupLate && len(lateStaticLibs) > 0 {
 		libFlagsList = append(libFlagsList, "-Wl,--end-group")
 	}
 
 	for _, lib := range sharedLibs {
-		dir, file := filepath.Split(lib)
+		dir, file := filepath.Split(lib.String())
 		if !strings.HasPrefix(file, "lib") {
-			panic("shared library " + lib + " does not start with lib")
+			panic("shared library " + lib.String() + " does not start with lib")
 		}
 		if !strings.HasSuffix(file, flags.toolchain.ShlibSuffix()) {
-			panic("shared library " + lib + " does not end with " + flags.toolchain.ShlibSuffix())
+			panic("shared library " + lib.String() + " does not end with " + flags.toolchain.ShlibSuffix())
 		}
 		libFlagsList = append(libFlagsList,
 			"-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), flags.toolchain.ShlibSuffix()))
@@ -345,29 +325,29 @@
 	deps = append(deps, staticLibs...)
 	deps = append(deps, lateStaticLibs...)
 	deps = append(deps, wholeStaticLibs...)
-	if crtBegin != "" {
-		deps = append(deps, crtBegin, crtEnd)
+	if crtBegin.Valid() {
+		deps = append(deps, crtBegin.Path(), crtEnd.Path())
 	}
 
-	ctx.Build(pctx, blueprint.BuildParams{
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
 		Rule:      ld,
-		Outputs:   []string{outputFile},
+		Output:    outputFile,
 		Inputs:    objFiles,
 		Implicits: deps,
 		Args: map[string]string{
 			"ldCmd":      ldCmd,
 			"ldDirFlags": ldDirsToFlags(ldDirs),
-			"crtBegin":   crtBegin,
+			"crtBegin":   crtBegin.String(),
 			"libFlags":   strings.Join(libFlagsList, " "),
 			"ldFlags":    flags.ldFlags,
-			"crtEnd":     crtEnd,
+			"crtEnd":     crtEnd.String(),
 		},
 	})
 }
 
 // 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) {
+func TransformObjsToObj(ctx common.AndroidModuleContext, objFiles common.Paths,
+	flags builderFlags, outputFile common.WritablePath) {
 
 	var ldCmd string
 	if flags.clang {
@@ -376,27 +356,27 @@
 		ldCmd = gccCmd(flags.toolchain, "g++")
 	}
 
-	ctx.Build(pctx, blueprint.BuildParams{
-		Rule:    partialLd,
-		Outputs: []string{outputFile},
-		Inputs:  objFiles,
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
+		Rule:   partialLd,
+		Output: outputFile,
+		Inputs: objFiles,
 		Args: map[string]string{
-			"ldCmd": ldCmd,
+			"ldCmd":   ldCmd,
 			"ldFlags": flags.ldFlags,
 		},
 	})
 }
 
 // Generate a rule for runing objcopy --prefix-symbols on a binary
-func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile string,
-	flags builderFlags, outputFile string) {
+func TransformBinaryPrefixSymbols(ctx common.AndroidModuleContext, prefix string, inputFile common.Path,
+	flags builderFlags, outputFile common.WritablePath) {
 
 	objcopyCmd := gccCmd(flags.toolchain, "objcopy")
 
-	ctx.Build(pctx, blueprint.BuildParams{
-		Rule:    prefixSymbols,
-		Outputs: []string{outputFile},
-		Inputs:  []string{inputFile},
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
+		Rule:   prefixSymbols,
+		Output: outputFile,
+		Input:  inputFile,
 		Args: map[string]string{
 			"objcopyCmd": objcopyCmd,
 			"prefix":     prefix,
@@ -405,11 +385,11 @@
 }
 
 func CopyGccLib(ctx common.AndroidModuleContext, libName string,
-	flags builderFlags, outputFile string) {
+	flags builderFlags, outputFile common.WritablePath) {
 
-	ctx.Build(pctx, blueprint.BuildParams{
-		Rule:    copyGccLib,
-		Outputs: []string{outputFile},
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
+		Rule:   copyGccLib,
+		Output: outputFile,
 		Args: map[string]string{
 			"ccCmd":   gccCmd(flags.toolchain, "gcc"),
 			"cFlags":  flags.globalFlags,