cmVisualStudio10TargetGenerator.cxx 116 KB
Newer Older
1 2 3
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5 6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8 9 10 11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
#include "windows.h"
13
#include "cmVisualStudio10TargetGenerator.h"
Brad King's avatar
Brad King committed
14
#include "cmGlobalVisualStudio10Generator.h"
15
#include "cmGeneratorTarget.h"
16 17 18 19 20 21 22
#include "cmTarget.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmVisualStudioGeneratorOptions.h"
#include "cmLocalVisualStudio7Generator.h"
23
#include "cmCustomCommandGenerator.h"
24
#include "cmVS10CLFlagTable.h"
25
#include "cmVS10RCFlagTable.h"
26
#include "cmVS10LinkFlagTable.h"
Bill Hoffman's avatar
Bill Hoffman committed
27
#include "cmVS10LibFlagTable.h"
28
#include "cmVS10MASMFlagTable.h"
29
#include "cmVS11CLFlagTable.h"
30
#include "cmVS11RCFlagTable.h"
31 32
#include "cmVS11LinkFlagTable.h"
#include "cmVS11LibFlagTable.h"
33
#include "cmVS11MASMFlagTable.h"
34
#include "cmVS12CLFlagTable.h"
35
#include "cmVS12RCFlagTable.h"
36 37
#include "cmVS12LinkFlagTable.h"
#include "cmVS12LibFlagTable.h"
38
#include "cmVS12MASMFlagTable.h"
39
#include "cmVS14CLFlagTable.h"
40
#include "cmVS14RCFlagTable.h"
41 42
#include "cmVS14LinkFlagTable.h"
#include "cmVS14LibFlagTable.h"
43
#include "cmVS14MASMFlagTable.h"
44

45 46
#include <cmsys/auto_ptr.hxx>

47
cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetClFlagTable() const
48
{
49 50
  if(this->MSTools)
    {
51
    cmGlobalVisualStudioGenerator::VSVersion
52
      v = this->LocalGenerator->GetVersion();
53
    if(v >= cmGlobalVisualStudioGenerator::VS14)
54
      { return cmVS14CLFlagTable; }
55
    else if(v >= cmGlobalVisualStudioGenerator::VS12)
56
      { return cmVS12CLFlagTable; }
57
    else if(v == cmGlobalVisualStudioGenerator::VS11)
58 59 60 61 62
      { return cmVS11CLFlagTable; }
    else
      { return cmVS10CLFlagTable; }
    }
  return 0;
63 64
}

65 66
cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetRcFlagTable() const
{
67 68
  if(this->MSTools)
    {
69
    cmGlobalVisualStudioGenerator::VSVersion
70
      v = this->LocalGenerator->GetVersion();
71
    if(v >= cmGlobalVisualStudioGenerator::VS14)
72
      { return cmVS14RCFlagTable; }
73
    else if(v >= cmGlobalVisualStudioGenerator::VS12)
74
      { return cmVS12RCFlagTable; }
75
    else if(v == cmGlobalVisualStudioGenerator::VS11)
76 77 78 79 80
      { return cmVS11RCFlagTable; }
    else
      { return cmVS10RCFlagTable; }
    }
  return 0;
81 82
}

83
cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLibFlagTable() const
84
{
85 86
  if(this->MSTools)
    {
87
    cmGlobalVisualStudioGenerator::VSVersion
88
      v = this->LocalGenerator->GetVersion();
89
    if(v >= cmGlobalVisualStudioGenerator::VS14)
90
      { return cmVS14LibFlagTable; }
91
    else if(v >= cmGlobalVisualStudioGenerator::VS12)
92
      { return cmVS12LibFlagTable; }
93
    else if(v == cmGlobalVisualStudioGenerator::VS11)
94 95 96 97 98
      { return cmVS11LibFlagTable; }
    else
      { return cmVS10LibFlagTable; }
    }
  return 0;
99 100
}

101
cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLinkFlagTable() const
102
{
103 104
  if(this->MSTools)
    {
105
    cmGlobalVisualStudioGenerator::VSVersion
106
      v = this->LocalGenerator->GetVersion();
107
    if(v >= cmGlobalVisualStudioGenerator::VS14)
108
      { return cmVS14LinkFlagTable; }
109
    else if(v >= cmGlobalVisualStudioGenerator::VS12)
110
      { return cmVS12LinkFlagTable; }
111
    else if(v == cmGlobalVisualStudioGenerator::VS11)
112 113 114 115 116
      { return cmVS11LinkFlagTable; }
    else
      { return cmVS10LinkFlagTable; }
    }
  return 0;
117 118
}

119 120 121 122
cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetMasmFlagTable() const
{
  if(this->MSTools)
    {
123
    cmGlobalVisualStudioGenerator::VSVersion
124
      v = this->LocalGenerator->GetVersion();
125
    if(v >= cmGlobalVisualStudioGenerator::VS14)
126
      { return cmVS14MASMFlagTable; }
127
    else if(v >= cmGlobalVisualStudioGenerator::VS12)
128
      { return cmVS12MASMFlagTable; }
129
    else if(v == cmGlobalVisualStudioGenerator::VS11)
130 131 132 133 134 135 136
      { return cmVS11MASMFlagTable; }
    else
      { return cmVS10MASMFlagTable; }
    }
  return 0;
}

137 138 139 140 141 142 143
static std::string cmVS10EscapeXML(std::string arg)
{
  cmSystemTools::ReplaceString(arg, "&", "&amp;");
  cmSystemTools::ReplaceString(arg, "<", "&lt;");
  cmSystemTools::ReplaceString(arg, ">", "&gt;");
  return arg;
}
144

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
static std::string cmVS10EscapeComment(std::string comment)
{
  // MSBuild takes the CDATA of a <Message></Message> element and just
  // does "echo $CDATA" with no escapes.  We must encode the string.
  // http://technet.microsoft.com/en-us/library/cc772462%28WS.10%29.aspx
  std::string echoable;
  for(std::string::iterator c = comment.begin(); c != comment.end(); ++c)
    {
    switch (*c)
      {
      case '\r': break;
      case '\n': echoable += '\t'; break;
      case '"': /* no break */
      case '|': /* no break */
      case '&': /* no break */
      case '<': /* no break */
      case '>': /* no break */
      case '^': echoable += '^'; /* no break */
      default:  echoable += *c; break;
      }
    }
  return echoable;
}

