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" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
16 #include "tools/gn/builder.h" | 17 #include "tools/gn/builder.h" |
17 #include "tools/gn/config.h" | 18 #include "tools/gn/config.h" |
18 #include "tools/gn/config_values_extractors.h" | 19 #include "tools/gn/config_values_extractors.h" |
19 #include "tools/gn/filesystem_utils.h" | 20 #include "tools/gn/filesystem_utils.h" |
20 #include "tools/gn/parse_tree.h" | 21 #include "tools/gn/parse_tree.h" |
21 #include "tools/gn/path_output.h" | 22 #include "tools/gn/path_output.h" |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 // outlive the output. | 146 // outlive the output. |
146 base::StringPiece FindParentDir(const std::string* path) { | 147 base::StringPiece FindParentDir(const std::string* path) { |
147 DCHECK(path && !path->empty()); | 148 DCHECK(path && !path->empty()); |
148 for (int i = static_cast<int>(path->size()) - 2; i >= 0; --i) { | 149 for (int i = static_cast<int>(path->size()) - 2; i >= 0; --i) { |
149 if (IsSlash((*path)[i])) | 150 if (IsSlash((*path)[i])) |
150 return base::StringPiece(path->data(), i); | 151 return base::StringPiece(path->data(), i); |
151 } | 152 } |
152 return base::StringPiece(); | 153 return base::StringPiece(); |
153 } | 154 } |
154 | 155 |
| 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 |
155 } // namespace | 176 } // namespace |
156 | 177 |
157 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name, | 178 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name, |
158 const std::string& _path, | 179 const std::string& _path, |
159 const std::string& _guid) | 180 const std::string& _guid) |
160 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {} | 181 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {} |
161 | 182 |
162 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default; | 183 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default; |
163 | 184 |
164 VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings) | 185 VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 std::stringstream vcxproj_string_out; | 265 std::stringstream vcxproj_string_out; |
245 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, | 266 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, |
246 err)) { | 267 err)) { |
247 projects_.pop_back(); | 268 projects_.pop_back(); |
248 return false; | 269 return false; |
249 } | 270 } |
250 | 271 |
251 // Only write the content to the file if it's different. That is | 272 // Only write the content to the file if it's different. That is |
252 // both a performance optimization and more importantly, prevents | 273 // both a performance optimization and more importantly, prevents |
253 // Visual Studio from reloading the projects. | 274 // Visual Studio from reloading the projects. |
254 if (!WriteFileIfChanged(vcxproj_path, vcxproj_string_out.str(), err)) | 275 if (!HasSameContent(vcxproj_string_out, vcxproj_path)) { |
255 return false; | 276 std::string content = vcxproj_string_out.str(); |
| 277 int size = static_cast<int>(content.size()); |
| 278 if (base::WriteFile(vcxproj_path, content.c_str(), size) != size) { |
| 279 *err = Err(Location(), "Couldn't open " + target->label().name() + |
| 280 ".vcxproj for writing"); |
| 281 return false; |
| 282 } |
| 283 } |
256 | 284 |
257 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); | 285 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); |
| 286 |
258 std::stringstream filters_string_out; | 287 std::stringstream filters_string_out; |
259 WriteFiltersFileContents(filters_string_out, target); | 288 WriteFiltersFileContents(filters_string_out, target); |
260 return WriteFileIfChanged(filters_path, filters_string_out.str(), err); | 289 |
| 290 if (!HasSameContent(filters_string_out, filters_path)) { |
| 291 std::string content = filters_string_out.str(); |
| 292 int size = static_cast<int>(content.size()); |
| 293 if (base::WriteFile(filters_path, content.c_str(), size) != size) { |
| 294 *err = Err(Location(), "Couldn't open " + target->label().name() + |
| 295 ".vcxproj.filters for writing"); |
| 296 return false; |
| 297 } |
| 298 } |
| 299 |
| 300 return true; |
261 } | 301 } |
262 | 302 |
263 bool VisualStudioWriter::WriteProjectFileContents( | 303 bool VisualStudioWriter::WriteProjectFileContents( |
264 std::ostream& out, | 304 std::ostream& out, |
265 const SolutionEntry& solution_project, | 305 const SolutionEntry& solution_project, |
266 const Target* target, | 306 const Target* target, |
267 Err* err) { | 307 Err* err) { |
268 PathOutput path_output(GetTargetOutputDir(target), | 308 PathOutput path_output(GetTargetOutputDir(target), |
269 build_settings_->root_path_utf8(), | 309 build_settings_->root_path_utf8(), |
270 EscapingMode::ESCAPE_NONE); | 310 EscapingMode::ESCAPE_NONE); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 return false; | 586 return false; |
547 | 587 |
548 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); | 588 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); |
549 | 589 |
550 std::stringstream string_out; | 590 std::stringstream string_out; |
551 WriteSolutionFileContents(string_out, sln_path.DirName()); | 591 WriteSolutionFileContents(string_out, sln_path.DirName()); |
552 | 592 |
553 // Only write the content to the file if it's different. That is | 593 // Only write the content to the file if it's different. That is |
554 // both a performance optimization and more importantly, prevents | 594 // both a performance optimization and more importantly, prevents |
555 // Visual Studio from reloading the projects. | 595 // Visual Studio from reloading the projects. |
556 return WriteFileIfChanged(sln_path, string_out.str(), err); | 596 if (HasSameContent(string_out, sln_path)) |
| 597 return true; |
| 598 |
| 599 std::string content = string_out.str(); |
| 600 int size = static_cast<int>(content.size()); |
| 601 if (base::WriteFile(sln_path, content.c_str(), size) != size) { |
| 602 *err = Err(Location(), "Couldn't open all.sln for writing"); |
| 603 return false; |
| 604 } |
| 605 |
| 606 return true; |
557 } | 607 } |
558 | 608 |
559 void VisualStudioWriter::WriteSolutionFileContents( | 609 void VisualStudioWriter::WriteSolutionFileContents( |
560 std::ostream& out, | 610 std::ostream& out, |
561 const base::FilePath& solution_dir_path) { | 611 const base::FilePath& solution_dir_path) { |
562 out << "Microsoft Visual Studio Solution File, Format Version 12.00" | 612 out << "Microsoft Visual Studio Solution File, Format Version 12.00" |
563 << std::endl; | 613 << std::endl; |
564 out << "# Visual Studio 2015" << std::endl; | 614 out << "# Visual Studio 2015" << std::endl; |
565 | 615 |
566 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); | 616 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 base::CompareCase::SENSITIVE)) { | 752 base::CompareCase::SENSITIVE)) { |
703 folder->parent_folder = parents.back(); | 753 folder->parent_folder = parents.back(); |
704 break; | 754 break; |
705 } else { | 755 } else { |
706 parents.pop_back(); | 756 parents.pop_back(); |
707 } | 757 } |
708 } | 758 } |
709 parents.push_back(folder); | 759 parents.push_back(folder); |
710 } | 760 } |
711 } | 761 } |
OLD | NEW |