Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: tools/gn/ninja_build_writer.cc

Issue 1828113002: 🌱 GN: Look at all target outputs when detecting duplicates (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bye bye gmock Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/ninja_build_writer.h ('k') | tools/gn/ninja_build_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « tools/gn/ninja_build_writer.h ('k') | tools/gn/ninja_build_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698