| 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_build_writer.h" | 5 #include "tools/gn/ninja_build_writer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <fstream> | 9 #include <fstream> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 "Two or more targets generate the same output:\n " + | 123 "Two or more targets generate the same output:\n " + |
| 124 bad_output.value() + "\n\n" | 124 bad_output.value() + "\n\n" |
| 125 "This is can often be fixed by changing one of the target names, or by \n" | 125 "This is can often be fixed by changing one of the target names, or by \n" |
| 126 "setting an output_name on one of them.\n" | 126 "setting an output_name on one of them.\n" |
| 127 "\nCollisions:\n" + matches_string); | 127 "\nCollisions:\n" + matches_string); |
| 128 for (size_t i = 1; i < matches.size(); i++) | 128 for (size_t i = 1; i < matches.size(); i++) |
| 129 result.AppendSubErr(Err(matches[i]->defined_from(), "Collision.")); | 129 result.AppendSubErr(Err(matches[i]->defined_from(), "Collision.")); |
| 130 return result; | 130 return result; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Given two toolchains with the same name, generates an error message |
| 134 // that describes the problem. |
| 135 Err GetDuplicateToolchainError(const SourceFile& source_file, |
| 136 const Toolchain* previous_toolchain, |
| 137 const Toolchain* toolchain) { |
| 138 Err result(toolchain->defined_from(), "Duplicate toolchain.", |
| 139 "Two or more toolchains write to the same directory:\n " + |
| 140 source_file.GetDir().value() + "\n\n" |
| 141 "This can be fixed by making sure that distinct toolchains have\n" |
| 142 "distinct names.\n"); |
| 143 result.AppendSubErr( |
| 144 Err(previous_toolchain->defined_from(), "Previous toolchain.")); |
| 145 return result; |
| 146 } |
| 147 |
| 133 } // namespace | 148 } // namespace |
| 134 | 149 |
| 135 NinjaBuildWriter::NinjaBuildWriter( | 150 NinjaBuildWriter::NinjaBuildWriter( |
| 136 const BuildSettings* build_settings, | 151 const BuildSettings* build_settings, |
| 137 const std::unordered_map<const Settings*, const Toolchain*>& | 152 const std::unordered_map<const Settings*, const Toolchain*>& |
| 138 used_toolchains, | 153 used_toolchains, |
| 139 const Toolchain* default_toolchain, | 154 const Toolchain* default_toolchain, |
| 140 const std::vector<const Target*>& default_toolchain_targets, | 155 const std::vector<const Target*>& default_toolchain_targets, |
| 141 std::ostream& out, | 156 std::ostream& out, |
| 142 std::ostream& dep_out) | 157 std::ostream& dep_out) |
| 143 : build_settings_(build_settings), | 158 : build_settings_(build_settings), |
| 144 used_toolchains_(used_toolchains), | 159 used_toolchains_(used_toolchains), |
| 145 default_toolchain_(default_toolchain), | 160 default_toolchain_(default_toolchain), |
| 146 default_toolchain_targets_(default_toolchain_targets), | 161 default_toolchain_targets_(default_toolchain_targets), |
| 147 out_(out), | 162 out_(out), |
| 148 dep_out_(dep_out), | 163 dep_out_(dep_out), |
| 149 path_output_(build_settings->build_dir(), | 164 path_output_(build_settings->build_dir(), |
| 150 build_settings->root_path_utf8(), | 165 build_settings->root_path_utf8(), |
| 151 ESCAPE_NINJA) {} | 166 ESCAPE_NINJA) {} |
| 152 | 167 |
| 153 NinjaBuildWriter::~NinjaBuildWriter() { | 168 NinjaBuildWriter::~NinjaBuildWriter() { |
| 154 } | 169 } |
| 155 | 170 |
| 156 bool NinjaBuildWriter::Run(Err* err) { | 171 bool NinjaBuildWriter::Run(Err* err) { |
| 157 WriteNinjaRules(); | 172 WriteNinjaRules(); |
| 158 WriteAllPools(); | 173 WriteAllPools(); |
| 159 WriteSubninjas(); | 174 return WriteSubninjas(err) && WritePhonyAndAllRules(err); |
| 160 return WritePhonyAndAllRules(err); | |
| 161 } | 175 } |
| 162 | 176 |
| 163 // static | 177 // static |
| 164 bool NinjaBuildWriter::RunAndWriteFile( | 178 bool NinjaBuildWriter::RunAndWriteFile( |
| 165 const BuildSettings* build_settings, | 179 const BuildSettings* build_settings, |
| 166 const Builder& builder, | 180 const Builder& builder, |
| 167 Err* err) { | 181 Err* err) { |
| 168 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja"); | 182 ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja"); |
| 169 | 183 |
| 170 std::vector<const Target*> all_targets = builder.GetAllResolvedTargets(); | 184 std::vector<const Target*> all_targets = builder.GetAllResolvedTargets(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 [&pool_name](const Pool* a, const Pool* b) { | 294 [&pool_name](const Pool* a, const Pool* b) { |
| 281 return pool_name(a) < pool_name(b); | 295 return pool_name(a) < pool_name(b); |
| 282 }); | 296 }); |
| 283 for (const Pool* pool : sorted_pools) { | 297 for (const Pool* pool : sorted_pools) { |
| 284 out_ << "pool " << pool_name(pool) << std::endl | 298 out_ << "pool " << pool_name(pool) << std::endl |
| 285 << " depth = " << pool->depth() << std::endl | 299 << " depth = " << pool->depth() << std::endl |
| 286 << std::endl; | 300 << std::endl; |
| 287 } | 301 } |
| 288 } | 302 } |
| 289 | 303 |
| 290 void NinjaBuildWriter::WriteSubninjas() { | 304 bool NinjaBuildWriter::WriteSubninjas(Err* err) { |
| 291 // Write toolchains sorted by their name, to make output deterministic. | 305 // Write toolchains sorted by their name, to make output deterministic. |
| 292 std::vector<std::pair<const Settings*, const Toolchain*>> sorted_settings( | 306 std::vector<std::pair<const Settings*, const Toolchain*>> sorted_settings( |
| 293 used_toolchains_.begin(), used_toolchains_.end()); | 307 used_toolchains_.begin(), used_toolchains_.end()); |
| 294 std::sort(sorted_settings.begin(), sorted_settings.end(), | 308 std::sort(sorted_settings.begin(), sorted_settings.end(), |
| 295 [this](const std::pair<const Settings*, const Toolchain*>& a, | 309 [this](const std::pair<const Settings*, const Toolchain*>& a, |
| 296 const std::pair<const Settings*, const Toolchain*>& b) { | 310 const std::pair<const Settings*, const Toolchain*>& b) { |
| 297 // Always put the default toolchain first. | 311 // Always put the default toolchain first. |
| 298 if (b.second == default_toolchain_) | 312 if (b.second == default_toolchain_) |
| 299 return false; | 313 return false; |
| 300 if (a.second == default_toolchain_) | 314 if (a.second == default_toolchain_) |
| 301 return true; | 315 return true; |
| 302 return GetNinjaFileForToolchain(a.first) < | 316 return GetNinjaFileForToolchain(a.first) < |
| 303 GetNinjaFileForToolchain(b.first); | 317 GetNinjaFileForToolchain(b.first); |
| 304 }); | 318 }); |
| 319 |
| 320 SourceFile previous_subninja; |
| 321 const Toolchain* previous_toolchain = nullptr; |
| 322 |
| 305 for (const auto& pair : sorted_settings) { | 323 for (const auto& pair : sorted_settings) { |
| 324 SourceFile subninja = GetNinjaFileForToolchain(pair.first); |
| 325 |
| 326 // Since the toolchains are sorted, comparing to the previous subninja is |
| 327 // enough to find duplicates. |
| 328 if (subninja == previous_subninja) { |
| 329 *err = |
| 330 GetDuplicateToolchainError(subninja, previous_toolchain, pair.second); |
| 331 return false; |
| 332 } |
| 333 |
| 306 out_ << "subninja "; | 334 out_ << "subninja "; |
| 307 path_output_.WriteFile(out_, GetNinjaFileForToolchain(pair.first)); | 335 path_output_.WriteFile(out_, subninja); |
| 308 out_ << std::endl; | 336 out_ << std::endl; |
| 337 previous_subninja = subninja; |
| 338 previous_toolchain = pair.second; |
| 309 } | 339 } |
| 310 out_ << std::endl; | 340 out_ << std::endl; |
| 341 return true; |
| 311 } | 342 } |
| 312 | 343 |
| 313 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { | 344 bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { |
| 314 // Track rules as we generate them so we don't accidentally write a phony | 345 // Track rules as we generate them so we don't accidentally write a phony |
| 315 // rule that collides with something else. | 346 // rule that collides with something else. |
| 316 // GN internally generates an "all" target, so don't duplicate it. | 347 // GN internally generates an "all" target, so don't duplicate it. |
| 317 base::hash_set<std::string> written_rules; | 348 base::hash_set<std::string> written_rules; |
| 318 written_rules.insert("all"); | 349 written_rules.insert("all"); |
| 319 | 350 |
| 320 // Set if we encounter a target named "//:default". | 351 // Set if we encounter a target named "//:default". |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 EscapeOptions ninja_escape; | 505 EscapeOptions ninja_escape; |
| 475 ninja_escape.mode = ESCAPE_NINJA; | 506 ninja_escape.mode = ESCAPE_NINJA; |
| 476 | 507 |
| 477 // Escape for special chars Ninja will handle. | 508 // Escape for special chars Ninja will handle. |
| 478 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); | 509 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); |
| 479 | 510 |
| 480 out_ << "build " << escaped << ": phony "; | 511 out_ << "build " << escaped << ": phony "; |
| 481 path_output_.WriteFile(out_, target->dependency_output_file()); | 512 path_output_.WriteFile(out_, target->dependency_output_file()); |
| 482 out_ << std::endl; | 513 out_ << std::endl; |
| 483 } | 514 } |
| OLD | NEW |