Support subtracting sources from globs

Support -file or -path/glob in file lists that contain globs to
subtract files from the resulting glob.  Also move source file
prefixing and handling into a common function.

Change-Id: Ib6d74ce22f53cae7348c4ba35b779976d90359a6
diff --git a/cc/cc.go b/cc/cc.go
index a5af73e..f634697 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -525,8 +525,7 @@
 
 	buildFlags := ccFlagsToBuilderFlags(flags)
 
-	srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx))
-	srcFiles = common.ExpandGlobs(ctx, srcFiles)
+	srcFiles = common.ExpandSources(ctx, srcFiles)
 	srcFiles, deps := genSources(ctx, srcFiles, buildFlags)
 
 	return TransformSourceToObj(ctx, subdir, srcFiles, buildFlags, deps)
diff --git a/common/glob.go b/common/glob.go
index a3cfab2..7bb623d 100644
--- a/common/glob.go
+++ b/common/glob.go
@@ -68,16 +68,23 @@
 	return false
 }
 
-func ExpandGlobs(ctx AndroidModuleContext, in []string) []string {
+func expandGlobs(ctx AndroidModuleContext, in []string) []string {
 	if !hasGlob(in) {
 		return in
 	}
 
+	var excludes []string
+	for _, s := range in {
+		if s[0] == '-' {
+			excludes = append(excludes, s[1:])
+		}
+	}
+
 	out := make([]string, 0, len(in))
 	for _, s := range in {
 		if glob.IsGlob(s) {
-			out = append(out, Glob(ctx, s)...)
-		} else {
+			out = append(out, Glob(ctx, s, excludes)...)
+		} else if s[0] != '-' {
 			out = append(out, s)
 		}
 	}
@@ -85,12 +92,10 @@
 	return out
 }
 
-func Glob(ctx AndroidModuleContext, globPattern string) []string {
+func Glob(ctx AndroidModuleContext, globPattern string, excludes []string) []string {
 	fileListFile := filepath.Join(ModuleOutDir(ctx), "glob", globToString(globPattern))
 	depFile := fileListFile + ".d"
 
-	var excludes []string
-
 	// Get a globbed file list, and write out fileListFile and depFile
 	files, err := glob.GlobWithDepFile(globPattern, fileListFile, depFile, excludes)
 	if err != nil {
diff --git a/common/module.go b/common/module.go
index d497076..bafb583 100644
--- a/common/module.go
+++ b/common/module.go
@@ -432,3 +432,17 @@
 	_, ok := m.(AndroidModule)
 	return ok
 }
+
+func ExpandSources(ctx AndroidModuleContext, srcFiles []string) []string {
+	prefix := ModuleSrcDir(ctx)
+	for i, srcFile := range srcFiles {
+		if srcFile[0] == '-' {
+			srcFiles[i] = "-" + filepath.Join(prefix, srcFile[1:])
+		} else {
+			srcFiles[i] = filepath.Join(prefix, srcFile)
+		}
+	}
+
+	srcFiles = expandGlobs(ctx, srcFiles)
+	return srcFiles
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 589758d..1361631 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -67,9 +67,7 @@
 		Command: g.properties.Cmd,
 	})
 
-	srcFiles := g.properties.Srcs
-	srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx))
-	srcFiles = common.ExpandGlobs(ctx, srcFiles)
+	srcFiles := common.ExpandSources(ctx, g.properties.Srcs)
 
 	g.outputFiles = make([]string, 0, len(srcFiles))
 
diff --git a/glob/glob.go b/glob/glob.go
index a8c348d..a07501a 100644
--- a/glob/glob.go
+++ b/glob/glob.go
@@ -65,7 +65,12 @@
 				}
 				if match {
 					for _, e := range excludes {
-						excludeMatch, err := filepath.Match(e, info.Name())
+						var excludeMatch bool
+						if filepath.Base(e) == e {
+							excludeMatch, err = filepath.Match(e, info.Name())
+						} else {
+							excludeMatch, err = filepath.Match(e, path)
+						}
 						if err != nil {
 							return err
 						}
diff --git a/java/java.go b/java/java.go
index 8750dbf..c604186 100644
--- a/java/java.go
+++ b/java/java.go
@@ -24,7 +24,6 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 
 	"android/soong/common"
 )
@@ -193,9 +192,7 @@
 
 	var javacDeps []string
 
-	srcFiles := j.properties.Srcs
-	srcFiles = pathtools.PrefixPaths(srcFiles, common.ModuleSrcDir(ctx))
-	srcFiles = common.ExpandGlobs(ctx, srcFiles)
+	srcFiles := common.ExpandSources(ctx, j.properties.Srcs)
 
 	classpath, bootClasspath, classJarSpecs, resourceJarSpecs := j.collectDeps(ctx)