| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 } | 107 } |
| 108 return false; | 108 return false; |
| 109 } | 109 } |
| 110 | 110 |
| 111 // Given an output that appears more than once, generates an error message | 111 // Given an output that appears more than once, generates an error message |
| 112 // that describes the problem and which targets generate it. | 112 // that describes the problem and which targets generate it. |
| 113 Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets, | 113 Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets, |
| 114 const OutputFile& bad_output) { | 114 const OutputFile& bad_output) { |
| 115 std::vector<const Target*> matches; | 115 std::vector<const Target*> matches; |
| 116 for (const Target* target : all_targets) { | 116 for (const Target* target : all_targets) { |
| 117 if (GetTargetOutputFile(target) == bad_output) | 117 for (const auto& output : target->computed_outputs()) { |
| 118 matches.push_back(target); | 118 if (output == bad_output) { |
| 119 matches.push_back(target); |
| 120 break; |
| 121 } |
| 122 } |
| 119 } | 123 } |
| 120 | 124 |
| 121 // There should always be at least two targets generating this file for this | 125 // There should always be at least two targets generating this file for this |
| 122 // function to be called in the first place. | 126 // function to be called in the first place. |
| 123 DCHECK(matches.size() >= 2); | 127 DCHECK(matches.size() >= 2); |
| 124 std::string matches_string; | 128 std::string matches_string; |
| 125 for (const Target* target : matches) | 129 for (const Target* target : matches) |
| 126 matches_string += " " + target->label().GetUserVisibleName(false) + "\n"; | 130 matches_string += " " + target->label().GetUserVisibleName(false) + "\n"; |
| 127 | 131 |
| 128 Err result(matches[0]->defined_from(), "Duplicate output file.", | 132 Err result(matches[0]->defined_from(), "Duplicate output file.", |
| 129 "Two or more targets generate the same output:\n " + | 133 "Two or more targets generate the same output:\n " + |
| 130 bad_output.value() + "\n" | 134 bad_output.value() + "\n\n" |
| 131 "This is normally the result of either overriding the output name or\n" | 135 "This is can often be fixed by changing one of the target names, or by \n" |
| 132 "having two shared libraries or executables in different directories\n" | 136 "setting an output_name on one of them.\n" |
| 133 "with the same name (since all such targets will be written to the root\n" | 137 "\nCollisions:\n" + matches_string); |
| 134 "output directory).\n\nCollisions:\n" + matches_string); | |
| 135 for (size_t i = 1; i < matches.size(); i++) | 138 for (size_t i = 1; i < matches.size(); i++) |
| 136 result.AppendSubErr(Err(matches[i]->defined_from(), "Collision.")); | 139 result.AppendSubErr(Err(matches[i]->defined_from(), "Collision.")); |
| 137 return result; | 140 return result; |
| 138 } | 141 } |
| 139 | 142 |
| 140 } // namespace | 143 } // namespace |
| 141 | 144 |
| 142 NinjaBuildWriter::NinjaBuildWriter( | 145 NinjaBuildWriter::NinjaBuildWriter( |
| 143 const BuildSettings* build_settings, | 146 const BuildSettings* build_settings, |
| 144 const std::vector<const Settings*>& all_settings, | 147 const std::vector<const Settings*>& all_settings, |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 | 290 |
| 288 // Add the files to the list of generated targets so we don't write phony | 291 // Add the files to the list of generated targets so we don't write phony |
| 289 // rules that collide. | 292 // rules that collide. |
| 290 std::string target_file(target->dependency_output_file().value()); | 293 std::string target_file(target->dependency_output_file().value()); |
| 291 NormalizePath(&target_file); | 294 NormalizePath(&target_file); |
| 292 written_rules.insert(target_file); | 295 written_rules.insert(target_file); |
| 293 } | 296 } |
| 294 | 297 |
| 295 for (const auto& target : default_toolchain_targets_) { | 298 for (const auto& target : default_toolchain_targets_) { |
| 296 const Label& label = target->label(); | 299 const Label& label = target->label(); |
| 297 OutputFile target_file = GetTargetOutputFile(target); | 300 for (const auto& output : target->computed_outputs()) { |
| 298 if (!target_files.insert(target_file.value()).second) { | 301 if (!target_files.insert(output.value()).second) { |
| 299 *err = GetDuplicateOutputError(default_toolchain_targets_, target_file); | 302 *err = GetDuplicateOutputError(default_toolchain_targets_, output); |
| 300 return false; | 303 return false; |
| 304 } |
| 301 } | 305 } |
| 302 | 306 |
| 307 OutputFile target_file = GetTargetOutputFile(target); |
| 303 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". | 308 // Write the long name "foo/bar:baz" for the target "//foo/bar:baz". |
| 304 std::string long_name = label.GetUserVisibleName(false); | 309 std::string long_name = label.GetUserVisibleName(false); |
| 305 base::TrimString(long_name, "/", &long_name); | 310 base::TrimString(long_name, "/", &long_name); |
| 306 WritePhonyRule(target, target_file, long_name, &written_rules); | 311 WritePhonyRule(target, target_file, long_name, &written_rules); |
| 307 | 312 |
| 308 // Write the directory name with no target name if they match | 313 // Write the directory name with no target name if they match |
| 309 // (e.g. "//foo/bar:bar" -> "foo/bar"). | 314 // (e.g. "//foo/bar:bar" -> "foo/bar"). |
| 310 if (FindLastDirComponent(label.dir()) == label.name()) { | 315 if (FindLastDirComponent(label.dir()) == label.name()) { |
| 311 std::string medium_name = DirectoryWithNoLastSlash(label.dir()); | 316 std::string medium_name = DirectoryWithNoLastSlash(label.dir()); |
| 312 base::TrimString(medium_name, "/", &medium_name); | 317 base::TrimString(medium_name, "/", &medium_name); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 EscapeOptions ninja_escape; | 397 EscapeOptions ninja_escape; |
| 393 ninja_escape.mode = ESCAPE_NINJA; | 398 ninja_escape.mode = ESCAPE_NINJA; |
| 394 | 399 |
| 395 // Escape for special chars Ninja will handle. | 400 // Escape for special chars Ninja will handle. |
| 396 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); | 401 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); |
| 397 | 402 |
| 398 out_ << "build " << escaped << ": phony "; | 403 out_ << "build " << escaped << ": phony "; |
| 399 path_output_.WriteFile(out_, target_file); | 404 path_output_.WriteFile(out_, target_file); |
| 400 out_ << std::endl; | 405 out_ << std::endl; |
| 401 } | 406 } |
| OLD | NEW |