169 170
cmVisualStudio10TargetGenerator::
cmVisualStudio10TargetGenerator(cmTarget* target,
Brad King's avatar
Brad King committed
171
                                cmGlobalVisualStudio10Generator* gg)
172 173 174
{
  this->GlobalGenerator = gg;
  this->Target = target;
175
  this->GeneratorTarget = gg->GetGeneratorTarget(target);
176
  this->Makefile = target->GetMakefile();
177
  this->Makefile->GetConfigurations(this->Configurations);
178
  this->LocalGenerator =
179
    (cmLocalVisualStudio7Generator*)
180
    this->GeneratorTarget->GetLocalGenerator();
181 182
  this->Name = this->Target->GetName();
  this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str());
Brad King's avatar
Brad King committed
183
  this->Platform = gg->GetPlatformName();
184
  this->NsightTegra = gg->IsNsightTegra();
185 186 187 188 189 190 191 192
  for(int i =
        sscanf(gg->GetNsightTegraVersion().c_str(), "%u.%u.%u.%u",
               &this->NsightTegraVersion[0], &this->NsightTegraVersion[1],
               &this->NsightTegraVersion[2], &this->NsightTegraVersion[3]);
      i < 4; ++i)
    {
    this->NsightTegraVersion[i] = 0;
    }
193
  this->MSTools = !this->NsightTegra;
194
  this->TargetCompileAsWinRT = false;
195
  this->BuildFileStream = 0;
196 197
  this->IsMissingFiles = false;
  this->DefaultArtifactDir =
198
    this->Makefile->GetCurrentBinaryDirectory() + std::string("/") +
199
    this->LocalGenerator->GetTargetDirectory(*this->Target);
200 201 202 203
}

cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
204 205 206 207 208
  for(OptionsMap::iterator i = this->ClOptions.begin();
      i != this->ClOptions.end(); ++i)
    {
    delete i->second;
    }
209 210 211 212 213
  for(OptionsMap::iterator i = this->LinkOptions.begin();
      i != this->LinkOptions.end(); ++i)
    {
    delete i->second;
    }
214 215 216 217
  if(!this->BuildFileStream)
    {
    return;
    }
218 219 220 221 222
  if (this->BuildFileStream->Close())
    {
    this->GlobalGenerator
      ->FileReplacedDuringGenerate(this->PathToVcxproj);
    }
223 224 225 226 227
  delete this->BuildFileStream;
}

void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
  const char* tag,
228
  const std::string& config,
229 230 231 232 233 234 235 236 237 238 239
  int indentLevel,
  const char* attribute,
  const char* end,
  std::ostream* stream)

{
  if(!stream)
    {
    stream = this->BuildFileStream;
    }
  stream->fill(' ');
240
  stream->width(indentLevel*2 );
241
  (*stream ) << "";
242
  (*stream ) << "<" << tag
243
             << " Condition=\"'$(Configuration)|$(Platform)'=='";
Brad King's avatar
Brad King committed
244
  (*stream ) << config << "|" << this->Platform << "'\"";
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
  if(attribute)
    {
    (*stream ) << attribute;
    }
  // close the tag
  (*stream ) << ">";
  if(end)
    {
    (*stream ) << end;
    }
}

void cmVisualStudio10TargetGenerator::WriteString(const char* line,
                                                  int indentLevel)
{
  this->BuildFileStream->fill(' ');
  this->BuildFileStream->width(indentLevel*2 );
  // write an empty string to get the fill level indent to print
  (*this->BuildFileStream ) << "";
  (*this->BuildFileStream ) << line;
}

267
#define VS10_USER_PROPS "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"
268

269
void cmVisualStudio10TargetGenerator::Generate()
270 271
{
  // do not generate external ms projects
272 273
  if(this->Target->GetType() == cmTarget::INTERFACE_LIBRARY
      || this->Target->GetProperty("EXTERNAL_MSPROJECT"))
274 275 276
    {
    return;
    }
277
  // Tell the global generator the name of the project file
278
  this->Target->SetProperty("GENERATOR_FILE_NAME",this->Name.c_str());
279 280
  this->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
                            ".vcxproj");
281
  if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
282
    {
283 284 285 286
    if(!this->ComputeClOptions())
      {
      return;
      }
287 288 289 290
    if(!this->ComputeRcOptions())
      {
      return;
      }
291 292 293 294
    if(!this->ComputeMasmOptions())
      {
      return;
      }
295 296 297 298
    if(!this->ComputeLinkOptions())
      {
      return;
      }
299
    }
300
  cmMakefile* mf = this->Target->GetMakefile();
301
  std::string path =  mf->GetCurrentBinaryDirectory();
302
  path += "/";
303
  path += this->Name;
304 305 306
  path += ".vcxproj";
  this->BuildFileStream =
    new cmGeneratedFileStream(path.c_str());
307
  this->PathToVcxproj = path;
308
  this->BuildFileStream->SetCopyIfDifferent(true);
309

310
  // Write the encoding header into the file
311
  char magic[] = {char(0xEF), char(0xBB), char(0xBF)};
312
  this->BuildFileStream->write(magic, 3);
313 314 315

  //get the tools version to use
  const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
316
  std::string project_defaults=
317 318
    "<?xml version=\"1.0\" encoding=\"" +
    this->GlobalGenerator->Encoding() + "\"?>\n";
319 320 321 322 323 324
  project_defaults.append("<Project DefaultTargets=\"Build\" ToolsVersion=\"");
  project_defaults.append(toolsVer +"\" ");
  project_defaults.append(
          "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
  this->WriteString(project_defaults.c_str(),0);

325 326 327
  if(this->NsightTegra)
    {
    this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1);
328 329 330
    const int nsightTegraMajorVersion = this->NsightTegraVersion[0];
    const int nsightTegraMinorVersion = this->NsightTegraVersion[1];
    if (nsightTegraMajorVersion >= 2)
331
      {
332 333 334 335 336 337 338 339 340 341 342 343
      this->WriteString("<NsightTegraProjectRevisionNumber>", 2);
      if (nsightTegraMajorVersion > 3 ||
          (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1))
        {
        (*this->BuildFileStream) << "11";
        }
      else
        {
        // Nsight Tegra 2.0 uses project revision 9.
        (*this->BuildFileStream) << "9";
        }
      (*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n";
344 345 346 347 348 349 350 351 352 353 354 355
      // Tell newer versions to upgrade silently when loading.
      this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>"
                        "true"
                        "</NsightTegraUpgradeOnceWithoutPrompt>\n", 2);
      }
    else
      {
      // Require Nsight Tegra 1.6 for JCompile support.
      this->WriteString("<NsightTegraProjectRevisionNumber>"
                        "7"
                        "</NsightTegraProjectRevisionNumber>\n", 2);
      }
356 357 358
    this->WriteString("</PropertyGroup>\n", 1);
    }

