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

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

Issue 1667773002: Support different project toolchains (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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 <map> 8 #include <map>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 175
176 } // namespace 176 } // namespace
177 177
178 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name, 178 VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name,
179 const std::string& _path, 179 const std::string& _path,
180 const std::string& _guid) 180 const std::string& _guid)
181 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {} 181 : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {}
182 182
183 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default; 183 VisualStudioWriter::SolutionEntry::~SolutionEntry() = default;
184 184
185 VisualStudioWriter::SolutionProject::SolutionProject(
186 const std::string& _name,
187 const std::string& _path,
188 const std::string& _guid,
189 const std::string& _label_dir_path,
190 const std::string& _config_platform)
191 : SolutionEntry(_name, _path, _guid),
192 label_dir_path(_label_dir_path),
193 config_platform(_config_platform) {}
194
195 VisualStudioWriter::SolutionProject::~SolutionProject() = default;
196
185 VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings) 197 VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings)
186 : build_settings_(build_settings) { 198 : build_settings_(build_settings) {
187 const Value* value = build_settings->build_args().GetArgOverride("is_debug"); 199 const Value* value = build_settings->build_args().GetArgOverride("is_debug");
188 is_debug_config_ = value == nullptr || value->boolean_value(); 200 is_debug_config_ = value == nullptr || value->boolean_value();
189 config_platform_ = "Win32"; 201 config_platform_ = "Win32";
190 value = build_settings->build_args().GetArgOverride(variables::kTargetCpu); 202 value = build_settings->build_args().GetArgOverride(variables::kTargetCpu);
191 if (value != nullptr && value->string_value() == "x64") 203 if (value != nullptr && value->string_value() == "x64")
192 config_platform_ = "x64"; 204 config_platform_ = "x64";
193 205
194 windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs(); 206 windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs();
195 } 207 }
196 208
197 VisualStudioWriter::~VisualStudioWriter() { 209 VisualStudioWriter::~VisualStudioWriter() {
198 STLDeleteContainerPointers(projects_.begin(), projects_.end()); 210 STLDeleteContainerPointers(projects_.begin(), projects_.end());
199 STLDeleteContainerPointers(folders_.begin(), folders_.end()); 211 STLDeleteContainerPointers(folders_.begin(), folders_.end());
200 } 212 }
201 213
202 // static 214 // static
203 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings, 215 bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings,
204 Builder* builder, 216 Builder* builder,
205 Err* err) { 217 Err* err) {
206 std::vector<const Target*> targets = builder->GetAllResolvedTargets(); 218 std::vector<const Target*> targets = builder->GetAllResolvedTargets();
207 219
208 VisualStudioWriter writer(build_settings); 220 VisualStudioWriter writer(build_settings);
209 writer.projects_.reserve(targets.size()); 221 writer.projects_.reserve(targets.size());
210 writer.folders_.reserve(targets.size()); 222 writer.folders_.reserve(targets.size());
211 223
212 std::set<std::string> processed_targets;
213 for (const Target* target : targets) { 224 for (const Target* target : targets) {
214 // Skip targets which are duplicated in vector.
215 std::string target_path =
216 target->label().dir().value() + target->label().name();
217 if (processed_targets.find(target_path) != processed_targets.end())
218 continue;
219
220 // Skip actions and groups. 225 // Skip actions and groups.
221 if (target->output_type() == Target::GROUP || 226 if (target->output_type() == Target::GROUP ||
222 target->output_type() == Target::COPY_FILES || 227 target->output_type() == Target::COPY_FILES ||
223 target->output_type() == Target::ACTION || 228 target->output_type() == Target::ACTION ||
224 target->output_type() == Target::ACTION_FOREACH) { 229 target->output_type() == Target::ACTION_FOREACH) {
225 continue; 230 continue;
226 } 231 }
227 232
228 if (!writer.WriteProjectFiles(target, err)) 233 if (!writer.WriteProjectFiles(target, err))
229 return false; 234 return false;
230
231 processed_targets.insert(target_path);
232 } 235 }
233 236
234 if (writer.projects_.empty()) { 237 if (writer.projects_.empty()) {
235 *err = Err(Location(), "No Visual Studio projects generated."); 238 *err = Err(Location(), "No Visual Studio projects generated.");
236 return false; 239 return false;
237 } 240 }
238 241
239 writer.ResolveSolutionFolders(); 242 writer.ResolveSolutionFolders();
240 return writer.WriteSolutionFile(err); 243 return writer.WriteSolutionFile(err);
241 } 244 }
242 245
243 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) { 246 bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
247 std::string project_name = target->label().name();
248 std::string project_config_platform = config_platform_;
249 if (!target->settings()->is_default()) {
250 project_name += "_" + target->toolchain()->label().name();
251 project_config_platform = target->toolchain()
252 ->settings()
253 ->build_settings()
254 ->build_args()
255 .GetArgOverride(variables::kCurrentCpu)
256 ->string_value();
257 if (project_config_platform == "x86")
258 project_config_platform = "Win32";
259 }
260
244 SourceFile target_file = GetTargetOutputDir(target).ResolveRelativeFile( 261 SourceFile target_file = GetTargetOutputDir(target).ResolveRelativeFile(
245 Value(nullptr, target->label().name() + ".vcxproj"), err); 262 Value(nullptr, project_name + ".vcxproj"), err);
246 if (target_file.is_null()) 263 if (target_file.is_null())
247 return false; 264 return false;
248 265
249 base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file); 266 base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file);
250 std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path); 267 std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path);
251 268
252 projects_.push_back( 269 projects_.push_back(new SolutionProject(
253 new SolutionEntry(target->label().name(), vcxproj_path_str, 270 project_name, vcxproj_path_str,
254 MakeGuid(vcxproj_path_str, kGuidSeedProject))); 271 MakeGuid(vcxproj_path_str, kGuidSeedProject),
255 projects_.back()->label_dir_path = 272 FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())),
256 FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())); 273 project_config_platform));
257 274
258 std::stringstream vcxproj_string_out; 275 std::stringstream vcxproj_string_out;
259 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target, 276 if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target,
260 err)) { 277 err)) {
261 projects_.pop_back(); 278 projects_.pop_back();
262 return false; 279 return false;
263 } 280 }
264 281
265 // Only write the content to the file if it's different. That is 282 // Only write the content to the file if it's different. That is
266 // both a performance optimization and more importantly, prevents 283 // both a performance optimization and more importantly, prevents
(...skipping 21 matching lines...) Expand all
288 ".vcxproj.filters for writing"); 305 ".vcxproj.filters for writing");
289 return false; 306 return false;
290 } 307 }
291 } 308 }
292 309
293 return true; 310 return true;
294 } 311 }
295 312
296 bool VisualStudioWriter::WriteProjectFileContents( 313 bool VisualStudioWriter::WriteProjectFileContents(
297 std::ostream& out, 314 std::ostream& out,
298 const SolutionEntry& solution_project, 315 const SolutionProject& solution_project,
299 const Target* target, 316 const Target* target,
300 Err* err) { 317 Err* err) {
301 PathOutput path_output(GetTargetOutputDir(target), 318 PathOutput path_output(GetTargetOutputDir(target),
302 build_settings_->root_path_utf8(), 319 build_settings_->root_path_utf8(),
303 EscapingMode::ESCAPE_NONE); 320 EscapingMode::ESCAPE_NONE);
304 321
305 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; 322 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
306 XmlElementWriter project( 323 XmlElementWriter project(
307 out, "Project", 324 out, "Project",
308 XmlAttributes("DefaultTargets", "Build") 325 XmlAttributes("DefaultTargets", "Build")
309 .add("ToolsVersion", kVisualStudioVersion) 326 .add("ToolsVersion", kVisualStudioVersion)
310 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")); 327 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"));
311 328
312 { 329 {
313 scoped_ptr<XmlElementWriter> configurations = project.SubElement( 330 scoped_ptr<XmlElementWriter> configurations = project.SubElement(
314 "ItemGroup", XmlAttributes("Label", "ProjectConfigurations")); 331 "ItemGroup", XmlAttributes("Label", "ProjectConfigurations"));
315 std::string config_name = is_debug_config_ ? "Debug" : "Release"; 332 std::string config_name = is_debug_config_ ? "Debug" : "Release";
316 scoped_ptr<XmlElementWriter> project_config = configurations->SubElement( 333 scoped_ptr<XmlElementWriter> project_config = configurations->SubElement(
317 "ProjectConfiguration", 334 "ProjectConfiguration",
318 XmlAttributes("Include", config_name + '|' + config_platform_)); 335 XmlAttributes("Include",
336 config_name + '|' + solution_project.config_platform));
319 project_config->SubElement("Configuration")->Text(config_name); 337 project_config->SubElement("Configuration")->Text(config_name);
320 project_config->SubElement("Platform")->Text(config_platform_); 338 project_config->SubElement("Platform")
339 ->Text(solution_project.config_platform);
321 } 340 }
322 341
323 { 342 {
324 scoped_ptr<XmlElementWriter> globals = 343 scoped_ptr<XmlElementWriter> globals =
325 project.SubElement("PropertyGroup", XmlAttributes("Label", "Globals")); 344 project.SubElement("PropertyGroup", XmlAttributes("Label", "Globals"));
326 globals->SubElement("ProjectGuid")->Text(solution_project.guid); 345 globals->SubElement("ProjectGuid")->Text(solution_project.guid);
327 globals->SubElement("Keyword")->Text("Win32Proj"); 346 globals->SubElement("Keyword")->Text("Win32Proj");
328 globals->SubElement("RootNamespace")->Text(target->label().name()); 347 globals->SubElement("RootNamespace")->Text(target->label().name());
329 globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true"); 348 globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true");
330 globals->SubElement("PreferredToolArchitecture")->Text("x64"); 349 globals->SubElement("PreferredToolArchitecture")->Text("x64");
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name 637 out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name
619 << "\", \"" << RebasePath(project->path, solution_dir, "/") << "\", \"" 638 << "\", \"" << RebasePath(project->path, solution_dir, "/") << "\", \""
620 << project->guid << "\"" << std::endl; 639 << project->guid << "\"" << std::endl;
621 out << "EndProject" << std::endl; 640 out << "EndProject" << std::endl;
622 } 641 }
623 642
624 out << "Global" << std::endl; 643 out << "Global" << std::endl;
625 644
626 out << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" 645 out << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"
627 << std::endl; 646 << std::endl;
628 const std::string config_mode = 647 const std::string config_mode_prefix =
629 std::string(is_debug_config_ ? "Debug" : "Release") + '|' + 648 std::string(is_debug_config_ ? "Debug" : "Release") + '|';
630 config_platform_; 649 const std::string config_mode = config_mode_prefix + config_platform_;
631 out << "\t\t" << config_mode << " = " << config_mode << std::endl; 650 out << "\t\t" << config_mode << " = " << config_mode << std::endl;
632 out << "\tEndGlobalSection" << std::endl; 651 out << "\tEndGlobalSection" << std::endl;
633 652
634 out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" 653 out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"
635 << std::endl; 654 << std::endl;
636 for (const SolutionEntry* project : projects_) { 655 for (const SolutionProject* project : projects_) {
656 const std::string project_config_mode =
657 config_mode_prefix + project->config_platform;
637 out << "\t\t" << project->guid << '.' << config_mode 658 out << "\t\t" << project->guid << '.' << config_mode
638 << ".ActiveCfg = " << config_mode << std::endl; 659 << ".ActiveCfg = " << project_config_mode << std::endl;
639 out << "\t\t" << project->guid << '.' << config_mode 660 out << "\t\t" << project->guid << '.' << config_mode
640 << ".Build.0 = " << config_mode << std::endl; 661 << ".Build.0 = " << project_config_mode << std::endl;
641 } 662 }
642 out << "\tEndGlobalSection" << std::endl; 663 out << "\tEndGlobalSection" << std::endl;
643 664
644 out << "\tGlobalSection(SolutionProperties) = preSolution" << std::endl; 665 out << "\tGlobalSection(SolutionProperties) = preSolution" << std::endl;
645 out << "\t\tHideSolutionNode = FALSE" << std::endl; 666 out << "\t\tHideSolutionNode = FALSE" << std::endl;
646 out << "\tEndGlobalSection" << std::endl; 667 out << "\tEndGlobalSection" << std::endl;
647 668
648 out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl; 669 out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl;
649 for (const SolutionEntry* folder : folders_) { 670 for (const SolutionEntry* folder : folders_) {
650 if (folder->parent_folder) { 671 if (folder->parent_folder) {
651 out << "\t\t" << folder->guid << " = " << folder->parent_folder->guid 672 out << "\t\t" << folder->guid << " = " << folder->parent_folder->guid
652 << std::endl; 673 << std::endl;
653 } 674 }
654 } 675 }
655 for (const SolutionEntry* project : projects_) { 676 for (const SolutionEntry* project : projects_) {
656 out << "\t\t" << project->guid << " = " << project->parent_folder->guid 677 out << "\t\t" << project->guid << " = " << project->parent_folder->guid
657 << std::endl; 678 << std::endl;
658 } 679 }
659 out << "\tEndGlobalSection" << std::endl; 680 out << "\tEndGlobalSection" << std::endl;
660 681
661 out << "EndGlobal" << std::endl; 682 out << "EndGlobal" << std::endl;
662 } 683 }
663 684
664 void VisualStudioWriter::ResolveSolutionFolders() { 685 void VisualStudioWriter::ResolveSolutionFolders() {
665 root_folder_path_.clear(); 686 root_folder_path_.clear();
666 687
667 // Get all project directories. Create solution folder for each directory. 688 // Get all project directories. Create solution folder for each directory.
668 std::map<base::StringPiece, SolutionEntry*> processed_paths; 689 std::map<base::StringPiece, SolutionEntry*> processed_paths;
669 for (SolutionEntry* project : projects_) { 690 for (SolutionProject* project : projects_) {
670 base::StringPiece folder_path = project->label_dir_path; 691 base::StringPiece folder_path = project->label_dir_path;
671 if (IsSlash(folder_path[folder_path.size() - 1])) 692 if (IsSlash(folder_path[folder_path.size() - 1]))
672 folder_path = folder_path.substr(0, folder_path.size() - 1); 693 folder_path = folder_path.substr(0, folder_path.size() - 1);
673 auto it = processed_paths.find(folder_path); 694 auto it = processed_paths.find(folder_path);
674 if (it != processed_paths.end()) { 695 if (it != processed_paths.end()) {
675 project->parent_folder = it->second; 696 project->parent_folder = it->second;
676 } else { 697 } else {
677 std::string folder_path_str = folder_path.as_string(); 698 std::string folder_path_str = folder_path.as_string();
678 SolutionEntry* folder = new SolutionEntry( 699 SolutionEntry* folder = new SolutionEntry(
679 FindLastDirComponent(SourceDir(folder_path)).as_string(), 700 FindLastDirComponent(SourceDir(folder_path)).as_string(),
(...skipping 20 matching lines...) Expand all
700 if (common_prefix_len < root_folder_path_.size()) { 721 if (common_prefix_len < root_folder_path_.size()) {
701 if (IsSlash(root_folder_path_[common_prefix_len - 1])) 722 if (IsSlash(root_folder_path_[common_prefix_len - 1]))
702 --common_prefix_len; 723 --common_prefix_len;
703 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len); 724 root_folder_path_ = root_folder_path_.substr(0, common_prefix_len);
704 } 725 }
705 } 726 }
706 } 727 }
707 } 728 }
708 729
709 // Create also all parent folders up to |root_folder_path_|. 730 // Create also all parent folders up to |root_folder_path_|.
710 SolutionEntries additional_folders; 731 SolutionFolders additional_folders;
711 for (SolutionEntry* folder : folders_) { 732 for (SolutionEntry* folder : folders_) {
712 if (folder->path == root_folder_path_) 733 if (folder->path == root_folder_path_)
713 continue; 734 continue;
714 735
715 base::StringPiece parent_path; 736 base::StringPiece parent_path;
716 while ((parent_path = FindParentDir(&folder->path)) != root_folder_path_) { 737 while ((parent_path = FindParentDir(&folder->path)) != root_folder_path_) {
717 auto it = processed_paths.find(parent_path); 738 auto it = processed_paths.find(parent_path);
718 if (it != processed_paths.end()) { 739 if (it != processed_paths.end()) {
719 folder = it->second; 740 folder = it->second;
720 } else { 741 } else {
(...skipping 10 matching lines...) Expand all
731 additional_folders.end()); 752 additional_folders.end());
732 753
733 // Sort folders by path. 754 // Sort folders by path.
734 std::sort(folders_.begin(), folders_.end(), 755 std::sort(folders_.begin(), folders_.end(),
735 [](const SolutionEntry* a, const SolutionEntry* b) { 756 [](const SolutionEntry* a, const SolutionEntry* b) {
736 return a->path < b->path; 757 return a->path < b->path;
737 }); 758 });
738 759
739 // Match subfolders with their parents. Since |folders_| are sorted by path we 760 // Match subfolders with their parents. Since |folders_| are sorted by path we
740 // know that parent folder always precedes its children in vector. 761 // know that parent folder always precedes its children in vector.
741 SolutionEntries parents; 762 SolutionFolders parents;
742 for (SolutionEntry* folder : folders_) { 763 for (SolutionEntry* folder : folders_) {
743 while (!parents.empty()) { 764 while (!parents.empty()) {
744 if (base::StartsWith(folder->path, parents.back()->path, 765 if (base::StartsWith(folder->path, parents.back()->path,
745 base::CompareCase::SENSITIVE)) { 766 base::CompareCase::SENSITIVE)) {
746 folder->parent_folder = parents.back(); 767 folder->parent_folder = parents.back();
747 break; 768 break;
748 } else { 769 } else {
749 parents.pop_back(); 770 parents.pop_back();
750 } 771 }
751 } 772 }
752 parents.push_back(folder); 773 parents.push_back(folder);
753 } 774 }
754 } 775 }
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