cmGlobalVisualStudio6Generator.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmGlobalVisualStudio6Generator.h"
  11. #include "cmLocalVisualStudio6Generator.h"
  12. #include "cmMakefile.h"
  13. #include "cmake.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include <cmsys/FStream.hxx>
  16. // Utility function to make a valid VS6 *.dsp filename out
  17. // of a CMake target name:
  18. //
  19. std::string GetVS6TargetName(const std::string& targetName)
  20. {
  21. std::string name(targetName);
  22. // Eliminate hyphens. VS6 cannot handle hyphens in *.dsp filenames...
  23. // Replace them with underscores.
  24. //
  25. cmSystemTools::ReplaceString(name, "-", "_");
  26. return name;
  27. }
  28. cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator()
  29. {
  30. this->MSDevCommandInitialized = false;
  31. }
  32. void cmGlobalVisualStudio6Generator
  33. ::EnableLanguage(std::vector<std::string>const& lang,
  34. cmMakefile *mf,
  35. bool optional)
  36. {
  37. cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
  38. mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
  39. mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
  40. this->GenerateConfigurations(mf);
  41. this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
  42. }
  43. void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
  44. {
  45. std::string fname= mf->GetRequiredDefinition("CMAKE_ROOT");
  46. const char* def= mf->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
  47. if(def)
  48. {
  49. fname = def;
  50. }
  51. else
  52. {
  53. fname += "/Templates";
  54. }
  55. fname += "/CMakeVisualStudio6Configurations.cmake";
  56. if(!mf->ReadListFile(mf->GetCurrentListFile(), fname.c_str()))
  57. {
  58. cmSystemTools::Error("Cannot open ", fname.c_str(),
  59. ". Please copy this file from the main "
  60. "CMake/Templates directory and edit it for "
  61. "your build configurations.");
  62. }
  63. else if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
  64. {
  65. cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ",
  66. fname.c_str(),
  67. ". Please copy this file from the main "
  68. "CMake/Templates directory and edit it for "
  69. "your build configurations.");
  70. }
  71. }
  72. //----------------------------------------------------------------------------
  73. void cmGlobalVisualStudio6Generator::FindMakeProgram(cmMakefile* mf)
  74. {
  75. this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf);
  76. mf->AddDefinition("CMAKE_VS_MSDEV_COMMAND",
  77. this->GetMSDevCommand().c_str());
  78. }
  79. //----------------------------------------------------------------------------
  80. std::string const& cmGlobalVisualStudio6Generator::GetMSDevCommand()
  81. {
  82. if(!this->MSDevCommandInitialized)
  83. {
  84. this->MSDevCommandInitialized = true;
  85. this->MSDevCommand = this->FindMSDevCommand();
  86. }
  87. return this->MSDevCommand;
  88. }
  89. //----------------------------------------------------------------------------
  90. std::string cmGlobalVisualStudio6Generator::FindMSDevCommand()
  91. {
  92. std::string vscmd;
  93. std::string vskey = this->GetRegistryBase() + "\\Setup;VsCommonDir";
  94. if(cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
  95. cmSystemTools::KeyWOW64_32))
  96. {
  97. cmSystemTools::ConvertToUnixSlashes(vscmd);
  98. vscmd += "/MSDev98/Bin/";
  99. }
  100. vscmd += "msdev.exe";
  101. return vscmd;
  102. }
  103. //----------------------------------------------------------------------------
  104. void
  105. cmGlobalVisualStudio6Generator::GenerateBuildCommand(
  106. std::vector<std::string>& makeCommand,
  107. const char* makeProgram,
  108. const std::string& projectName,
  109. const std::string& /*projectDir*/,
  110. const std::string& targetName,
  111. const std::string& config,
  112. bool /*fast*/,
  113. std::vector<std::string> const& makeOptions
  114. )
  115. {
  116. // now build the test
  117. makeCommand.push_back(
  118. this->SelectMakeProgram(makeProgram, this->GetMSDevCommand())
  119. );
  120. makeCommand.push_back(std::string(projectName)+".dsw");
  121. makeCommand.push_back("/MAKE");
  122. std::string targetArg;
  123. bool clean = false;
  124. std::string realTarget = targetName;
  125. if ( realTarget == "clean" )
  126. {
  127. clean = true;
  128. realTarget = "ALL_BUILD";
  129. }
  130. if (!realTarget.empty())
  131. {
  132. targetArg += realTarget;
  133. }
  134. else
  135. {
  136. targetArg += "ALL_BUILD";
  137. }
  138. targetArg += " - ";
  139. if(!config.empty())
  140. {
  141. targetArg += config;
  142. }
  143. else
  144. {
  145. targetArg += "Debug";
  146. }
  147. makeCommand.push_back(targetArg);
  148. if(clean)
  149. {
  150. makeCommand.push_back("/CLEAN");
  151. }
  152. else
  153. {
  154. makeCommand.push_back("/BUILD");
  155. }
  156. makeCommand.insert(makeCommand.end(),
  157. makeOptions.begin(), makeOptions.end());
  158. }
  159. ///! Create a local generator appropriate to this Global Generator
  160. cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator()
  161. {
  162. cmLocalGenerator *lg = new cmLocalVisualStudio6Generator;
  163. lg->SetGlobalGenerator(this);
  164. return lg;
  165. }
  166. void cmGlobalVisualStudio6Generator::Generate()
  167. {
  168. // first do the superclass method
  169. this->cmGlobalVisualStudioGenerator::Generate();
  170. // Now write out the DSW
  171. this->OutputDSWFile();
  172. }
  173. // Write a DSW file to the stream
  174. void cmGlobalVisualStudio6Generator
  175. ::WriteDSWFile(std::ostream& fout,cmLocalGenerator* root,
  176. std::vector<cmLocalGenerator*>& generators)
  177. {
  178. // Write out the header for a DSW file
  179. this->WriteDSWHeader(fout);
  180. // Collect all targets under this root generator and the transitive
  181. // closure of their dependencies.
  182. TargetDependSet projectTargets;
  183. TargetDependSet originalTargets;
  184. this->GetTargetSets(projectTargets, originalTargets, root, generators);
  185. OrderedTargetDependSet orderedProjectTargets(projectTargets);
  186. for(OrderedTargetDependSet::const_iterator
  187. tt = orderedProjectTargets.begin();
  188. tt != orderedProjectTargets.end(); ++tt)
  189. {
  190. cmTarget const* target = *tt;
  191. if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
  192. {
  193. continue;
  194. }
  195. // Write the project into the DSW file
  196. const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
  197. if(expath)
  198. {
  199. std::string project = target->GetName();
  200. std::string location = expath;
  201. this->WriteExternalProject(fout, project.c_str(),
  202. location.c_str(), target->GetUtilities());
  203. }
  204. else
  205. {
  206. std::string dspname = GetVS6TargetName(target->GetName());
  207. std::string dir = target->GetMakefile()->GetStartOutputDirectory();
  208. dir = root->Convert(dir.c_str(), cmLocalGenerator::START_OUTPUT);
  209. this->WriteProject(fout, dspname.c_str(), dir.c_str(), *target);
  210. }
  211. }
  212. // Write the footer for the DSW file
  213. this->WriteDSWFooter(fout);
  214. }
  215. void cmGlobalVisualStudio6Generator
  216. ::OutputDSWFile(cmLocalGenerator* root,
  217. std::vector<cmLocalGenerator*>& generators)
  218. {
  219. if(generators.size() == 0)
  220. {
  221. return;
  222. }
  223. std::string fname = root->GetMakefile()->GetStartOutputDirectory();
  224. fname += "/";
  225. fname += root->GetMakefile()->GetProjectName();
  226. fname += ".dsw";
  227. cmsys::ofstream fout(fname.c_str());
  228. if(!fout)
  229. {
  230. cmSystemTools::Error("Error can not open DSW file for write: ",
  231. fname.c_str());
  232. cmSystemTools::ReportLastSystemError("");
  233. return;
  234. }
  235. this->WriteDSWFile(fout, root, generators);
  236. }
  237. // output the DSW file
  238. void cmGlobalVisualStudio6Generator::OutputDSWFile()
  239. {
  240. std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
  241. for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
  242. {
  243. this->OutputDSWFile(it->second[0], it->second);
  244. }
  245. }
  246. // Write a dsp file into the DSW file,
  247. // Note, that dependencies from executables to
  248. // the libraries it uses are also done here
  249. void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
  250. const std::string& dspname,
  251. const char* dir,
  252. cmTarget const& target)
  253. {
  254. fout << "#########################################################"
  255. "######################\n\n";
  256. fout << "Project: \"" << dspname << "\"="
  257. << dir << "\\" << dspname << ".dsp - Package Owner=<4>\n\n";
  258. fout << "Package=<5>\n{{{\n}}}\n\n";
  259. fout << "Package=<4>\n";
  260. fout << "{{{\n";
  261. VSDependSet const& depends = this->VSTargetDepends[&target];
  262. for(VSDependSet::const_iterator di = depends.begin();
  263. di != depends.end(); ++di)
  264. {
  265. const char* name = di->c_str();
  266. fout << "Begin Project Dependency\n";
  267. fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n";
  268. fout << "End Project Dependency\n";
  269. }
  270. fout << "}}}\n\n";
  271. UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
  272. if(ui != this->UtilityDepends.end())
  273. {
  274. const char* uname = ui->second.c_str();
  275. fout << "Project: \"" << uname << "\"="
  276. << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n";
  277. fout <<
  278. "Package=<5>\n{{{\n}}}\n\n"
  279. "Package=<4>\n"
  280. "{{{\n"
  281. "Begin Project Dependency\n"
  282. "Project_Dep_Name " << dspname << "\n"
  283. "End Project Dependency\n"
  284. "}}}\n\n";
  285. ;
  286. }
  287. }
  288. // Write a dsp file into the DSW file,
  289. // Note, that dependencies from executables to
  290. // the libraries it uses are also done here
  291. void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream& fout,
  292. const std::string& name,
  293. const char* location,
  294. const std::set<std::string>& dependencies)
  295. {
  296. fout << "#########################################################"
  297. "######################\n\n";
  298. fout << "Project: \"" << name << "\"="
  299. << location << " - Package Owner=<4>\n\n";
  300. fout << "Package=<5>\n{{{\n}}}\n\n";
  301. fout << "Package=<4>\n";
  302. fout << "{{{\n";
  303. std::set<std::string>::const_iterator i, end;
  304. // write dependencies.
  305. i = dependencies.begin();
  306. end = dependencies.end();
  307. for(;i!= end; ++i)
  308. {
  309. fout << "Begin Project Dependency\n";
  310. fout << "Project_Dep_Name " << GetVS6TargetName(*i) << "\n";
  311. fout << "End Project Dependency\n";
  312. }
  313. fout << "}}}\n\n";
  314. }
  315. // Standard end of dsw file
  316. void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream& fout)
  317. {
  318. fout << "######################################################"
  319. "#########################\n\n";
  320. fout << "Global:\n\n";
  321. fout << "Package=<5>\n{{{\n}}}\n\n";
  322. fout << "Package=<3>\n{{{\n}}}\n\n";
  323. fout << "#####################################################"
  324. "##########################\n\n";
  325. }
  326. // ouput standard header for dsw file
  327. void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout)
  328. {
  329. fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
  330. fout << "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
  331. }
  332. //----------------------------------------------------------------------------
  333. std::string
  334. cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget const* target)
  335. {
  336. std::string pname = target->GetName();
  337. pname += "_UTILITY";
  338. pname = GetVS6TargetName(pname.c_str());
  339. std::string fname = target->GetMakefile()->GetStartOutputDirectory();
  340. fname += "/";
  341. fname += pname;
  342. fname += ".dsp";
  343. cmGeneratedFileStream fout(fname.c_str());
  344. fout.SetCopyIfDifferent(true);
  345. fout <<
  346. "# Microsoft Developer Studio Project File - Name=\""
  347. << pname << "\" - Package Owner=<4>\n"
  348. "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"
  349. "# ** DO NOT EDIT **\n"
  350. "\n"
  351. "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n"
  352. "\n"
  353. "CFG=" << pname << " - Win32 Debug\n"
  354. "!MESSAGE \"" << pname << " - Win32 Debug\""
  355. " (based on \"Win32 (x86) Generic Project\")\n"
  356. "!MESSAGE \"" << pname << " - Win32 Release\" "
  357. "(based on \"Win32 (x86) Generic Project\")\n"
  358. "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" "
  359. "(based on \"Win32 (x86) Generic Project\")\n"
  360. "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" "
  361. "(based on \"Win32 (x86) Generic Project\")\n"
  362. "\n"
  363. "# Begin Project\n"
  364. "# Begin Target\n"
  365. "# Name \"" << pname << " - Win32 Debug\"\n"
  366. "# Name \"" << pname << " - Win32 Release\"\n"
  367. "# Name \"" << pname << " - Win32 MinSizeRel\"\n"
  368. "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n"
  369. "# End Target\n"
  370. "# End Project\n"
  371. ;
  372. return pname;
  373. }
  374. //----------------------------------------------------------------------------
  375. void cmGlobalVisualStudio6Generator
  376. ::GetDocumentation(cmDocumentationEntry& entry)
  377. {
  378. entry.Name = cmGlobalVisualStudio6Generator::GetActualName();
  379. entry.Brief = "Generates Visual Studio 6 project files.";
  380. }
  381. //----------------------------------------------------------------------------
  382. void
  383. cmGlobalVisualStudio6Generator
  384. ::AppendDirectoryForConfig(const std::string& prefix,
  385. const std::string& config,
  386. const std::string& suffix,
  387. std::string& dir)
  388. {
  389. if(!config.empty())
  390. {
  391. dir += prefix;
  392. dir += config;
  393. dir += suffix;
  394. }
  395. }