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/androidmk.go b/cc/androidmk.go
index 7554ef4..11d7614 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -16,7 +16,6 @@
 
 import (
 	"io"
-	"path/filepath"
 	"strings"
 
 	"android/soong/common"
@@ -29,7 +28,7 @@
 		ret.Class = "SHARED_LIBRARIES"
 	}
 	ret.OutputFile = c.outputFile()
-	ret.Extra = func(name, prefix, outputFile string, arch common.Arch) (ret []string) {
+	ret.Extra = func(name, prefix string, outputFile common.Path, arch common.Arch) (ret []string) {
 		exportedIncludes := c.exportedFlags()
 		for i := range exportedIncludes {
 			exportedIncludes[i] = strings.TrimPrefix(exportedIncludes[i], "-I")
@@ -38,7 +37,7 @@
 			ret = append(ret, "LOCAL_EXPORT_C_INCLUDE_DIRS := "+strings.Join(exportedIncludes, " "))
 		}
 
-		ret = append(ret, "LOCAL_MODULE_SUFFIX := "+filepath.Ext(outputFile))
+		ret = append(ret, "LOCAL_MODULE_SUFFIX := "+outputFile.Ext())
 		ret = append(ret, "LOCAL_SHARED_LIBRARIES_"+arch.ArchType.String()+" := "+strings.Join(c.savedDepNames.SharedLibs, " "))
 
 		if c.Properties.Relative_install_path != "" {
@@ -57,9 +56,9 @@
 func (c *ccObject) AndroidMk() (ret common.AndroidMkData) {
 	ret.OutputFile = c.outputFile()
 	ret.Custom = func(w io.Writer, name, prefix string) {
-		out := c.outputFile()
+		out := c.outputFile().Path()
 
-		io.WriteString(w, "$("+prefix+"TARGET_OUT_INTERMEDIATE_LIBRARIES)/"+name+objectExtension+": "+out+" | $(ACP)\n")
+		io.WriteString(w, "$("+prefix+"TARGET_OUT_INTERMEDIATE_LIBRARIES)/"+name+objectExtension+": "+out.String()+" | $(ACP)\n")
 		io.WriteString(w, "\t$(copy-file-to-target)\n")
 	}
 	return
@@ -67,7 +66,7 @@
 
 func (c *CCBinary) AndroidMk() (ret common.AndroidMkData) {
 	ret.Class = "EXECUTABLES"
-	ret.Extra = func(name, prefix, outputFile string, arch common.Arch) []string {
+	ret.Extra = func(name, prefix string, outputFile common.Path, arch common.Arch) []string {
 		ret := []string{
 			"LOCAL_CXX_STL := none",
 			"LOCAL_SYSTEM_SHARED_LIBRARIES :=",
diff --git a/cc/arm64_device.go b/cc/arm64_device.go
index 055f948..8d773ed 100644
--- a/cc/arm64_device.go
+++ b/cc/arm64_device.go
@@ -78,7 +78,7 @@
 func init() {
 	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
 
-	pctx.StaticVariable("arm64GccRoot",
+	pctx.SourcePathVariable("arm64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
 
 	pctx.StaticVariable("arm64GccTriple", "aarch64-linux-android")
diff --git a/cc/arm_device.go b/cc/arm_device.go
index ccfefba..5c91a82 100644
--- a/cc/arm_device.go
+++ b/cc/arm_device.go
@@ -154,7 +154,7 @@
 
 	pctx.StaticVariable("armGccVersion", armGccVersion)
 
-	pctx.StaticVariable("armGccRoot",
+	pctx.SourcePathVariable("armGccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
 
 	pctx.StaticVariable("armGccTriple", "arm-linux-androideabi")
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,
diff --git a/cc/cc.go b/cc/cc.go
index 489bffe..b497d66 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -24,7 +24,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong"
@@ -64,10 +63,9 @@
 
 var (
 	HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", common.Config.PrebuiltOS)
-	SrcDir          = pctx.VariableConfigMethod("SrcDir", common.Config.SrcDir)
 
-	LibcRoot = pctx.StaticVariable("LibcRoot", "bionic/libc")
-	LibmRoot = pctx.StaticVariable("LibmRoot", "bionic/libm")
+	LibcRoot = pctx.SourcePathVariable("LibcRoot", "bionic/libc")
+	LibmRoot = pctx.SourcePathVariable("LibmRoot", "bionic/libm")
 )
 
 // Flags used by lots of devices.  Putting them in package static variables will save bytes in
@@ -127,19 +125,20 @@
 
 	// Everything in this list is a crime against abstraction and dependency tracking.
 	// Do not add anything to this list.
-	pctx.StaticVariable("commonGlobalIncludes", strings.Join([]string{
-		"-isystem ${SrcDir}/system/core/include",
-		"-isystem ${SrcDir}/hardware/libhardware/include",
-		"-isystem ${SrcDir}/hardware/libhardware_legacy/include",
-		"-isystem ${SrcDir}/hardware/ril/include",
-		"-isystem ${SrcDir}/libnativehelper/include",
-		"-isystem ${SrcDir}/frameworks/native/include",
-		"-isystem ${SrcDir}/frameworks/native/opengl/include",
-		"-isystem ${SrcDir}/frameworks/av/include",
-		"-isystem ${SrcDir}/frameworks/base/include",
-	}, " "))
+	pctx.PrefixedPathsForSourceVariable("commonGlobalIncludes", "-isystem ",
+		[]string{
+			"system/core/include",
+			"hardware/libhardware/include",
+			"hardware/libhardware_legacy/include",
+			"hardware/ril/include",
+			"libnativehelper/include",
+			"frameworks/native/include",
+			"frameworks/native/opengl/include",
+			"frameworks/av/include",
+			"frameworks/base/include",
+		})
 
-	pctx.StaticVariable("clangPath", "${SrcDir}/prebuilts/clang/host/${HostPrebuiltTag}/3.8/bin/")
+	pctx.SourcePathVariable("clangPath", "prebuilts/clang/host/${HostPrebuiltTag}/3.8/bin")
 }
 
 type CCModuleContext common.AndroidBaseContext
@@ -162,23 +161,36 @@
 	depsMutator(common.AndroidBottomUpMutatorContext)
 
 	// Compile objects into final module
-	compileModule(common.AndroidModuleContext, CCFlags, CCDeps, []string)
+	compileModule(common.AndroidModuleContext, CCFlags, CCPathDeps, common.Paths)
 
 	// Install the built module.
 	installModule(common.AndroidModuleContext, CCFlags)
 
 	// Return the output file (.o, .a or .so) for use by other modules
-	outputFile() string
+	outputFile() common.OptionalPath
 }
 
 type CCDeps struct {
-	StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs, ObjFiles, Cflags, ReexportedCflags []string
+	StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs []string
 
-	WholeStaticLibObjFiles []string
+	ObjFiles common.Paths
+
+	Cflags, ReexportedCflags []string
 
 	CrtBegin, CrtEnd string
 }
 
+type CCPathDeps struct {
+	StaticLibs, SharedLibs, LateStaticLibs, WholeStaticLibs common.Paths
+
+	ObjFiles               common.Paths
+	WholeStaticLibObjFiles common.Paths
+
+	Cflags, ReexportedCflags []string
+
+	CrtBegin, CrtEnd common.OptionalPath
+}
+
 type CCFlags struct {
 	GlobalFlags []string // Flags that apply to C, C++, and assembly source files
 	AsFlags     []string // Flags that apply to assembly source files
@@ -440,7 +452,7 @@
 
 	ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.savedDepNames.SharedLibs...)
 
-	ctx.AddDependency(ctx.Module(), c.savedDepNames.ObjFiles...)
+	ctx.AddDependency(ctx.Module(), c.savedDepNames.ObjFiles.Strings()...)
 	if c.savedDepNames.CrtBegin != "" {
 		ctx.AddDependency(ctx.Module(), c.savedDepNames.CrtBegin)
 	}
@@ -472,17 +484,14 @@
 	}
 
 	// Include dir cflags
-	common.CheckSrcDirsExist(ctx, c.Properties.Include_dirs, "include_dirs")
-	common.CheckModuleSrcDirsExist(ctx, c.Properties.Local_include_dirs, "local_include_dirs")
-
-	rootIncludeDirs := pathtools.PrefixPaths(c.Properties.Include_dirs, ctx.AConfig().SrcDir())
-	localIncludeDirs := pathtools.PrefixPaths(c.Properties.Local_include_dirs, common.ModuleSrcDir(ctx))
+	rootIncludeDirs := common.PathsForSource(ctx, c.Properties.Include_dirs)
+	localIncludeDirs := common.PathsForModuleSrc(ctx, c.Properties.Local_include_dirs)
 	flags.GlobalFlags = append(flags.GlobalFlags,
 		includeDirsToFlags(localIncludeDirs),
 		includeDirsToFlags(rootIncludeDirs))
 
-	rootIncludeFiles := pathtools.PrefixPaths(c.Properties.Include_files, ctx.AConfig().SrcDir())
-	localIncludeFiles := pathtools.PrefixPaths(c.Properties.Local_include_files, common.ModuleSrcDir(ctx))
+	rootIncludeFiles := common.PathsForSource(ctx, c.Properties.Include_files)
+	localIncludeFiles := common.PathsForModuleSrc(ctx, c.Properties.Local_include_files)
 
 	flags.GlobalFlags = append(flags.GlobalFlags,
 		includeFilesToFlags(rootIncludeFiles),
@@ -493,13 +502,13 @@
 			flags.GlobalFlags = append(flags.GlobalFlags,
 				"${commonGlobalIncludes}",
 				toolchain.IncludeFlags(),
-				"-I${SrcDir}/libnativehelper/include/nativehelper")
+				"-I"+common.PathForSource(ctx, "libnativehelper/include/nativehelper").String())
 		}
 
 		flags.GlobalFlags = append(flags.GlobalFlags, []string{
-			"-I" + common.ModuleSrcDir(ctx),
-			"-I" + common.ModuleOutDir(ctx),
-			"-I" + common.ModuleGenDir(ctx),
+			"-I" + common.PathForModuleSrc(ctx).String(),
+			"-I" + common.PathForModuleOut(ctx).String(),
+			"-I" + common.PathForModuleGen(ctx).String(),
 		}...)
 	}
 
@@ -636,18 +645,18 @@
 
 // Compile a list of source files into objects a specified subdirectory
 func (c *CCBase) customCompileObjs(ctx common.AndroidModuleContext, flags CCFlags,
-	subdir string, srcFiles, excludes []string) []string {
+	subdir string, srcFiles, excludes []string) common.Paths {
 
 	buildFlags := ccFlagsToBuilderFlags(flags)
 
-	srcFiles = ctx.ExpandSources(srcFiles, excludes)
-	srcFiles, deps := genSources(ctx, srcFiles, buildFlags)
+	inputFiles := ctx.ExpandSources(srcFiles, excludes)
+	srcPaths, deps := genSources(ctx, inputFiles, buildFlags)
 
-	return TransformSourceToObj(ctx, subdir, srcFiles, buildFlags, deps)
+	return TransformSourceToObj(ctx, subdir, srcPaths, buildFlags, deps)
 }
 
 // Compile files listed in c.Properties.Srcs into objects
-func (c *CCBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) []string {
+func (c *CCBase) compileObjs(ctx common.AndroidModuleContext, flags CCFlags) common.Paths {
 
 	if c.Properties.SkipCompileObjs {
 		return nil
@@ -657,8 +666,8 @@
 }
 
 // Compile generated source files from dependencies
-func (c *CCBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags) []string {
-	var srcs []string
+func (c *CCBase) compileGeneratedObjs(ctx common.AndroidModuleContext, flags CCFlags) common.Paths {
+	var srcs common.Paths
 
 	if c.Properties.SkipCompileObjs {
 		return nil
@@ -677,13 +686,13 @@
 	return TransformSourceToObj(ctx, "", srcs, ccFlagsToBuilderFlags(flags), nil)
 }
 
-func (c *CCBase) outputFile() string {
-	return ""
+func (c *CCBase) outputFile() common.OptionalPath {
+	return common.OptionalPath{}
 }
 
 func (c *CCBase) depsToPathsFromList(ctx common.AndroidModuleContext,
 	names []string) (modules []common.AndroidModule,
-	outputFiles []string, exportedFlags []string) {
+	outputFiles common.Paths, exportedFlags []string) {
 
 	for _, n := range names {
 		found := false
@@ -707,12 +716,12 @@
 					return
 				}
 
-				if outputFile := a.outputFile(); outputFile != "" {
+				if outputFile := a.outputFile(); outputFile.Valid() {
 					if found {
 						ctx.ModuleErrorf("multiple modules satisified dependency on %q", otherName)
 						return
 					}
-					outputFiles = append(outputFiles, outputFile)
+					outputFiles = append(outputFiles, outputFile.Path())
 					modules = append(modules, a)
 					if i, ok := a.(ccExportedFlagsProducer); ok {
 						exportedFlags = append(exportedFlags, i.exportedFlags()...)
@@ -735,10 +744,10 @@
 	return modules, outputFiles, exportedFlags
 }
 
-// Convert depenedency names to paths.  Takes a CCDeps containing names and returns a CCDeps
+// Convert dependency names to paths.  Takes a CCDeps containing names and returns a CCPathDeps
 // containing paths
-func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) CCDeps {
-	var depPaths CCDeps
+func (c *CCBase) depsToPaths(ctx common.AndroidModuleContext, depNames CCDeps) CCPathDeps {
+	var depPaths CCPathDeps
 	var newCflags []string
 
 	var wholeStaticLibModules []common.AndroidModule
@@ -778,7 +787,12 @@
 					depPaths.CrtEnd = obj.object().outputFile()
 				}
 			} else {
-				depPaths.ObjFiles = append(depPaths.ObjFiles, obj.object().outputFile())
+				output := obj.object().outputFile()
+				if output.Valid() {
+					depPaths.ObjFiles = append(depPaths.ObjFiles, output.Path())
+				} else {
+					ctx.ModuleErrorf("module %s did not provide an output file", otherName)
+				}
 			}
 		}
 	})
@@ -908,11 +922,11 @@
 		// tree is in good enough shape to not need it.
 		// Host builds will use GNU libstdc++.
 		if ctx.Device() {
-			flags.CFlags = append(flags.CFlags, "-I${SrcDir}/bionic/libstdc++/include")
+			flags.CFlags = append(flags.CFlags, "-I"+common.PathForSource(ctx, "bionic/libstdc++/include").String())
 		}
 	case "ndk_system":
-		ndkSrcRoot := ctx.AConfig().SrcDir() + "/prebuilts/ndk/current/sources/"
-		flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot+"cxx-stl/system/include")
+		ndkSrcRoot := common.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
+		flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String())
 	case "ndk_libc++_shared", "ndk_libc++_static":
 		// TODO(danalbert): This really shouldn't be here...
 		flags.CppFlags = append(flags.CppFlags, "-std=c++11")
@@ -1067,23 +1081,23 @@
 	} `android:"arch_variant"`
 
 	// local file name to pass to the linker as --version_script
-	Version_script string `android:"arch_variant"`
+	Version_script *string `android:"arch_variant"`
 	// local file name to pass to the linker as -unexported_symbols_list
-	Unexported_symbols_list string `android:"arch_variant"`
+	Unexported_symbols_list *string `android:"arch_variant"`
 	// local file name to pass to the linker as -force_symbols_not_weak_list
-	Force_symbols_not_weak_list string `android:"arch_variant"`
+	Force_symbols_not_weak_list *string `android:"arch_variant"`
 	// local file name to pass to the linker as -force_symbols_weak_list
-	Force_symbols_weak_list string `android:"arch_variant"`
+	Force_symbols_weak_list *string `android:"arch_variant"`
 }
 
 type CCLibrary struct {
 	CCLinked
 
 	reuseFrom     ccLibraryInterface
-	reuseObjFiles []string
-	objFiles      []string
+	reuseObjFiles common.Paths
+	objFiles      common.Paths
 	exportFlags   []string
-	out           string
+	out           common.Path
 	systemLibs    []string
 
 	LibraryProperties CCLibraryProperties
@@ -1102,8 +1116,8 @@
 	ccLibrary() *CCLibrary
 	setReuseFrom(ccLibraryInterface)
 	getReuseFrom() ccLibraryInterface
-	getReuseObjFiles() []string
-	allObjFiles() []string
+	getReuseObjFiles() common.Paths
+	allObjFiles() common.Paths
 }
 
 var _ ccLibraryInterface = (*CCLibrary)(nil)
@@ -1154,11 +1168,11 @@
 	return depNames
 }
 
-func (c *CCLibrary) outputFile() string {
-	return c.out
+func (c *CCLibrary) outputFile() common.OptionalPath {
+	return common.OptionalPathForPath(c.out)
 }
 
-func (c *CCLibrary) getReuseObjFiles() []string {
+func (c *CCLibrary) getReuseObjFiles() common.Paths {
 	return c.reuseObjFiles
 }
 
@@ -1170,7 +1184,7 @@
 	return c.reuseFrom
 }
 
-func (c *CCLibrary) allObjFiles() []string {
+func (c *CCLibrary) allObjFiles() common.Paths {
 	return c.objFiles
 }
 
@@ -1225,7 +1239,7 @@
 }
 
 func (c *CCLibrary) compileStaticLibrary(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	staticFlags := flags
 	objFilesStatic := c.customCompileObjs(ctx, staticFlags, common.DeviceStaticLibrary,
@@ -1234,7 +1248,7 @@
 	objFiles = append(objFiles, objFilesStatic...)
 	objFiles = append(objFiles, deps.WholeStaticLibObjFiles...)
 
-	outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+staticLibraryExtension)
+	outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+staticLibraryExtension)
 
 	if ctx.Darwin() {
 		TransformDarwinObjToStaticLib(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
@@ -1245,8 +1259,7 @@
 	c.objFiles = objFiles
 	c.out = outputFile
 
-	common.CheckModuleSrcDirsExist(ctx, c.Properties.Export_include_dirs, "export_include_dirs")
-	includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx))
+	includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
 	c.exportFlags = []string{includeDirsToFlags(includeDirs)}
 	c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...)
 
@@ -1254,7 +1267,7 @@
 }
 
 func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	sharedFlags := flags
 	objFilesShared := c.customCompileObjs(ctx, sharedFlags, common.DeviceSharedLibrary,
@@ -1262,43 +1275,43 @@
 
 	objFiles = append(objFiles, objFilesShared...)
 
-	outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+flags.Toolchain.ShlibSuffix())
+	outputFile := common.PathForModuleOut(ctx, ctx.ModuleName()+flags.Toolchain.ShlibSuffix())
 
-	var linkerDeps []string
+	var linkerDeps common.Paths
 
+	versionScript := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Version_script)
+	unexportedSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Unexported_symbols_list)
+	forceNotWeakSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Force_symbols_not_weak_list)
+	forceWeakSymbols := common.OptionalPathForModuleSrc(ctx, c.LibraryProperties.Force_symbols_weak_list)
 	if !ctx.Darwin() {
-		if c.LibraryProperties.Version_script != "" {
-			versionScript := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Version_script)
-			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,--version-script,"+versionScript)
-			linkerDeps = append(linkerDeps, versionScript)
+		if versionScript.Valid() {
+			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,--version-script,"+versionScript.String())
+			linkerDeps = append(linkerDeps, versionScript.Path())
 		}
-		if c.LibraryProperties.Unexported_symbols_list != "" {
+		if unexportedSymbols.Valid() {
 			ctx.PropertyErrorf("unexported_symbols_list", "Only supported on Darwin")
 		}
-		if c.LibraryProperties.Force_symbols_not_weak_list != "" {
+		if forceNotWeakSymbols.Valid() {
 			ctx.PropertyErrorf("force_symbols_not_weak_list", "Only supported on Darwin")
 		}
-		if c.LibraryProperties.Force_symbols_weak_list != "" {
+		if forceWeakSymbols.Valid() {
 			ctx.PropertyErrorf("force_symbols_weak_list", "Only supported on Darwin")
 		}
 	} else {
-		if c.LibraryProperties.Version_script != "" {
+		if versionScript.Valid() {
 			ctx.PropertyErrorf("version_script", "Not supported on Darwin")
 		}
-		if c.LibraryProperties.Unexported_symbols_list != "" {
-			localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Unexported_symbols_list)
-			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-unexported_symbols_list,"+localFile)
-			linkerDeps = append(linkerDeps, localFile)
+		if unexportedSymbols.Valid() {
+			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-unexported_symbols_list,"+unexportedSymbols.String())
+			linkerDeps = append(linkerDeps, unexportedSymbols.Path())
 		}
-		if c.LibraryProperties.Force_symbols_not_weak_list != "" {
-			localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Force_symbols_not_weak_list)
-			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+localFile)
-			linkerDeps = append(linkerDeps, localFile)
+		if forceNotWeakSymbols.Valid() {
+			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_not_weak_list,"+forceNotWeakSymbols.String())
+			linkerDeps = append(linkerDeps, forceNotWeakSymbols.Path())
 		}
-		if c.LibraryProperties.Force_symbols_weak_list != "" {
-			localFile := filepath.Join(common.ModuleSrcDir(ctx), c.LibraryProperties.Force_symbols_weak_list)
-			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_weak_list,"+localFile)
-			linkerDeps = append(linkerDeps, localFile)
+		if forceWeakSymbols.Valid() {
+			sharedFlags.LdFlags = append(sharedFlags.LdFlags, "-Wl,-force_symbols_weak_list,"+forceWeakSymbols.String())
+			linkerDeps = append(linkerDeps, forceWeakSymbols.Path())
 		}
 	}
 
@@ -1307,13 +1320,13 @@
 		ccFlagsToBuilderFlags(sharedFlags), outputFile)
 
 	c.out = outputFile
-	includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx))
+	includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
 	c.exportFlags = []string{includeDirsToFlags(includeDirs)}
 	c.exportFlags = append(c.exportFlags, deps.ReexportedCflags...)
 }
 
 func (c *CCLibrary) compileModule(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	// Reuse the object files from the matching static library if it exists
 	if c.getReuseFrom().ccLibrary() == c {
@@ -1321,7 +1334,7 @@
 	} else {
 		if c.getReuseFrom().ccLibrary().LibraryProperties.Static.Cflags == nil &&
 			c.LibraryProperties.Shared.Cflags == nil {
-			objFiles = append([]string(nil), c.getReuseFrom().getReuseObjFiles()...)
+			objFiles = append(common.Paths(nil), c.getReuseFrom().getReuseObjFiles()...)
 		}
 	}
 
@@ -1363,7 +1376,7 @@
 
 type ccObject struct {
 	CCBase
-	out string
+	out common.OptionalPath
 }
 
 func (c *ccObject) object() *ccObject {
@@ -1382,19 +1395,20 @@
 }
 
 func (c *ccObject) compileModule(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	objFiles = append(objFiles, deps.ObjFiles...)
 
-	var outputFile string
+	var outputFile common.Path
 	if len(objFiles) == 1 {
 		outputFile = objFiles[0]
 	} else {
-		outputFile = filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+objectExtension)
-		TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), outputFile)
+		output := common.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
+		TransformObjsToObj(ctx, objFiles, ccFlagsToBuilderFlags(flags), output)
+		outputFile = output
 	}
 
-	c.out = outputFile
+	c.out = common.OptionalPathForPath(outputFile)
 
 	ctx.CheckbuildFile(outputFile)
 }
@@ -1403,7 +1417,7 @@
 	// Object files do not get installed.
 }
 
