| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |