cmVisualStudioGeneratorOptions.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include "cmVisualStudioGeneratorOptions.h"
  2. #include "cmSystemTools.h"
  3. #include <cmsys/System.h>
  4. #include "cmVisualStudio10TargetGenerator.h"
  5. inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
  6. {
  7. std::string ret = s;
  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. inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s)
  15. {
  16. std::string ret = s;
  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::UsingUnicode() const
  101. {
  102. // Look for the a _UNICODE definition.
  103. for(std::vector<std::string>::const_iterator di = this->Defines.begin();
  104. di != this->Defines.end(); ++di)
  105. {
  106. if(*di == "_UNICODE")
  107. {
  108. return true;
  109. }
  110. }
  111. return false;
  112. }
  113. //----------------------------------------------------------------------------
  114. bool cmVisualStudioGeneratorOptions::UsingSBCS() const
  115. {
  116. // Look for the a _SBCS definition.
  117. for(std::vector<std::string>::const_iterator di = this->Defines.begin();
  118. di != this->Defines.end(); ++di)
  119. {
  120. if(*di == "_SBCS")
  121. {
  122. return true;
  123. }
  124. }
  125. return false;
  126. }
  127. //----------------------------------------------------------------------------
  128. void cmVisualStudioGeneratorOptions::Parse(const char* flags)
  129. {
  130. // Parse the input string as a windows command line since the string
  131. // is intended for writing directly into the build files.
  132. std::vector<std::string> args;
  133. cmSystemTools::ParseWindowsCommandLine(flags, args);
  134. // Process flags that need to be represented specially in the IDE
  135. // project file.
  136. for(std::vector<std::string>::iterator ai = args.begin();
  137. ai != args.end(); ++ai)
  138. {
  139. this->HandleFlag(ai->c_str());
  140. }
  141. }
  142. //----------------------------------------------------------------------------
  143. void cmVisualStudioGeneratorOptions::ParseFinish()
  144. {
  145. if(this->CurrentTool == FortranCompiler)
  146. {
  147. // "RuntimeLibrary" attribute values:
  148. // "rtMultiThreaded", "0", /threads /libs:static
  149. // "rtMultiThreadedDLL", "2", /threads /libs:dll
  150. // "rtMultiThreadedDebug", "1", /threads /dbglibs /libs:static
  151. // "rtMultiThreadedDebugDLL", "3", /threads /dbglibs /libs:dll
  152. // These seem unimplemented by the IDE:
  153. // "rtSingleThreaded", "4", /libs:static
  154. // "rtSingleThreadedDLL", "10", /libs:dll
  155. // "rtSingleThreadedDebug", "5", /dbglibs /libs:static
  156. // "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll
  157. std::string rl = "rtMultiThreaded";
  158. rl += this->FortranRuntimeDebug? "Debug" : "";
  159. rl += this->FortranRuntimeDLL? "DLL" : "";
  160. this->FlagMap["RuntimeLibrary"] = rl;
  161. }
  162. }
  163. //----------------------------------------------------------------------------
  164. void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
  165. {
  166. // Look for Intel Fortran flags that do not map well in the flag table.
  167. if(this->CurrentTool == FortranCompiler)
  168. {
  169. if(strcmp(flag, "/dbglibs") == 0)
  170. {
  171. this->FortranRuntimeDebug = true;
  172. return;
  173. }
  174. if(strcmp(flag, "/threads") == 0)
  175. {
  176. this->FortranRuntimeMT = true;
  177. return;
  178. }
  179. if(strcmp(flag, "/libs:dll") == 0)
  180. {
  181. this->FortranRuntimeDLL = true;
  182. return;
  183. }
  184. if(strcmp(flag, "/libs:static") == 0)
  185. {
  186. this->FortranRuntimeDLL = false;
  187. return;
  188. }
  189. }
  190. // This option is not known. Store it in the output flags.
  191. this->FlagString += " ";
  192. this->FlagString +=
  193. cmSystemTools::EscapeWindowsShellArgument(
  194. flag,
  195. cmsysSystem_Shell_Flag_AllowMakeVariables |
  196. cmsysSystem_Shell_Flag_VSIDE);
  197. }
  198. //----------------------------------------------------------------------------
  199. void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
  200. {
  201. this->Configuration = config;
  202. }
  203. //----------------------------------------------------------------------------
  204. void
  205. cmVisualStudioGeneratorOptions
  206. ::OutputPreprocessorDefinitions(std::ostream& fout,
  207. const char* prefix,
  208. const char* suffix,
  209. const std::string& lang)
  210. {
  211. if(this->Defines.empty())
  212. {
  213. return;
  214. }
  215. if(this->Version >= cmLocalVisualStudioGenerator::VS10)
  216. {
  217. // if there are configuration specific flags, then
  218. // use the configuration specific tag for PreprocessorDefinitions
  219. if(this->Configuration.size())
  220. {
  221. fout << prefix;
  222. this->TargetGenerator->WritePlatformConfigTag(
  223. "PreprocessorDefinitions",
  224. this->Configuration.c_str(),
  225. 0,
  226. 0, 0, &fout);
  227. }
  228. else
  229. {
  230. fout << prefix << "<PreprocessorDefinitions>";
  231. }
  232. }
  233. else
  234. {
  235. fout << prefix << "PreprocessorDefinitions=\"";
  236. }
  237. const char* sep = "";
  238. for(std::vector<std::string>::const_iterator di = this->Defines.begin();
  239. di != this->Defines.end(); ++di)
  240. {
  241. // Escape the definition for the compiler.
  242. std::string define;
  243. if(this->Version < cmLocalVisualStudioGenerator::VS10)
  244. {
  245. define =
  246. this->LocalGenerator->EscapeForShell(di->c_str(), true);
  247. }
  248. else
  249. {
  250. define = *di;
  251. }
  252. // Escape this flag for the IDE.
  253. if(this->Version >= cmLocalVisualStudioGenerator::VS10)
  254. {
  255. define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str());
  256. if(lang == "RC")
  257. {
  258. cmSystemTools::ReplaceString(define, "\"", "\\\"");
  259. }
  260. }
  261. else
  262. {
  263. define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str());
  264. }
  265. // Store the flag in the project file.
  266. fout << sep << define;
  267. sep = ";";
  268. }
  269. if(this->Version >= cmLocalVisualStudioGenerator::VS10)
  270. {
  271. fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix;
  272. }
  273. else
  274. {
  275. fout << "\"" << suffix;
  276. }
  277. }
  278. //----------------------------------------------------------------------------
  279. void
  280. cmVisualStudioGeneratorOptions
  281. ::OutputFlagMap(std::ostream& fout, const char* indent)
  282. {
  283. if(this->Version >= cmLocalVisualStudioGenerator::VS10)
  284. {
  285. for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin();
  286. m != this->FlagMap.end(); ++m)
  287. {
  288. fout << indent;
  289. if(this->Configuration.size())
  290. {
  291. this->TargetGenerator->WritePlatformConfigTag(
  292. m->first.c_str(),
  293. this->Configuration.c_str(),
  294. 0,
  295. 0, 0, &fout);
  296. }
  297. else
  298. {
  299. fout << "<" << m->first << ">";
  300. }
  301. fout << m->second;
  302. if (m->first == "AdditionalIncludeDirectories")
  303. {
  304. fout << ";%(AdditionalIncludeDirectories)";
  305. }
  306. fout << "</" << m->first << ">\n";
  307. }
  308. }
  309. else
  310. {
  311. for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin();
  312. m != this->FlagMap.end(); ++m)
  313. {
  314. fout << indent << m->first << "=\"" << m->second << "\"\n";
  315. }
  316. }
  317. }
  318. //----------------------------------------------------------------------------
  319. void
  320. cmVisualStudioGeneratorOptions
  321. ::OutputAdditionalOptions(std::ostream& fout,
  322. const char* prefix,
  323. const char* suffix)
  324. {
  325. if(!this->FlagString.empty())
  326. {
  327. if(this->Version >= cmLocalVisualStudioGenerator::VS10)
  328. {
  329. fout << prefix;
  330. if(this->Configuration.size())
  331. {
  332. this->TargetGenerator->WritePlatformConfigTag(
  333. "AdditionalOptions",
  334. this->Configuration.c_str(),
  335. 0,
  336. 0, 0, &fout);
  337. }
  338. else
  339. {
  340. fout << "<AdditionalOptions>";
  341. }
  342. fout << this->FlagString.c_str()
  343. << " %(AdditionalOptions)</AdditionalOptions>\n";
  344. }
  345. else
  346. {
  347. fout << prefix << "AdditionalOptions=\"";
  348. fout <<
  349. cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str());
  350. fout << "\"" << suffix;
  351. }
  352. }
  353. }