-func (c *ccObject) outputFile() string {
+func (c *ccObject) outputFile() common.OptionalPath {
 	return c.out
 }
 
@@ -1433,8 +1447,8 @@
 
 type CCBinary struct {
 	CCLinked
-	out              string
-	installFile      string
+	out              common.Path
+	installFile      common.Path
 	BinaryProperties CCBinaryProperties
 }
 
@@ -1569,23 +1583,23 @@
 }
 
 func (c *CCBinary) compileModule(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	if !Bool(c.BinaryProperties.Static_executable) && inList("libc", c.Properties.Static_libs) {
 		ctx.ModuleErrorf("statically linking libc to dynamic executable, please remove libc\n" +
 			"from static libs or set static_executable: true")
 	}
 
-	outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx)+flags.Toolchain.ExecutableSuffix())
+	outputFile := common.PathForModuleOut(ctx, c.getStem(ctx)+flags.Toolchain.ExecutableSuffix())
 	c.out = outputFile
 	if c.BinaryProperties.Prefix_symbols != "" {
 		afterPrefixSymbols := outputFile
-		outputFile = outputFile + ".intermediate"
+		outputFile = common.PathForModuleOut(ctx, c.getStem(ctx)+".intermediate")
 		TransformBinaryPrefixSymbols(ctx, c.BinaryProperties.Prefix_symbols, outputFile,
 			ccFlagsToBuilderFlags(flags), afterPrefixSymbols)
 	}
 
