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 |