summaryrefslogtreecommitdiffstats
path: root/Source/cmLocalVisualStudio10Generator.cxx
blob: d45c3356d7133c3e99b214caa83076325edc913e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmLocalVisualStudio10Generator.h"

#include "cmGeneratorTarget.h"
#include "cmGlobalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmVisualStudio10TargetGenerator.h"
#include "cmXMLParser.h"
#include "cmake.h"

#include "cm_expat.h"

class cmVS10XMLParser : public cmXMLParser
{
public:
  virtual void EndElement(const std::string& /* name */) {}
  virtual void CharacterDataHandler(const char* data, int length)
  {
    if (this->DoGUID) {
      if (data[0] == '{') {
        // remove surrounding curly brackets
        this->GUID.assign(data + 1, length - 2);
      } else {
        this->GUID.assign(data, length);
      }
      this->DoGUID = false;
    }
  }
  virtual void StartElement(const std::string& name, const char**)
  {
    // once the GUID is found do nothing
    if (!this->GUID.empty()) {
      return;
    }
    if ("ProjectGUID" == name || "ProjectGuid" == name) {
      this->DoGUID = true;
    }
  }
  int InitializeParser()
  {
    this->DoGUID = false;
    int ret = cmXMLParser::InitializeParser();
    if (ret == 0) {
      return ret;
    }
    // visual studio projects have a strange encoding, but it is
    // really utf-8
    XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
    return 1;
  }
  std::string GUID;
  bool DoGUID;
};

cmLocalVisualStudio10Generator::cmLocalVisualStudio10Generator(
  cmGlobalGenerator* gg, cmMakefile* mf)
  : cmLocalVisualStudio7Generator(gg, mf)
{
}

cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
{
}

void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst(
  cmGeneratorTarget* target, std::vector<cmGeneratorTarget*>& remaining)
{
  if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
    return;
  }
  // Find this target in the list of remaining targets.
  auto it = std::find(remaining.begin(), remaining.end(), target);
  if (it == remaining.end()) {
    // This target was already handled.
    return;
  }
  // Remove this target from the list of remaining targets because
  // we are handling it now.
  *it = nullptr;
  auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target);
  for (auto& d : deps) {
    // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here.
    auto dependee = const_cast<cmGeneratorTarget*>(&*d);
    GenerateTargetsDepthFirst(dependee, remaining);
    // Take the union of visited source files of custom commands
    auto visited = GetSourcesVisited(dependee);
    GetSourcesVisited(target).insert(visited.begin(), visited.end());
  }
  if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
        ->TargetIsFortranOnly(target)) {
    this->CreateSingleVCProj(target->GetName(), target);
  } else {
    cmVisualStudio10TargetGenerator tg(
      target,
      static_cast<cmGlobalVisualStudio10Generator*>(
        this->GetGlobalGenerator()));
    tg.Generate();
  }
}

void cmLocalVisualStudio10Generator::Generate()
{
  std::vector<cmGeneratorTarget*> remaining = this->GetGeneratorTargets();
  for (auto& t : remaining) {
    if (t) {
      GenerateTargetsDepthFirst(t, remaining);
    }
  }
  this->WriteStampFiles();
}

void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID(
  const std::string& name, const char* path)
{
  cmVS10XMLParser parser;
  parser.ParseFile(path);

  // if we can not find a GUID then we will generate one later
  if (parser.GUID.empty()) {
    return;
  }

  std::string guidStoreName = name;
  guidStoreName += "_GUID_CMAKE";
  // save the GUID in the cache
  this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
    guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
    cmStateEnums::INTERNAL);
}

const char* cmLocalVisualStudio10Generator::ReportErrorLabel() const
{
  return ":VCEnd";
}