359 360 361 362 363
  this->WriteProjectConfigurations();
  this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
  this->WriteString("<ProjectGUID>", 2);
  (*this->BuildFileStream) <<  "{" << this->GUID << "}</ProjectGUID>\n";

364
  if(this->MSTools && this->Target->GetType() <= cmTarget::GLOBAL_TARGET)
365 366
    {
    this->WriteApplicationTypeSettings();
367
    this->VerifyNecessaryFiles();
368 369
    }

370 371 372 373 374 375 376 377 378
  const char* vsProjectTypes =
    this->Target->GetProperty("VS_GLOBAL_PROJECT_TYPES");
  if(vsProjectTypes)
    {
    this->WriteString("<ProjectTypes>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectTypes) <<
      "</ProjectTypes>\n";
    }

Steven Velez's avatar
Steven Velez committed
379 380 381 382
  const char* vsProjectName = this->Target->GetProperty("VS_SCC_PROJECTNAME");
  const char* vsLocalPath = this->Target->GetProperty("VS_SCC_LOCALPATH");
  const char* vsProvider = this->Target->GetProperty("VS_SCC_PROVIDER");

383
  if( vsProjectName && vsLocalPath && vsProvider )
Steven Velez's avatar
Steven Velez committed
384 385 386 387 388 389 390 391 392 393
    {
    this->WriteString("<SccProjectName>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName) <<
      "</SccProjectName>\n";
    this->WriteString("<SccLocalPath>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath) <<
      "</SccLocalPath>\n";
    this->WriteString("<SccProvider>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider) <<
      "</SccProvider>\n";
394 395 396 397 398 399 400 401

    const char* vsAuxPath = this->Target->GetProperty("VS_SCC_AUXPATH");
    if( vsAuxPath )
      {
      this->WriteString("<SccAuxPath>", 2);
       (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath) <<
         "</SccAuxPath>\n";
      }
Steven Velez's avatar
Steven Velez committed
402 403
    }

404 405 406 407 408
  if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT"))
    {
    this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
    }

409 410 411 412 413 414 415 416 417 418 419 420 421
  const char* vsGlobalKeyword =
    this->Target->GetProperty("VS_GLOBAL_KEYWORD");
  if(!vsGlobalKeyword)
    {
    this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
    }
  else
    {
    this->WriteString("<Keyword>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword) <<
      "</Keyword>\n";
    }

422 423 424 425 426 427 428 429 430
  const char* vsGlobalRootNamespace =
    this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
  if(vsGlobalRootNamespace)
    {
    this->WriteString("<RootNamespace>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace) <<
      "</RootNamespace>\n";
    }

Brad King's avatar
Brad King committed
431
  this->WriteString("<Platform>", 2);
432 433
  (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
                           << "</Platform>\n";
434 435 436 437 438 439
  const char* projLabel = this->Target->GetProperty("PROJECT_LABEL");
  if(!projLabel)
    {
    projLabel = this->Name.c_str();
    }
  this->WriteString("<ProjectName>", 2);
440
  (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
441 442 443 444
  if(const char* targetFrameworkVersion = this->Target->GetProperty(
       "VS_DOTNET_TARGET_FRAMEWORK_VERSION"))
    {
    this->WriteString("<TargetFrameworkVersion>", 2);
445
    (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
446 447
                             << "</TargetFrameworkVersion>\n";
    }
448 449 450 451 452 453 454 455
  this->WriteString("</PropertyGroup>\n", 1);
  this->WriteString("<Import Project="
                    "\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n",
                    1);
  this->WriteProjectConfigurationValues();
  this->WriteString(
    "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1);
  this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
456 457 458 459 460
  if (this->GlobalGenerator->IsMasmEnabled())
    {
    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                      "BuildCustomizations\\masm.props\" />\n", 2);
    }
461 462
  this->WriteString("</ImportGroup>\n", 1);
  this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
463 464
  this->WriteString("<Import Project=\"" VS10_USER_PROPS "\""
                    " Condition=\"exists('" VS10_USER_PROPS "')\""
465
                    " Label=\"LocalAppDataPlatform\" />\n", 2);
466 467
  this->WriteString("</ImportGroup>\n", 1);
  this->WriteString("<PropertyGroup Label=\"UserMacros\" />\n", 1);
468
  this->WriteWinRTPackageCertificateKeyFile();
469 470 471
  this->WritePathAndIncrementalLinkOptions();
  this->WriteItemDefinitionGroups();
  this->WriteCustomCommands();
472
  this->WriteAllSources();
473
  this->WriteDotNetReferences();
474
  this->WriteEmbeddedResourceGroup();
475
  this->WriteXamlFilesGroup();
476
  this->WriteWinRTReferences();
477 478 479 480
  this->WriteProjectReferences();
  this->WriteString(
    "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\""
    " />\n", 1);
481
  this->WriteTargetSpecificReferences();
482
  this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
483 484 485 486 487
  if (this->GlobalGenerator->IsMasmEnabled())
    {
    this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
                      "BuildCustomizations\\masm.targets\" />\n", 2);
    }
488 489 490 491 492 493
  this->WriteString("</ImportGroup>\n", 1);
  this->WriteString("</Project>", 0);
  // The groups are stored in a separate file for VS 10
  this->WriteGroups();
}

494 495
void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
{
496 497 498 499 500 501 502
  std::vector<std::string> references;
  if(const char* vsDotNetReferences =
     this->Target->GetProperty("VS_DOTNET_REFERENCES"))
    {
    cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
    }
  if(!references.empty())
503 504
    {
    this->WriteString("<ItemGroup>\n", 1);
505 506
    for(std::vector<std::string>::iterator ri = references.begin();
        ri != references.end(); ++ri)
507 508
      {
      this->WriteString("<Reference Include=\"", 2);
509
      (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
510 511 512 513 514 515 516 517 518 519
      this->WriteString("<CopyLocalSatelliteAssemblies>true"
                        "</CopyLocalSatelliteAssemblies>\n", 3);
      this->WriteString("<ReferenceOutputAssembly>true"
                        "</ReferenceOutputAssembly>\n", 3);
      this->WriteString("</Reference>\n", 2);
      }
    this->WriteString("</ItemGroup>\n", 1);
    }
}

520 521
void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
{
522
  std::vector<cmSourceFile const*> resxObjs;
523
    this->GeneratorTarget->GetResxSources(resxObjs, "");
524 525 526
  if(!resxObjs.empty())
    {
    this->WriteString("<ItemGroup>\n", 1);
527
    for(std::vector<cmSourceFile const*>::const_iterator oi = resxObjs.begin();
528 529 530 531 532 533 534 535 536
        oi != resxObjs.end(); ++oi)
      {
      std::string obj = (*oi)->GetFullPath();
      this->WriteString("<EmbeddedResource Include=\"", 2);
      this->ConvertToWindowsSlash(obj);
      (*this->BuildFileStream ) << obj << "\">\n";

      this->WriteString("<DependentUpon>", 3);
      std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
537
      (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
538

539 540 541
      for(std::vector<std::string>::const_iterator
            i = this->Configurations.begin();
          i != this->Configurations.end(); ++i)
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
        {
        this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
        if(this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE"))
          {
          (*this->BuildFileStream ) << "$(RootNamespace).";
          }
        (*this->BuildFileStream ) << "%(Filename)";
        (*this->BuildFileStream ) << ".resources";
        (*this->BuildFileStream ) << "</LogicalName>\n";
        }

      this->WriteString("</EmbeddedResource>\n", 2);
      }
    this->WriteString("</ItemGroup>\n", 1);
    }
}

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
{
  std::vector<cmSourceFile const*> xamlObjs;
  this->GeneratorTarget->GetXamlSources(xamlObjs, "");
  if (!xamlObjs.empty())
    {
    this->WriteString("<ItemGroup>\n", 1);
    for (std::vector<cmSourceFile const*>::const_iterator
           oi = xamlObjs.begin(); oi != xamlObjs.end(); ++oi)
      {
      std::string obj = (*oi)->GetFullPath();
      std::string xamlType;
      const char * xamlTypeProperty = (*oi)->GetProperty("VS_XAML_TYPE");
      if (xamlTypeProperty)
        {
        xamlType = xamlTypeProperty;
        }
      else
        {
        xamlType = "Page";
        }

      this->WriteSource(xamlType, *oi, ">\n");
      this->WriteString("<SubType>Designer</SubType>\n", 3);
      this->WriteString("</", 2);
      (*this->BuildFileStream) << xamlType << ">\n";

      }
    this->WriteString("</ItemGroup>\n", 1);
    }
}

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
{
  if(this->MSTools)
    {
    if(this->GlobalGenerator->TargetsWindowsPhone() &&
       this->GlobalGenerator->GetSystemVersion() == "8.0")
      {
      this->WriteString(
        "<Import Project=\""
        "$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
        "$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
        "$(TargetPlatformVersion).targets\" />\n", 1);
      }
    }
}

607 608
void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
{
609 610 611 612 613 614
  std::vector<std::string> references;
  if(const char* vsWinRTReferences =
     this->Target->GetProperty("VS_WINRT_REFERENCES"))
    {
    cmSystemTools::ExpandListArgument(vsWinRTReferences, references);
    }
615 616 617 618 619 620 621

  if(this->GlobalGenerator->TargetsWindowsPhone() &&
     this->GlobalGenerator->GetSystemVersion() == "8.0" &&
     references.empty())
    {
    references.push_back("platform.winmd");
    }
622
  if(!references.empty())
623 624
    {
    this->WriteString("<ItemGroup>\n", 1);
625 626
    for(std::vector<std::string>::iterator ri = references.begin();
        ri != references.end(); ++ri)
627 628
      {
      this->WriteString("<Reference Include=\"", 2);
629
      (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
630 631 632 633 634 635 636
      this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
      this->WriteString("</Reference>\n", 2);
      }
    this->WriteString("</ItemGroup>\n", 1);
    }
}

637 638 639 640 641
// ConfigurationType Application, Utility StaticLibrary DynamicLibrary

void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
{
  this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
642 643 644
  for(std::vector<std::string>::const_iterator
        i = this->Configurations.begin();
      i != this->Configurations.end(); ++i)
645 646
    {
    this->WriteString("<ProjectConfiguration Include=\"", 2);
Brad King's avatar
Brad King committed
647
    (*this->BuildFileStream ) <<  *i << "|" << this->Platform << "\">\n";
648 649
    this->WriteString("<Configuration>", 3);
    (*this->BuildFileStream ) <<  *i << "</Configuration>\n";
Brad King's avatar
Brad King committed
650
    this->WriteString("<Platform>", 3);
651 652
    (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
                             << "</Platform>\n";
653 654 655 656 657 658 659
    this->WriteString("</ProjectConfiguration>\n", 2);
    }
  this->WriteString("</ItemGroup>\n", 1);
}

void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
660 661 662
  for(std::vector<std::string>::const_iterator
        i = this->Configurations.begin();
      i != this->Configurations.end(); ++i)
663 664 665 666 667 668 669 670 671 672 673
    {
    this->WritePlatformConfigTag("PropertyGroup",
                                 i->c_str(),
                                 1, " Label=\"Configuration\"", "\n");
    std::string configType = "<ConfigurationType>";
    switch(this->Target->GetType())
      {
      case cmTarget::SHARED_LIBRARY:
      case cmTarget::MODULE_LIBRARY:
        configType += "DynamicLibrary";
        break;
674
      case cmTarget::OBJECT_LIBRARY:
675 676 677 678
      case cmTarget::STATIC_LIBRARY:
        configType += "StaticLibrary";
        break;
      case cmTarget::EXECUTABLE:
679 680
        if(this->NsightTegra &&
           !this->Target->GetPropertyAsBool("ANDROID_GUI"))
681 682 683 684 685 686 687 688
          {
          // Android executables are .so too.
          configType += "DynamicLibrary";
          }
        else
          {
          configType += "Application";
          }
689 690
        break;
      case cmTarget::UTILITY:
691
      case cmTarget::GLOBAL_TARGET:
692 693 694 695 696 697 698 699 700
        if(this->NsightTegra)
          {
          // Tegra-Android platform does not understand "Utility".
          configType += "StaticLibrary";
          }
        else
          {
          configType += "Utility";
          }
701
        break;
702
      case cmTarget::UNKNOWN_LIBRARY:
703
      case cmTarget::INTERFACE_LIBRARY:
704
        break;
705 706
      }
    configType += "</ConfigurationType>\n";
707
    this->WriteString(configType.c_str(), 2);
708

709 710 711 712
    if(this->MSTools)
      {
      this->WriteMSToolConfigurationValues(*i);
      }
713 714 715 716
    else if(this->NsightTegra)
      {
      this->WriteNsightTegraConfigurationValues(*i);
      }
717

718 719 720
    this->WriteString("</PropertyGroup>\n", 1);
    }
}
721

722 723 724 725 726 727 728 729 730
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator
::WriteMSToolConfigurationValues(std::string const& config)
{
  cmGlobalVisualStudio10Generator* gg =
    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
  const char* mfcFlag =
    this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG");
  std::string mfcFlagValue = mfcFlag ? mfcFlag : "0";
731

732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
  std::string useOfMfcValue = "false";
  if(mfcFlagValue == "1")
    {
    useOfMfcValue = "Static";
    }
  else if(mfcFlagValue == "2")
    {
    useOfMfcValue = "Dynamic";
    }
  std::string mfcLine = "<UseOfMfc>";
  mfcLine += useOfMfcValue + "</UseOfMfc>\n";
  this->WriteString(mfcLine.c_str(), 2);

  if((this->Target->GetType() <= cmTarget::OBJECT_LIBRARY &&
      this->ClOptions[config]->UsingUnicode()) ||
747
     this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
748 749
     this->GlobalGenerator->TargetsWindowsPhone() ||
     this->GlobalGenerator->TargetsWindowsStore() ||
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
     this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
    {
    this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
    }
  else if (this->Target->GetType() <= cmTarget::MODULE_LIBRARY &&
           this->ClOptions[config]->UsingSBCS())
    {
    this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
    }
  else
    {
    this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
    }
  if(const char* toolset = gg->GetPlatformToolset())
    {
    std::string pts = "<PlatformToolset>";
    pts += toolset;
    pts += "</PlatformToolset>\n";
    this->WriteString(pts.c_str(), 2);
    }
770 771
  if(this->Target->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
     this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
772 773 774
    {
    this->WriteString("<WindowsAppContainer>true"
                      "</WindowsAppContainer>\n", 2);
775 776 777
    }
}

778 779 780 781 782 783 784 785 786 787 788
//----------------------------------------------------------------------------
void cmVisualStudio10TargetGenerator
::WriteNsightTegraConfigurationValues(std::string const&)
{
  cmGlobalVisualStudio10Generator* gg =
    static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
  const char* toolset = gg->GetPlatformToolset();
  std::string ntv = "<NdkToolchainVersion>";
  ntv += toolset? toolset : "Default";
  ntv += "</NdkToolchainVersion>\n";
  this->WriteString(ntv.c_str(), 2);
789 790 791 792 793 794
  if(const char* minApi = this->Target->GetProperty("ANDROID_API_MIN"))
    {
    this->WriteString("<AndroidMinAPI>", 2);
    (*this->BuildFileStream ) <<
      "android-" << cmVS10EscapeXML(minApi) << "</AndroidMinAPI>\n";
    }
795 796 797 798 799 800
  if(const char* api = this->Target->GetProperty("ANDROID_API"))
    {
    this->WriteString("<AndroidTargetAPI>", 2);
    (*this->BuildFileStream ) <<
      "android-" << cmVS10EscapeXML(api) << "</AndroidTargetAPI>\n";
    }
801 802 803 804 805 806 807 808 809 810 811 812 813 814

  if(const char* cpuArch = this->Target->GetProperty("ANDROID_ARCH"))
    {
    this->WriteString("<AndroidArch>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) <<
      "</AndroidArch>\n";
    }

  if(const char* stlType = this->Target->GetProperty("ANDROID_STL_TYPE"))
    {
    this->WriteString("<AndroidStlType>", 2);
    (*this->BuildFileStream) << cmVS10EscapeXML(stlType) <<
      "</AndroidStlType>\n";
    }
815 816
}

817
void cmVisualStudio10TargetGenerator::WriteCustomCommands()
818 819
{
  this->SourcesVisited.clear();
820
  std::vector<cmSourceFile const*> customCommands;
821
  this->GeneratorTarget->GetCustomCommands(customCommands, "");
822
  for(std::vector<cmSourceFile const*>::const_iterator
823 824
        si = customCommands.begin();
      si != customCommands.end(); ++si)
825
    {
826
    this->WriteCustomCommand(*si);
827 828 829 830
    }
}

//----------------------------------------------------------------------------
831 832
void cmVisualStudio10TargetGenerator
::WriteCustomCommand(cmSourceFile const* sf)
833 834 835 836
{
  if(this->SourcesVisited.insert(sf).second)
    {
    if(std::vector<cmSourceFile*> const* depends =
837
       this->GeneratorTarget->GetSourceDepends(sf))
838
      {
839 840 841 842 843
      for(std::vector<cmSourceFile*>::const_iterator di = depends->begin();
          di != depends->end(); ++di)
        {
        this->WriteCustomCommand(*di);
        }
844
      }
845 846 847 848 849 850 851
    if(cmCustomCommand const* command = sf->GetCustomCommand())
      {
      this->WriteString("<ItemGroup>\n", 1);
      this->WriteCustomRule(sf, *command);
      this->WriteString("</ItemGroup>\n", 1);
      }
    }
852 853
}

854
void
855
cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source,
856
                                                 cmCustomCommand const &
857 858 859
                                                 command)
{
  std::string sourcePath = source->GetFullPath();
860 861
  // VS 10 will always rebuild a custom command attached to a .rule
  // file that doesn't exist so create the file explicitly.
862
  if (source->GetPropertyAsBool("__CMAKE_RULE"))
863 864 865
    {
    if(!cmSystemTools::FileExists(sourcePath.c_str()))
      {
866 867 868
      // Make sure the path exists for the file
      std::string path = cmSystemTools::GetFilenamePath(sourcePath);
      cmSystemTools::MakeDirectory(path.c_str());
869
      cmsys::ofstream fout(sourcePath.c_str());
870 871 872 873 874
      if(fout)
        {
        fout << "# generated from CMake\n";
        fout.flush();
        fout.close();
875 876 877
        // Force given file to have a very old timestamp, thus
        // preventing dependent rebuilds.
        this->ForceOld(sourcePath);
878
        }
879 880 881 882 883 884 885 886
      else
        {
        std::string error = "Could not create file: [";
        error +=  sourcePath;
        error += "]  ";
        cmSystemTools::Error
          (error.c_str(), cmSystemTools::GetLastSystemError().c_str());
        }
887 888 889
      }
    }
  cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
890 891 892

  this->WriteSource("CustomBuild", source, ">\n");

893 894 895
  for(std::vector<std::string>::const_iterator
        i = this->Configurations.begin();
      i != this->Configurations.end(); ++i)
896
    {
897
    cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
898 899
    std::string comment = lg->ConstructComment(ccg);
    comment = cmVS10EscapeComment(comment);
900
    std::string script =
901
      cmVS10EscapeXML(lg->ConstructScript(ccg));
902
    this->WritePlatformConfigTag("Message",i->c_str(), 3);
903
    (*this->BuildFileStream ) << cmVS10EscapeXML(comment) << "</Message>\n";
904 905 906
    this->WritePlatformConfigTag("Command", i->c_str(), 3);
    (*this->BuildFileStream ) << script << "</Command>\n";
    this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3);
907

908
    (*this->BuildFileStream ) << cmVS10EscapeXML(source->GetFullPath());
909
    for(std::vector<std::string>::const_iterator d =
910 911
          ccg.GetDepends().begin();
        d != ccg.GetDepends().end();
912 913
        ++d)
      {
914 915 916 917
      std::string dep;
      if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep))
        {
        this->ConvertToWindowsSlash(dep);
918
        (*this->BuildFileStream ) << ";" << cmVS10EscapeXML(dep);
919
        }
920 921 922 923
      }
    (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n";
    this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
    const char* sep = "";
924
    for(std::vector<std::string>::const_iterator o =
925 926
          ccg.GetOutputs().begin();
        o != ccg.GetOutputs().end();
927 928 929 930
        ++o)
      {
      std::string out = *o;
      this->ConvertToWindowsSlash(out);
931
      (*this->BuildFileStream ) << sep << cmVS10EscapeXML(out);
932 933
      sep = ";";
      }
934
    (*this->BuildFileStream ) << "</Outputs>\n";
935 936
    if(this->LocalGenerator->GetVersion()
                                        > cmGlobalVisualStudioGenerator::VS10)
937 938 939 940 941
      {
      // VS >= 11 let us turn off linking of custom command outputs.
      this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3);
      (*this->BuildFileStream ) << "false</LinkObjects>\n";
      }
942 943 944 945
    }
  this->WriteString("</CustomBuild>\n", 2);
}

946 947 948 949 950 951
std::string
cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path,
                                             bool forceRelative)
{
  return forceRelative
    ? cmSystemTools::RelativePath(
952
      this->Makefile->GetCurrentBinaryDirectory(), path.c_str())
953
    : path.c_str();
954 955
}

956 957 958 959 960 961 962 963 964 965 966
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
{
  // first convert all of the slashes
  std::string::size_type pos = 0;
  while((pos = s.find('/', pos)) != std::string::npos)
    {
    s[pos] = '\\';
    pos++;
    }
}
void cmVisualStudio10TargetGenerator::WriteGroups()
967
{
968
  // collect up group information
969
  std::vector<cmSourceGroup> sourceGroups =
970
    this->Makefile->GetSourceGroups();
971
  std::vector<cmSourceFile*> classes;
972
  if (!this->GeneratorTarget->GetConfigCommonSourceFiles(classes))
973 974 975
    {
    return;
    }
976

977
  std::set<cmSourceGroup*> groupsUsed;
978
  for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
979 980
      s != classes.end(); s++)
    {
981
    cmSourceFile* sf = *s;
982
    std::string const& source = sf->GetFullPath();
983
    cmSourceGroup* sourceGroup =
984
      this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
985
    groupsUsed.insert(sourceGroup);
986
    }
987 988 989

  this->AddMissingSourceGroups(groupsUsed, sourceGroups);

990
  // Write out group file
991
  std::string path =  this->Makefile->GetCurrentBinaryDirectory();
992
  path += "/";
993
  path += this->Name;
994 995
  path += ".vcxproj.filters";
  cmGeneratedFileStream fout(path.c_str());
996
  fout.SetCopyIfDifferent(true);
997
  char magic[] = {char(0xEF), char(0xBB), char(0xBF)};
998 999 1000
  fout.write(magic, 3);
  cmGeneratedFileStream* save = this->BuildFileStream;
  this->BuildFileStream = & fout;
1001 1002 1003

  //get the tools version to use
  const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
1004
  std::string project_defaults=
1005 1006
    "<?xml version=\"1.0\" encoding=\"" +
    this->GlobalGenerator->Encoding() + "\"?>\n";
1007 1008 1009 1010 1011 1012
  project_defaults.append("<Project ToolsVersion=\"");
  project_defaults.append(toolsVer +"\" ");
  project_defaults.append(
        "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
  this->WriteString(project_defaults.c_str(),0);

1013 1014 1015 1016 1017
  for(ToolSourceMap::const_iterator ti = this->Tools.begin();
      ti != this->Tools.end(); ++ti)
    {
    this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
    }
1018

1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
  // Added files are images and the manifest.
  if (!this->AddedFiles.empty())
    {
    this->WriteString("<ItemGroup>\n", 1);
    for(std::vector<std::string>::const_iterator
          oi = this->AddedFiles.begin(); oi != this->AddedFiles.end(); ++oi)
      {
      std::string fileName = cmSystemTools::LowerCase(
        cmSystemTools::GetFilenameName(*oi));
      if (fileName == "wmappmanifest.xml")
        {
        this->WriteString("<XML Include=\"", 2);
        (*this->BuildFileStream) << *oi << "\">\n";
        this->WriteString("<Filter>Resource Files</Filter>\n", 3);
        this->WriteString("</XML>\n", 2);
        }
      else if(cmSystemTools::GetFilenameExtension(fileName) ==
              ".appxmanifest")
        {
        this->WriteString("<AppxManifest Include=\"", 2);
        (*this->BuildFileStream) << *oi << "\">\n";
        this->WriteString("<Filter>Resource Files</Filter>\n", 3);
        this->WriteString("</AppxManifest>\n", 2);
        }
      else if(cmSystemTools::GetFilenameExtension(fileName) ==
              ".pfx")
        {
        this->WriteString("<None Include=\"", 2);
        (*this->BuildFileStream) << *oi << "\">\n";
        this->WriteString("<Filter>Resource Files</Filter>\n", 3);
        this->WriteString("</None>\n", 2);
        }
      else
        {
        this->WriteString("<Image Include=\"", 2);
        (*this->BuildFileStream) << *oi << "\">\n";
        this->WriteString("<Filter>Resource Files</Filter>\n", 3);
        this->WriteString("</Image>\n", 2);
        }
      }
    this->WriteString("</ItemGroup>\n", 1);
    }

1062
  std::vector<cmSourceFile const*> resxObjs;
1063
    this->GeneratorTarget->GetResxSources(resxObjs, "");
1064 1065 1066
  if(!resxObjs.empty())
    {
    this->WriteString("<ItemGroup>\n", 1);
1067
    for(std::vector<cmSourceFile const*>::const_iterator oi = resxObjs.begin();
1068 1069 1070 1071 1072
        oi != resxObjs.end(); ++oi)
      {
      std::string obj = (*oi)->GetFullPath();
      this->WriteString("<EmbeddedResource Include=\"", 2);
      this->ConvertToWindowsSlash(obj);
1073
      (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n";
1074 1075 1076 1077 1078 1079
      this->WriteString("<Filter>Resource Files</Filter>\n", 3);
      this->WriteString("</EmbeddedResource>\n", 2);
      }
    this->WriteString("</ItemGroup>\n", 1);
    }

1080 1081
  // Add object library contents as external objects.
  std::vector<std::string> objs;
1082
  this->GeneratorTarget->UseObjectLibraries(objs, "");
1083 1084 1085 1086 1087 1088 1089 1090 1091
  if(!objs.empty())
    {
    this->WriteString("<ItemGroup>\n", 1);
    for(std::vector<std::string>::const_iterator
          oi = objs.begin(); oi != objs.end(); ++oi)
      {
      std::string obj = *oi;
      this->WriteString("<Object Include=\"", 2);
      this->ConvertToWindowsSlash(obj);
1092
      (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n";
1093 1094 1095 1096 1097 1098
      this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
      this->WriteString("</Object>\n", 2);
      }
    this->WriteString("</ItemGroup>\n", 1);
    }

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
  this->WriteString("<ItemGroup>\n", 1);
  for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
      g != groupsUsed.end(); ++g)
    {
    cmSourceGroup* sg = *g;
    const char* name = sg->GetFullName();
    if(strlen(name) != 0)
      {
      this->WriteString("<Filter Include=\"", 2);
      (*this->BuildFileStream) << name << "\">\n";
      std::string guidName = "SG_Filter_";
      guidName += name;
      this->WriteString("<UniqueIdentifier>", 3);
1112
      std::string guid
1113
        = this->GlobalGenerator->GetGUID(guidName.c_str());
1114
      (*this->BuildFileStream)
1115 1116 1117 1118 1119 1120
        << "{"
        << guid << "}"
        << "</UniqueIdentifier>\n";
      this->WriteString("</Filter>\n", 2);
      }
    }
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
  if(!objs.empty())
    {
    this->WriteString("<Filter Include=\"Object Libraries\">\n", 2);
    std::string guidName = "SG_Filter_Object Libraries";
    this->WriteString("<UniqueIdentifier>", 3);
    std::string guid =
      this->GlobalGenerator->GetGUID(guidName.c_str());
    (*this->BuildFileStream) << "{" << guid << "}"
                             << "</UniqueIdentifier>\n";
    this->WriteString("</Filter>\n", 2);
    }
1132

1133
  if(!resxObjs.empty() || !this->AddedFiles.empty())
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
    {
    this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
    std::string guidName = "SG_Filter_Resource Files";
    this->WriteString("<UniqueIdentifier>", 3);
    std::string guid =
      this->GlobalGenerator->GetGUID(guidName.c_str());
    (*this->BuildFileStream) << "{" << guid << "}"
                             << "</UniqueIdentifier>\n";
    this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
    (*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
    (*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
    this->WriteString("</Filter>\n", 2);
  }

1148 1149 1150 1151
  this->WriteString("</ItemGroup>\n", 1);
  this->WriteString("</Project>\n", 0);
  // restore stream pointer
  this->BuildFileStream = save;
1152 1153 1154 1155 1156

  if (fout.Close())
    {
    this->GlobalGenerator->FileReplacedDuringGenerate(path);
    }
1157 1158
}

1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
// Add to groupsUsed empty source groups that have non-empty children.
void
cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
  std::set<cmSourceGroup*>& groupsUsed,
  const std::vector<cmSourceGroup>& allGroups
  )
{
  for(std::vector<cmSourceGroup>::const_iterator current = allGroups.begin();
      current != allGroups.end(); ++current)
    {
    std::vector<cmSourceGroup> const& children = current->GetGroupChildren();
    if(children.empty())
      {
      continue; // the group is really empty
      }

    this->AddMissingSourceGroups(groupsUsed, children);

    cmSourceGroup* current_ptr = const_cast<cmSourceGroup*>(&(*current));
    if(groupsUsed.find(current_ptr) != groupsUsed.end())
      {
      continue; // group has already been added to set
      }

    // check if it least one of the group's descendants is not empty
    // (at least one child must already have been added)
    std::vector<cmSourceGroup>::const_iterator child_it = children.begin();
    while(child_it != children.end())
      {
      cmSourceGroup* child_ptr = const_cast<cmSourceGroup*>(&(*child_it));
      if(groupsUsed.find(child_ptr) != groupsUsed.end())
        {
        break; // found a child that was already added => add current group too
        }
      child_it++;
      }

    if(child_it == children.end())
      {
      continue; // no descendants have source files => ignore this group
      }

    groupsUsed.insert(current_ptr);
    }
}

1205
void
1206 1207
cmVisualStudio10TargetGenerator::
WriteGroupSources(const char* name,
1208
                  ToolSources const& sources,
1209 1210 1211
                  std::vector<cmSourceGroup>& sourceGroups)
{
  this->WriteString("<ItemGroup>\n", 1);
1212
  for(ToolSources::const_iterator s = sources.begin();
1213 1214
      s != sources.end(); ++s)
    {
1215
    cmSourceFile const* sf = s->SourceFile;
1216
    std::string const& source = sf->GetFullPath();
1217
    cmSourceGroup* sourceGroup =
1218
      this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
1219
    const char* filter = sourceGroup->GetFullName();
1220
    this->WriteString("<", 2);
1221
    std::string path = this->ConvertPath(source, s->RelativePath);
1222 1223
    this->ConvertToWindowsSlash(path);
    (*this->BuildFileStream) << name << " Include=\""
1224
                             << cmVS10EscapeXML(path);
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
    if(strlen(filter))
      {
      (*this->BuildFileStream) << "\">\n";
      this->WriteString("<Filter>", 3);
      (*this->BuildFileStream) << filter << "</Filter>\n";
      this->WriteString("</", 2);
      (*this->BuildFileStream) << name << ">\n";
      }
    else
      {
      (*this->BuildFileStream) << "\" />\n";
      }
    }
  this->WriteString("</ItemGroup>\n", 1);
}
1240

1241 1242
void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
{
1243 1244
  std::string const& fileName = sf->GetFullPath();
  if (this->IsResxHeader(fileName))
1245 1246 1247 1248 1249
    {
    this->WriteSource("ClInclude", sf, ">\n");
    this->WriteString("<FileType>CppForm</FileType>\n", 3);
    this->WriteString("</ClInclude>\n", 2);
    }
1250 1251 1252 1253 1254 1255 1256 1257
  else if (this->IsXamlHeader(fileName))
    {
    this->WriteSource("ClInclude", sf, ">\n");
    this->WriteString("<DependentUpon>", 3);
    std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
    (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
    this->WriteString("</ClInclude>\n", 2);
    }
1258 1259 1260 1261
  else
    {
    this->WriteSource("ClInclude", sf);
    }
1262 1263
}

1264 1265
void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
{
1266
  bool toolHasSettings = false;
1267
  std::string tool = "None";
1268
  std::string shaderType;
1269 1270
  std::string shaderEntryPoint;
  std::string shaderModel;
1271
  std::string shaderAdditionalFlags;
1272
  std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
1273
  if(ext == "hlsl")
1274 1275 1276 1277 1278 1279 1280 1281
    {
    tool = "FXCompile";
    // Figure out the type of shader compiler to use.
    if(const char* st = sf->GetProperty("VS_SHADER_TYPE"))
      {
      shaderType = st;
      toolHasSettings = true;
      }
1282 1283 1284 1285 1286 1287
    // Figure out which entry point to use if any
    if (const char* se = sf->GetProperty("VS_SHADER_ENTRYPOINT"))
      {
      shaderEntryPoint = se;
      toolHasSettings = true;
      }
1288
    // Figure out which shader model to use if any
1289 1290 1291 1292 1293
    if (const char* sm = sf->GetProperty("VS_SHADER_MODEL"))
      {
      shaderModel = sm;
      toolHasSettings = true;
      }
1294 1295 1296 1297 1298 1299
    // Figure out if there's any additional flags to use
    if (const char* saf = sf->GetProperty("VS_SHADER_FLAGS"))
      {
      shaderAdditionalFlags = saf;
      toolHasSettings = true;
      }
1300
    }
1301 1302 1303 1304 1305
  else if(ext == "jpg" ||
          ext == "png")
    {
    tool = "Image";
    }
Brad King's avatar
Brad King committed
1306 1307 1308 1309
  else if(ext == "xml")
    {
    tool = "XML";
    }
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
  if(this->NsightTegra)
    {
    // Nsight Tegra needs specific file types to check up-to-dateness.
    std::string name =
      cmSystemTools::LowerCase(sf->GetLocation().GetName());
    if(name == "androidmanifest.xml" ||
       name == "build.xml" ||
       name == "proguard.cfg" ||
       name == "proguard-project.txt" ||
       ext == "properties")
      {
      tool = "AndroidBuild";
      }
    else if(ext == "java")
      {
      tool = "JCompile";
      }
    else if(ext == "asm" || ext == "s")
      {
      tool = "ClCompile";
      }
    }
1332

1333
  std::string deployContent;
1334
  std::string deployLocation;
1335 1336 1337 1338 1339 1340 1341 1342
  if(this->GlobalGenerator->TargetsWindowsPhone() ||
     this->GlobalGenerator->TargetsWindowsStore())
    {
    const char* content = sf->GetProperty("VS_DEPLOYMENT_CONTENT");
    if(content && *content)
      {
      toolHasSettings = true;
      deployContent = content;
1343 1344 1345 1346 1347 1348

      const char* location = sf->GetProperty("VS_DEPLOYMENT_LOCATION");
      if(location && *location)
        {
        deployLocation = location;
        }
1349 1350 1351
      }
    }

1352 1353 1354 1355
  if(toolHasSettings)
    {
    this->WriteSource(tool, sf, ">\n");

1356 1357 1358 1359 1360
    if(!deployContent.empty())
      {
      cmGeneratorExpression ge;
      cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
        ge.Parse(deployContent);
1361 1362 1363 1364 1365 1366 1367 1368
      // Deployment location cannot be set on a configuration basis
      if(!deployLocation.empty())
        {
        this->WriteString("<Link>", 3);
        (*this->BuildFileStream) << deployLocation
                                 << "\\%(FileName)%(Extension)";
        this->WriteString("</Link>\n", 0);
        }
1369
      for(size_t i = 0; i != this->Configurations.size(); ++i)