Chromium Code Reviews| Index: tools/gn/setup.cc |
| diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc |
| index d956c0f94ac0339c45941fa0dce63a40dbdfaf96..6a8dbbee9d358a0cfb02b3029d73fc941366dafd 100644 |
| --- a/tools/gn/setup.cc |
| +++ b/tools/gn/setup.cc |
| @@ -7,6 +7,7 @@ |
| #include <stdlib.h> |
| #include <algorithm> |
| +#include <sstream> |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| @@ -133,6 +134,8 @@ void DecrementWorkCount() { |
| // CommonSetup ----------------------------------------------------------------- |
| +const char CommonSetup::kBuildArgFileName[] = "gn.args"; |
|
scottmg
2014/05/01 19:25:02
Should it be .gn extension so that a syntax highli
brettw
2014/05/01 19:46:55
Good idea, I renamed it args.gn
|
| + |
| CommonSetup::CommonSetup() |
| : build_settings_(), |
| loader_(new LoaderImpl(&build_settings_)), |
| @@ -215,7 +218,8 @@ bool CommonSetup::RunPostMessageLoop() { |
| Setup::Setup() |
| : CommonSetup(), |
| empty_settings_(&empty_build_settings_, std::string()), |
| - dotfile_scope_(&empty_settings_) { |
| + dotfile_scope_(&empty_settings_), |
| + fill_arguments_(true) { |
| empty_settings_.set_toolchain_label(Label()); |
| build_settings_.set_item_defined_callback( |
| base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_)); |
| @@ -236,8 +240,8 @@ bool Setup::DoSetup(const std::string& build_dir) { |
| cmdline->HasSwitch(kTracelogSwitch)) |
| EnableTracing(); |
| - if (!FillArguments(*cmdline)) |
| - return false; |
| + ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "DoSetup"); |
| + |
| if (!FillSourceDir(*cmdline)) |
| return false; |
| if (!RunConfigFile()) |
| @@ -246,6 +250,10 @@ bool Setup::DoSetup(const std::string& build_dir) { |
| return false; |
| if (!FillBuildDir(build_dir)) // Must be after FillSourceDir to resolve. |
| return false; |
| + if (fill_arguments_) { |
| + if (!FillArguments(*cmdline)) |
| + return false; |
| + } |
| FillPythonPath(); |
| return true; |
| @@ -262,14 +270,59 @@ Scheduler* Setup::GetScheduler() { |
| return &scheduler_; |
| } |
| +SourceFile Setup::GetBuildArgFile() const { |
| + return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName); |
| +} |
| + |
| bool Setup::FillArguments(const CommandLine& cmdline) { |
| - std::string args = cmdline.GetSwitchValueASCII(kSwitchArgs); |
| - if (args.empty()) |
| - return true; // Nothing to set. |
| + // Add a dependency on the build arguments file. If this changes, we want |
| + // to re-generated the build. |
| + g_scheduler->AddGenDependency(build_settings_.GetFullPath(GetBuildArgFile())); |
| + |
| + // Use the args on the command line if specified, and save them. Do this even |
| + // if the list is empty (this means clear any defaults). |
| + if (cmdline.HasSwitch(kSwitchArgs)) { |
| + if (!FillArgsFromCommandLine(cmdline.GetSwitchValueASCII(kSwitchArgs))) |
| + return false; |
| + SaveArgsToFile(); |
| + return true; |
| + } |
| + |
| + // No command line args given, use the arguments from the build dir (if any). |
| + return FillArgsFromFile(); |
| +} |
| +bool Setup::FillArgsFromCommandLine(const std::string& args) { |
| args_input_file_.reset(new InputFile(SourceFile())); |
| args_input_file_->SetContents(args); |
| - args_input_file_->set_friendly_name("the command-line \"--args\" settings"); |
| + args_input_file_->set_friendly_name("the command-line \"--args\""); |
| + return FillArgsFromArgsInputFile(); |
| +} |
| + |
| +bool Setup::FillArgsFromFile() { |
| + ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Load args file"); |
| + |
| + SourceFile build_arg_source_file = GetBuildArgFile(); |
| + base::FilePath build_arg_file = |
| + build_settings_.GetFullPath(build_arg_source_file); |
| + |
| + std::string contents; |
| + if (!base::ReadFileToString(build_arg_file, &contents)) |
| + return true; // File doesn't exist, continue with default args. |
| + if (contents.empty()) |
| + return true; // Empty file, do nothing. |
| + |
| + args_input_file_.reset(new InputFile(build_arg_source_file)); |
| + args_input_file_->SetContents(contents); |
| + args_input_file_->set_friendly_name( |
| + "build arg file (use \"gn args <out_dir>\" to edit)"); |
| + |
| + setup_trace.Done(); // Only want to count the load as part of the trace. |
| + return FillArgsFromArgsInputFile(); |
| +} |
| + |
| +bool Setup::FillArgsFromArgsInputFile() { |
| + ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Parse args"); |
| Err err; |
| args_tokens_ = Tokenizer::Tokenize(args_input_file_.get(), &err); |
| @@ -298,6 +351,42 @@ bool Setup::FillArguments(const CommandLine& cmdline) { |
| return true; |
| } |
| +bool Setup::SaveArgsToFile() { |
| + ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Save args file"); |
| + |
| + Scope::KeyValueMap args = build_settings_.build_args().GetAllOverrides(); |
| + |
| + std::ostringstream stream; |
| + for (Scope::KeyValueMap::const_iterator i = args.begin(); |
| + i != args.end(); ++i) { |
| + stream << i->first.as_string() << " = " << i->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. |
| + base::FilePath build_arg_file = |
| + build_settings_.GetFullPath(GetBuildArgFile()); |
| + base::CreateDirectory(build_arg_file.DirName()); |
| + |
| + std::string contents = stream.str(); |
| +#if defined(OS_WIN) |
| + // Use Windows lineendings for this file since it will often open in |
| + // Notepad which can't handle Unix ones. |
| + ReplaceSubstringsAfterOffset(&contents, 0, "\n", "\r\n"); |
| +#endif |
| + if (base::WriteFile(build_arg_file, contents.c_str(), contents.size()) == |
| + -1) { |
| + Err(Location(), "Args file could not be written.", |
| + "The file is \"" + FilePathToUTF8(build_arg_file) + |
| + "\"").PrintToStdout(); |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| bool Setup::FillSourceDir(const CommandLine& cmdline) { |
| // Find the .gn file. |
| base::FilePath root_path; |
| @@ -369,6 +458,8 @@ bool Setup::FillBuildDir(const std::string& build_dir) { |
| } |
| void Setup::FillPythonPath() { |
| + // Trace this since it tends to be a bit slow on Windows. |
| + ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path"); |
| #if defined(OS_WIN) |
| // Find Python on the path so we can use the absolute path in the build. |
| const base::char16 kGetPython[] = |