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/ninja_toolchain_writer.h" | 5 #include "tools/gn/ninja_toolchain_writer.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/strings/stringize_macros.h" | 10 #include "base/strings/stringize_macros.h" |
11 #include "tools/gn/build_settings.h" | 11 #include "tools/gn/build_settings.h" |
| 12 #include "tools/gn/filesystem_utils.h" |
| 13 #include "tools/gn/ninja_utils.h" |
12 #include "tools/gn/settings.h" | 14 #include "tools/gn/settings.h" |
| 15 #include "tools/gn/substitution_writer.h" |
13 #include "tools/gn/target.h" | 16 #include "tools/gn/target.h" |
14 #include "tools/gn/toolchain.h" | 17 #include "tools/gn/toolchain.h" |
15 #include "tools/gn/trace.h" | 18 #include "tools/gn/trace.h" |
16 | 19 |
| 20 namespace { |
| 21 |
| 22 const char kIndent[] = " "; |
| 23 |
| 24 } // namespace |
| 25 |
17 NinjaToolchainWriter::NinjaToolchainWriter( | 26 NinjaToolchainWriter::NinjaToolchainWriter( |
18 const Settings* settings, | 27 const Settings* settings, |
19 const Toolchain* toolchain, | 28 const Toolchain* toolchain, |
20 const std::vector<const Target*>& targets, | 29 const std::vector<const Target*>& targets, |
21 std::ostream& out) | 30 std::ostream& out) |
22 : settings_(settings), | 31 : settings_(settings), |
23 toolchain_(toolchain), | 32 toolchain_(toolchain), |
24 targets_(targets), | 33 targets_(targets), |
25 out_(out), | 34 out_(out), |
26 path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA), | 35 path_output_(settings_->build_settings()->build_dir(), ESCAPE_NINJA) { |
27 helper_(settings->build_settings()) { | |
28 } | 36 } |
29 | 37 |
30 NinjaToolchainWriter::~NinjaToolchainWriter() { | 38 NinjaToolchainWriter::~NinjaToolchainWriter() { |
31 } | 39 } |
32 | 40 |
33 void NinjaToolchainWriter::Run() { | 41 void NinjaToolchainWriter::Run() { |
34 WriteRules(); | 42 WriteRules(); |
35 WriteSubninjas(); | 43 WriteSubninjas(); |
36 } | 44 } |
37 | 45 |
38 // static | 46 // static |
39 bool NinjaToolchainWriter::RunAndWriteFile( | 47 bool NinjaToolchainWriter::RunAndWriteFile( |
40 const Settings* settings, | 48 const Settings* settings, |
41 const Toolchain* toolchain, | 49 const Toolchain* toolchain, |
42 const std::vector<const Target*>& targets) { | 50 const std::vector<const Target*>& targets) { |
43 NinjaHelper helper(settings->build_settings()); | |
44 base::FilePath ninja_file(settings->build_settings()->GetFullPath( | 51 base::FilePath ninja_file(settings->build_settings()->GetFullPath( |
45 helper.GetNinjaFileForToolchain(settings).GetSourceFile( | 52 GetNinjaFileForToolchain(settings))); |
46 settings->build_settings()))); | |
47 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, FilePathToUTF8(ninja_file)); | 53 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, FilePathToUTF8(ninja_file)); |
48 | 54 |
49 base::CreateDirectory(ninja_file.DirName()); | 55 base::CreateDirectory(ninja_file.DirName()); |
50 | 56 |
51 std::ofstream file; | 57 std::ofstream file; |
52 file.open(FilePathToUTF8(ninja_file).c_str(), | 58 file.open(FilePathToUTF8(ninja_file).c_str(), |
53 std::ios_base::out | std::ios_base::binary); | 59 std::ios_base::out | std::ios_base::binary); |
54 if (file.fail()) | 60 if (file.fail()) |
55 return false; | 61 return false; |
56 | 62 |
57 NinjaToolchainWriter gen(settings, toolchain, targets, file); | 63 NinjaToolchainWriter gen(settings, toolchain, targets, file); |
58 gen.Run(); | 64 gen.Run(); |
59 return true; | 65 return true; |
60 } | 66 } |
61 | 67 |
62 void NinjaToolchainWriter::WriteRules() { | 68 void NinjaToolchainWriter::WriteRules() { |
63 std::string indent(" "); | 69 std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_); |
64 | |
65 NinjaHelper helper(settings_->build_settings()); | |
66 std::string rule_prefix = helper.GetRulePrefix(settings_); | |
67 | 70 |
68 for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) { | 71 for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) { |
69 Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i); | 72 Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i); |
70 const Toolchain::Tool& tool = toolchain_->GetTool(tool_type); | 73 const Tool* tool = toolchain_->GetTool(tool_type); |
71 if (tool.command.empty()) | 74 if (tool) |
72 continue; | 75 WriteToolRule(tool_type, tool, rule_prefix); |
| 76 } |
| 77 out_ << std::endl; |
| 78 } |
73 | 79 |
74 out_ << "rule " << rule_prefix << Toolchain::ToolTypeToName(tool_type) | 80 void NinjaToolchainWriter::WriteToolRule(const Toolchain::ToolType type, |
75 << std::endl; | 81 const Tool* tool, |
| 82 const std::string& rule_prefix) { |
| 83 out_ << "rule " << rule_prefix << Toolchain::ToolTypeToName(type) |
| 84 << std::endl; |
76 | 85 |
77 #define WRITE_ARG(name) \ | 86 // Rules explicitly include shell commands, so don't try to escape. |
78 if (!tool.name.empty()) \ | 87 EscapeOptions options; |
79 out_ << indent << " " STRINGIZE(name) " = " << tool.name << std::endl; | 88 options.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND; |
80 WRITE_ARG(command); | |
81 WRITE_ARG(depfile); | |
82 WRITE_ARG(description); | |
83 WRITE_ARG(pool); | |
84 WRITE_ARG(restat); | |
85 WRITE_ARG(rspfile); | |
86 WRITE_ARG(rspfile_content); | |
87 #undef WRITE_ARG | |
88 | 89 |
89 // Deps is called "depsformat" in GN to avoid confusion with dependencies. | 90 CHECK(!tool->command().empty()) << "Command should not be empty"; |
90 if (!tool.depsformat.empty()) \ | 91 WriteRulePattern("command", tool->command(), options); |
91 out_ << indent << " deps = " << tool.depsformat << std::endl; | 92 |
| 93 WriteRulePattern("description", tool->description(), options); |
| 94 WriteRulePattern("rspfile", tool->rspfile(), options); |
| 95 WriteRulePattern("rspfile_content", tool->rspfile_content(), options); |
| 96 |
| 97 if (tool->depsformat() == Tool::DEPS_GCC) { |
| 98 // GCC-style deps require a depfile. |
| 99 if (!tool->depfile().empty()) { |
| 100 WriteRulePattern("depfile", tool->depfile(), options); |
| 101 out_ << kIndent << "deps = gcc" << std::endl; |
| 102 } |
| 103 } else if (tool->depsformat() == Tool::DEPS_MSVC) { |
| 104 // MSVC deps don't have a depfile. |
| 105 out_ << kIndent << "deps = msvc" << std::endl; |
92 } | 106 } |
| 107 |
| 108 if (!tool->pool().empty()) |
| 109 out_ << kIndent << "pool = " << tool->pool() << std::endl; |
| 110 if (tool->restat()) |
| 111 out_ << kIndent << "restat = 1" << std::endl; |
| 112 } |
| 113 |
| 114 void NinjaToolchainWriter::WriteRulePattern(const char* name, |
| 115 const SubstitutionPattern& pattern, |
| 116 const EscapeOptions& options) { |
| 117 if (pattern.empty()) |
| 118 return; |
| 119 out_ << kIndent << name << " = "; |
| 120 SubstitutionWriter::WriteWithNinjaVariables(pattern, options, out_); |
93 out_ << std::endl; | 121 out_ << std::endl; |
94 } | 122 } |
95 | 123 |
96 void NinjaToolchainWriter::WriteSubninjas() { | 124 void NinjaToolchainWriter::WriteSubninjas() { |
97 // Write subninja commands for each generated target. | 125 // Write subninja commands for each generated target. |
98 for (size_t i = 0; i < targets_.size(); i++) { | 126 for (size_t i = 0; i < targets_.size(); i++) { |
99 OutputFile ninja_file = helper_.GetNinjaFileForTarget(targets_[i]); | 127 OutputFile ninja_file(targets_[i]->settings()->build_settings(), |
| 128 GetNinjaFileForTarget(targets_[i])); |
100 out_ << "subninja "; | 129 out_ << "subninja "; |
101 path_output_.WriteFile(out_, ninja_file); | 130 path_output_.WriteFile(out_, ninja_file); |
102 out_ << std::endl; | 131 out_ << std::endl; |
103 } | 132 } |
104 out_ << std::endl; | 133 out_ << std::endl; |
105 } | 134 } |
OLD | NEW |