-	var linkerDeps []string
+	var linkerDeps common.Paths
 
 	TransformObjToDynamicBinary(ctx, objFiles, deps.SharedLibs, deps.StaticLibs,
 		deps.LateStaticLibs, deps.WholeStaticLibs, linkerDeps, deps.CrtBegin, deps.CrtEnd, true,
@@ -1596,11 +1610,11 @@
 	c.installFile = ctx.InstallFile(filepath.Join("bin", c.Properties.Relative_install_path), c.out)
 }
 
-func (c *CCBinary) HostToolPath() string {
+func (c *CCBinary) HostToolPath() common.OptionalPath {
 	if c.HostOrDevice().Host() {
-		return c.installFile
+		return common.OptionalPathForPath(c.installFile)
 	}
-	return ""
+	return common.OptionalPath{}
 }
 
 func (c *CCBinary) testPerSrc() bool {
@@ -1649,7 +1663,7 @@
 
 	// TODO(danalbert): Make gtest export its dependencies.
 	flags.CFlags = append(flags.CFlags,
-		"-I"+filepath.Join(ctx.AConfig().SrcDir(), "external/gtest/include"))
+		"-I"+common.PathForSource(ctx, "external/gtest/include").String())
 
 	return flags
 }
@@ -1832,10 +1846,10 @@
 }
 
 func (c *toolchainLibrary) compileModule(ctx common.AndroidModuleContext,
-	flags CCFlags, deps CCDeps, objFiles []string) {
+	flags CCFlags, deps CCPathDeps, objFiles common.Paths) {
 
 	libName := ctx.ModuleName() + staticLibraryExtension
-	outputFile := filepath.Join(common.ModuleOutDir(ctx), libName)
+	outputFile := common.PathForModuleOut(ctx, libName)
 
 	CopyGccLib(ctx, libName, ccFlagsToBuilderFlags(flags), outputFile)
 
@@ -1854,19 +1868,19 @@
 // either (with the exception of the shared STLs, which are installed to the app's directory rather
 // than to the system image).
 
-func getNdkLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, version string) string {
-	return fmt.Sprintf("%s/prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib",
-		ctx.AConfig().SrcDir(), version, toolchain.Name())
+func getNdkLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, version string) common.SourcePath {
+	return common.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib",
+		version, toolchain.Name()))
 }
 
 func ndkPrebuiltModuleToPath(ctx common.AndroidModuleContext, toolchain Toolchain,
-	ext string, version string) string {
+	ext string, version string) common.Path {
 
 	// NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
 	// We want to translate to just NAME.EXT
 	name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
 	dir := getNdkLibDir(ctx, toolchain, version)
-	return filepath.Join(dir, name+ext)
+	return dir.Join(ctx, name+ext)
 }
 
 type ndkPrebuiltObject struct {
@@ -1884,13 +1898,13 @@
 }
 
 func (c *ndkPrebuiltObject) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
-	deps CCDeps, objFiles []string) {
+	deps CCPathDeps, objFiles common.Paths) {
 	// A null build step, but it sets up the output path.
 	if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
 		ctx.ModuleErrorf("NDK prebuilts must have an ndk_crt prefixed name")
 	}
 
-	c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, c.Properties.Sdk_version)
+	c.out = common.OptionalPathForPath(ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, c.Properties.Sdk_version))
 }
 
 func (c *ndkPrebuiltObject) installModule(ctx common.AndroidModuleContext, flags CCFlags) {
@@ -1915,14 +1929,14 @@
 }
 
 func (c *ndkPrebuiltLibrary) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
-	deps CCDeps, objFiles []string) {
+	deps CCPathDeps, objFiles common.Paths) {
 	// A null build step, but it sets up the output path.
 	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
 		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
 	}
 
-	includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx))
-	c.exportFlags = []string{common.JoinWithPrefix(includeDirs, "-isystem ")}
+	includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
+	c.exportFlags = []string{common.JoinWithPrefix(includeDirs.Strings(), "-isystem ")}
 
 	c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
 		c.Properties.Sdk_version)
@@ -1960,7 +1974,7 @@
 	return NewCCLibrary(&module.CCLibrary, module, common.DeviceSupported)
 }
 
