| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 std::stringstream vcxproj_string_out; | 237 std::stringstream vcxproj_string_out; |
| 259 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, | 238 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, |
| 260 err)) { | 239 err)) { |
| 261 projects_.pop_back(); | 240 projects_.pop_back(); |
| 262 return false; | 241 return false; |
| 263 } | 242 } |
| 264 | 243 |
| 265 // Only write the content to the file if it's different. That is | 244 // Only write the content to the file if it's different. That is |
| 266 // both a performance optimization and more importantly, prevents | 245 // both a performance optimization and more importantly, prevents |
| 267 // Visual Studio from reloading the projects. | 246 // Visual Studio from reloading the projects. |
| 268 if (!HasSameContent(vcxproj_string_out, vcxproj_path)) { | 247 if (!WriteFileIfChanged(vcxproj_path, &vcxproj_string_out)) { |
| 269 std::string content = vcxproj_string_out.str(); | 248 *err = Err(Location(), |
| 270 int size = static_cast<int>(content.size()); | 249 "Couldn't write " + target->label().name() + ".vcxproj"); |
| 271 if (base::WriteFile(vcxproj_path, content.c_str(), size) != size) { | 250 return false; |
| 272 *err = Err(Location(), "Couldn't open " + target->label().name() + | |
| 273 ".vcxproj for writing"); | |
| 274 return false; | |
| 275 } | |
| 276 } | 251 } |
| 277 | 252 |
| 278 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); | 253 base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters"); |
| 279 | 254 |
| 280 std::stringstream filters_string_out; | 255 std::stringstream filters_string_out; |
| 281 WriteFiltersFileContents(filters_string_out, target); | 256 WriteFiltersFileContents(filters_string_out, target); |
| 282 | 257 |
| 283 if (!HasSameContent(filters_string_out, filters_path)) { | 258 if (!WriteFileIfChanged(filters_path, &filters_string_out)) { |
| 284 std::string content = filters_string_out.str(); | 259 *err = Err(Location(), |
| 285 int size = static_cast<int>(content.size()); | 260 "Couldn't write " + target->label().name() + ".vcxproj.filters"); |
| 286 if (base::WriteFile(filters_path, content.c_str(), size) != size) { | |
| 287 *err = Err(Location(), "Couldn't open " + target->label().name() + | |
| 288 ".vcxproj.filters for writing"); | |
| 289 return false; | |
| 290 } | |
| 291 } | 261 } |
| 292 | 262 |
| 293 return true; | 263 return true; |
| 294 } | 264 } |
| 295 | 265 |
| 296 bool VisualStudioWriter::WriteProjectFileContents( | 266 bool VisualStudioWriter::WriteProjectFileContents( |
| 297 std::ostream& out, | 267 std::ostream& out, |
| 298 const SolutionEntry& solution_project, | 268 const SolutionEntry& solution_project, |
| 299 const Target* target, | 269 const Target* target, |
| 300 Err* err) { | 270 Err* err) { |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 return false; | 549 return false; |
| 580 | 550 |
| 581 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); | 551 base::FilePath sln_path = build_settings_->GetFullPath(sln_file); |
| 582 | 552 |
| 583 std::stringstream string_out; | 553 std::stringstream string_out; |
| 584 WriteSolutionFileContents(string_out, sln_path.DirName()); | 554 WriteSolutionFileContents(string_out, sln_path.DirName()); |
| 585 | 555 |
| 586 // Only write the content to the file if it's different. That is | 556 // Only write the content to the file if it's different. That is |
| 587 // both a performance optimization and more importantly, prevents | 557 // both a performance optimization and more importantly, prevents |
| 588 // Visual Studio from reloading the projects. | 558 // Visual Studio from reloading the projects. |
| 589 if (HasSameContent(string_out, sln_path)) | 559 if (!WriteFileIfChanged(sln_path, &string_out)) { |
| 590 return true; | 560 *err = Err(Location(), "Couldn't write all.sln"); |
| 591 | |
| 592 std::string content = string_out.str(); | |
| 593 int size = static_cast<int>(content.size()); | |
| 594 if (base::WriteFile(sln_path, content.c_str(), size) != size) { | |
| 595 *err = Err(Location(), "Couldn't open all.sln for writing"); | |
| 596 return false; | 561 return false; |
| 597 } | 562 } |
| 598 | 563 |
| 599 return true; | 564 return true; |
| 600 } | 565 } |
| 601 | 566 |
| 602 void VisualStudioWriter::WriteSolutionFileContents( | 567 void VisualStudioWriter::WriteSolutionFileContents( |
| 603 std::ostream& out, | 568 std::ostream& out, |
| 604 const base::FilePath& solution_dir_path) { | 569 const base::FilePath& solution_dir_path) { |
| 605 out << "Microsoft Visual Studio Solution File, Format Version 12.00" | 570 out << "Microsoft Visual Studio Solution File, Format Version 12.00" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 base::CompareCase::SENSITIVE)) { | 710 base::CompareCase::SENSITIVE)) { |
| 746 folder->parent_folder = parents.back(); | 711 folder->parent_folder = parents.back(); |
| 747 break; | 712 break; |
| 748 } else { | 713 } else { |
| 749 parents.pop_back(); | 714 parents.pop_back(); |
| 750 } | 715 } |
| 751 } | 716 } |
| 752 parents.push_back(folder); | 717 parents.push_back(folder); |
| 753 } | 718 } |
| 754 } | 719 } |
| OLD | NEW |