Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: tools/gn/setup.cc

Issue 265693003: Redo GN "args" command (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: windows Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/setup.h" 5 #include "tools/gn/setup.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <sstream>
10 11
11 #include "base/bind.h" 12 #include "base/bind.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/file_util.h" 14 #include "base/file_util.h"
14 #include "base/files/file_path.h" 15 #include "base/files/file_path.h"
15 #include "base/process/launch.h" 16 #include "base/process/launch.h"
16 #include "base/strings/string_split.h" 17 #include "base/strings/string_split.h"
17 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
19 #include "build/build_config.h" 20 #include "build/build_config.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 } 127 }
127 128
128 void DecrementWorkCount() { 129 void DecrementWorkCount() {
129 g_scheduler->DecrementWorkCount(); 130 g_scheduler->DecrementWorkCount();
130 } 131 }
131 132
132 } // namespace 133 } // namespace
133 134
134 // CommonSetup ----------------------------------------------------------------- 135 // CommonSetup -----------------------------------------------------------------
135 136
137 const char CommonSetup::kBuildArgFileName[] = "gn.args";
138
136 CommonSetup::CommonSetup() 139 CommonSetup::CommonSetup()
137 : build_settings_(), 140 : build_settings_(),
138 loader_(new LoaderImpl(&build_settings_)), 141 loader_(new LoaderImpl(&build_settings_)),
139 builder_(new Builder(loader_.get())), 142 builder_(new Builder(loader_.get())),
140 root_build_file_("//BUILD.gn"), 143 root_build_file_("//BUILD.gn"),
141 check_for_bad_items_(true), 144 check_for_bad_items_(true),
142 check_for_unused_overrides_(true), 145 check_for_unused_overrides_(true),
143 check_public_headers_(false) { 146 check_public_headers_(false) {
144 loader_->set_complete_callback(base::Bind(&DecrementWorkCount)); 147 loader_->set_complete_callback(base::Bind(&DecrementWorkCount));
145 } 148 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 SaveTraces(cmdline->GetSwitchValuePath(kTracelogSwitch)); 211 SaveTraces(cmdline->GetSwitchValuePath(kTracelogSwitch));
209 212
210 return true; 213 return true;
211 } 214 }
212 215
213 // Setup ----------------------------------------------------------------------- 216 // Setup -----------------------------------------------------------------------
214 217
215 Setup::Setup() 218 Setup::Setup()
216 : CommonSetup(), 219 : CommonSetup(),
217 empty_settings_(&empty_build_settings_, std::string()), 220 empty_settings_(&empty_build_settings_, std::string()),
218 dotfile_scope_(&empty_settings_) { 221 dotfile_scope_(&empty_settings_),
222 fill_arguments_(true) {
219 empty_settings_.set_toolchain_label(Label()); 223 empty_settings_.set_toolchain_label(Label());
220 build_settings_.set_item_defined_callback( 224 build_settings_.set_item_defined_callback(
221 base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_)); 225 base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_));
222 226
223 // The scheduler's main loop wasn't created when the Loader was created, so 227 // The scheduler's main loop wasn't created when the Loader was created, so
224 // we need to set it now. 228 // we need to set it now.
225 loader_->set_main_loop(scheduler_.main_loop()); 229 loader_->set_main_loop(scheduler_.main_loop());
226 } 230 }
227 231
228 Setup::~Setup() { 232 Setup::~Setup() {
229 } 233 }
230 234
231 bool Setup::DoSetup(const std::string& build_dir) { 235 bool Setup::DoSetup(const std::string& build_dir) {
232 CommandLine* cmdline = CommandLine::ForCurrentProcess(); 236 CommandLine* cmdline = CommandLine::ForCurrentProcess();
233 237
234 scheduler_.set_verbose_logging(cmdline->HasSwitch(kSwitchVerbose)); 238 scheduler_.set_verbose_logging(cmdline->HasSwitch(kSwitchVerbose));
235 if (cmdline->HasSwitch(kTimeSwitch) || 239 if (cmdline->HasSwitch(kTimeSwitch) ||
236 cmdline->HasSwitch(kTracelogSwitch)) 240 cmdline->HasSwitch(kTracelogSwitch))
237 EnableTracing(); 241 EnableTracing();
238 242
239 if (!FillArguments(*cmdline)) 243 ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "DoSetup");
240 return false; 244
241 if (!FillSourceDir(*cmdline)) 245 if (!FillSourceDir(*cmdline))
242 return false; 246 return false;
243 if (!RunConfigFile()) 247 if (!RunConfigFile())
244 return false; 248 return false;
245 if (!FillOtherConfig(*cmdline)) 249 if (!FillOtherConfig(*cmdline))
246 return false; 250 return false;
247 if (!FillBuildDir(build_dir)) // Must be after FillSourceDir to resolve. 251 if (!FillBuildDir(build_dir)) // Must be after FillSourceDir to resolve.
248 return false; 252 return false;
253 if (fill_arguments_) {
254 if (!FillArguments(*cmdline))
255 return false;
256 }
249 FillPythonPath(); 257 FillPythonPath();
250 258
251 return true; 259 return true;
252 } 260 }
253 261
254 bool Setup::Run() { 262 bool Setup::Run() {
255 RunPreMessageLoop(); 263 RunPreMessageLoop();
256 if (!scheduler_.Run()) 264 if (!scheduler_.Run())
257 return false; 265 return false;
258 return RunPostMessageLoop(); 266 return RunPostMessageLoop();
259 } 267 }
260 268
261 Scheduler* Setup::GetScheduler() { 269 Scheduler* Setup::GetScheduler() {
262 return &scheduler_; 270 return &scheduler_;
263 } 271 }
264 272
273 SourceFile Setup::GetBuildArgFile() const {
274 return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName);
275 }
276
265 bool Setup::FillArguments(const CommandLine& cmdline) { 277 bool Setup::FillArguments(const CommandLine& cmdline) {
266 std::string args = cmdline.GetSwitchValueASCII(kSwitchArgs); 278 // Add a dependency on the build arguments file. If this changes, we want
267 if (args.empty()) 279 // to re-generated the build.
268 return true; // Nothing to set. 280 g_scheduler->AddGenDependency(build_settings_.GetFullPath(GetBuildArgFile()));
269 281
282 // Use the args on the command line if specified, and save them. Do this even
283 // if the list is empty (this means clear any defaults).
284 if (cmdline.HasSwitch(kSwitchArgs)) {
285 if (!FillArgsFromCommandLine(cmdline.GetSwitchValueASCII(kSwitchArgs)))
286 return false;
287 SaveArgsToFile();
288 return true;
289 }
290
291 // No command line args given, use the arguments from the build dir (if any).
292 return FillArgsFromFile();
293 }
294
295 bool Setup::FillArgsFromCommandLine(const std::string& args) {
270 args_input_file_.reset(new InputFile(SourceFile())); 296 args_input_file_.reset(new InputFile(SourceFile()));
271 args_input_file_->SetContents(args); 297 args_input_file_->SetContents(args);
272 args_input_file_->set_friendly_name("the command-line \"--args\" settings"); 298 args_input_file_->set_friendly_name("the command-line \"--args\"");
299 return FillArgsFromArgsInputFile();
300 }
301
302 bool Setup::FillArgsFromFile() {
303 ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Load args file");
304
305 SourceFile build_arg_source_file = GetBuildArgFile();
306 base::FilePath build_arg_file =
307 build_settings_.GetFullPath(build_arg_source_file);
308
309 std::string contents;
310 if (!base::ReadFileToString(build_arg_file, &contents))
311 return true; // File doesn't exist, continue with default args.
312 if (contents.empty())
313 return true; // Empty file, do nothing.
314
315 args_input_file_.reset(new InputFile(build_arg_source_file));
316 args_input_file_->SetContents(contents);
317 args_input_file_->set_friendly_name(
318 "build arg file (use \"gn args <out_dir>\" to edit)");
319
320 setup_trace.Done(); // Only want to count the load as part of the trace.
321 return FillArgsFromArgsInputFile();
322 }
323
324 bool Setup::FillArgsFromArgsInputFile() {
325 ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Parse args");
273 326
274 Err err; 327 Err err;
275 args_tokens_ = Tokenizer::Tokenize(args_input_file_.get(), &err); 328 args_tokens_ = Tokenizer::Tokenize(args_input_file_.get(), &err);
276 if (err.has_error()) { 329 if (err.has_error()) {
277 err.PrintToStdout(); 330 err.PrintToStdout();
278 return false; 331 return false;
279 } 332 }
280 333
281 args_root_ = Parser::Parse(args_tokens_, &err); 334 args_root_ = Parser::Parse(args_tokens_, &err);
282 if (err.has_error()) { 335 if (err.has_error()) {
283 err.PrintToStdout(); 336 err.PrintToStdout();
284 return false; 337 return false;
285 } 338 }
286 339
287 Scope arg_scope(&empty_settings_); 340 Scope arg_scope(&empty_settings_);
288 args_root_->AsBlock()->ExecuteBlockInScope(&arg_scope, &err); 341 args_root_->AsBlock()->ExecuteBlockInScope(&arg_scope, &err);
289 if (err.has_error()) { 342 if (err.has_error()) {
290 err.PrintToStdout(); 343 err.PrintToStdout();
291 return false; 344 return false;
292 } 345 }
293 346
294 // Save the result of the command args. 347 // Save the result of the command args.
295 Scope::KeyValueMap overrides; 348 Scope::KeyValueMap overrides;
296 arg_scope.GetCurrentScopeValues(&overrides); 349 arg_scope.GetCurrentScopeValues(&overrides);
297 build_settings_.build_args().AddArgOverrides(overrides); 350 build_settings_.build_args().AddArgOverrides(overrides);
298 return true; 351 return true;
299 } 352 }
300 353
354 bool Setup::SaveArgsToFile() {
355 ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Save args file");
356
357 Scope::KeyValueMap args = build_settings_.build_args().GetAllOverrides();
358
359 std::ostringstream stream;
360 for (Scope::KeyValueMap::const_iterator i = args.begin();
361 i != args.end(); ++i) {
362 stream << i->first.as_string() << " = " << i->second.ToString(true);
363 stream << std::endl;
364 }
365
366 // For the first run, the build output dir might not be created yet, so do
367 // that so we can write a file into it. Ignore errors, we'll catch the error
368 // when we try to write a file to it below.
369 base::FilePath build_arg_file =
370 build_settings_.GetFullPath(GetBuildArgFile());
371 base::CreateDirectory(build_arg_file.DirName());
372
373 std::string contents = stream.str();
374 #if defined(OS_WIN)
375 // Use Windows lineendings for this file since it will often open in
376 // Notepad which can't handle Unix ones.
377 ReplaceSubstringsAfterOffset(&contents, 0, "\n", "\r\n");
378 #endif
379 if (base::WriteFile(build_arg_file, contents.c_str(), contents.size()) ==
380 -1) {
381 Err(Location(), "Args file could not be written.",
382 "The file is \"" + FilePathToUTF8(build_arg_file) +
383 "\"").PrintToStdout();
384 return false;
385 }
386
387 return true;
388 }
389
301 bool Setup::FillSourceDir(const CommandLine& cmdline) { 390 bool Setup::FillSourceDir(const CommandLine& cmdline) {
302 // Find the .gn file. 391 // Find the .gn file.
303 base::FilePath root_path; 392 base::FilePath root_path;
304 393
305 // Prefer the command line args to the config file. 394 // Prefer the command line args to the config file.
306 base::FilePath relative_root_path = cmdline.GetSwitchValuePath(kSwitchRoot); 395 base::FilePath relative_root_path = cmdline.GetSwitchValuePath(kSwitchRoot);
307 if (!relative_root_path.empty()) { 396 if (!relative_root_path.empty()) {
308 root_path = base::MakeAbsoluteFilePath(relative_root_path); 397 root_path = base::MakeAbsoluteFilePath(relative_root_path);
309 if (root_path.empty()) { 398 if (root_path.empty()) {
310 Err(Location(), "Root source path not found.", 399 Err(Location(), "Root source path not found.",
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 return false; 451 return false;
363 } 452 }
364 453
365 if (scheduler_.verbose_logging()) 454 if (scheduler_.verbose_logging())
366 scheduler_.Log("Using build dir", resolved.value()); 455 scheduler_.Log("Using build dir", resolved.value());
367 build_settings_.SetBuildDir(resolved); 456 build_settings_.SetBuildDir(resolved);
368 return true; 457 return true;
369 } 458 }
370 459
371 void Setup::FillPythonPath() { 460 void Setup::FillPythonPath() {
461 // Trace this since it tends to be a bit slow on Windows.
462 ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path");
372 #if defined(OS_WIN) 463 #if defined(OS_WIN)
373 // Find Python on the path so we can use the absolute path in the build. 464 // Find Python on the path so we can use the absolute path in the build.
374 const base::char16 kGetPython[] = 465 const base::char16 kGetPython[] =
375 L"cmd.exe /c python -c \"import sys; print sys.executable\""; 466 L"cmd.exe /c python -c \"import sys; print sys.executable\"";
376 std::string python_path; 467 std::string python_path;
377 if (base::GetAppOutput(kGetPython, &python_path)) { 468 if (base::GetAppOutput(kGetPython, &python_path)) {
378 base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path); 469 base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path);
379 if (scheduler_.verbose_logging()) 470 if (scheduler_.verbose_logging())
380 scheduler_.Log("Found python", python_path); 471 scheduler_.Log("Found python", python_path);
381 } else { 472 } else {
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 } 591 }
501 592
502 void DependentSetup::RunPreMessageLoop() { 593 void DependentSetup::RunPreMessageLoop() {
503 CommonSetup::RunPreMessageLoop(); 594 CommonSetup::RunPreMessageLoop();
504 } 595 }
505 596
506 bool DependentSetup::RunPostMessageLoop() { 597 bool DependentSetup::RunPostMessageLoop() {
507 return CommonSetup::RunPostMessageLoop(); 598 return CommonSetup::RunPostMessageLoop();
508 } 599 }
509 600
OLDNEW
« tools/gn/args.cc ('K') | « tools/gn/setup.h ('k') | tools/gn/trace.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698