gn: make gn gen preserve import statements passed in --args

Previously, gn gen would expand all imports and only record the final
arg keyvalue pairs in args.gn, if called as gn gen --args='import...'.

Now the actual import statement will be recorded. This allows avoiding
a manual args.gn edit of you want an actual import statement there, for
example if the imported gni houses a predefined set of default args
that you want to follow, and want to re-gn when it changes.

R=brettw@chromium.org,dpranke@chromium.org
BUG=588513

Review-Url: https://codereview.chromium.org/2250623004
Cr-Original-Commit-Position: refs/heads/master@{#412687}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 9f58d6d943aa2c6bd32be6dbe85a130b8c75efe5
diff --git a/tools/gn/command_format.cc b/tools/gn/command_format.cc
index 3106b2c..dafba6e 100644
--- a/tools/gn/command_format.cc
+++ b/tools/gn/command_format.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "tools/gn/command_format.h"
+
 #include <stddef.h>
 
 #include <sstream>
diff --git a/tools/gn/command_format.h b/tools/gn/command_format.h
new file mode 100644
index 0000000..97c3e4c
--- /dev/null
+++ b/tools/gn/command_format.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_COMAND_FORMAT_H_
+#define TOOLS_GN_COMAND_FORMAT_H_
+
+#include <string>
+
+class Setup;
+class SourceFile;
+
+namespace commands {
+
+bool FormatFileToString(Setup* setup,
+                        const SourceFile& file,
+                        bool dump_tree,
+                        std::string* output);
+
+bool FormatStringToString(const std::string& input,
+                          bool dump_tree,
+                          std::string* output);
+
+}  // namespace commands
+
+#endif  // TOOLS_GN_COMAND_FORMAT_H_
+
diff --git a/tools/gn/command_format_unittest.cc b/tools/gn/command_format_unittest.cc
index d753b33..802dfbd 100644
--- a/tools/gn/command_format_unittest.cc
+++ b/tools/gn/command_format_unittest.cc
@@ -6,16 +6,10 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/command_format.h"
 #include "tools/gn/commands.h"
 #include "tools/gn/setup.h"
 
-namespace commands {
-bool FormatFileToString(Setup* setup,
-                        const SourceFile& file,
-                        bool dump_tree,
-                        std::string* output);
-}  // namespace commands
-
 #define FORMAT_TEST(n)                                                      \
   TEST(Format, n) {                                                         \
     ::Setup setup;                                                          \
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc
index 490204d..240c11f 100644
--- a/tools/gn/setup.cc
+++ b/tools/gn/setup.cc
@@ -21,6 +21,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "tools/gn/command_format.h"
 #include "tools/gn/commands.h"
 #include "tools/gn/filesystem_utils.h"
 #include "tools/gn/input_file.h"
@@ -261,6 +262,7 @@
       dotfile_scope_(&dotfile_settings_),
       fill_arguments_(true) {
   dotfile_settings_.set_toolchain_label(Label());
+
   build_settings_.set_item_defined_callback(
       base::Bind(&ItemDefinedCallback, scheduler_.task_runner(), &builder_));
 
@@ -440,6 +442,10 @@
   }
 
   Scope arg_scope(&dotfile_settings_);
+  // Set soure dir so relative imports in args work.
+  SourceDir root_source_dir =
+      SourceDirForCurrentDirectory(build_settings_.root_path());
+  arg_scope.set_source_dir(root_source_dir);
   args_root_->Execute(&arg_scope, &err);
   if (err.has_error()) {
     err.PrintToStdout();
@@ -456,12 +462,6 @@
 bool Setup::SaveArgsToFile() {
   ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Save args file");
 
-  std::ostringstream stream;
-  for (const auto& pair : build_settings_.build_args().GetAllOverrides()) {
-    stream << pair.first.as_string() << " = " << pair.second.ToString(true);
-    stream << std::endl;
-  }
-
   // For the first run, the build output dir might not be created yet, so do
   // that so we can write a file into it. Ignore errors, we'll catch the error
   // when we try to write a file to it below.
@@ -469,7 +469,8 @@
       build_settings_.GetFullPath(GetBuildArgFile());
   base::CreateDirectory(build_arg_file.DirName());
 
-  std::string contents = stream.str();
+  std::string contents = args_input_file_->contents();
+  commands::FormatStringToString(contents, false, &contents);
 #if defined(OS_WIN)
   // Use Windows lineendings for this file since it will often open in
   // Notepad which can't handle Unix ones.