Add exclude_* and remove arch_subtract / "-file"

To align with the current make build system, add exclude_srcs and
exclude_java_resource_dirs. These replace the functionality of
arch_subtract and glob exclusions that use "-file" to exclude a file.

Change-Id: I91c23d5e3c9409f2d9f7921f950153a03a68ad61
diff --git a/androidbp/cmd/soong.go b/androidbp/cmd/soong.go
index ecae5b0..18b8af0 100644
--- a/androidbp/cmd/soong.go
+++ b/androidbp/cmd/soong.go
@@ -23,6 +23,7 @@
 
 	// ==== LIST PROPERTIES ====
 	"srcs":               {"LOCAL_SRC_FILES", bpparser.List},
+	"exclude_srcs":       {"LOCAL_SRC_FILES_EXCLUDE", bpparser.List},
 	"shared_libs":        {"LOCAL_SHARED_LIBRARIES", bpparser.List},
 	"static_libs":        {"LOCAL_STATIC_LIBRARIES", bpparser.List},
 	"whole_static_libs":  {"LOCAL_WHOLE_STATIC_LIBRARIES", bpparser.List},
diff --git a/cc/cc.go b/cc/cc.go
index 1bef029..2cc4ffb 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -154,7 +154,11 @@
 // Properties used to compile all C or C++ modules
 type CCBaseProperties struct {
 	// list of source files used to compile the C/C++ module.  May be .c, .cpp, or .S files.
-	Srcs []string `android:"arch_variant,arch_subtract"`
+	Srcs []string `android:"arch_variant"`
+
+	// list of source files that should not be used to build the C/C++ module.
+	// This is most useful in the arch/multilib variants to remove non-common files
+	Exclude_srcs []string `android:"arch_variant"`
 
 	// list of module-specific flags that will be used for C and C++ compiles.
 	Cflags []string `android:"arch_variant"`
@@ -528,11 +532,11 @@
 
 // Compile a list of source files into objects a specified subdirectory
 func (c *CCBase) customCompileObjs(ctx common.AndroidModuleContext, flags CCFlags,
-	subdir string, srcFiles []string) []string {
+	subdir string, srcFiles, excludes []string) []string {
 
 	buildFlags := ccFlagsToBuilderFlags(flags)
 
-	srcFiles = ctx.ExpandSources(srcFiles)
+	srcFiles = ctx.ExpandSources(srcFiles, excludes)
 	srcFiles, deps := genSources(ctx, srcFiles, buildFlags)
 
 	return TransformSourceToObj(ctx, subdir, srcFiles, buildFlags, deps)
@@ -545,7 +549,7 @@
 		return nil
 	}
 
-	return c.customCompileObjs(ctx, flags, "", c.Properties.Srcs)
+	return c.customCompileObjs(ctx, flags, "", c.Properties.Srcs, c.Properties.Exclude_srcs)
 }
 
 // Compile generated source files from dependencies
@@ -929,6 +933,7 @@
 	BuildShared bool `blueprint:"mutated"`
 	Static      struct {
 		Srcs              []string `android:"arch_variant"`
+		Exclude_srcs      []string `android:"arch_variant"`
 		Cflags            []string `android:"arch_variant"`
 		Whole_static_libs []string `android:"arch_variant"`
 		Static_libs       []string `android:"arch_variant"`
@@ -936,6 +941,7 @@
 	} `android:"arch_variant"`
 	Shared struct {
 		Srcs              []string `android:"arch_variant"`
+		Exclude_srcs      []string `android:"arch_variant"`
 		Cflags            []string `android:"arch_variant"`
 		Whole_static_libs []string `android:"arch_variant"`
 		Static_libs       []string `android:"arch_variant"`
@@ -1088,7 +1094,7 @@
 
 	staticFlags := flags
 	objFilesStatic := c.customCompileObjs(ctx, staticFlags, common.DeviceStaticLibrary,
-		c.LibraryProperties.Static.Srcs)
+		c.LibraryProperties.Static.Srcs, c.LibraryProperties.Static.Exclude_srcs)
 
 	objFiles = append(objFiles, objFilesStatic...)
 	objFiles = append(objFiles, deps.WholeStaticLibObjFiles...)
