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/java/java.go b/java/java.go
index 2bd5bff..839fb01 100644
--- a/java/java.go
+++ b/java/java.go
@@ -20,11 +20,9 @@
 
 import (
 	"fmt"
-	"path/filepath"
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 
 	"android/soong"
 	"android/soong/common"
@@ -93,7 +91,7 @@
 	Java_static_libs []string `android:"arch_variant"`
 
 	// manifest file to be included in resulting jar
-	Manifest string
+	Manifest *string
 
 	// if not blank, set to the version of the sdk to compile against
 	Sdk_version string
@@ -103,7 +101,7 @@
 	Dex bool `blueprint:"mutated"`
 
 	// if not blank, run jarjar using the specified rules file
-	Jarjar_rules string
+	Jarjar_rules *string
 
 	// directories to pass to aidl tool
 	Aidl_includes []string
@@ -122,10 +120,10 @@
 	properties javaBaseProperties
 
 	// output file suitable for inserting into the classpath of another compile
-	classpathFile string
+	classpathFile common.Path
 
 	// output file suitable for installing or running
-	outputFile string
+	outputFile common.Path
 
 	// jarSpecs suitable for inserting classes from a static library into another jar
 	classJarSpecs []jarSpec
@@ -133,16 +131,16 @@
 	// jarSpecs suitable for inserting resources from a static library into another jar
 	resourceJarSpecs []jarSpec
 
-	exportAidlIncludeDirs []string
+	exportAidlIncludeDirs common.Paths
 
-	logtagsSrcs []string
+	logtagsSrcs common.Paths
 
 	// filelists of extra source files that should be included in the javac command line,
 	// for example R.java generated by aapt for android apps
-	ExtraSrcLists []string
+	ExtraSrcLists common.Paths
 
 	// installed file for binary dependency
-	installFile string
+	installFile common.Path
 }
 
 type AndroidJavaModuleContext common.AndroidBaseContext
@@ -153,10 +151,10 @@
 }
 
 type JavaDependency interface {
-	ClasspathFile() string
+	ClasspathFile() common.Path
 	ClassJarSpecs() []jarSpec
 	ResourceJarSpecs() []jarSpec
-	AidlIncludeDirs() []string
+	AidlIncludeDirs() common.Paths
 }
 
 func NewJavaBase(base *javaBase, module JavaModuleType, hod common.HostOrDeviceSupported,
@@ -217,35 +215,35 @@
 	return deps
 }
 
-func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess string,
-	aidlIncludeDirs []string) []string {
+func (j *javaBase) aidlFlags(ctx common.AndroidModuleContext, aidlPreprocess common.OptionalPath,
+	aidlIncludeDirs common.Paths) []string {
 
-	localAidlIncludes := pathtools.PrefixPaths(j.properties.Aidl_includes, common.ModuleSrcDir(ctx))
+	localAidlIncludes := common.PathsForModuleSrc(ctx, j.properties.Aidl_includes)
 
 	var flags []string
-	if aidlPreprocess != "" {
-		flags = append(flags, "-p"+aidlPreprocess)
+	if aidlPreprocess.Valid() {
+		flags = append(flags, "-p"+aidlPreprocess.String())
 	} else {
-		flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs, "-I"))
+		flags = append(flags, common.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
 	}
 
-	flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs, "-I"))
-	flags = append(flags, common.JoinWithPrefix(localAidlIncludes, "-I"))
-	flags = append(flags, "-I"+common.ModuleSrcDir(ctx))
-	flags = append(flags, "-I"+filepath.Join(common.ModuleSrcDir(ctx), "src"))
+	flags = append(flags, common.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
+	flags = append(flags, common.JoinWithPrefix(localAidlIncludes.Strings(), "-I"))
+	flags = append(flags, "-I"+common.PathForModuleSrc(ctx).String())
+	flags = append(flags, "-I"+common.PathForModuleSrc(ctx, "src").String())
 
 	return flags
 }
 
