OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/visual_studio_writer.h" | 5 #include "tools/gn/visual_studio_writer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 | 11 |
12 #include "base/files/file_util.h" | |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
15 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
16 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
17 #include "tools/gn/builder.h" | 16 #include "tools/gn/builder.h" |
18 #include "tools/gn/config.h" | 17 #include "tools/gn/config.h" |
19 #include "tools/gn/config_values_extractors.h" | 18 #include "tools/gn/config_values_extractors.h" |
20 #include "tools/gn/filesystem_utils.h" | 19 #include "tools/gn/filesystem_utils.h" |
21 #include "tools/gn/parse_tree.h" | 20 #include "tools/gn/parse_tree.h" |
22 #include "tools/gn/path_output.h" | 21 #include "tools/gn/path_output.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 // outlive the output. | 145 // outlive the output. |
147 base::StringPiece FindParentDir(const std::string* path) { | 146 base::StringPiece FindParentDir(const std::string* path) { |
148 DCHECK(path && !path->empty()); | 147 DCHECK(path && !path->empty()); |
149 for (int i = static_cast<int>(path->size()) - 2; i >= 0; --i) { | 148 for (int i = static_cast<int>(path->size()) - 2; i >= 0; --i) { |
150 if (IsSlash((*path)[i])) | 149 if (IsSlash((*path)[i])) |
151 return base::StringPiece(path->data(), i); | 150 return base::StringPiece(path->data(), i); |
152 } | 151 } |
153 return base::StringPiece(); | 152 return base::StringPiece(); |
154 } | 153 } |
155 | 154 |
156 bool HasSameContent(std::stringstream& data_1, const base::FilePath& data_2) { | |
157 // Compare file sizes first. Quick and will save us some time if they are | |
158 // different sizes. | |
159 int64_t data_1_len = data_1.tellp(); | |
160 | |
161 int64_t data_2_len; | |
162 if (!base::GetFileSize(data_2, &data_2_len) || data_1_len != data_2_len) | |
163 return false; | |
164 | |
165 std::string data_2_data; | |
166 data_2_data.resize(data_2_len); | |
167 if (!base::ReadFileToString(data_2, &data_2_data)) | |
168 return false; | |
169 | |
170 std::string data_1_data; | |
171 data_1_data = data_1.str(); | |
172 | |
173 return data_1_data == data_2_data; | |
174 } | |
175 | |
176 } // namespace | 155 } // namespace |
177 | 156 |
178 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name, | 157 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name, |
179 const std::string& _path, | 158 const std::string& _path, |
180 const std::string& _guid) | 159 const std::string& _guid) |
181 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {} | 160 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {} |
182 | 161 |
183 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default; | 162 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default; |
184 | 163 |
185 VisualStudioWriter::SolutionProject::SolutionProject( | 164 VisualStudioWriter::SolutionProject::SolutionProject( |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 std::stringstream vcxproj_string_out; | 261 std::stringstream vcxproj_string_out; |
283 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, | 262 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, |
284 err)) { | 263 err)) { |
285 projects_.pop_back(); | 264 projects_.pop_back(); |
286 return false; | 265 return false; |
287 } | 266 } |
288 | 267 |
289 // Only write the content to the file if it's different. That is | 268 // Only write the content to the file if it's different. That is |
290 // both a performance optimization and more importantly, prevents | 269 // both a performance optimization and more importantly, prevents |
291 // Visual Studio from reloading the projects. | 270 // Visual Studio from reloading the projects. |
292 if (!HasSameContent(vcxproj_string_out, vcxproj_path)) { | 271 if (!WriteFileIfChanged(vcxproj_path, vcxproj_string_out.str(), err)) |
293 std::string content = vcxproj_string_out.str(); | 272 return false; |
294 int size = static_cast<int>(content.size()); | |
295 if (base::WriteFile(vcxproj_path, content.c_str(), size) != size) { | |
296 *err = Err(Location(), "Couldn't open " + target->label().name() + | |
297 ".vcxproj for writing"); | |
298 return false; | |
299 } | |
300 } | |
301 | 273 |
302 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); | 274 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); |
303 | |
304 std::stringstream filters_string_out; | 275 std::stringstream filters_string_out; |
305 WriteFiltersFileContents(filters_string_out, target); | 276 WriteFiltersFileContents(filters_string_out, target); |
306 | 277 return WriteFileIfChanged(filters_path, filters_string_out.str(), err); |
307 if (!HasSameContent(filters_string_out, filters_path)) { | |
308 std::string content = filters_string_out.str(); | |
309 int size = static_cast<int>(content.size()); | |
310 if (base::WriteFile(filters_path, content.c_str(), size) != size) { | |
311 *err = Err(Location(), "Couldn't open " + target->label().name() + | |
312 ".vcxproj.filters for writing"); | |
313 return false; | |
314 } | |
315 } | |
316 | |
317 return true; | |
318 } | 278 } |
319 | 279 |
320 bool VisualStudioWriter::WriteProjectFileContents( | 280 bool VisualStudioWriter::WriteProjectFileContents( |
321 std::ostream& out, | 281 std::ostream& out, |
322 const SolutionProject& solution_project, | 282 const SolutionProject& solution_project, |
323 const Target* target, | 283 const Target* target, |
324 Err* err) { | 284 Err* err) { |
325 PathOutput path_output(GetTargetOutputDir(target), | 285 PathOutput path_output(GetTargetOutputDir(target), |
326 build_settings_->root_path_utf8(), | 286 build_settings_->root_path_utf8(), |
327 EscapingMode::ESCAPE_NONE); | 287 EscapingMode::ESCAPE_NONE); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 return false; | 565 return false; |
606 | 566 |
607 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); | 567 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); |
608 | 568 |
609 std::stringstream string_out; | 569 std::stringstream string_out; |
610 WriteSolutionFileContents(string_out, sln_path.DirName()); | 570 WriteSolutionFileContents(string_out, sln_path.DirName()); |
611 | 571 |
612 // Only write the content to the file if it's different. That is | 572 // Only write the content to the file if it's different. That is |
613 // both a performance optimization and more importantly, prevents | 573 // both a performance optimization and more importantly, prevents |
614 // Visual Studio from reloading the projects. | 574 // Visual Studio from reloading the projects. |
615 if (HasSameContent(string_out, sln_path)) | 575 return WriteFileIfChanged(sln_path, string_out.str(), err); |
616 return true; | |
617 | |
618 std::string content = string_out.str(); | |
619 int size = static_cast<int>(content.size()); | |
620 if (base::WriteFile(sln_path, content.c_str(), size) != size) { | |
621 *err = Err(Location(), "Couldn't open all.sln for writing"); | |
622 return false; | |
623 } | |
624 | |
625 return true; | |
626 } | 576 } |
627 | 577 |
628 void VisualStudioWriter::WriteSolutionFileContents( | 578 void VisualStudioWriter::WriteSolutionFileContents( |
629 std::ostream& out, | 579 std::ostream& out, |
630 const base::FilePath& solution_dir_path) { | 580 const base::FilePath& solution_dir_path) { |
631 out << "Microsoft Visual Studio Solution File, Format Version 12.00" | 581 out << "Microsoft Visual Studio Solution File, Format Version 12.00" |
632 << std::endl; | 582 << std::endl; |
633 out << "# Visual Studio 2015" << std::endl; | 583 out << "# Visual Studio 2015" << std::endl; |
634 | 584 |
635 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); | 585 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 base::CompareCase::SENSITIVE)) { | 723 base::CompareCase::SENSITIVE)) { |
774 folder->parent_folder = parents.back(); | 724 folder->parent_folder = parents.back(); |
775 break; | 725 break; |
776 } else { | 726 } else { |
777 parents.pop_back(); | 727 parents.pop_back(); |
778 } | 728 } |
779 } | 729 } |
780 parents.push_back(folder); | 730 parents.push_back(folder); |
781 } | 731 } |
782 } | 732 } |
OLD | NEW |