@@ -1116,7 +1122,7 @@
 
 	sharedFlags := flags
 	objFilesShared := c.customCompileObjs(ctx, sharedFlags, common.DeviceSharedLibrary,
-		c.LibraryProperties.Shared.Srcs)
+		c.LibraryProperties.Shared.Srcs, c.LibraryProperties.Shared.Exclude_srcs)
 
 	objFiles = append(objFiles, objFilesShared...)
 
diff --git a/common/arch.go b/common/arch.go
index ba1f671..60a17e4 100644
--- a/common/arch.go
+++ b/common/arch.go
@@ -628,12 +628,7 @@
 				dstFieldValue, srcFieldValue,
 				newRecursePrefix)
 		case reflect.Slice:
-			val, err := archCombineSlices(dstFieldValue, srcFieldValue, tags["arch_subtract"])
-			if err != nil {
-				ctx.PropertyErrorf(propertyName, err.Error())
-				continue
-			}
-			dstFieldValue.Set(val)
+			dstFieldValue.Set(reflect.AppendSlice(dstFieldValue, srcFieldValue))
 		case reflect.Ptr, reflect.Interface:
 			// Recursively extend the pointed-to struct's fields.
 			if dstFieldValue.IsNil() != srcFieldValue.IsNil() {
@@ -654,38 +649,3 @@
 		}
 	}
 }
-
-func archCombineSlices(general, arch reflect.Value, canSubtract bool) (reflect.Value, error) {
-	if !canSubtract {
-		// Append the extension slice.
-		return reflect.AppendSlice(general, arch), nil
-	}
-
-	// Support -val in arch list to subtract a value from original list
-	l := general.Interface().([]string)
-	for archIndex := 0; archIndex < arch.Len(); archIndex++ {
-		archString := arch.Index(archIndex).String()
-		if strings.HasPrefix(archString, "-") {
-			generalIndex := findStringInSlice(archString[1:], l)
-			if generalIndex == -1 {
-				return reflect.Value{},
-					fmt.Errorf("can't find %q to subtract from general properties", archString[1:])
-			}
-			l = append(l[:generalIndex], l[generalIndex+1:]...)
-		} else {
-			l = append(l, archString)
-		}
-	}
-
-	return reflect.ValueOf(l), nil
-}
-
-func findStringInSlice(str string, slice []string) int {
-	for i, s := range slice {
-		if s == str {
-			return i
-		}
-	}
-
-	return -1
-}
diff --git a/common/module.go b/common/module.go
index 77e0295..1d17de1 100644
--- a/common/module.go
+++ b/common/module.go
@@ -53,7 +53,7 @@
 	blueprint.ModuleContext
 	androidBaseContext
 
-	ExpandSources(srcFiles []string) []string
+	ExpandSources(srcFiles, excludes []string) []string
 	Glob(globPattern string, excludes []string) []string
 
 	InstallFile(installPath, srcPath string, deps ...string) string
@@ -472,32 +472,37 @@
 	return ok
 }
 
