Add a command line to define/overwrite "root" in ".gn"

The new command line option "--root-target" will tell GN where to find
the initial BUILD.gn. This is equivalent to define the "root" variable
in ".gn" as before. And after this CL if "root" is also defined in
".gn", this option will overwite the value defined in ".gn".

This is to achieve, to some extend, the "partial configuration"
ability. For example, if we only want to configure and build the
targets in a subfolder of Chromium like "//third_party/icu". We only
need to run

```
gn gen out/icu --root-target="//third_party/icu"
```

The motivation of this feature is to make sharing packages between
Chrome and CrOS much easier.

BUG=chromium:1133101
TEST=It can indeed only configure subfolder of chromium like
TEST="third_party/icu" and "third_party/grpc".
TEST=It can overwrite the "root" variable in ".gn" correctly.

Change-Id: If0742b409a529f34f435c6498de57667fabe7fc1
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/10140
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/setup.cc b/src/gn/setup.cc
index d1ba197..1535276 100644
--- a/src/gn/setup.cc
+++ b/src/gn/setup.cc
@@ -122,6 +122,9 @@
       cause the file //BUILD.gn to be loaded. Note that build_file_extension
       applies to the default case as well.
 
+      The command-line switch --root-target will override this value (see "gn
+      help --root-target").
+
   script_executable [optional]
       Path to specific Python executable or other interpreter to use in
       action targets and exec_script calls. By default GN searches the
@@ -840,17 +843,32 @@
   }
 
   // Root build file.
-  const Value* root_value = dotfile_scope_.GetValue("root", true);
-  if (root_value) {
-    if (!root_value->VerifyTypeIs(Value::STRING, err)) {
-      return false;
-    }
-
+  if (cmdline.HasSwitch(switches::kRootTarget)) {
+    auto switch_value =
+        cmdline.GetSwitchValueASCII(switches::kRootTarget);
+    Value root_value(nullptr, switch_value);
     root_target_label = Label::Resolve(current_dir, std::string_view(), Label(),
-                                       *root_value, err);
+                                       root_value, err);
     if (err->has_error()) {
       return false;
     }
+    if (dotfile_scope_.GetValue("root", true)) {
+      // The "kRootTarget" switch overwrites the "root" variable in ".gn".
+      dotfile_scope_.MarkUsed("root");
+    }
+  } else {
+    const Value* root_value = dotfile_scope_.GetValue("root", true);
+    if (root_value) {
+      if (!root_value->VerifyTypeIs(Value::STRING, err)) {
+        return false;
+      }
+
+      root_target_label = Label::Resolve(current_dir, std::string_view(),
+                                         Label(), *root_value, err);
+      if (err->has_error()) {
+        return false;
+      }
+    }
   }
   // Set the root build file here in order to take into account the values of
   // "build_file_extension" and "root".
diff --git a/src/gn/switches.cc b/src/gn/switches.cc
index 2b42e13..b94bc47 100644
--- a/src/gn/switches.cc
+++ b/src/gn/switches.cc
@@ -60,7 +60,7 @@
 const char kDotfile_Help[] =
     R"(--dotfile: Override the name of the ".gn" file.
 
-  Normally GN loads the ".gn"file  from the source root for some basic
+  Normally GN loads the ".gn" file from the source root for some basic
   configuration (see "gn help dotfile"). This flag allows you to
   use a different file.
 )";
@@ -175,6 +175,37 @@
   gn desc //out/Default --root="C:\Users\BObama\My Documents\foo"
 )";
 
+const char kRootTarget[] = "root-target";
+const char kRootTarget_HelpShort[] =
+    "--root-target: Override the root target.";
+const char kRootTarget_Help[] =
+    R"(--root-target: Override the root target.
+
+  The root target is the target initially loaded to begin population of the
+  build graph. It defaults to "//:" which normally causes the "//BUILD.gn" file
+  to be loaded. It can be specified in the .gn file via the "root" variable (see
+  "gn help dotfile").
+
+  If specified, the value of this switch will be take precedence over the value
+  in ".gn". The target name (after the colon) is ignored, only the directory
+  name is required. Relative paths will be resolved relative to the current "//"
+  directory.
+
+  Specifying a different initial BUILD.gn file does not change the meaning of
+  the source root (the "//" directory) which can be independently set via the
+  --root switch. It also does not prevent the build file located at "//BUILD.gn"
+  from being loaded if a target in the build references that directory.
+
+  One use-case of this feature is to load a different set of initial targets
+  from project that uses GN without modifying any files.
+
+Examples
+
+  gn gen //out/Default --root-target="//third_party/icu"
+
+  gn gen //out/Default --root-target="//third_party/grpc"
+)";
+
 const char kRuntimeDepsListFile[] = "runtime-deps-list-file";
 const char kRuntimeDepsListFile_HelpShort[] =
     "--runtime-deps-list-file: Save runtime dependencies for targets in file.";
@@ -298,6 +329,7 @@
     INSERT_VARIABLE(Markdown)
     INSERT_VARIABLE(NoColor)
     INSERT_VARIABLE(Root)
+    INSERT_VARIABLE(RootTarget)
     INSERT_VARIABLE(Quiet)
     INSERT_VARIABLE(RuntimeDepsListFile)
     INSERT_VARIABLE(ScriptExecutable)
diff --git a/src/gn/switches.h b/src/gn/switches.h
index 69c47b6..2f89e50 100644
--- a/src/gn/switches.h
+++ b/src/gn/switches.h
@@ -74,6 +74,10 @@
 extern const char kRoot_HelpShort[];
 extern const char kRoot_Help[];
 
+extern const char kRootTarget[];
+extern const char kRootTarget_HelpShort[];
+extern const char kRootTarget_Help[];
+
 extern const char kRuntimeDepsListFile[];
 extern const char kRuntimeDepsListFile_HelpShort[];
 extern const char kRuntimeDepsListFile_Help[];