Merge "soong_ui: Add --build-mode flag in soong_ui"
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index ad9fb24..0356a7e 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -61,10 +61,8 @@
 		config: func(ctx build.Context, args ...string) build.Config {
 			return build.NewConfig(ctx, args...)
 		},
-		stdio: func() terminal.StdioInterface {
-			return terminal.StdioImpl{}
-		},
-		run: make,
+		stdio: stdio,
+		run:   make,
 	}, {
 		flag:        "--dumpvar-mode",
 		description: "print the value of the legacy make variable VAR to stdout",
@@ -77,6 +75,12 @@
 		config:      dumpVarConfig,
 		stdio:       customStdio,
 		run:         dumpVars,
+	}, {
+		flag:        "--build-mode",
+		description: "build modules based on the specified build action",
+		config:      buildActionConfig,
+		stdio:       stdio,
+		run:         make,
 	},
 }
 
@@ -299,6 +303,10 @@
 	}
 }
 
+func stdio() terminal.StdioInterface {
+	return terminal.StdioImpl{}
+}
+
 func customStdio() terminal.StdioInterface {
 	return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
 }
@@ -308,6 +316,88 @@
 	return build.NewConfig(ctx)
 }
 
+func buildActionConfig(ctx build.Context, args ...string) build.Config {
+	flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
+	flags.Usage = func() {
+		fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
+		fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
+		fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
+		fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
+		fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
+		fmt.Fprintln(ctx.Writer, "")
+		flags.PrintDefaults()
+	}
+
+	buildActionFlags := []struct {
+		name              string
+		description       string
+		action            build.BuildAction
+		buildDependencies bool
+		set               bool
+	}{{
+		name:              "all-modules",
+		description:       "Build action: build from the top of the source tree.",
+		action:            build.BUILD_MODULES_IN_A_DIRECTORY,
+		buildDependencies: true,
+	}, {
+		name:              "modules-in-a-dir-no-deps",
+		description:       "Build action: builds all of the modules in the current directory without their dependencies.",
+		action:            build.BUILD_MODULES_IN_A_DIRECTORY,
+		buildDependencies: false,
+	}, {
+		name:              "modules-in-dirs-no-deps",
+		description:       "Build action: builds all of the modules in the supplied directories without their dependencies.",
+		action:            build.BUILD_MODULES_IN_DIRECTORIES,
+		buildDependencies: false,
+	}, {
+		name:              "modules-in-a-dir",
+		description:       "Build action: builds all of the modules in the current directory and their dependencies.",
+		action:            build.BUILD_MODULES_IN_A_DIRECTORY,
+		buildDependencies: true,
+	}, {
+		name:              "modules-in-dirs",
+		description:       "Build action: builds all of the modules in the supplied directories and their dependencies.",
+		action:            build.BUILD_MODULES_IN_DIRECTORIES,
+		buildDependencies: true,
+	}}
+	for i, flag := range buildActionFlags {
+		flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
+	}
+	dir := flags.String("dir", "", "Directory of the executed build command.")
+
+	// Only interested in the first two args which defines the build action and the directory.
+	// The remaining arguments are passed down to the config.
+	const numBuildActionFlags = 2
+	if len(args) < numBuildActionFlags {
+		flags.Usage()
+		ctx.Fatalln("Improper build action arguments.")
+	}
+	flags.Parse(args[0:numBuildActionFlags])
+
+	// The next block of code is to validate that exactly one build action is set and the dir flag
+	// is specified.
+	buildActionCount := 0
+	var buildAction build.BuildAction
+	buildDependency := false
+	for _, flag := range buildActionFlags {
+		if flag.set {
+			buildActionCount++
+			buildAction = flag.action
+			buildDependency = flag.buildDependencies
+		}
+	}
+	if buildActionCount != 1 {
+		ctx.Fatalln("Build action not defined.")
+	}
+	if *dir == "" {
+		ctx.Fatalln("-dir not specified.")
+	}
+
+	// Remove the build action flags from the args as they are not recognized by the config.
+	args = args[numBuildActionFlags:]
+	return build.NewBuildActionConfig(buildAction, *dir, buildDependency, ctx, args...)
+}
+
 func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
 	if config.IsVerbose() {
 		writer := ctx.Writer