-func (ctx *androidModuleContext) ExpandSources(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)
+func findStringInSlice(str string, slice []string) int {
+	for i, s := range slice {
+		if s == str {
+			return i
 		}
 	}
+	return -1
+}
+
+func (ctx *androidModuleContext) ExpandSources(srcFiles, excludes []string) []string {
+	prefix := ModuleSrcDir(ctx)
+	for i, e := range excludes {
+		j := findStringInSlice(e, srcFiles)
+		if j != -1 {
+			srcFiles = append(srcFiles[:j], srcFiles[j+1:]...)
+		}
+
+		excludes[i] = filepath.Join(prefix, e)
+	}
+
+	for i, srcFile := range srcFiles {
+		srcFiles[i] = filepath.Join(prefix, srcFile)
+	}
 
 	if !hasGlob(srcFiles) {
 		return srcFiles
 	}
 
-	var excludes []string
-	for _, s := range srcFiles {
-		if s[0] == '-' {
-			excludes = append(excludes, s[1:])
-		}
-	}
-
 	globbedSrcFiles := make([]string, 0, len(srcFiles))
 	for _, s := range srcFiles {
-		if s[0] == '-' {
-			continue
-		} else if glob.IsGlob(s) {
+		if glob.IsGlob(s) {
 			globbedSrcFiles = append(globbedSrcFiles, ctx.Glob(s, excludes)...)
 		} else {
 			globbedSrcFiles = append(globbedSrcFiles, s)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index b393831..2052dfd 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -134,7 +134,7 @@
 	properties := &genSrcsProperties{}
 
 	tasks := func(ctx common.AndroidModuleContext) []generateTask {
-		srcFiles := ctx.ExpandSources(properties.Srcs)
+		srcFiles := ctx.ExpandSources(properties.Srcs, nil)
 		tasks := make([]generateTask, 0, len(srcFiles))
 		for _, in := range srcFiles {
 			out := pathtools.ReplaceExtension(in, properties.Output_extension)
@@ -161,7 +161,7 @@
 	tasks := func(ctx common.AndroidModuleContext) []generateTask {
 		return []generateTask{
 			{
-				in:  ctx.ExpandSources(properties.Srcs),
+				in:  ctx.ExpandSources(properties.Srcs, nil),
 				out: filepath.Join(common.ModuleGenDir(ctx), properties.Out),
 			},
 		}
diff --git a/java/java.go b/java/java.go
index a16d1d6..94f6914 100644
--- a/java/java.go
+++ b/java/java.go
@@ -47,11 +47,18 @@
 type javaBaseProperties struct {
 	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
 	// or .aidl files.
-	Srcs []string `android:"arch_variant,arch_subtract"`
+	Srcs []string `android:"arch_variant"`
+
+	// list of source files that should not be used to build the Java module.
+	// This is most useful in the arch/multilib variants to remove non-common files
+	Exclude_srcs []string `android:"arch_variant"`
 
 	// list of directories containing Java resources
 	Java_resource_dirs []string `android:"arch_variant"`
 
+	// list of directories that should be excluded from java_resource_dirs
+	Exclude_java_resource_dirs []string `android:"arch_variant"`
+
 	// don't build against the default libraries (core-libart, core-junit,
 	// ext, and framework for device targets)
 	No_standard_libraries bool
@@ -294,7 +301,7 @@
 		javacDeps = append(javacDeps, classpath...)
 	}
 
-	srcFiles := ctx.ExpandSources(j.properties.Srcs)
+	srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
 
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
@@ -316,7 +323,7 @@
 		classJarSpecs = append([]jarSpec{classes}, classJarSpecs...)
 	}
 
-	resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs),
+	resourceJarSpecs = append(ResourceDirsToJarSpecs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs),
 		resourceJarSpecs...)
 
 	manifest := j.properties.Manifest
diff --git a/java/resources.go b/java/resources.go
index f9d7a05..dfdbeb5 100644
--- a/java/resources.go
+++ b/java/resources.go
@@ -29,13 +29,20 @@
 	"**/*~",
 }
 
-func ResourceDirsToJarSpecs(ctx common.AndroidModuleContext, resourceDirs []string) []jarSpec {
+func isStringInSlice(str string, slice []string) bool {
+	for _, s := range slice {
+		if s == str {
+			return true
+		}
+	}
+	return false
+}
+
+func ResourceDirsToJarSpecs(ctx common.AndroidModuleContext, resourceDirs, excludeDirs []string) []jarSpec {
 	var excludes []string
 
-	for _, resourceDir := range resourceDirs {
-		if resourceDir[0] == '-' {
-			excludes = append(excludes, filepath.Join(common.ModuleSrcDir(ctx), resourceDir[1:], "**/*"))
-		}
+	for _, exclude := range excludeDirs {
+		excludes = append(excludes, filepath.Join(common.ModuleSrcDir(ctx), exclude, "**/*"))
 	}
 
 	excludes = append(excludes, resourceExcludes...)
@@ -43,7 +50,7 @@
 	var jarSpecs []jarSpec
 
 	for _, resourceDir := range resourceDirs {
-		if resourceDir[0] == '-' {
+		if isStringInSlice(resourceDir, excludeDirs) {
 			continue
 		}
 		resourceDir := filepath.Join(common.ModuleSrcDir(ctx), resourceDir)