cmVisualStudioGeneratorOptions.cxx 12 KB

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