Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmVisualStudioGeneratorOptions.cxx
1 #include "cmVisualStudioGeneratorOptions.h"
2 #include "cmSystemTools.h"
3 #include <cmsys/System.h>
4 #include "cmVisualStudio10TargetGenerator.h"
5
6 inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
7 {
8   std::string ret = s;
9   cmSystemTools::ReplaceString(ret, ";", "%3B");
10   cmSystemTools::ReplaceString(ret, "&", "&amp;");
11   cmSystemTools::ReplaceString(ret, "<", "&lt;");
12   cmSystemTools::ReplaceString(ret, ">", "&gt;");
13   return ret;
14 }
15
16 inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s)
17 {
18   std::string ret = s;
19   cmSystemTools::ReplaceString(ret, "&", "&amp;");
20   cmSystemTools::ReplaceString(ret, "\"", "&quot;");
21   cmSystemTools::ReplaceString(ret, "<", "&lt;");
22   cmSystemTools::ReplaceString(ret, ">", "&gt;");
23   cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
24   return ret;
25 }
26
27 //----------------------------------------------------------------------------
28 cmVisualStudioGeneratorOptions
29 ::cmVisualStudioGeneratorOptions(cmLocalVisualStudioGenerator* lg,
30                                  Tool tool,
31                                  cmVS7FlagTable const* table,
32                                  cmVS7FlagTable const* extraTable,
33                                  cmVisualStudio10TargetGenerator* g):
34   cmIDEOptions(),
35   LocalGenerator(lg), Version(lg->GetVersion()), CurrentTool(tool),
36   TargetGenerator(g)
37 {
38   // Store the given flag tables.
39   cmIDEFlagTable const** ft = this->FlagTable;
40   if(table) { *ft++ = table; }
41   if(extraTable) { *ft++ = extraTable; }
42
43   // Preprocessor definitions are not allowed for linker tools.
44   this->AllowDefine = (tool != Linker);
45
46   // Slash options are allowed for VS.
47   this->AllowSlash = true;
48
49   this->FortranRuntimeDebug = false;
50   this->FortranRuntimeDLL = false;
51   this->FortranRuntimeMT = false;
52 }
53
54 //----------------------------------------------------------------------------
55 void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
56 {
57   // Exception handling is on by default because the platform file has
58   // "/EHsc" in the flags.  Normally, that will override this
59   // initialization to off, but the user has the option of removing
60   // the flag to disable exception handling.  When the user does
61   // remove the flag we need to override the IDE default of on.
62   switch (this->Version)
63     {
64     case cmLocalVisualStudioGenerator::VS7:
65     case cmLocalVisualStudioGenerator::VS71:
66       this->FlagMap["ExceptionHandling"] = "FALSE";
67       break;
68     case cmLocalVisualStudioGenerator::VS10:
69     case cmLocalVisualStudioGenerator::VS11:
70     case cmLocalVisualStudioGenerator::VS12:
71       // by default VS puts <ExceptionHandling></ExceptionHandling> empty
72       // for a project, to make our projects look the same put a new line
73       // and space over for the closing </ExceptionHandling> as the default
74       // value
75       this->FlagMap["ExceptionHandling"] = "\n      ";
76       break;
77     default:
78       this->FlagMap["ExceptionHandling"] = "0";
79     break;
80     }
81 }
82
83 //----------------------------------------------------------------------------
84 void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
85 {
86   // If verbose makefiles have been requested and the /nologo option
87   // was not given explicitly in the flags we want to add an attribute
88   // to the generated project to disable logo suppression.  Otherwise
89   // the GUI default is to enable suppression.
90   //
91   // On Visual Studio 10 (and later!), the value of this attribute should be
92   // an empty string, instead of "FALSE", in order to avoid a warning:
93   //   "cl ... warning D9035: option 'nologo-' has been deprecated"
94   //
95   if(verbose &&
96      this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end())
97     {
98     this->FlagMap["SuppressStartupBanner"] =
99       this->Version < cmLocalVisualStudioGenerator::VS10 ? "FALSE" : "";
100     }
101 }
102
103 bool cmVisualStudioGeneratorOptions::IsDebug() const
104 {
105   return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end();
106 }
107
108 //----------------------------------------------------------------------------
109 bool cmVisualStudioGeneratorOptions::UsingUnicode() const
110 {
111   // Look for the a _UNICODE definition.
112   for(std::vector<std::string>::const_iterator di = this->Defines.begin();
113       di != this->Defines.end(); ++di)
114     {
115     if(*di == "_UNICODE")
116       {
117       return true;
118       }
119     }
120   return false;
121 }
122 //----------------------------------------------------------------------------
123 bool cmVisualStudioGeneratorOptions::UsingSBCS() const
124 {
125   // Look for the a _SBCS definition.
126   for(std::vector<std::string>::const_iterator di = this->Defines.begin();
127       di != this->Defines.end(); ++di)
128     {
129     if(*di == "_SBCS")
130       {
131       return true;
132       }
133     }
134   return false;
135 }
136
137 //----------------------------------------------------------------------------
138 void cmVisualStudioGeneratorOptions::Parse(const char* flags)
139 {
140   // Parse the input string as a windows command line since the string
141   // is intended for writing directly into the build files.
142   std::vector<std::string> args;
143   cmSystemTools::ParseWindowsCommandLine(flags, args);
144
145   // Process flags that need to be represented specially in the IDE
146   // project file.
147   for(std::vector<std::string>::iterator ai = args.begin();
148       ai != args.end(); ++ai)
149     {
150     this->HandleFlag(ai->c_str());
151     }
152 }
153
154 //----------------------------------------------------------------------------
155 void cmVisualStudioGeneratorOptions::ParseFinish()
156 {
157   if(this->CurrentTool == FortranCompiler)
158     {
159     // "RuntimeLibrary" attribute values:
160     //  "rtMultiThreaded", "0", /threads /libs:static
161     //  "rtMultiThreadedDLL", "2", /threads /libs:dll
162     //  "rtMultiThreadedDebug", "1", /threads /dbglibs /libs:static
163     //  "rtMultiThreadedDebugDLL", "3", /threads /dbglibs /libs:dll
164     // These seem unimplemented by the IDE:
165     //  "rtSingleThreaded", "4", /libs:static
166     //  "rtSingleThreadedDLL", "10", /libs:dll
167     //  "rtSingleThreadedDebug", "5", /dbglibs /libs:static
168     //  "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll
169     std::string rl = "rtMultiThreaded";
170     rl += this->FortranRuntimeDebug? "Debug" : "";
171     rl += this->FortranRuntimeDLL? "DLL" : "";
172     this->FlagMap["RuntimeLibrary"] = rl;
173     }
174 }
175
176 //----------------------------------------------------------------------------
177 void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
178 {
179   // Look for Intel Fortran flags that do not map well in the flag table.
180   if(this->CurrentTool == FortranCompiler)
181     {
182     if(strcmp(flag, "/dbglibs") == 0)
183       {
184       this->FortranRuntimeDebug = true;
185       return;
186       }
187     if(strcmp(flag, "/threads") == 0)
188       {
189       this->FortranRuntimeMT = true;
190       return;
191       }
192     if(strcmp(flag, "/libs:dll") == 0)
193       {
194       this->FortranRuntimeDLL = true;
195       return;
196       }
197     if(strcmp(flag, "/libs:static") == 0)
198       {
199       this->FortranRuntimeDLL = false;
200       return;
201       }
202     }
203
204   // This option is not known.  Store it in the output flags.
205   this->FlagString += " ";
206   this->FlagString +=
207     cmSystemTools::EscapeWindowsShellArgument(
208       flag,
209       cmsysSystem_Shell_Flag_AllowMakeVariables |
210       cmsysSystem_Shell_Flag_VSIDE);
211 }
212
213 //----------------------------------------------------------------------------
214 void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
215 {
216   this->Configuration = config;
217 }
218
219 //----------------------------------------------------------------------------
220 void
221 cmVisualStudioGeneratorOptions
222 ::OutputPreprocessorDefinitions(std::ostream& fout,
223                                 const char* prefix,
224                                 const char* suffix,
225                                 const char* lang)
226 {
227   if(this->Defines.empty())
228     {
229     return;
230     }
231   if(this->Version >= cmLocalVisualStudioGenerator::VS10)
232     {
233     // if there are configuration specific flags, then
234     // use the configuration specific tag for PreprocessorDefinitions
235     if(this->Configuration.size())
236       {
237       fout << prefix;
238       this->TargetGenerator->WritePlatformConfigTag(
239         "PreprocessorDefinitions",
240         this->Configuration.c_str(),
241         0,
242         0, 0, &fout);
243       }
244     else
245       {
246       fout << prefix << "<PreprocessorDefinitions>";
247       }
248     }
249   else
250     {
251     fout << prefix <<  "PreprocessorDefinitions=\"";
252     }
253   const char* sep = "";
254   for(std::vector<std::string>::const_iterator di = this->Defines.begin();
255       di != this->Defines.end(); ++di)
256     {
257     // Escape the definition for the compiler.
258     std::string define;
259     if(this->Version < cmLocalVisualStudioGenerator::VS10)
260       {
261       define =
262         this->LocalGenerator->EscapeForShell(di->c_str(), true);
263       }
264     else
265       {
266       define = *di;
267       }
268     // Escape this flag for the IDE.
269     if(this->Version >= cmLocalVisualStudioGenerator::VS10)
270       {
271       define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str());
272
273       if(0 == strcmp(lang, "RC"))
274         {
275         cmSystemTools::ReplaceString(define, "\"", "\\\"");
276         }
277       }
278     else
279       {
280       define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str());
281       }
282     // Store the flag in the project file.
283     fout << sep << define;
284     sep = ";";
285     }
286   if(this->Version >= cmLocalVisualStudioGenerator::VS10)
287     {
288     fout <<  ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix;
289     }
290   else
291     {
292     fout << "\"" << suffix;
293     }
294 }
295
296 //----------------------------------------------------------------------------
297 void
298 cmVisualStudioGeneratorOptions
299 ::OutputFlagMap(std::ostream& fout, const char* indent)
300 {
301   if(this->Version >= cmLocalVisualStudioGenerator::VS10)
302     {
303     for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin();
304         m != this->FlagMap.end(); ++m)
305       {
306       fout << indent;
307       if(this->Configuration.size())
308         {
309         this->TargetGenerator->WritePlatformConfigTag(
310           m->first.c_str(),
311           this->Configuration.c_str(),
312           0,
313           0, 0, &fout);
314         }
315       else
316         {
317         fout << "<" << m->first << ">";
318         }
319       fout  << m->second;
320       if (m->first == "AdditionalIncludeDirectories")
321         {
322         fout  << ";%(AdditionalIncludeDirectories)";
323         }
324       fout  << "</" << m->first << ">\n";
325       }
326     }
327   else
328     {
329     for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin();
330         m != this->FlagMap.end(); ++m)
331       {
332       fout << indent << m->first << "=\"" << m->second << "\"\n";
333       }
334     }
335 }
336
337 //----------------------------------------------------------------------------
338 void
339 cmVisualStudioGeneratorOptions
340 ::OutputAdditionalOptions(std::ostream& fout,
341                           const char* prefix,
342                           const char* suffix)
343 {
344   if(!this->FlagString.empty())
345     {
346     if(this->Version >= cmLocalVisualStudioGenerator::VS10)
347       {
348       fout << prefix;
349       if(this->Configuration.size())
350         {
351         this->TargetGenerator->WritePlatformConfigTag(
352           "AdditionalOptions",
353           this->Configuration.c_str(),
354           0,
355           0, 0, &fout);
356         }
357       else
358         {
359         fout << "<AdditionalOptions>";
360         }
361       fout << this->FlagString.c_str()
362            << " %(AdditionalOptions)</AdditionalOptions>\n";
363       }
364     else
365       {
366       fout << prefix << "AdditionalOptions=\"";
367       fout <<
368         cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str());
369       fout << "\"" << suffix;
370       }
371     }
372 }