| 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 <memory> |
| 9 #include <set> | 10 #include <set> |
| 10 #include <string> | 11 #include <string> |
| 11 | 12 |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/memory/scoped_ptr.h" | |
| 14 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 17 #include "tools/gn/builder.h" | 17 #include "tools/gn/builder.h" |
| 18 #include "tools/gn/commands.h" | 18 #include "tools/gn/commands.h" |
| 19 #include "tools/gn/config.h" | 19 #include "tools/gn/config.h" |
| 20 #include "tools/gn/config_values_extractors.h" | 20 #include "tools/gn/config_values_extractors.h" |
| 21 #include "tools/gn/filesystem_utils.h" | 21 #include "tools/gn/filesystem_utils.h" |
| 22 #include "tools/gn/label_pattern.h" | 22 #include "tools/gn/label_pattern.h" |
| 23 #include "tools/gn/parse_tree.h" | 23 #include "tools/gn/parse_tree.h" |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 EscapingMode::ESCAPE_NONE); | 345 EscapingMode::ESCAPE_NONE); |
| 346 | 346 |
| 347 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; | 347 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; |
| 348 XmlElementWriter project( | 348 XmlElementWriter project( |
| 349 out, "Project", | 349 out, "Project", |
| 350 XmlAttributes("DefaultTargets", "Build") | 350 XmlAttributes("DefaultTargets", "Build") |
| 351 .add("ToolsVersion", project_version_) | 351 .add("ToolsVersion", project_version_) |
| 352 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")); | 352 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")); |
| 353 | 353 |
| 354 { | 354 { |
| 355 scoped_ptr<XmlElementWriter> configurations = project.SubElement( | 355 std::unique_ptr<XmlElementWriter> configurations = project.SubElement( |
| 356 "ItemGroup", XmlAttributes("Label", "ProjectConfigurations")); | 356 "ItemGroup", XmlAttributes("Label", "ProjectConfigurations")); |
| 357 scoped_ptr<XmlElementWriter> project_config = configurations->SubElement( | 357 std::unique_ptr<XmlElementWriter> project_config = |
| 358 "ProjectConfiguration", | 358 configurations->SubElement( |
| 359 XmlAttributes("Include", std::string(kConfigurationName) + '|' + | 359 "ProjectConfiguration", |
| 360 solution_project.config_platform)); | 360 XmlAttributes("Include", std::string(kConfigurationName) + '|' + |
| 361 solution_project.config_platform)); |
| 361 project_config->SubElement("Configuration")->Text(kConfigurationName); | 362 project_config->SubElement("Configuration")->Text(kConfigurationName); |
| 362 project_config->SubElement("Platform") | 363 project_config->SubElement("Platform") |
| 363 ->Text(solution_project.config_platform); | 364 ->Text(solution_project.config_platform); |
| 364 } | 365 } |
| 365 | 366 |
| 366 { | 367 { |
| 367 scoped_ptr<XmlElementWriter> globals = | 368 std::unique_ptr<XmlElementWriter> globals = |
| 368 project.SubElement("PropertyGroup", XmlAttributes("Label", "Globals")); | 369 project.SubElement("PropertyGroup", XmlAttributes("Label", "Globals")); |
| 369 globals->SubElement("ProjectGuid")->Text(solution_project.guid); | 370 globals->SubElement("ProjectGuid")->Text(solution_project.guid); |
| 370 globals->SubElement("Keyword")->Text("Win32Proj"); | 371 globals->SubElement("Keyword")->Text("Win32Proj"); |
| 371 globals->SubElement("RootNamespace")->Text(target->label().name()); | 372 globals->SubElement("RootNamespace")->Text(target->label().name()); |
| 372 globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true"); | 373 globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true"); |
| 373 globals->SubElement("PreferredToolArchitecture")->Text("x64"); | 374 globals->SubElement("PreferredToolArchitecture")->Text("x64"); |
| 374 } | 375 } |
| 375 | 376 |
| 376 project.SubElement( | 377 project.SubElement( |
| 377 "Import", XmlAttributes("Project", | 378 "Import", XmlAttributes("Project", |
| 378 "$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); | 379 "$(VCTargetsPath)\\Microsoft.Cpp.Default.props")); |
| 379 | 380 |
| 380 { | 381 { |
| 381 scoped_ptr<XmlElementWriter> configuration = project.SubElement( | 382 std::unique_ptr<XmlElementWriter> configuration = project.SubElement( |
| 382 "PropertyGroup", XmlAttributes("Label", "Configuration")); | 383 "PropertyGroup", XmlAttributes("Label", "Configuration")); |
| 383 configuration->SubElement("CharacterSet")->Text("Unicode"); | 384 configuration->SubElement("CharacterSet")->Text("Unicode"); |
| 384 std::string configuration_type = GetConfigurationType(target, err); | 385 std::string configuration_type = GetConfigurationType(target, err); |
| 385 if (configuration_type.empty()) | 386 if (configuration_type.empty()) |
| 386 return false; | 387 return false; |
| 387 configuration->SubElement("ConfigurationType")->Text(configuration_type); | 388 configuration->SubElement("ConfigurationType")->Text(configuration_type); |
| 388 } | 389 } |
| 389 | 390 |
| 390 { | 391 { |
| 391 scoped_ptr<XmlElementWriter> locals = | 392 std::unique_ptr<XmlElementWriter> locals = |
| 392 project.SubElement("PropertyGroup", XmlAttributes("Label", "Locals")); | 393 project.SubElement("PropertyGroup", XmlAttributes("Label", "Locals")); |
| 393 locals->SubElement("PlatformToolset")->Text(toolset_version_); | 394 locals->SubElement("PlatformToolset")->Text(toolset_version_); |
| 394 } | 395 } |
| 395 | 396 |
| 396 project.SubElement( | 397 project.SubElement( |
| 397 "Import", | 398 "Import", |
| 398 XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props")); | 399 XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props")); |
| 399 project.SubElement( | 400 project.SubElement( |
| 400 "Import", | 401 "Import", |
| 401 XmlAttributes("Project", | 402 XmlAttributes("Project", |
| 402 "$(VCTargetsPath)\\BuildCustomizations\\masm.props")); | 403 "$(VCTargetsPath)\\BuildCustomizations\\masm.props")); |
| 403 project.SubElement("ImportGroup", | 404 project.SubElement("ImportGroup", |
| 404 XmlAttributes("Label", "ExtensionSettings")); | 405 XmlAttributes("Label", "ExtensionSettings")); |
| 405 | 406 |
| 406 { | 407 { |
| 407 scoped_ptr<XmlElementWriter> property_sheets = project.SubElement( | 408 std::unique_ptr<XmlElementWriter> property_sheets = project.SubElement( |
| 408 "ImportGroup", XmlAttributes("Label", "PropertySheets")); | 409 "ImportGroup", XmlAttributes("Label", "PropertySheets")); |
| 409 property_sheets->SubElement( | 410 property_sheets->SubElement( |
| 410 "Import", | 411 "Import", |
| 411 XmlAttributes( | 412 XmlAttributes( |
| 412 "Condition", | 413 "Condition", |
| 413 "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") | 414 "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')") |
| 414 .add("Label", "LocalAppDataPlatform") | 415 .add("Label", "LocalAppDataPlatform") |
| 415 .add("Project", | 416 .add("Project", |
| 416 "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")); | 417 "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props")); |
| 417 } | 418 } |
| 418 | 419 |
| 419 project.SubElement("PropertyGroup", XmlAttributes("Label", "UserMacros")); | 420 project.SubElement("PropertyGroup", XmlAttributes("Label", "UserMacros")); |
| 420 | 421 |
| 421 { | 422 { |
| 422 scoped_ptr<XmlElementWriter> properties = | 423 std::unique_ptr<XmlElementWriter> properties = |
| 423 project.SubElement("PropertyGroup"); | 424 project.SubElement("PropertyGroup"); |
| 424 { | 425 { |
| 425 scoped_ptr<XmlElementWriter> out_dir = properties->SubElement("OutDir"); | 426 std::unique_ptr<XmlElementWriter> out_dir = |
| 427 properties->SubElement("OutDir"); |
| 426 path_output.WriteDir(out_dir->StartContent(false), | 428 path_output.WriteDir(out_dir->StartContent(false), |
| 427 build_settings_->build_dir(), | 429 build_settings_->build_dir(), |
| 428 PathOutput::DIR_NO_LAST_SLASH); | 430 PathOutput::DIR_NO_LAST_SLASH); |
| 429 } | 431 } |
| 430 properties->SubElement("TargetName")->Text("$(ProjectName)"); | 432 properties->SubElement("TargetName")->Text("$(ProjectName)"); |
| 431 if (target->output_type() != Target::GROUP) { | 433 if (target->output_type() != Target::GROUP) { |
| 432 properties->SubElement("TargetPath") | 434 properties->SubElement("TargetPath") |
| 433 ->Text("$(OutDir)\\$(ProjectName)$(TargetExt)"); | 435 ->Text("$(OutDir)\\$(ProjectName)$(TargetExt)"); |
| 434 } | 436 } |
| 435 } | 437 } |
| 436 | 438 |
| 437 { | 439 { |
| 438 scoped_ptr<XmlElementWriter> item_definitions = | 440 std::unique_ptr<XmlElementWriter> item_definitions = |
| 439 project.SubElement("ItemDefinitionGroup"); | 441 project.SubElement("ItemDefinitionGroup"); |
| 440 { | 442 { |
| 441 scoped_ptr<XmlElementWriter> cl_compile = | 443 std::unique_ptr<XmlElementWriter> cl_compile = |
| 442 item_definitions->SubElement("ClCompile"); | 444 item_definitions->SubElement("ClCompile"); |
| 443 { | 445 { |
| 444 scoped_ptr<XmlElementWriter> include_dirs = | 446 std::unique_ptr<XmlElementWriter> include_dirs = |
| 445 cl_compile->SubElement("AdditionalIncludeDirectories"); | 447 cl_compile->SubElement("AdditionalIncludeDirectories"); |
| 446 RecursiveTargetConfigToStream<SourceDir>( | 448 RecursiveTargetConfigToStream<SourceDir>( |
| 447 target, &ConfigValues::include_dirs, IncludeDirWriter(path_output), | 449 target, &ConfigValues::include_dirs, IncludeDirWriter(path_output), |
| 448 include_dirs->StartContent(false)); | 450 include_dirs->StartContent(false)); |
| 449 include_dirs->Text(windows_kits_include_dirs_ + | 451 include_dirs->Text(windows_kits_include_dirs_ + |
| 450 "$(VSInstallDir)\\VC\\atlmfc\\include;" + | 452 "$(VSInstallDir)\\VC\\atlmfc\\include;" + |
| 451 "%(AdditionalIncludeDirectories)"); | 453 "%(AdditionalIncludeDirectories)"); |
| 452 } | 454 } |
| 453 CompilerOptions options; | 455 CompilerOptions options; |
| 454 ParseCompilerOptions(target, &options); | 456 ParseCompilerOptions(target, &options); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 476 if (!options.optimization.empty()) | 478 if (!options.optimization.empty()) |
| 477 cl_compile->SubElement("Optimization")->Text(options.optimization); | 479 cl_compile->SubElement("Optimization")->Text(options.optimization); |
| 478 if (target->config_values().has_precompiled_headers()) { | 480 if (target->config_values().has_precompiled_headers()) { |
| 479 cl_compile->SubElement("PrecompiledHeader")->Text("Use"); | 481 cl_compile->SubElement("PrecompiledHeader")->Text("Use"); |
| 480 cl_compile->SubElement("PrecompiledHeaderFile") | 482 cl_compile->SubElement("PrecompiledHeaderFile") |
| 481 ->Text(target->config_values().precompiled_header()); | 483 ->Text(target->config_values().precompiled_header()); |
| 482 } else { | 484 } else { |
| 483 cl_compile->SubElement("PrecompiledHeader")->Text("NotUsing"); | 485 cl_compile->SubElement("PrecompiledHeader")->Text("NotUsing"); |
| 484 } | 486 } |
| 485 { | 487 { |
| 486 scoped_ptr<XmlElementWriter> preprocessor_definitions = | 488 std::unique_ptr<XmlElementWriter> preprocessor_definitions = |
| 487 cl_compile->SubElement("PreprocessorDefinitions"); | 489 cl_compile->SubElement("PreprocessorDefinitions"); |
| 488 RecursiveTargetConfigToStream<std::string>( | 490 RecursiveTargetConfigToStream<std::string>( |
| 489 target, &ConfigValues::defines, SemicolonSeparatedWriter(), | 491 target, &ConfigValues::defines, SemicolonSeparatedWriter(), |
| 490 preprocessor_definitions->StartContent(false)); | 492 preprocessor_definitions->StartContent(false)); |
| 491 preprocessor_definitions->Text("%(PreprocessorDefinitions)"); | 493 preprocessor_definitions->Text("%(PreprocessorDefinitions)"); |
| 492 } | 494 } |
| 493 if (!options.runtime_library.empty()) | 495 if (!options.runtime_library.empty()) |
| 494 cl_compile->SubElement("RuntimeLibrary")->Text(options.runtime_library); | 496 cl_compile->SubElement("RuntimeLibrary")->Text(options.runtime_library); |
| 495 if (!options.treat_warning_as_error.empty()) { | 497 if (!options.treat_warning_as_error.empty()) { |
| 496 cl_compile->SubElement("TreatWarningAsError") | 498 cl_compile->SubElement("TreatWarningAsError") |
| 497 ->Text(options.treat_warning_as_error); | 499 ->Text(options.treat_warning_as_error); |
| 498 } | 500 } |
| 499 if (!options.warning_level.empty()) | 501 if (!options.warning_level.empty()) |
| 500 cl_compile->SubElement("WarningLevel")->Text(options.warning_level); | 502 cl_compile->SubElement("WarningLevel")->Text(options.warning_level); |
| 501 } | 503 } |
| 502 | 504 |
| 503 // We don't include resource compilation and link options as ninja files | 505 // We don't include resource compilation and link options as ninja files |
| 504 // are used to generate real build. | 506 // are used to generate real build. |
| 505 } | 507 } |
| 506 | 508 |
| 507 { | 509 { |
| 508 scoped_ptr<XmlElementWriter> group = project.SubElement("ItemGroup"); | 510 std::unique_ptr<XmlElementWriter> group = project.SubElement("ItemGroup"); |
| 509 if (!target->config_values().precompiled_source().is_null()) { | 511 if (!target->config_values().precompiled_source().is_null()) { |
| 510 group | 512 group |
| 511 ->SubElement( | 513 ->SubElement( |
| 512 "ClCompile", "Include", | 514 "ClCompile", "Include", |
| 513 SourceFileWriter(path_output, | 515 SourceFileWriter(path_output, |
| 514 target->config_values().precompiled_source())) | 516 target->config_values().precompiled_source())) |
| 515 ->SubElement("PrecompiledHeader") | 517 ->SubElement("PrecompiledHeader") |
| 516 ->Text("Create"); | 518 ->Text("Create"); |
| 517 } | 519 } |
| 518 | 520 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 530 XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets")); | 532 XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets")); |
| 531 project.SubElement( | 533 project.SubElement( |
| 532 "Import", | 534 "Import", |
| 533 XmlAttributes("Project", | 535 XmlAttributes("Project", |
| 534 "$(VCTargetsPath)\\BuildCustomizations\\masm.targets")); | 536 "$(VCTargetsPath)\\BuildCustomizations\\masm.targets")); |
| 535 project.SubElement("ImportGroup", XmlAttributes("Label", "ExtensionTargets")); | 537 project.SubElement("ImportGroup", XmlAttributes("Label", "ExtensionTargets")); |
| 536 | 538 |
| 537 std::string ninja_target = GetNinjaTarget(target); | 539 std::string ninja_target = GetNinjaTarget(target); |
| 538 | 540 |
| 539 { | 541 { |
| 540 scoped_ptr<XmlElementWriter> build = | 542 std::unique_ptr<XmlElementWriter> build = |
| 541 project.SubElement("Target", XmlAttributes("Name", "Build")); | 543 project.SubElement("Target", XmlAttributes("Name", "Build")); |
| 542 build->SubElement( | 544 build->SubElement( |
| 543 "Exec", XmlAttributes("Command", | 545 "Exec", XmlAttributes("Command", |
| 544 "call ninja.exe -C $(OutDir) " + ninja_target)); | 546 "call ninja.exe -C $(OutDir) " + ninja_target)); |
| 545 } | 547 } |
| 546 | 548 |
| 547 { | 549 { |
| 548 scoped_ptr<XmlElementWriter> clean = | 550 std::unique_ptr<XmlElementWriter> clean = |
| 549 project.SubElement("Target", XmlAttributes("Name", "Clean")); | 551 project.SubElement("Target", XmlAttributes("Name", "Clean")); |
| 550 clean->SubElement( | 552 clean->SubElement( |
| 551 "Exec", | 553 "Exec", |
| 552 XmlAttributes("Command", | 554 XmlAttributes("Command", |
| 553 "call ninja.exe -C $(OutDir) -tclean " + ninja_target)); | 555 "call ninja.exe -C $(OutDir) -tclean " + ninja_target)); |
| 554 } | 556 } |
| 555 | 557 |
| 556 return true; | 558 return true; |
| 557 } | 559 } |
| 558 | 560 |
| 559 void VisualStudioWriter::WriteFiltersFileContents(std::ostream& out, | 561 void VisualStudioWriter::WriteFiltersFileContents(std::ostream& out, |
| 560 const Target* target) { | 562 const Target* target) { |
| 561 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; | 563 out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl; |
| 562 XmlElementWriter project( | 564 XmlElementWriter project( |
| 563 out, "Project", | 565 out, "Project", |
| 564 XmlAttributes("ToolsVersion", "4.0") | 566 XmlAttributes("ToolsVersion", "4.0") |
| 565 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")); | 567 .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003")); |
| 566 | 568 |
| 567 std::ostringstream files_out; | 569 std::ostringstream files_out; |
| 568 | 570 |
| 569 { | 571 { |
| 570 scoped_ptr<XmlElementWriter> filters_group = | 572 std::unique_ptr<XmlElementWriter> filters_group = |
| 571 project.SubElement("ItemGroup"); | 573 project.SubElement("ItemGroup"); |
| 572 XmlElementWriter files_group(files_out, "ItemGroup", XmlAttributes(), 2); | 574 XmlElementWriter files_group(files_out, "ItemGroup", XmlAttributes(), 2); |
| 573 | 575 |
| 574 // File paths are relative to vcxproj files which are generated to out dirs. | 576 // File paths are relative to vcxproj files which are generated to out dirs. |
| 575 // Filters tree structure need to reflect source directories and be relative | 577 // Filters tree structure need to reflect source directories and be relative |
| 576 // to target file. We need two path outputs then. | 578 // to target file. We need two path outputs then. |
| 577 PathOutput file_path_output(GetTargetOutputDir(target), | 579 PathOutput file_path_output(GetTargetOutputDir(target), |
| 578 build_settings_->root_path_utf8(), | 580 build_settings_->root_path_utf8(), |
| 579 EscapingMode::ESCAPE_NONE); | 581 EscapingMode::ESCAPE_NONE); |
| 580 PathOutput filter_path_output(target->label().dir(), | 582 PathOutput filter_path_output(target->label().dir(), |
| 581 build_settings_->root_path_utf8(), | 583 build_settings_->root_path_utf8(), |
| 582 EscapingMode::ESCAPE_NONE); | 584 EscapingMode::ESCAPE_NONE); |
| 583 | 585 |
| 584 std::set<std::string> processed_filters; | 586 std::set<std::string> processed_filters; |
| 585 | 587 |
| 586 for (const SourceFile& file : target->sources()) { | 588 for (const SourceFile& file : target->sources()) { |
| 587 SourceFileType type = GetSourceFileType(file); | 589 SourceFileType type = GetSourceFileType(file); |
| 588 if (type == SOURCE_H || type == SOURCE_CPP || type == SOURCE_C) { | 590 if (type == SOURCE_H || type == SOURCE_CPP || type == SOURCE_C) { |
| 589 scoped_ptr<XmlElementWriter> cl_item = files_group.SubElement( | 591 std::unique_ptr<XmlElementWriter> cl_item = files_group.SubElement( |
| 590 type == SOURCE_H ? "ClInclude" : "ClCompile", "Include", | 592 type == SOURCE_H ? "ClInclude" : "ClCompile", "Include", |
| 591 SourceFileWriter(file_path_output, file)); | 593 SourceFileWriter(file_path_output, file)); |
| 592 | 594 |
| 593 std::ostringstream target_relative_out; | 595 std::ostringstream target_relative_out; |
| 594 filter_path_output.WriteFile(target_relative_out, file); | 596 filter_path_output.WriteFile(target_relative_out, file); |
| 595 std::string target_relative_path = target_relative_out.str(); | 597 std::string target_relative_path = target_relative_out.str(); |
| 596 ConvertPathToSystem(&target_relative_path); | 598 ConvertPathToSystem(&target_relative_path); |
| 597 base::StringPiece filter_path = FindParentDir(&target_relative_path); | 599 base::StringPiece filter_path = FindParentDir(&target_relative_path); |
| 598 | 600 |
| 599 if (!filter_path.empty()) { | 601 if (!filter_path.empty()) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 } | 796 } |
| 795 } | 797 } |
| 796 | 798 |
| 797 std::string VisualStudioWriter::GetNinjaTarget(const Target* target) { | 799 std::string VisualStudioWriter::GetNinjaTarget(const Target* target) { |
| 798 std::ostringstream ninja_target_out; | 800 std::ostringstream ninja_target_out; |
| 799 DCHECK(!target->dependency_output_file().value().empty()); | 801 DCHECK(!target->dependency_output_file().value().empty()); |
| 800 ninja_path_output_.WriteFile(ninja_target_out, | 802 ninja_path_output_.WriteFile(ninja_target_out, |
| 801 target->dependency_output_file()); | 803 target->dependency_output_file()); |
| 802 return ninja_target_out.str(); | 804 return ninja_target_out.str(); |
| 803 } | 805 } |
| OLD | NEW |