| Index: tools/gn/ninja_build_writer.cc | 
| diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..a63765cd3aafadcb7d785d3a53db279a54456b7c | 
| --- /dev/null | 
| +++ b/tools/gn/ninja_build_writer.cc | 
| @@ -0,0 +1,165 @@ | 
| +// Copyright (c) 2013 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. | 
| + | 
| +#include "tools/gn/ninja_build_writer.h" | 
| + | 
| +#include <fstream> | 
| + | 
| +#include "base/command_line.h" | 
| +#include "base/file_util.h" | 
| +#include "base/process/process_handle.h" | 
| +#include "base/strings/utf_string_conversions.h" | 
| +#include "build/build_config.h" | 
| +#include "tools/gn/build_settings.h" | 
| +#include "tools/gn/filesystem_utils.h" | 
| +#include "tools/gn/input_file_manager.h" | 
| +#include "tools/gn/scheduler.h" | 
| +#include "tools/gn/target.h" | 
| + | 
| +#if defined(OS_WIN) | 
| +#include <windows.h> | 
| +#endif | 
| + | 
| +namespace { | 
| + | 
| +std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { | 
| +#if defined(OS_WIN) | 
| +  wchar_t module[MAX_PATH]; | 
| +  GetModuleFileName(NULL, module, MAX_PATH); | 
| +  //result = "\"" + WideToUTF8(module) + "\""; | 
| +  base::FilePath executable(module); | 
| +#elif defined(OS_MACOSX) | 
| +  // FIXME(brettw) write this on Mac! | 
| +  base::FilePath executable("gn"); | 
| +#else | 
| +  base::FilePath executable = | 
| +      base::GetProcessExecutablePath(base::GetCurrentProcessHandle()); | 
| +#endif | 
| + | 
| +/* | 
| +  // Append the root path. | 
| +  CommandLine* cmdline = CommandLine::ForCurrentProcess(); | 
| +  result += " --root=\"" + FilePathToUTF8(settings->root_path()) + "\""; | 
| +*/ | 
| + | 
| +  CommandLine cmdline(executable); | 
| +  cmdline.AppendSwitchPath("--root", build_settings->root_path()); | 
| + | 
| +  // TODO(brettw) append other parameters. | 
| + | 
| +#if defined(OS_WIN) | 
| +  return WideToUTF8(cmdline.GetCommandLineString()); | 
| +#else | 
| +  return cmdline.GetCommandLineString(); | 
| +#endif | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +NinjaBuildWriter::NinjaBuildWriter( | 
| +    const BuildSettings* build_settings, | 
| +    const std::vector<const Settings*>& all_settings, | 
| +    const std::vector<const Target*>& default_toolchain_targets, | 
| +    std::ostream& out) | 
| +    : build_settings_(build_settings), | 
| +      all_settings_(all_settings), | 
| +      default_toolchain_targets_(default_toolchain_targets), | 
| +      out_(out), | 
| +      path_output_(build_settings->build_dir(), ESCAPE_NINJA, true), | 
| +      helper_(build_settings) { | 
| +} | 
| + | 
| +NinjaBuildWriter::~NinjaBuildWriter() { | 
| +} | 
| + | 
| +void NinjaBuildWriter::Run() { | 
| +  WriteNinjaRules(); | 
| +  WriteSubninjas(); | 
| +  WritePhonyAndAllRules(); | 
| +} | 
| + | 
| +// static | 
| +bool NinjaBuildWriter::RunAndWriteFile( | 
| +    const BuildSettings* build_settings, | 
| +    const std::vector<const Settings*>& all_settings, | 
| +    const std::vector<const Target*>& default_toolchain_targets) { | 
| +  base::FilePath ninja_file(build_settings->GetFullPath( | 
| +      SourceFile(build_settings->build_dir().value() + "build.ninja"))); | 
| +  file_util::CreateDirectory(ninja_file.DirName()); | 
| + | 
| +  std::ofstream file; | 
| +  file.open(FilePathToUTF8(ninja_file).c_str(), | 
| +            std::ios_base::out | std::ios_base::binary); | 
| +  if (file.fail()) | 
| +    return false; | 
| + | 
| +  NinjaBuildWriter gen(build_settings, all_settings, | 
| +                       default_toolchain_targets, file); | 
| +  gen.Run(); | 
| +  return true; | 
| +} | 
| + | 
| +void NinjaBuildWriter::WriteNinjaRules() { | 
| +  out_ << "rule gn\n"; | 
| +  out_ << "  command = " << GetSelfInvocationCommand(build_settings_) << "\n"; | 
| +  out_ << "  description = GN the world\n\n"; | 
| + | 
| +  out_ << "build build.ninja: gn"; | 
| + | 
| +  // Input build files. | 
| +  std::vector<SourceFile> input_files; | 
| +  g_scheduler->input_file_manager()->GetAllInputFileNames(&input_files); | 
| +  for (size_t i = 0; i < input_files.size(); i++) { | 
| +    out_ << " "; | 
| +    path_output_.WriteFile(out_, input_files[i]); | 
| +  } | 
| + | 
| +  // Other files read by the build. | 
| +  std::vector<SourceFile> other_files = g_scheduler->GetGenDependencies(); | 
| +  for (size_t i = 0; i < other_files.size(); i++) { | 
| +    out_ << " "; | 
| +    path_output_.WriteFile(out_, other_files[i]); | 
| +  } | 
| + | 
| +  out_ << std::endl << std::endl; | 
| +} | 
| + | 
| +void NinjaBuildWriter::WriteSubninjas() { | 
| +  for (size_t i = 0; i < all_settings_.size(); i++) { | 
| +    out_ << "subninja "; | 
| +    path_output_.WriteFile(out_, | 
| +                           helper_.GetNinjaFileForToolchain(all_settings_[i])); | 
| +    out_ << std::endl; | 
| +  } | 
| +  out_ << std::endl; | 
| +} | 
| + | 
| +void NinjaBuildWriter::WritePhonyAndAllRules() { | 
| +  std::string all_rules; | 
| + | 
| +  // Write phony rules for the default toolchain (don't do other toolchains or | 
| +  // we'll get naming conflicts). | 
| +  for (size_t i = 0; i < default_toolchain_targets_.size(); i++) { | 
| +    const Target* target = default_toolchain_targets_[i]; | 
| +    if (target->output_type() == Target::NONE) | 
| +      continue;  // Nothing to generate. | 
| + | 
| +    OutputFile target_file = helper_.GetTargetOutputFile(target); | 
| +    if (target_file.value() != target->label().name()) { | 
| +      out_ << "build " << target->label().name() << ": phony "; | 
| +      path_output_.WriteFile(out_, target_file); | 
| +      out_ << std::endl; | 
| +    } | 
| + | 
| +    if (!all_rules.empty()) | 
| +      all_rules.append(" $\n    "); | 
| +    all_rules.append(target_file.value()); | 
| +  } | 
| + | 
| +  if (!all_rules.empty()) { | 
| +    out_ << "\nbuild all: phony " << all_rules << std::endl; | 
| +    out_ << "default all" << std::endl; | 
| +  } | 
| +} | 
| + | 
|  |