-func getNdkStlLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, stl string) string {
+func getNdkStlLibDir(ctx common.AndroidModuleContext, toolchain Toolchain, stl string) common.SourcePath {
 	gccVersion := toolchain.GccVersion()
 	var libDir string
 	switch stl {
@@ -1973,22 +1987,22 @@
 	}
 
 	if libDir != "" {
-		ndkSrcRoot := ctx.AConfig().SrcDir() + "/prebuilts/ndk/current/sources"
-		return fmt.Sprintf("%s/%s/%s", ndkSrcRoot, libDir, ctx.Arch().Abi)
+		ndkSrcRoot := "prebuilts/ndk/current/sources"
+		return common.PathForSource(ctx, ndkSrcRoot).Join(ctx, libDir, ctx.Arch().Abi[0])
 	}
 
 	ctx.ModuleErrorf("Unknown NDK STL: %s", stl)
-	return ""
+	return common.PathForSource(ctx, "")
 }
 
 func (c *ndkPrebuiltStl) compileModule(ctx common.AndroidModuleContext, flags CCFlags,
-	deps CCDeps, objFiles []string) {
+	deps CCPathDeps, objFiles common.Paths) {
 	// A null build step, but it sets up the output path.
 	if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
 		ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
 	}
 
-	includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx))
+	includeDirs := common.PathsForModuleSrc(ctx, c.Properties.Export_include_dirs)
 	c.exportFlags = []string{includeDirsToFlags(includeDirs)}
 
 	libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_")
