Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: tools/gn/visual_studio_writer.cc

Issue 1883593004: GN: Use std::unique_ptr for owned pointers in VisualStudioWriter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix bug Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/visual_studio_writer.h ('k') | tools/gn/visual_studio_writer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <iterator>
8 #include <map> 9 #include <map>
9 #include <memory> 10 #include <memory>
10 #include <set> 11 #include <set>
11 #include <string> 12 #include <string>
12 13
13 #include "base/logging.h" 14 #include "base/logging.h"
14 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
17 #include "tools/gn/builder.h" 18 #include "tools/gn/builder.h"
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 version_string_ = kVersionStringVs2015; 205 version_string_ = kVersionStringVs2015;
205 break; 206 break;
206 default: 207 default:
207 NOTREACHED() << "Not a valid Visual Studio Version: " << version; 208 NOTREACHED() << "Not a valid Visual Studio Version: " << version;
208 } 209 }
209 210
210 windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs(); 211 windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs();
211 } 212 }
212 213
213 VisualStudioWriter::~VisualStudioWriter() { 214 VisualStudioWriter::~VisualStudioWriter() {
214 STLDeleteContainerPointers(projects_.begin(), projects_.end());
215 STLDeleteContainerPointers(folders_.begin(), folders_.end());
216 } 215 }
217 216
218 // static 217 // static
219 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings, 218 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings,
220 Builder* builder, 219 Builder* builder,
221 Version version, 220 Version version,
222 const std::string& sln_name, 221 const std::string& sln_name,
223 const std::string& dir_filters, 222 const std::string& dir_filters,
224 Err* err) { 223 Err* err) {
225 std::vector<const Target*> targets; 224 std::vector<const Target*> targets;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 } 273 }
275 274
276 if (writer.projects_.empty()) { 275 if (writer.projects_.empty()) {
277 *err = Err(Location(), "No Visual Studio projects generated."); 276 *err = Err(Location(), "No Visual Studio projects generated.");
278 return false; 277 return false;
279 } 278 }
280 279
281 // Sort projects so they appear always in the same order in solution file. 280 // Sort projects so they appear always in the same order in solution file.
282 // Otherwise solution file is rewritten and reloaded by Visual Studio. 281 // Otherwise solution file is rewritten and reloaded by Visual Studio.
283 std::sort(writer.projects_.begin(), writer.projects_.end(), 282 std::sort(writer.projects_.begin(), writer.projects_.end(),
284 [](const SolutionEntry* a, const SolutionEntry* b) { 283 [](const std::unique_ptr<SolutionProject>& a,
284 const std::unique_ptr<SolutionProject>& b) {
285 return a->path < b->path; 285 return a->path < b->path;
286 }); 286 });
287 287
288 writer.ResolveSolutionFolders(); 288 writer.ResolveSolutionFolders();
289 return writer.WriteSolutionFile(sln_name, err); 289 return writer.WriteSolutionFile(sln_name, err);
290 } 290 }
291 291
292 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) { 292 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
293 std::string project_name = target->label().name(); 293 std::string project_name = target->label().name();
294 const char* project_config_platform = config_platform_; 294 const char* project_config_platform = config_platform_;
295 if (!target->settings()->is_default()) { 295 if (!target->settings()->is_default()) {
296 project_name += "_" + target->toolchain()->label().name(); 296 project_name += "_" + target->toolchain()->label().name();
297 const Value* value = 297 const Value* value =
298 target->settings()->base_config()->GetValue(variables::kCurrentCpu); 298 target->settings()->base_config()->GetValue(variables::kCurrentCpu);
299 if (value != nullptr && value->string_value() == "x64") 299 if (value != nullptr && value->string_value() == "x64")
300 project_config_platform = "x64"; 300 project_config_platform = "x64";
301 else 301 else
302 project_config_platform = "Win32"; 302 project_config_platform = "Win32";
303 } 303 }
304 304
305 SourceFile target_file = GetTargetOutputDir(target).ResolveRelativeFile( 305 SourceFile target_file = GetTargetOutputDir(target).ResolveRelativeFile(
306 Value(nullptr, project_name + ".vcxproj"), err); 306 Value(nullptr, project_name + ".vcxproj"), err);
307 if (target_file.is_null()) 307 if (target_file.is_null())
308 return false; 308 return false;
309 309
310 base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file); 310 base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file);
311 std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path); 311 std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path);
312 312
313 projects_.push_back(new SolutionProject( 313 projects_.emplace_back(new SolutionProject(
314 project_name, vcxproj_path_str, 314 project_name, vcxproj_path_str,
315 MakeGuid(vcxproj_path_str, kGuidSeedProject), 315 MakeGuid(vcxproj_path_str, kGuidSeedProject),
316 FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())), 316 FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())),
317 project_config_platform)); 317 project_config_platform));
318 318
319 std::stringstream vcxproj_string_out; 319 std::stringstream vcxproj_string_out;
320 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, 320 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target,
321 err)) { 321 err)) {
322 projects_.pop_back(); 322 projects_.pop_back();
323 return false; 323 return false;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 } 641 }
642 642
643 void VisualStudioWriter::WriteSolutionFileContents( 643 void VisualStudioWriter::WriteSolutionFileContents(
644 std::ostream& out, 644 std::ostream& out,
645 const base::FilePath& solution_dir_path) { 645 const base::FilePath& solution_dir_path) {
646 out << "Microsoft Visual Studio Solution File, Format Version 12.00" 646 out << "Microsoft Visual Studio Solution File, Format Version 12.00"
647 << std::endl; 647 << std::endl;
648 out << "# " << version_string_ << std::endl; 648 out << "# " << version_string_ << std::endl;
649 649
650 SourceDir solution_dir(FilePathToUTF8(solution_dir_path)); 650 SourceDir solution_dir(FilePathToUTF8(solution_dir_path));
651 for (const SolutionEntry* folder : folders_) { 651 for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
652 out << "Project(\"" << kGuidTypeFolder << "\") = \"(" << folder->name 652 out << "Project(\"" << kGuidTypeFolder << "\") = \"(" << folder->name
653 << ")\", \"" << RebasePath(folder->path, solution_dir) << "\", \"" 653 << ")\", \"" << RebasePath(folder->path, solution_dir) << "\", \""
654 << folder->guid << "\"" << std::endl; 654 << folder->guid << "\"" << std::endl;
655 out << "EndProject" << std::endl; 655 out << "EndProject" << std::endl;
656 } 656 }
657 657
658 for (const SolutionEntry* project : projects_) { 658 for (const std::unique_ptr<SolutionProject>& project : projects_) {
659 out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name 659 out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name
660 << "\", \"" << RebasePath(project->path, solution_dir) << "\", \"" 660 << "\", \"" << RebasePath(project->path, solution_dir) << "\", \""
661 << project->guid << "\"" << std::endl; 661 << project->guid << "\"" << std::endl;
662 out << "EndProject" << std::endl; 662 out << "EndProject" << std::endl;
663 } 663 }
664 664
665 out << "Global" << std::endl; 665 out << "Global" << std::endl;
666 666
667 out << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" 667 out << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"
668 << std::endl; 668 << std::endl;
669 const std::string config_mode_prefix = std::string(kConfigurationName) + '|'; 669 const std::string config_mode_prefix = std::string(kConfigurationName) + '|';
670 const std::string config_mode = config_mode_prefix + config_platform_; 670 const std::string config_mode = config_mode_prefix + config_platform_;
671 out << "\t\t" << config_mode << " = " << config_mode << std::endl; 671 out << "\t\t" << config_mode << " = " << config_mode << std::endl;
672 out << "\tEndGlobalSection" << std::endl; 672 out << "\tEndGlobalSection" << std::endl;
673 673
674 out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" 674 out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"
675 << std::endl; 675 << std::endl;
676 for (const SolutionProject* project : projects_) { 676 for (const std::unique_ptr<SolutionProject>& project : projects_) {
677 const std::string project_config_mode = 677 const std::string project_config_mode =
678 config_mode_prefix + project->config_platform; 678 config_mode_prefix + project->config_platform;
679 out << "\t\t" << project->guid << '.' << config_mode 679 out << "\t\t" << project->guid << '.' << config_mode
680 << ".ActiveCfg = " << project_config_mode << std::endl; 680 << ".ActiveCfg = " << project_config_mode << std::endl;
681 out << "\t\t" << project->guid << '.' << config_mode 681 out << "\t\t" << project->guid << '.' << config_mode
682 << ".Build.0 = " << project_config_mode << std::endl; 682 << ".Build.0 = " << project_config_mode << std::endl;
683 } 683 }
684 out << "\tEndGlobalSection" << std::endl; 684 out << "\tEndGlobalSection" << std::endl;
685 685
686 out << "\tGlobalSection(SolutionProperties) = preSolution" << std::endl; 686 out << "\tGlobalSection(SolutionProperties) = preSolution" << std::endl;
687 out << "\t\tHideSolutionNode = FALSE" << std::endl; 687 out << "\t\tHideSolutionNode = FALSE" << std::endl;
688 out << "\tEndGlobalSection" << std::endl; 688 out << "\tEndGlobalSection" << std::endl;
689 689
690 out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl; 690 out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl;
691 for (const SolutionEntry* folder : folders_) { 691 for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
692 if (folder->parent_folder) { 692 if (folder->parent_folder) {
693 out << "\t\t" << folder->guid << " = " << folder->parent_folder->guid 693 out << "\t\t" << folder->guid << " = " << folder->parent_folder->guid
694 << std::endl; 694 << std::endl;
695 } 695 }
696 } 696 }
697 for (const SolutionEntry* project : projects_) { 697 for (const std::unique_ptr<SolutionProject>& project : projects_) {
698 out << "\t\t" << project->guid << " = " << project->parent_folder->guid 698 out << "\t\t" << project->guid << " = " << project->parent_folder->guid
699 << std::endl; 699 << std::endl;
700 } 700 }
701 out << "\tEndGlobalSection" << std::endl; 701 out << "\tEndGlobalSection" << std::endl;
702 702
703 out << "EndGlobal" << std::endl; 703 out << "EndGlobal" << std::endl;
704 } 704 }
705 705
706 void VisualStudioWriter::ResolveSolutionFolders() { 706 void VisualStudioWriter::ResolveSolutionFolders() {
707 root_folder_path_.clear(); 707 root_folder_path_.clear();
708 708
709 // Get all project directories. Create solution folder for each directory. 709 // Get all project directories. Create solution folder for each directory.
710 std::map<base::StringPiece, SolutionEntry*> processed_paths; 710 std::map<base::StringPiece, SolutionEntry*> processed_paths;
711 for (SolutionProject* project : projects_) { 711 for (const std::unique_ptr<SolutionProject>& project : projects_) {
712 base::StringPiece folder_path = project->label_dir_path; 712 base::StringPiece folder_path = project->label_dir_path;
713 if (IsSlash(folder_path[folder_path.size() - 1])) 713 if (IsSlash(folder_path[folder_path.size() - 1]))
714 folder_path = folder_path.substr(0, folder_path.size() - 1); 714 folder_path = folder_path.substr(0, folder_path.size() - 1);
715 auto it = processed_paths.find(folder_path); 715 auto it = processed_paths.find(folder_path);
716 if (it != processed_paths.end()) { 716 if (it != processed_paths.end()) {
717 project->parent_folder = it->second; 717 project->parent_folder = it->second;
718 } else { 718 } else {
719 std::string folder_path_str = folder_path.as_string(); 719 std::string folder_path_str = folder_path.as_string();
720 SolutionEntry* folder = new SolutionEntry( 720 std::unique_ptr<SolutionEntry> folder(new SolutionEntry(
721 FindLastDirComponent(SourceDir(folder_path)).as_string(), 721 FindLastDirComponent(SourceDir(folder_path)).as_string(),
722 folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder)); 722 folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder)));
723 folders_.push_back(folder); 723 project->parent_folder = folder.get();
724 project->parent_folder = folder; 724 processed_paths[folder_path] = folder.get();
725 processed_paths[folder_path] = folder; 725 folders_.push_back(std::move(folder));
726 726
727 if (root_folder_path_.empty()) { 727 if (root_folder_path_.empty()) {
728 root_folder_path_ = folder_path_str; 728 root_folder_path_ = folder_path_str;
729 } else { 729 } else {
730 size_t common_prefix_len = 0; 730 size_t common_prefix_len = 0;
731 size_t max_common_length = 731 size_t max_common_length =
732 std::min(root_folder_path_.size(), folder_path.size()); 732 std::min(root_folder_path_.size(), folder_path.size());
733 size_t i; 733 size_t i;
734 for (i = common_prefix_len; i < max_common_length; ++i) { 734 for (i = common_prefix_len; i < max_common_length; ++i) {
735 if (IsSlash(root_folder_path_[i]) && IsSlash(folder_path[i])) 735 if (IsSlash(root_folder_path_[i]) && IsSlash(folder_path[i]))
736 common_prefix_len = i + 1; 736 common_prefix_len = i + 1;
737 else if (root_folder_path_[i] != folder_path[i]) 737 else if (root_folder_path_[i] != folder_path[i])
738 break; 738 break;
739 } 739 }
740 if (i == max_common_length && 740 if (i == max_common_length &&
741 (i == folder_path.size() || IsSlash(folder_path[i]))) 741 (i == folder_path.size() || IsSlash(folder_path[i])))
742 common_prefix_len = max_common_length; 742 common_prefix_len = max_common_length;
743 if (common_prefix_len < root_folder_path_.size()) { 743 if (common_prefix_len < root_folder_path_.size()) {
744 if (IsSlash(root_folder_path_[common_prefix_len - 1])) 744 if (IsSlash(root_folder_path_[common_prefix_len - 1]))
745 --common_prefix_len; 745 --common_prefix_len;
746 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len); 746 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len);
747 } 747 }
748 } 748 }
749 } 749 }
750 } 750 }
751 751
752 // Create also all parent folders up to |root_folder_path_|. 752 // Create also all parent folders up to |root_folder_path_|.
753 SolutionFolders additional_folders; 753 SolutionFolders additional_folders;
754 for (SolutionEntry* folder : folders_) { 754 for (const std::unique_ptr<SolutionEntry>& solution_folder : folders_) {
755 if (folder->path == root_folder_path_) 755 if (solution_folder->path == root_folder_path_)
756 continue; 756 continue;
757 757
758 SolutionEntry* folder = solution_folder.get();
758 base::StringPiece parent_path; 759 base::StringPiece parent_path;
759 while ((parent_path = FindParentDir(&folder->path)) != root_folder_path_) { 760 while ((parent_path = FindParentDir(&folder->path)) != root_folder_path_) {
760 auto it = processed_paths.find(parent_path); 761 auto it = processed_paths.find(parent_path);
761 if (it != processed_paths.end()) { 762 if (it != processed_paths.end()) {
762 folder = it->second; 763 folder = it->second;
763 } else { 764 } else {
764 folder = new SolutionEntry( 765 std::unique_ptr<SolutionEntry> new_folder(new SolutionEntry(
765 FindLastDirComponent(SourceDir(parent_path)).as_string(), 766 FindLastDirComponent(SourceDir(parent_path)).as_string(),
766 parent_path.as_string(), 767 parent_path.as_string(),
767 MakeGuid(parent_path.as_string(), kGuidSeedFolder)); 768 MakeGuid(parent_path.as_string(), kGuidSeedFolder)));
768 additional_folders.push_back(folder); 769 processed_paths[parent_path] = new_folder.get();
769 processed_paths[parent_path] = folder; 770 folder = new_folder.get();
771 additional_folders.push_back(std::move(new_folder));
770 } 772 }
771 } 773 }
772 } 774 }
773 folders_.insert(folders_.end(), additional_folders.begin(), 775 folders_.insert(folders_.end(),
774 additional_folders.end()); 776 std::make_move_iterator(additional_folders.begin()),
777 std::make_move_iterator(additional_folders.end()));
775 778
776 // Sort folders by path. 779 // Sort folders by path.
777 std::sort(folders_.begin(), folders_.end(), 780 std::sort(folders_.begin(), folders_.end(),
778 [](const SolutionEntry* a, const SolutionEntry* b) { 781 [](const std::unique_ptr<SolutionEntry>& a,
782 const std::unique_ptr<SolutionEntry>& b) {
779 return a->path < b->path; 783 return a->path < b->path;
780 }); 784 });
781 785
782 // Match subfolders with their parents. Since |folders_| are sorted by path we 786 // Match subfolders with their parents. Since |folders_| are sorted by path we
783 // know that parent folder always precedes its children in vector. 787 // know that parent folder always precedes its children in vector.
784 SolutionFolders parents; 788 std::vector<SolutionEntry*> parents;
785 for (SolutionEntry* folder : folders_) { 789 for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
786 while (!parents.empty()) { 790 while (!parents.empty()) {
787 if (base::StartsWith(folder->path, parents.back()->path, 791 if (base::StartsWith(folder->path, parents.back()->path,
788 base::CompareCase::SENSITIVE)) { 792 base::CompareCase::SENSITIVE)) {
789 folder->parent_folder = parents.back(); 793 folder->parent_folder = parents.back();
790 break; 794 break;
791 } else { 795 } else {
792 parents.pop_back(); 796 parents.pop_back();
793 } 797 }
794 } 798 }
795 parents.push_back(folder); 799 parents.push_back(folder.get());
796 } 800 }
797 } 801 }
798 802
799 std::string VisualStudioWriter::GetNinjaTarget(const Target* target) { 803 std::string VisualStudioWriter::GetNinjaTarget(const Target* target) {
800 std::ostringstream ninja_target_out; 804 std::ostringstream ninja_target_out;
801 DCHECK(!target->dependency_output_file().value().empty()); 805 DCHECK(!target->dependency_output_file().value().empty());
802 ninja_path_output_.WriteFile(ninja_target_out, 806 ninja_path_output_.WriteFile(ninja_target_out,
803 target->dependency_output_file()); 807 target->dependency_output_file());
804 return ninja_target_out.str(); 808 return ninja_target_out.str();
805 } 809 }
OLDNEW
« no previous file with comments | « tools/gn/visual_studio_writer.h ('k') | tools/gn/visual_studio_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698