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

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

Issue 1506343003: No GN phony rules when it matches outputs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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 | « no previous file | no next file » | 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 <fstream> 7 #include <fstream>
8 #include <map> 8 #include <map>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 } 78 }
79 79
80 OutputFile GetTargetOutputFile(const Target* target) { 80 OutputFile GetTargetOutputFile(const Target* target) {
81 OutputFile result(target->dependency_output_file()); 81 OutputFile result(target->dependency_output_file());
82 82
83 // The output files may have leading "./" so normalize those away. 83 // The output files may have leading "./" so normalize those away.
84 NormalizePath(&result.value()); 84 NormalizePath(&result.value());
85 return result; 85 return result;
86 } 86 }
87 87
88 bool HasOutputIdenticalToLabel(const Target* target,
89 const std::string& short_name) {
90 if (target->output_type() != Target::ACTION &&
91 target->output_type() != Target::ACTION_FOREACH)
92 return false;
93
94 // Rather than convert all outputs to be relative to the build directory
95 // and then compare to the short name, convert the short name to look like a
96 // file in the output directory since this is only one conversion.
97 SourceFile short_name_as_source_file(
98 target->settings()->build_settings()->build_dir().value() + short_name);
99
100 std::vector<SourceFile> outputs_as_source;
101 target->action_values().GetOutputsAsSourceFiles(target, &outputs_as_source);
102 for (const SourceFile& output_as_source : outputs_as_source) {
103 if (output_as_source == short_name_as_source_file)
104 return true;
105 }
106 return false;
107 }
108
88 // Given an output that appears more than once, generates an error message 109 // Given an output that appears more than once, generates an error message
89 // that describes the problem and which targets generate it. 110 // that describes the problem and which targets generate it.
90 Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets, 111 Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets,
91 const OutputFile& bad_output) { 112 const OutputFile& bad_output) {
92 std::vector<const Target*> matches; 113 std::vector<const Target*> matches;
93 for (const Target* target : all_targets) { 114 for (const Target* target : all_targets) {
94 if (GetTargetOutputFile(target) == bad_output) 115 if (GetTargetOutputFile(target) == bad_output)
95 matches.push_back(target); 116 matches.push_back(target);
96 } 117 }
97 118
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // target which we already wrote. 308 // target which we already wrote.
288 if (medium_name != label.name()) 309 if (medium_name != label.name())
289 WritePhonyRule(target, target_file, medium_name, &written_rules); 310 WritePhonyRule(target, target_file, medium_name, &written_rules);
290 } 311 }
291 312
292 // Write short names for ones which are either completely unique or there 313 // Write short names for ones which are either completely unique or there
293 // at least only one of them in the default toolchain that is an exe. 314 // at least only one of them in the default toolchain that is an exe.
294 if (small_name_count[label.name()] == 1 || 315 if (small_name_count[label.name()] == 1 ||
295 (target->output_type() == Target::EXECUTABLE && 316 (target->output_type() == Target::EXECUTABLE &&
296 exe_count[label.name()] == 1)) { 317 exe_count[label.name()] == 1)) {
297 WritePhonyRule(target, target_file, label.name(), &written_rules); 318 // It's reasonable to generate output files in the root build directory
319 // with the same name as the target. Don't generate phony rules for
320 // these cases.
321 //
322 // All of this does not do the general checking of all target's outputs
323 // which may theoretically collide. But it's not very reasonable for
324 // a script target named "foo" to generate a file named "bar" with no
325 // extension in the root build directory while another target is named
326 // "bar". If this does occur, the user is likely to be confused when
327 // building "bar" that is builds foo anyway, so you probably just
328 // shouldn't do that.
329 //
330 // We should fix this however, and build up all generated script outputs
331 // and check everything against that. There are other edge cases that the
332 // current phony rule generator doesn't check. We may need to make a big
333 // set of every possible generated file in the build for this purpose.
334 if (!HasOutputIdenticalToLabel(target, label.name()))
335 WritePhonyRule(target, target_file, label.name(), &written_rules);
298 } 336 }
299 337
300 if (!all_rules.empty()) 338 if (!all_rules.empty())
301 all_rules.append(" $\n "); 339 all_rules.append(" $\n ");
302 all_rules.append(target_file.value()); 340 all_rules.append(target_file.value());
303 } 341 }
304 342
305 // Pick up phony rules for the toplevel targets with non-unique names (which 343 // Pick up phony rules for the toplevel targets with non-unique names (which
306 // would have been skipped in the above loop). 344 // would have been skipped in the above loop).
307 for (const auto& toplevel_target : toplevel_targets) { 345 for (const auto& toplevel_target : toplevel_targets) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 EscapeOptions ninja_escape; 386 EscapeOptions ninja_escape;
349 ninja_escape.mode = ESCAPE_NINJA; 387 ninja_escape.mode = ESCAPE_NINJA;
350 388
351 // Escape for special chars Ninja will handle. 389 // Escape for special chars Ninja will handle.
352 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr); 390 std::string escaped = EscapeString(phony_name, ninja_escape, nullptr);
353 391
354 out_ << "build " << escaped << ": phony "; 392 out_ << "build " << escaped << ": phony ";
355 path_output_.WriteFile(out_, target_file); 393 path_output_.WriteFile(out_, target_file);
356 out_ << std::endl; 394 out_ << std::endl;
357 } 395 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698