@@ -2000,7 +2014,7 @@
 	stlName := strings.TrimSuffix(libName, "_shared")
 	stlName = strings.TrimSuffix(stlName, "_static")
 	libDir := getNdkStlLibDir(ctx, flags.Toolchain, stlName)
-	c.out = libDir + "/" + libName + libExt
+	c.out = libDir.Join(ctx, libName+libExt)
 }
 
 func linkageMutator(mctx common.AndroidBottomUpMutatorContext) {
diff --git a/cc/gen.go b/cc/gen.go
index be50d75..035f40e 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -19,18 +19,15 @@
 // functions.
 
 import (
-	"path/filepath"
-
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 
 	"android/soong/common"
 )
 
 func init() {
-	pctx.StaticVariable("lexCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/flex/flex-2.5.39")
-	pctx.StaticVariable("yaccCmd", "${SrcDir}/prebuilts/misc/${HostPrebuiltTag}/bison/bison")
-	pctx.StaticVariable("yaccDataDir", "${SrcDir}/external/bison/data")
+	pctx.SourcePathVariable("lexCmd", "prebuilts/misc/${HostPrebuiltTag}/flex/flex-2.5.39")
+	pctx.SourcePathVariable("yaccCmd", "prebuilts/misc/${HostPrebuiltTag}/bison/bison")
+	pctx.SourcePathVariable("yaccDataDir", "external/bison/data")
 }
 
 var (
@@ -51,49 +48,45 @@
 		})
 )
 
