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::VisualStudioWriter(const BuildSettings* build_settings) | 164 VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 std::stringstream vcxproj_string_out; | 244 std::stringstream vcxproj_string_out; |
266 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, | 245 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, |
267 err)) { | 246 err)) { |
268 projects_.pop_back(); | 247 projects_.pop_back(); |
269 return false; | 248 return false; |
270 } | 249 } |
271 | 250 |
272 // Only write the content to the file if it's different. That is | 251 // Only write the content to the file if it's different. That is |
273 // both a performance optimization and more importantly, prevents | 252 // both a performance optimization and more importantly, prevents |
274 // Visual Studio from reloading the projects. | 253 // Visual Studio from reloading the projects. |
275 if (!HasSameContent(vcxproj_string_out, vcxproj_path)) { | 254 if (!WriteFileIfChanged(vcxproj_path, vcxproj_string_out.str(), err)) |
276 std::string content = vcxproj_string_out.str(); | 255 return false; |
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 } | |
284 | 256 |
285 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); | 257 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); |
286 | |
287 std::stringstream filters_string_out; | 258 std::stringstream filters_string_out; |
288 WriteFiltersFileContents(filters_string_out, target); | 259 WriteFiltersFileContents(filters_string_out, target); |
289 | 260 return WriteFileIfChanged(filters_path, filters_string_out.str(), err); |
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; | |
301 } | 261 } |
302 | 262 |
303 bool VisualStudioWriter::WriteProjectFileContents( | 263 bool VisualStudioWriter::WriteProjectFileContents( |
304 std::ostream& out, | 264 std::ostream& out, |
305 const SolutionEntry& solution_project, | 265 const SolutionEntry& solution_project, |
306 const Target* target, | 266 const Target* target, |
307 Err* err) { | 267 Err* err) { |
308 PathOutput path_output(GetTargetOutputDir(target), | 268 PathOutput path_output(GetTargetOutputDir(target), |
309 build_settings_->root_path_utf8(), | 269 build_settings_->root_path_utf8(), |
310 EscapingMode::ESCAPE_NONE); | 270 EscapingMode::ESCAPE_NONE); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 return false; | 546 return false; |
587 | 547 |
588 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); | 548 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); |
589 | 549 |
590 std::stringstream string_out; | 550 std::stringstream string_out; |
591 WriteSolutionFileContents(string_out, sln_path.DirName()); | 551 WriteSolutionFileContents(string_out, sln_path.DirName()); |
592 | 552 |
593 // Only write the content to the file if it's different. That is | 553 // Only write the content to the file if it's different. That is |
594 // both a performance optimization and more importantly, prevents | 554 // both a performance optimization and more importantly, prevents |
595 // Visual Studio from reloading the projects. | 555 // Visual Studio from reloading the projects. |
596 if (HasSameContent(string_out, sln_path)) | 556 return WriteFileIfChanged(sln_path, string_out.str(), err); |
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; | |
607 } | 557 } |
608 | 558 |
609 void VisualStudioWriter::WriteSolutionFileContents( | 559 void VisualStudioWriter::WriteSolutionFileContents( |
610 std::ostream& out, | 560 std::ostream& out, |
611 const base::FilePath& solution_dir_path) { | 561 const base::FilePath& solution_dir_path) { |
612 out << "Microsoft Visual Studio Solution File, Format Version 12.00" | 562 out << "Microsoft Visual Studio Solution File, Format Version 12.00" |
613 << std::endl; | 563 << std::endl; |
614 out << "# Visual Studio 2015" << std::endl; | 564 out << "# Visual Studio 2015" << std::endl; |
615 | 565 |
616 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); | 566 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
752 base::CompareCase::SENSITIVE)) { | 702 base::CompareCase::SENSITIVE)) { |
753 folder->parent_folder = parents.back(); | 703 folder->parent_folder = parents.back(); |
754 break; | 704 break; |
755 } else { | 705 } else { |
756 parents.pop_back(); | 706 parents.pop_back(); |
757 } | 707 } |
758 } | 708 } |
759 parents.push_back(folder); | 709 parents.push_back(folder); |
760 } | 710 } |
761 } | 711 } |
OLD | NEW |