10dc25808ec791508069b218ce7ce25e22524751
[platform/upstream/cmake.git] / Source / cmGlobalVisualStudio11Generator.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmGlobalVisualStudio11Generator.h"
4
5 #include <cstring>
6 #include <sstream>
7 #include <utility>
8 #include <vector>
9
10 #include "cmDocumentationEntry.h"
11 #include "cmGlobalGenerator.h"
12 #include "cmGlobalGeneratorFactory.h"
13 #include "cmGlobalVisualStudioGenerator.h"
14 #include "cmMakefile.h"
15 #include "cmMessageType.h"
16 #include "cmStringAlgorithms.h"
17 #include "cmSystemTools.h"
18
19 static const char vs11generatorName[] = "Visual Studio 11 2012";
20
21 // Map generator name without year to name with year.
22 static const char* cmVS11GenName(const std::string& name, std::string& genName)
23 {
24   if (strncmp(name.c_str(), vs11generatorName,
25               sizeof(vs11generatorName) - 6) != 0) {
26     return 0;
27   }
28   const char* p = name.c_str() + sizeof(vs11generatorName) - 6;
29   if (cmHasLiteralPrefix(p, " 2012")) {
30     p += 5;
31   }
32   genName = std::string(vs11generatorName) + p;
33   return p;
34 }
35
36 class cmGlobalVisualStudio11Generator::Factory
37   : public cmGlobalGeneratorFactory
38 {
39 public:
40   std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
41     const std::string& name, bool allowArch, cmake* cm) const override
42   {
43     std::string genName;
44     const char* p = cmVS11GenName(name, genName);
45     if (!p) {
46       return std::unique_ptr<cmGlobalGenerator>();
47     }
48     if (!*p) {
49       return std::unique_ptr<cmGlobalGenerator>(
50         new cmGlobalVisualStudio11Generator(cm, genName, ""));
51     }
52     if (!allowArch || *p++ != ' ') {
53       return std::unique_ptr<cmGlobalGenerator>();
54     }
55     if (strcmp(p, "Win64") == 0) {
56       return std::unique_ptr<cmGlobalGenerator>(
57         new cmGlobalVisualStudio11Generator(cm, genName, "x64"));
58     }
59     if (strcmp(p, "ARM") == 0) {
60       return std::unique_ptr<cmGlobalGenerator>(
61         new cmGlobalVisualStudio11Generator(cm, genName, "ARM"));
62     }
63
64     std::set<std::string> installedSDKs =
65       cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
66
67     if (installedSDKs.find(p) == installedSDKs.end()) {
68       return std::unique_ptr<cmGlobalGenerator>();
69     }
70
71     auto ret = std::unique_ptr<cmGlobalVisualStudio11Generator>(
72       new cmGlobalVisualStudio11Generator(cm, name, p));
73     ret->WindowsCEVersion = "8.00";
74     return std::unique_ptr<cmGlobalGenerator>(std::move(ret));
75   }
76
77   void GetDocumentation(cmDocumentationEntry& entry) const override
78   {
79     entry.Name = std::string(vs11generatorName) + " [arch]";
80     entry.Brief = "Generates Visual Studio 2012 project files.  "
81                   "Optional [arch] can be \"Win64\" or \"ARM\".";
82   }
83
84   std::vector<std::string> GetGeneratorNames() const override
85   {
86     std::vector<std::string> names;
87     names.push_back(vs11generatorName);
88     return names;
89   }
90
91   std::vector<std::string> GetGeneratorNamesWithPlatform() const override
92   {
93     std::vector<std::string> names;
94     names.push_back(vs11generatorName + std::string(" ARM"));
95     names.push_back(vs11generatorName + std::string(" Win64"));
96
97     std::set<std::string> installedSDKs =
98       cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
99     for (std::string const& i : installedSDKs) {
100       names.push_back(std::string(vs11generatorName) + " " + i);
101     }
102
103     return names;
104   }
105
106   bool SupportsToolset() const override { return true; }
107   bool SupportsPlatform() const override { return true; }
108
109   std::vector<std::string> GetKnownPlatforms() const override
110   {
111     std::vector<std::string> platforms;
112     platforms.emplace_back("x64");
113     platforms.emplace_back("Win32");
114     platforms.emplace_back("ARM");
115
116     std::set<std::string> installedSDKs =
117       cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
118     for (std::string const& i : installedSDKs) {
119       platforms.emplace_back(i);
120     }
121
122     return platforms;
123   }
124
125   std::string GetDefaultPlatformName() const override { return "Win32"; }
126 };
127
128 std::unique_ptr<cmGlobalGeneratorFactory>
129 cmGlobalVisualStudio11Generator::NewFactory()
130 {
131   return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory);
132 }
133
134 cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
135   cmake* cm, const std::string& name,
136   std::string const& platformInGeneratorName)
137   : cmGlobalVisualStudio10Generator(cm, name, platformInGeneratorName)
138 {
139   std::string vc11Express;
140   this->ExpressEdition = cmSystemTools::ReadRegistryValue(
141     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\11.0\\Setup\\VC;"
142     "ProductDir",
143     vc11Express, cmSystemTools::KeyWOW64_32);
144   this->DefaultPlatformToolset = "v110";
145   this->DefaultCLFlagTableName = "v11";
146   this->DefaultCSharpFlagTableName = "v11";
147   this->DefaultLibFlagTableName = "v11";
148   this->DefaultLinkFlagTableName = "v11";
149   this->DefaultMasmFlagTableName = "v11";
150   this->DefaultRCFlagTableName = "v11";
151   this->Version = VSVersion::VS11;
152 }
153
154 bool cmGlobalVisualStudio11Generator::MatchesGeneratorName(
155   const std::string& name) const
156 {
157   std::string genName;
158   if (cmVS11GenName(name, genName)) {
159     return genName == this->GetName();
160   }
161   return false;
162 }
163
164 bool cmGlobalVisualStudio11Generator::InitializeWindowsPhone(cmMakefile* mf)
165 {
166   if (!this->SelectWindowsPhoneToolset(this->DefaultPlatformToolset)) {
167     std::ostringstream e;
168     if (this->DefaultPlatformToolset.empty()) {
169       e << this->GetName() << " supports Windows Phone '8.0', but not '"
170         << this->SystemVersion << "'.  Check CMAKE_SYSTEM_VERSION.";
171     } else {
172       e << "A Windows Phone component with CMake requires both the Windows "
173         << "Desktop SDK as well as the Windows Phone '" << this->SystemVersion
174         << "' SDK. Please make sure that you have both installed";
175     }
176     mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
177     return false;
178   }
179   return true;
180 }
181
182 bool cmGlobalVisualStudio11Generator::InitializeWindowsStore(cmMakefile* mf)
183 {
184   if (!this->SelectWindowsStoreToolset(this->DefaultPlatformToolset)) {
185     std::ostringstream e;
186     if (this->DefaultPlatformToolset.empty()) {
187       e << this->GetName() << " supports Windows Store '8.0', but not '"
188         << this->SystemVersion << "'.  Check CMAKE_SYSTEM_VERSION.";
189     } else {
190       e << "A Windows Store component with CMake requires both the Windows "
191         << "Desktop SDK as well as the Windows Store '" << this->SystemVersion
192         << "' SDK. Please make sure that you have both installed";
193     }
194     mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
195     return false;
196   }
197   return true;
198 }
199
200 bool cmGlobalVisualStudio11Generator::SelectWindowsPhoneToolset(
201   std::string& toolset) const
202 {
203   if (this->SystemVersion == "8.0") {
204     if (this->IsWindowsPhoneToolsetInstalled() &&
205         this->IsWindowsDesktopToolsetInstalled()) {
206       toolset = "v110_wp80";
207       return true;
208     } else {
209       return false;
210     }
211   }
212   return this->cmGlobalVisualStudio10Generator::SelectWindowsPhoneToolset(
213     toolset);
214 }
215
216 bool cmGlobalVisualStudio11Generator::SelectWindowsStoreToolset(
217   std::string& toolset) const
218 {
219   if (this->SystemVersion == "8.0") {
220     if (this->IsWindowsStoreToolsetInstalled() &&
221         this->IsWindowsDesktopToolsetInstalled()) {
222       toolset = "v110";
223       return true;
224     } else {
225       return false;
226     }
227   }
228   return this->cmGlobalVisualStudio10Generator::SelectWindowsStoreToolset(
229     toolset);
230 }
231
232 bool cmGlobalVisualStudio11Generator::UseFolderProperty() const
233 {
234   // Intentionally skip up to the top-level class implementation.
235   // Folders are not supported by the Express editions in VS10 and earlier,
236   // but they are in VS11 Express and above.
237   return cmGlobalGenerator::UseFolderProperty();
238 }
239
240 std::set<std::string>
241 cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
242 {
243   const char sdksKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
244                          "Windows CE Tools\\SDKs";
245
246   std::vector<std::string> subkeys;
247   cmSystemTools::GetRegistrySubKeys(sdksKey, subkeys,
248                                     cmSystemTools::KeyWOW64_32);
249
250   std::set<std::string> ret;
251   for (std::string const& i : subkeys) {
252     std::string key = sdksKey;
253     key += '\\';
254     key += i;
255     key += ';';
256
257     std::string path;
258     if (cmSystemTools::ReadRegistryValue(key, path,
259                                          cmSystemTools::KeyWOW64_32) &&
260         !path.empty()) {
261       ret.insert(i);
262     }
263   }
264
265   return ret;
266 }
267
268 bool cmGlobalVisualStudio11Generator::TargetSystemSupportsDeployment() const
269 {
270   return this->SystemIsWindowsPhone || this->SystemIsWindowsStore ||
271     cmGlobalVisualStudio10Generator::TargetSystemSupportsDeployment();
272 }
273
274 bool cmGlobalVisualStudio11Generator::IsWindowsDesktopToolsetInstalled() const
275 {
276   const char desktop80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
277                               "VisualStudio\\11.0\\VC\\Libraries\\Extended";
278   const char VS2012DesktopExpressKey[] =
279     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
280     "WDExpress\\11.0;InstallDir";
281
282   std::vector<std::string> subkeys;
283   std::string path;
284   return cmSystemTools::ReadRegistryValue(VS2012DesktopExpressKey, path,
285                                           cmSystemTools::KeyWOW64_32) ||
286     cmSystemTools::GetRegistrySubKeys(desktop80Key, subkeys,
287                                       cmSystemTools::KeyWOW64_32);
288 }
289
290 bool cmGlobalVisualStudio11Generator::IsWindowsPhoneToolsetInstalled() const
291 {
292   const char wp80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
293                          "Microsoft SDKs\\WindowsPhone\\v8.0\\"
294                          "Install Path;Install Path";
295
296   std::string path;
297   cmSystemTools::ReadRegistryValue(wp80Key, path, cmSystemTools::KeyWOW64_32);
298   return !path.empty();
299 }
300
301 bool cmGlobalVisualStudio11Generator::IsWindowsStoreToolsetInstalled() const
302 {
303   const char win80Key[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
304                           "VisualStudio\\11.0\\VC\\Libraries\\Core\\Arm";
305
306   std::vector<std::string> subkeys;
307   return cmSystemTools::GetRegistrySubKeys(win80Key, subkeys,
308                                            cmSystemTools::KeyWOW64_32);
309 }