Index: tools/gn/ninja_build_writer.cc |
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc |
index 43916763db56231856526a099441e7b9d7b1cbdc..d27ebdcce66420b813f64cafbbdffc505809911b 100644 |
--- a/tools/gn/ninja_build_writer.cc |
+++ b/tools/gn/ninja_build_writer.cc |
@@ -76,6 +76,44 @@ std::string GetSelfInvocationCommand(const BuildSettings* build_settings) { |
return cmdline.GetCommandLineString(); |
#endif |
} |
+ |
+OutputFile GetTargetOutputFile(const Target* target) { |
+ OutputFile result(target->dependency_output_file()); |
+ |
+ // The output files may have leading "./" so normalize those away. |
+ NormalizePath(&result.value()); |
+ return result; |
+} |
+ |
+// Given an output that appears more than once, generates an error message |
+// that describes the problem and which targets generate it. |
+Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets, |
+ const OutputFile& bad_output) { |
+ std::vector<const Target*> matches; |
+ for (const Target* target : all_targets) { |
+ if (GetTargetOutputFile(target) == bad_output) |
+ matches.push_back(target); |
+ } |
+ |
+ // There should always be at least two targets generating this file for this |
+ // function to be called in the first place. |
+ DCHECK(matches.size() >= 2); |
+ std::string matches_string; |
+ for (const Target* target : matches) |
+ matches_string += " " + target->label().GetUserVisibleName(false) + "\n"; |
+ |
+ Err result(matches[0]->defined_from(), "Duplicate output file.", |
+ "Two or more targets generate the same output:\n " + |
+ bad_output.value() + "\n" |
+ "This is normally the result of either overriding the output name or\n" |
+ "having two shared libraries or executables in different directories\n" |
+ "with the same name (since all such targets will be written to the root\n" |
+ "output directory).\n\nCollisions:\n" + matches_string); |
+ for (size_t i = 1; i < matches.size(); i++) |
+ result.AppendSubErr(Err(matches[i]->defined_from(), "Collision.")); |
+ return result; |
+} |
+ |
} // namespace |
NinjaBuildWriter::NinjaBuildWriter( |
@@ -242,11 +280,9 @@ bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) { |
for (const auto& target : default_toolchain_targets_) { |
const Label& label = target->label(); |
- OutputFile target_file(target->dependency_output_file()); |
- // The output files may have leading "./" so normalize those away. |
- NormalizePath(&target_file.value()); |
+ OutputFile target_file = GetTargetOutputFile(target); |
if (!target_files.insert(target_file.value()).second) { |
- *err = Err(Location(), "Duplicate rules for " + target_file.value()); |
+ *err = GetDuplicateOutputError(default_toolchain_targets_, target_file); |
return false; |
} |