-func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath []string,
-	bootClasspath string, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess string,
-	aidlIncludeDirs []string, srcFileLists []string) {
+func (j *javaBase) collectDeps(ctx common.AndroidModuleContext) (classpath common.Paths,
+	bootClasspath common.OptionalPath, classJarSpecs, resourceJarSpecs []jarSpec, aidlPreprocess common.OptionalPath,
+	aidlIncludeDirs common.Paths, srcFileLists common.Paths) {
 
 	ctx.VisitDirectDeps(func(module blueprint.Module) {
 		otherName := ctx.OtherModuleName(module)
 		if javaDep, ok := module.(JavaDependency); ok {
 			if otherName == j.BootClasspath(ctx) {
-				bootClasspath = javaDep.ClasspathFile()
+				bootClasspath = common.OptionalPathForPath(javaDep.ClasspathFile())
 			} else if inList(otherName, defaultJavaLibraries) {
 				classpath = append(classpath, javaDep.ClasspathFile())
 			} else if inList(otherName, j.properties.Java_libs) {
@@ -265,8 +263,8 @@
 			}
 			aidlIncludeDirs = append(aidlIncludeDirs, javaDep.AidlIncludeDirs()...)
 			if sdkDep, ok := module.(sdkDependency); ok {
-				if sdkDep.AidlPreprocessed() != "" {
-					if aidlPreprocess != "" {
+				if sdkDep.AidlPreprocessed().Valid() {
+					if aidlPreprocess.Valid() {
 						ctx.ModuleErrorf("multiple dependencies with preprocessed aidls:\n %q\n %q",
 							aidlPreprocess, sdkDep.AidlPreprocessed())
 					} else {
@@ -287,8 +285,7 @@
 
 func (j *javaBase) GenerateJavaBuildActions(ctx common.AndroidModuleContext) {
 
-	j.exportAidlIncludeDirs = pathtools.PrefixPaths(j.properties.Export_aidl_include_dirs,
-		common.ModuleSrcDir(ctx))
+	j.exportAidlIncludeDirs = common.PathsForModuleSrc(ctx, j.properties.Export_aidl_include_dirs)
 
 	classpath, bootClasspath, classJarSpecs, resourceJarSpecs, aidlPreprocess,
 		aidlIncludeDirs, srcFileLists := j.collectDeps(ctx)
@@ -307,15 +304,15 @@
 		flags.aidlFlags = "$aidlFlags"
 	}
 
-	var javacDeps []string
+	var javacDeps common.Paths
 
-	if bootClasspath != "" {
-		flags.bootClasspath = "-bootclasspath " + bootClasspath
-		javacDeps = append(javacDeps, bootClasspath)
+	if bootClasspath.Valid() {
+		flags.bootClasspath = "-bootclasspath " + bootClasspath.String()
+		javacDeps = append(javacDeps, bootClasspath.Path())
 	}
 
 	if len(classpath) > 0 {
-		flags.classpath = "-classpath " + strings.Join(classpath, ":")
+		flags.classpath = "-classpath " + strings.Join(classpath.Strings(), ":")
 		javacDeps = append(javacDeps, classpath...)
 	}
 
@@ -344,10 +341,7 @@
 	resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs),
 		resourceJarSpecs...)
 
-	manifest := j.properties.Manifest
-	if manifest != "" {
-		manifest = filepath.Join(common.ModuleSrcDir(ctx), manifest)
-	}
+	manifest := common.OptionalPathForModuleSrc(ctx, j.properties.Manifest)
 
 	allJarSpecs := append([]jarSpec(nil), classJarSpecs...)
 	allJarSpecs = append(allJarSpecs, resourceJarSpecs...)
@@ -358,8 +352,8 @@
 		return
 	}
 
-	if j.properties.Jarjar_rules != "" {
-		jarjar_rules := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Jarjar_rules)
+	if j.properties.Jarjar_rules != nil {
+		jarjar_rules := common.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
 		// Transform classes-full-debug.jar into classes-jarjar.jar
 		outputFile = TransformJarJar(ctx, outputFile, jarjar_rules)
 		if ctx.Failed() {
@@ -394,7 +388,7 @@
 			dxFlags = append(dxFlags,
 				"--debug",
 				"--verbose",
-				"--dump-to="+filepath.Join(common.ModuleOutDir(ctx), "classes.lst"),
+				"--dump-to="+common.PathForModuleOut(ctx, "classes.lst").String(),
 				"--dump-width=1000")
 		}
 
@@ -415,7 +409,7 @@
 
 var _ JavaDependency = (*JavaLibrary)(nil)
 
-func (j *javaBase) ClasspathFile() string {
+func (j *javaBase) ClasspathFile() common.Path {
 	return j.classpathFile
 }
 
@@ -427,13 +421,13 @@
 	return j.resourceJarSpecs
 }
 
-func (j *javaBase) AidlIncludeDirs() []string {
+func (j *javaBase) AidlIncludeDirs() common.Paths {
 	return j.exportAidlIncludeDirs
 }
 
 var _ logtagsProducer = (*javaBase)(nil)
 
-func (j *javaBase) logtags() []string {
+func (j *javaBase) logtags() common.Paths {
 	return j.logtagsSrcs
 }
 
@@ -485,7 +479,7 @@
 
 	// Depend on the installed jar (j.installFile) so that the wrapper doesn't get executed by
 	// another build rule before the jar has been installed.
-	ctx.InstallFile("bin", filepath.Join(common.ModuleSrcDir(ctx), j.binaryProperties.Wrapper),
+	ctx.InstallFile("bin", common.PathForModuleSrc(ctx, j.binaryProperties.Wrapper),
 		j.installFile)
 }
 
@@ -516,7 +510,7 @@
 
 	properties javaPrebuiltProperties
 
-	classpathFile                   string
+	classpathFile                   common.Path
 	classJarSpecs, resourceJarSpecs []jarSpec
 }
 
@@ -525,7 +519,7 @@
 		ctx.ModuleErrorf("expected exactly one jar in srcs")
 		return
 	}
-	prebuilt := filepath.Join(common.ModuleSrcDir(ctx), j.properties.Srcs[0])
+	prebuilt := common.PathForModuleSrc(ctx, j.properties.Srcs[0])
 
 	classJarSpec, resourceJarSpec := TransformPrebuiltJarToClasses(ctx, prebuilt)
 
@@ -537,7 +531,7 @@
 
 var _ JavaDependency = (*JavaPrebuilt)(nil)
 
-func (j *JavaPrebuilt) ClasspathFile() string {
+func (j *JavaPrebuilt) ClasspathFile() common.Path {
 	return j.classpathFile
 }
 
@@ -549,7 +543,7 @@
 	return j.resourceJarSpecs
 }
 
-func (j *JavaPrebuilt) AidlIncludeDirs() []string {
+func (j *JavaPrebuilt) AidlIncludeDirs() common.Paths {
 	return nil
 }
 
@@ -566,13 +560,13 @@
 
 type sdkDependency interface {
 	JavaDependency
-	AidlPreprocessed() string
+	AidlPreprocessed() common.OptionalPath
 }
 
 var _ sdkDependency = (*sdkPrebuilt)(nil)
 
 type sdkPrebuiltProperties struct {
-	Aidl_preprocessed string
+	Aidl_preprocessed *string
 }
 
 type sdkPrebuilt struct {
@@ -580,18 +574,16 @@
 
 	sdkProperties sdkPrebuiltProperties
 
-	aidlPreprocessed string
+	aidlPreprocessed common.OptionalPath
 }
 
 func (j *sdkPrebuilt) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
 	j.JavaPrebuilt.GenerateAndroidBuildActions(ctx)
 
-	if j.sdkProperties.Aidl_preprocessed != "" {
-		j.aidlPreprocessed = filepath.Join(common.ModuleSrcDir(ctx), j.sdkProperties.Aidl_preprocessed)
-	}
+	j.aidlPreprocessed = common.OptionalPathForModuleSrc(ctx, j.sdkProperties.Aidl_preprocessed)
 }
 
-func (j *sdkPrebuilt) AidlPreprocessed() string {
+func (j *sdkPrebuilt) AidlPreprocessed() common.OptionalPath {
 	return j.aidlPreprocessed
 }