cmGlobalVisualStudio71Generator.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "windows.h" // this must be first to define GetCurrentDirectory
  14. #include "cmGlobalVisualStudio71Generator.h"
  15. #include "cmLocalVisualStudio7Generator.h"
  16. #include "cmMakefile.h"
  17. #include "cmake.h"
  18. cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator()
  19. {
  20. this->FindMakeProgramFile = "CMakeVS71FindMake.cmake";
  21. this->ProjectConfigurationSectionName = "ProjectConfiguration";
  22. }
  23. ///! Create a local generator appropriate to this Global Generator
  24. cmLocalGenerator *cmGlobalVisualStudio71Generator::CreateLocalGenerator()
  25. {
  26. cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator;
  27. lg->SetVersion71();
  28. lg->SetGlobalGenerator(this);
  29. return lg;
  30. }
  31. void cmGlobalVisualStudio71Generator::AddPlatformDefinitions(cmMakefile* mf)
  32. {
  33. mf->AddDefinition("MSVC71", "1");
  34. }
  35. // Write a SLN file to the stream
  36. void cmGlobalVisualStudio71Generator::WriteSLNFile(std::ostream& fout,
  37. cmLocalGenerator* root,
  38. std::vector<cmLocalGenerator*>& generators)
  39. {
  40. // Write out the header for a SLN file
  41. this->WriteSLNHeader(fout);
  42. // Get the start directory with the trailing slash
  43. std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
  44. rootdir += "/";
  45. bool doneAllBuild = false;
  46. bool doneCheckBuild = false;
  47. bool doneRunTests = false;
  48. bool doneInstall = false;
  49. bool doneEditCache = false;
  50. bool doneRebuildCache = false;
  51. bool donePackage = false;
  52. // For each cmMakefile, create a VCProj for it, and
  53. // add it to this SLN file
  54. unsigned int i;
  55. for(i = 0; i < generators.size(); ++i)
  56. {
  57. if(this->IsExcluded(root, generators[i]))
  58. {
  59. continue;
  60. }
  61. cmMakefile* mf = generators[i]->GetMakefile();
  62. // Get the source directory from the makefile
  63. std::string dir = mf->GetStartOutputDirectory();
  64. // remove the home directory and / from the source directory
  65. // this gives a relative path
  66. cmSystemTools::ReplaceString(dir, rootdir.c_str(), "");
  67. // Get the list of create dsp files names from the cmVCProjWriter, more
  68. // than one dsp could have been created per input CMakeLists.txt file
  69. // for each target
  70. std::vector<std::string> dspnames =
  71. static_cast<cmLocalVisualStudio7Generator *>(generators[i])
  72. ->GetCreatedProjectNames();
  73. cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
  74. cmTargets::iterator l = tgts.begin();
  75. for(std::vector<std::string>::iterator si = dspnames.begin();
  76. l != tgts.end() && si != dspnames.end(); ++l)
  77. {
  78. // special handling for the current makefile
  79. if(mf == generators[0]->GetMakefile())
  80. {
  81. dir = "."; // no subdirectory for project generated
  82. // if this is the special ALL_BUILD utility, then
  83. // make it depend on every other non UTILITY project.
  84. // This is done by adding the names to the GetUtilities
  85. // vector on the makefile
  86. if(l->first == "ALL_BUILD" && !doneAllBuild)
  87. {
  88. unsigned int j;
  89. for(j = 0; j < generators.size(); ++j)
  90. {
  91. cmTargets &atgts = generators[j]->GetMakefile()->GetTargets();
  92. for(cmTargets::iterator al = atgts.begin();
  93. al != atgts.end(); ++al)
  94. {
  95. if (al->second.IsInAll())
  96. {
  97. if (al->second.GetType() == cmTarget::UTILITY ||
  98. al->second.GetType() == cmTarget::GLOBAL_TARGET)
  99. {
  100. l->second.AddUtility(al->first.c_str());
  101. }
  102. else
  103. {
  104. l->second.AddLinkLibrary(al->first,cmTarget::GENERAL);
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }
  111. // Write the project into the SLN file
  112. if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
  113. {
  114. cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
  115. const cmCustomCommandLines& cmds = cc.GetCommandLines();
  116. std::string project = cmds[0][0];
  117. std::string location = cmds[0][1];
  118. this->WriteExternalProject(fout, project.c_str(), location.c_str(), cc.GetDepends());
  119. }
  120. else
  121. {
  122. if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  123. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
  124. {
  125. bool skip = false;
  126. if(l->first == "ALL_BUILD" )
  127. {
  128. if(doneAllBuild)
  129. {
  130. skip = true;
  131. }
  132. else
  133. {
  134. doneAllBuild = true;
  135. }
  136. }
  137. if(l->first == CMAKE_CHECK_BUILD_SYSTEM_TARGET)
  138. {
  139. if(doneCheckBuild)
  140. {
  141. skip = true;
  142. }
  143. else
  144. {
  145. doneCheckBuild = true;
  146. }
  147. }
  148. if(l->first == "INSTALL")
  149. {
  150. if(doneInstall)
  151. {
  152. skip = true;
  153. }
  154. else
  155. {
  156. doneInstall = true;
  157. }
  158. }
  159. if(l->first == "RUN_TESTS")
  160. {
  161. if(doneRunTests)
  162. {
  163. skip = true;
  164. }
  165. else
  166. {
  167. doneRunTests = true;
  168. }
  169. }
  170. if(l->first == "EDIT_CACHE")
  171. {
  172. if(doneEditCache)
  173. {
  174. skip = true;
  175. }
  176. else
  177. {
  178. doneEditCache = true;
  179. }
  180. }
  181. if(l->first == "REBUILD_CACHE")
  182. {
  183. if(doneRebuildCache)
  184. {
  185. skip = true;
  186. }
  187. else
  188. {
  189. doneRebuildCache = true;
  190. }
  191. }
  192. if(l->first == "PACKAGE")
  193. {
  194. if(donePackage)
  195. {
  196. skip = true;
  197. }
  198. else
  199. {
  200. donePackage = true;
  201. }
  202. }
  203. if(!skip)
  204. {
  205. this->WriteProject(fout, si->c_str(), dir.c_str(),l->second);
  206. }
  207. ++si;
  208. }
  209. }
  210. }
  211. }
  212. fout << "Global\n";
  213. this->WriteSolutionConfigurations(fout);
  214. fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName
  215. << ") = postSolution\n";
  216. // loop over again and compute the depends
  217. for(i = 0; i < generators.size(); ++i)
  218. {
  219. cmMakefile* mf = generators[i]->GetMakefile();
  220. cmLocalVisualStudio7Generator* pg =
  221. static_cast<cmLocalVisualStudio7Generator*>(generators[i]);
  222. // Get the list of create dsp files names from the cmVCProjWriter, more
  223. // than one dsp could have been created per input CMakeLists.txt file
  224. // for each target
  225. std::vector<std::string> dspnames =
  226. pg->GetCreatedProjectNames();
  227. cmTargets &tgts = pg->GetMakefile()->GetTargets();
  228. cmTargets::iterator l = tgts.begin();
  229. std::string dir = mf->GetStartDirectory();
  230. for(std::vector<std::string>::iterator si = dspnames.begin();
  231. l != tgts.end() && si != dspnames.end(); ++l)
  232. {
  233. if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
  234. {
  235. cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
  236. const cmCustomCommandLines& cmds = cc.GetCommandLines();
  237. std::string project = cmds[0][0];
  238. this->WriteProjectConfigurations(fout, project.c_str(), l->second.IsInAll());
  239. }
  240. else if ((l->second.GetType() != cmTarget::INSTALL_FILES)
  241. && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
  242. {
  243. this->WriteProjectConfigurations(fout, si->c_str(), l->second.IsInAll());
  244. ++si;
  245. }
  246. }
  247. }
  248. fout << "\tEndGlobalSection\n";
  249. // Write the footer for the SLN file
  250. this->WriteSLNFooter(fout);
  251. }
  252. void
  253. cmGlobalVisualStudio71Generator
  254. ::WriteSolutionConfigurations(std::ostream& fout)
  255. {
  256. fout << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
  257. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  258. i != this->Configurations.end(); ++i)
  259. {
  260. fout << "\t\t" << *i << " = " << *i << "\n";
  261. }
  262. fout << "\tEndGlobalSection\n";
  263. }
  264. // Write a dsp file into the SLN file,
  265. // Note, that dependencies from executables to
  266. // the libraries it uses are also done here
  267. void
  268. cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout,
  269. const char* dspname,
  270. const char* dir,
  271. cmTarget& t)
  272. {
  273. std::string d = cmSystemTools::ConvertToOutputPath(dir);
  274. fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
  275. << dspname << "\", \""
  276. << d << "\\" << dspname << ".vcproj\", \"{"
  277. << this->GetGUID(dspname) << "}\"\n";
  278. fout << "\tProjectSection(ProjectDependencies) = postProject\n";
  279. this->WriteProjectDepends(fout, dspname, dir, t);
  280. fout << "\tEndProjectSection\n";
  281. fout <<"EndProject\n";
  282. }
  283. // Write a dsp file into the SLN file,
  284. // Note, that dependencies from executables to
  285. // the libraries it uses are also done here
  286. void
  287. cmGlobalVisualStudio71Generator
  288. ::WriteProjectDepends(std::ostream& fout,
  289. const char* dspname,
  290. const char*, cmTarget& target)
  291. {
  292. // insert Begin Project Dependency Project_Dep_Name project stuff here
  293. if (target.GetType() != cmTarget::STATIC_LIBRARY)
  294. {
  295. cmTarget::LinkLibraryVectorType::const_iterator j, jend;
  296. j = target.GetLinkLibraries().begin();
  297. jend = target.GetLinkLibraries().end();
  298. for(;j!= jend; ++j)
  299. {
  300. if(j->first != dspname)
  301. {
  302. // is the library part of this SLN ? If so add dependency
  303. if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
  304. {
  305. fout << "\t\t{" << this->GetGUID(j->first.c_str()) << "} = {"
  306. << this->GetGUID(j->first.c_str()) << "}\n";
  307. }
  308. }
  309. }
  310. }
  311. std::set<cmStdString>::const_iterator i, end;
  312. // write utility dependencies.
  313. i = target.GetUtilities().begin();
  314. end = target.GetUtilities().end();
  315. for(;i!= end; ++i)
  316. {
  317. if(*i != dspname)
  318. {
  319. std::string name = i->c_str();
  320. if(strncmp(name.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
  321. {
  322. // kind of weird removing the first 27 letters.
  323. // my recommendatsions:
  324. // use cmCustomCommand::GetCommand() to get the project name
  325. // or get rid of the target name starting with "INCLUDE_EXTERNAL_MSPROJECT_" and use another
  326. // indicator/flag somewhere. These external project names shouldn't conflict with cmake
  327. // target names anyways.
  328. name.erase(name.begin(), name.begin() + 27);
  329. }
  330. std::string guid = this->GetGUID(name.c_str());
  331. if(guid.size() == 0)
  332. {
  333. std::string m = "Target: ";
  334. m += target.GetName();
  335. m += " depends on unknown target: ";
  336. m += name;
  337. cmSystemTools::Error(m.c_str());
  338. }
  339. fout << "\t\t{" << guid << "} = {" << guid << "}\n";
  340. }
  341. }
  342. }
  343. // Write a dsp file into the SLN file,
  344. // Note, that dependencies from executables to
  345. // the libraries it uses are also done here
  346. void cmGlobalVisualStudio71Generator::WriteExternalProject(std::ostream& fout,
  347. const char* name,
  348. const char* location,
  349. const std::vector<std::string>& depends)
  350. {
  351. std::string d = cmSystemTools::ConvertToOutputPath(location);
  352. fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
  353. << name << "\", \""
  354. << d << "\", \"{"
  355. << this->GetGUID(name)
  356. << "}\"\n";
  357. // write out the dependencies here
  358. // VS 7.1 includes dependencies with the project instead of in the global section
  359. if(!depends.empty())
  360. {
  361. fout << "\tProjectSection(ProjectDependencies) = postProject\n";
  362. std::vector<std::string>::const_iterator it;
  363. for(it = depends.begin(); it != depends.end(); ++it)
  364. {
  365. if(it->size() > 0)
  366. {
  367. fout << "\t\t{"
  368. << this->GetGUID(it->c_str())
  369. << "} = {"
  370. << this->GetGUID(it->c_str())
  371. << "}\n";
  372. }
  373. }
  374. fout << "\tEndProjectSection\n";
  375. }
  376. fout << "EndProject\n";
  377. }
  378. // Write a dsp file into the SLN file,
  379. // Note, that dependencies from executables to
  380. // the libraries it uses are also done here
  381. void
  382. cmGlobalVisualStudio71Generator::WriteProjectConfigurations(std::ostream& fout,
  383. const char* name,
  384. bool in_all_build)
  385. {
  386. std::string guid = this->GetGUID(name);
  387. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  388. i != this->Configurations.end(); ++i)
  389. {
  390. fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|Win32\n";
  391. if (in_all_build)
  392. {
  393. fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << *i << "|Win32\n";
  394. }
  395. }
  396. }
  397. // Standard end of dsw file
  398. void cmGlobalVisualStudio71Generator::WriteSLNFooter(std::ostream& fout)
  399. {
  400. fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
  401. << "\tEndGlobalSection\n"
  402. << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
  403. << "\tEndGlobalSection\n"
  404. << "EndGlobal\n";
  405. }
  406. // ouput standard header for dsw file
  407. void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
  408. {
  409. fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n";
  410. }
  411. //----------------------------------------------------------------------------
  412. void cmGlobalVisualStudio71Generator::GetDocumentation(cmDocumentationEntry& entry) const
  413. {
  414. entry.name = this->GetName();
  415. entry.brief = "Generates Visual Studio .NET 2003 project files.";
  416. entry.full = "";
  417. }