| // 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_toolchain_writer.h" | 
 |  | 
 | #include <fstream> | 
 |  | 
 | #include "base/files/file_util.h" | 
 | #include "base/strings/stringize_macros.h" | 
 | #include "tools/gn/build_settings.h" | 
 | #include "tools/gn/filesystem_utils.h" | 
 | #include "tools/gn/ninja_utils.h" | 
 | #include "tools/gn/pool.h" | 
 | #include "tools/gn/settings.h" | 
 | #include "tools/gn/substitution_writer.h" | 
 | #include "tools/gn/target.h" | 
 | #include "tools/gn/toolchain.h" | 
 | #include "tools/gn/trace.h" | 
 |  | 
 | namespace { | 
 |  | 
 | const char kIndent[] = "  "; | 
 |  | 
 | }  // namespace | 
 |  | 
 | NinjaToolchainWriter::NinjaToolchainWriter( | 
 |     const Settings* settings, | 
 |     const Toolchain* toolchain, | 
 |     std::ostream& out) | 
 |     : settings_(settings), | 
 |       toolchain_(toolchain), | 
 |       out_(out), | 
 |       path_output_(settings_->build_settings()->build_dir(), | 
 |                    settings_->build_settings()->root_path_utf8(), | 
 |                    ESCAPE_NINJA) { | 
 | } | 
 |  | 
 | NinjaToolchainWriter::~NinjaToolchainWriter() = default; | 
 |  | 
 | void NinjaToolchainWriter::Run( | 
 |     const std::vector<NinjaWriter::TargetRulePair>& rules) { | 
 |   std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); | 
 |  | 
 |   for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) { | 
 |     Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i); | 
 |     const Tool* tool = toolchain_->GetTool(tool_type); | 
 |     if (tool_type == Toolchain::TYPE_ACTION) | 
 |       continue; | 
 |     if (tool) | 
 |       WriteToolRule(tool_type, tool, rule_prefix); | 
 |   } | 
 |   out_ << std::endl; | 
 |  | 
 |   for (const auto& pair : rules) | 
 |     out_ << pair.second; | 
 | } | 
 |  | 
 | // static | 
 | bool NinjaToolchainWriter::RunAndWriteFile( | 
 |     const Settings* settings, | 
 |     const Toolchain* toolchain, | 
 |     const std::vector<NinjaWriter::TargetRulePair>& rules) { | 
 |   base::FilePath ninja_file(settings->build_settings()->GetFullPath( | 
 |       GetNinjaFileForToolchain(settings))); | 
 |   ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, FilePathToUTF8(ninja_file)); | 
 |  | 
 |   base::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; | 
 |  | 
 |   NinjaToolchainWriter gen(settings, toolchain, file); | 
 |   gen.Run(rules); | 
 |   return true; | 
 | } | 
 |  | 
 | void NinjaToolchainWriter::WriteToolRule(const Toolchain::ToolType type, | 
 |                                          const Tool* tool, | 
 |                                          const std::string& rule_prefix) { | 
 |   out_ << "rule " << rule_prefix << Toolchain::ToolTypeToName(type) | 
 |        << std::endl; | 
 |  | 
 |   // Rules explicitly include shell commands, so don't try to escape. | 
 |   EscapeOptions options; | 
 |   options.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND; | 
 |  | 
 |   CHECK(!tool->command().empty()) << "Command should not be empty"; | 
 |   WriteRulePattern("command", tool->command(), options); | 
 |  | 
 |   WriteRulePattern("description", tool->description(), options); | 
 |   WriteRulePattern("rspfile", tool->rspfile(), options); | 
 |   WriteRulePattern("rspfile_content", tool->rspfile_content(), options); | 
 |  | 
 |   if (tool->depsformat() == Tool::DEPS_GCC) { | 
 |     // GCC-style deps require a depfile. | 
 |     if (!tool->depfile().empty()) { | 
 |       WriteRulePattern("depfile", tool->depfile(), options); | 
 |       out_ << kIndent << "deps = gcc" << std::endl; | 
 |     } | 
 |   } else if (tool->depsformat() == Tool::DEPS_MSVC) { | 
 |     // MSVC deps don't have a depfile. | 
 |     out_ << kIndent << "deps = msvc" << std::endl; | 
 |   } | 
 |  | 
 |   // Use pool is specified. | 
 |   if (tool->pool().ptr) { | 
 |     std::string pool_name = | 
 |         tool->pool().ptr->GetNinjaName(settings_->default_toolchain_label()); | 
 |     out_ << kIndent << "pool = " << pool_name << std::endl; | 
 |   } | 
 |  | 
 |   if (tool->restat()) | 
 |     out_ << kIndent << "restat = 1" << std::endl; | 
 | } | 
 |  | 
 | void NinjaToolchainWriter::WriteRulePattern(const char* name, | 
 |                                             const SubstitutionPattern& pattern, | 
 |                                             const EscapeOptions& options) { | 
 |   if (pattern.empty()) | 
 |     return; | 
 |   out_ << kIndent << name << " = "; | 
 |   SubstitutionWriter::WriteWithNinjaVariables(pattern, options, out_); | 
 |   out_ << std::endl; | 
 | } |