-func genYacc(ctx common.AndroidModuleContext, yaccFile, yaccFlags string) (cppFile, headerFile string) {
-	cppFile = common.SrcDirRelPath(ctx, yaccFile)
-	cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile)
-	cppFile = pathtools.ReplaceExtension(cppFile, "cpp")
-	hppFile := pathtools.ReplaceExtension(cppFile, "hpp")
-	headerFile = pathtools.ReplaceExtension(cppFile, "h")
+func genYacc(ctx common.AndroidModuleContext, yaccFile common.Path, yaccFlags string) (cppFile, headerFile common.ModuleGenPath) {
+	cppFile = common.GenPathWithExt(ctx, yaccFile, "cpp")
+	hppFile := common.GenPathWithExt(ctx, yaccFile, "hpp")
+	headerFile = common.GenPathWithExt(ctx, yaccFile, "h")
 
-	ctx.Build(pctx, blueprint.BuildParams{
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
 		Rule:    yacc,
-		Outputs: []string{cppFile, headerFile},
-		Inputs:  []string{yaccFile},
+		Outputs: common.WritablePaths{cppFile, headerFile},
+		Input:   yaccFile,
 		Args: map[string]string{
 			"yaccFlags": yaccFlags,
-			"cppFile":   cppFile,
-			"hppFile":   hppFile,
-			"hFile":     headerFile,
+			"cppFile":   cppFile.String(),
+			"hppFile":   hppFile.String(),
+			"hFile":     headerFile.String(),
 		},
 	})
 
 	return cppFile, headerFile
 }
 
-func genLex(ctx common.AndroidModuleContext, lexFile string) (cppFile string) {
-	cppFile = common.SrcDirRelPath(ctx, lexFile)
-	cppFile = filepath.Join(common.ModuleGenDir(ctx), cppFile)
-	cppFile = pathtools.ReplaceExtension(cppFile, "cpp")
+func genLex(ctx common.AndroidModuleContext, lexFile common.Path) (cppFile common.ModuleGenPath) {
+	cppFile = common.GenPathWithExt(ctx, lexFile, "cpp")
 
-	ctx.Build(pctx, blueprint.BuildParams{
-		Rule:    lex,
-		Outputs: []string{cppFile},
-		Inputs:  []string{lexFile},
+	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
+		Rule:   lex,
+		Output: cppFile,
+		Input:  lexFile,
 	})
 
 	return cppFile
 }
 
-func genSources(ctx common.AndroidModuleContext, srcFiles []string,
-	buildFlags builderFlags) ([]string, []string) {
+func genSources(ctx common.AndroidModuleContext, srcFiles common.Paths,
+	buildFlags builderFlags) (common.Paths, common.Paths) {
 
-	var deps []string
+	var deps common.Paths
 
 	for i, srcFile := range srcFiles {
-		switch filepath.Ext(srcFile) {
+		switch srcFile.Ext() {
 		case ".y", ".yy":
 			cppFile, headerFile := genYacc(ctx, srcFile, buildFlags.yaccFlags)
 			srcFiles[i] = cppFile
diff --git a/cc/mips64_device.go b/cc/mips64_device.go
index 5aa5bc3..44ca4f8 100644
--- a/cc/mips64_device.go
+++ b/cc/mips64_device.go
@@ -90,7 +90,7 @@
 
 	pctx.StaticVariable("mips64GccVersion", mips64GccVersion)
 
-	pctx.StaticVariable("mips64GccRoot",
+	pctx.SourcePathVariable("mips64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mips64GccVersion}")
 
 	pctx.StaticVariable("mips64GccTriple", "mips64el-linux-android")
diff --git a/cc/mips_device.go b/cc/mips_device.go
index 8b47f8a..ba6b81a 100644
--- a/cc/mips_device.go
+++ b/cc/mips_device.go
@@ -121,7 +121,7 @@
 
 	pctx.StaticVariable("mipsGccVersion", mipsGccVersion)
 
-	pctx.StaticVariable("mipsGccRoot",
+	pctx.SourcePathVariable("mipsGccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/mips/mips64el-linux-android-${mipsGccVersion}")
 
 	pctx.StaticVariable("mipsGccTriple", "mips64el-linux-android")
diff --git a/cc/util.go b/cc/util.go
index efc89f0..2fc717b 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -24,12 +24,12 @@
 
 // Efficiently converts a list of include directories to a single string
 // of cflags with -I prepended to each directory.
-func includeDirsToFlags(dirs []string) string {
-	return common.JoinWithPrefix(dirs, "-I")
+func includeDirsToFlags(dirs common.Paths) string {
+	return common.JoinWithPrefix(dirs.Strings(), "-I")
 }
 
-func includeFilesToFlags(dirs []string) string {
-	return common.JoinWithPrefix(dirs, "-include ")
+func includeFilesToFlags(files common.Paths) string {
+	return common.JoinWithPrefix(files.Strings(), "-include ")
 }
 
 func ldDirsToFlags(dirs []string) string {
diff --git a/cc/x86_64_device.go b/cc/x86_64_device.go
index ba190a0..b4f96b9 100644
--- a/cc/x86_64_device.go
+++ b/cc/x86_64_device.go
@@ -137,7 +137,7 @@
 
 	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
 
-	pctx.StaticVariable("x86_64GccRoot",
+	pctx.SourcePathVariable("x86_64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
 
 	pctx.StaticVariable("x86_64GccTriple", "x86_64-linux-android")
diff --git a/cc/x86_darwin_host.go b/cc/x86_darwin_host.go
index 108bb85..9693de6 100644
--- a/cc/x86_darwin_host.go
+++ b/cc/x86_darwin_host.go
@@ -83,8 +83,8 @@
 	pctx.StaticVariable("macSdkRoot", "${macSdkPath}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk")
 
 	pctx.StaticVariable("darwinGccVersion", darwinGccVersion)
-	pctx.StaticVariable("darwinGccRoot",
-		"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${darwinGccVersion}")
+	pctx.SourcePathVariable("darwinGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${darwinGccVersion}")
 
 	pctx.StaticVariable("darwinGccTriple", "i686-apple-darwin11")
 
diff --git a/cc/x86_device.go b/cc/x86_device.go
index 6dfbd6a..a44b293 100644
--- a/cc/x86_device.go
+++ b/cc/x86_device.go
@@ -139,7 +139,7 @@
 
 	pctx.StaticVariable("x86GccVersion", x86GccVersion)
 
-	pctx.StaticVariable("x86GccRoot",
+	pctx.SourcePathVariable("x86GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
 
 	pctx.StaticVariable("x86GccTriple", "x86_64-linux-android")
diff --git a/cc/x86_linux_host.go b/cc/x86_linux_host.go
index 98bceef..a3c50d1 100644
--- a/cc/x86_linux_host.go
+++ b/cc/x86_linux_host.go
@@ -108,8 +108,8 @@
 func init() {
 	pctx.StaticVariable("linuxGccVersion", linuxGccVersion)
 
-	pctx.StaticVariable("linuxGccRoot",
-		"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${linuxGccVersion}")
+	pctx.SourcePathVariable("linuxGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc2.15-${linuxGccVersion}")
 
 	pctx.StaticVariable("linuxGccTriple", "x86_64-linux")
 
diff --git a/cc/x86_windows_host.go b/cc/x86_windows_host.go
index 5f06bec..8556a64 100644
--- a/cc/x86_windows_host.go
+++ b/cc/x86_windows_host.go
@@ -68,8 +68,8 @@
 func init() {
 	pctx.StaticVariable("windowsGccVersion", windowsGccVersion)
 
-	pctx.StaticVariable("windowsGccRoot",
-		"${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${windowsGccVersion}")
+	pctx.SourcePathVariable("windowsGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${windowsGccVersion}")
 
 	pctx.StaticVariable("windowsGccTriple", "x86_64-w64-mingw32")