cmGlobalVisualStudio7Generator.cxx 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  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 "windows.h" // this must be first to define GetCurrentDirectory
  11. #include <assert.h>
  12. #include "cmGlobalVisualStudio7Generator.h"
  13. #include "cmGeneratedFileStream.h"
  14. #include "cmLocalVisualStudio7Generator.h"
  15. #include "cmMakefile.h"
  16. #include "cmake.h"
  17. #include <cmsys/Encoding.hxx>
  18. cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
  19. const std::string& platformName)
  20. {
  21. this->IntelProjectVersion = 0;
  22. this->DevEnvCommandInitialized = false;
  23. if (platformName.empty())
  24. {
  25. this->PlatformName = "Win32";
  26. }
  27. else
  28. {
  29. this->PlatformName = platformName;
  30. }
  31. }
  32. cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator()
  33. {
  34. free(this->IntelProjectVersion);
  35. }
  36. // Package GUID of Intel Visual Fortran plugin to VS IDE
  37. #define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}"
  38. const char* cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
  39. {
  40. if(!this->IntelProjectVersion)
  41. {
  42. // Compute the version of the Intel plugin to the VS IDE.
  43. // If the key does not exist then use a default guess.
  44. std::string intelVersion;
  45. std::string vskey = this->GetRegistryBase();
  46. vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
  47. cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion,
  48. cmSystemTools::KeyWOW64_32);
  49. unsigned int intelVersionNumber = ~0u;
  50. sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
  51. if(intelVersionNumber >= 11)
  52. {
  53. // Default to latest known project file version.
  54. intelVersion = "11.0";
  55. }
  56. else if(intelVersionNumber == 10)
  57. {
  58. // Version 10.x actually uses 9.10 in project files!
  59. intelVersion = "9.10";
  60. }
  61. else
  62. {
  63. // Version <= 9: use ProductVersion from registry.
  64. }
  65. this->IntelProjectVersion = strdup(intelVersion.c_str());
  66. }
  67. return this->IntelProjectVersion;
  68. }
  69. void cmGlobalVisualStudio7Generator
  70. ::EnableLanguage(std::vector<std::string>const & lang,
  71. cmMakefile *mf, bool optional)
  72. {
  73. mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
  74. mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
  75. if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
  76. {
  77. mf->AddCacheDefinition(
  78. "CMAKE_CONFIGURATION_TYPES",
  79. "Debug;Release;MinSizeRel;RelWithDebInfo",
  80. "Semicolon separated list of supported configuration types, "
  81. "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
  82. "anything else will be ignored.",
  83. cmCacheManager::STRING);
  84. }
  85. // Create list of configurations requested by user's cache, if any.
  86. this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
  87. this->GenerateConfigurations(mf);
  88. // if this environment variable is set, then copy it to
  89. // a static cache entry. It will be used by
  90. // cmLocalGenerator::ConstructScript, to add an extra PATH
  91. // to all custom commands. This is because the VS IDE
  92. // does not use the environment it is run in, and this allows
  93. // for running commands and using dll's that the IDE environment
  94. // does not know about.
  95. const char* extraPath = cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH");
  96. if(extraPath)
  97. {
  98. mf->AddCacheDefinition
  99. ("CMAKE_MSVCIDE_RUN_PATH", extraPath,
  100. "Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
  101. cmCacheManager::STATIC);
  102. }
  103. }
  104. //----------------------------------------------------------------------------
  105. void cmGlobalVisualStudio7Generator::FindMakeProgram(cmMakefile* mf)
  106. {
  107. this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf);
  108. mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND",
  109. this->GetDevEnvCommand().c_str());
  110. }
  111. //----------------------------------------------------------------------------
  112. std::string const& cmGlobalVisualStudio7Generator::GetDevEnvCommand()
  113. {
  114. if(!this->DevEnvCommandInitialized)
  115. {
  116. this->DevEnvCommandInitialized = true;
  117. this->DevEnvCommand = this->FindDevEnvCommand();
  118. }
  119. return this->DevEnvCommand;
  120. }
  121. //----------------------------------------------------------------------------
  122. std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand()
  123. {
  124. std::string vscmd;
  125. std::string vskey = this->GetRegistryBase() + ";InstallDir";
  126. if(cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
  127. cmSystemTools::KeyWOW64_32))
  128. {
  129. cmSystemTools::ConvertToUnixSlashes(vscmd);
  130. vscmd += "/";
  131. }
  132. vscmd += "devenv.com";
  133. return vscmd;
  134. }
  135. //----------------------------------------------------------------------------
  136. const char* cmGlobalVisualStudio7Generator::ExternalProjectType(
  137. const char* location)
  138. {
  139. std::string extension = cmSystemTools::GetFilenameLastExtension(location);
  140. if (extension == ".vbproj")
  141. {
  142. return "F184B08F-C81C-45F6-A57F-5ABD9991F28F";
  143. }
  144. else if (extension == ".csproj")
  145. {
  146. return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
  147. }
  148. else if (extension == ".fsproj")
  149. {
  150. return "F2A71F9B-5D33-465A-A702-920D77279786";
  151. }
  152. else if (extension == ".vdproj")
  153. {
  154. return "54435603-DBB4-11D2-8724-00A0C9A8B90C";
  155. }
  156. else if (extension == ".dbproj")
  157. {
  158. return "C8D11400-126E-41CD-887F-60BD40844F9E";
  159. }
  160. else if (extension == ".wixproj")
  161. {
  162. return "930C7802-8A8C-48F9-8165-68863BCCD9DD";
  163. }
  164. else if (extension == ".pyproj")
  165. {
  166. return "888888A0-9F3D-457C-B088-3A5042F75D52";
  167. }
  168. return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
  169. }
  170. //----------------------------------------------------------------------------
  171. void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
  172. std::vector<std::string>& makeCommand,
  173. const std::string& makeProgram,
  174. const std::string& projectName,
  175. const std::string& /*projectDir*/,
  176. const std::string& targetName,
  177. const std::string& config,
  178. bool /*fast*/,
  179. std::vector<std::string> const& makeOptions)
  180. {
  181. // Select the caller- or user-preferred make program, else devenv.
  182. std::string makeProgramSelected =
  183. this->SelectMakeProgram(makeProgram, this->GetDevEnvCommand());
  184. // Ignore the above preference if it is msbuild.
  185. // Assume any other value is either a devenv or
  186. // command-line compatible with devenv.
  187. std::string makeProgramLower = makeProgramSelected;
  188. cmSystemTools::LowerCase(makeProgramLower);
  189. if(makeProgramLower.find("msbuild") != std::string::npos)
  190. {
  191. makeProgramSelected = this->GetDevEnvCommand();
  192. }
  193. makeCommand.push_back(makeProgramSelected);
  194. makeCommand.push_back(std::string(projectName) + ".sln");
  195. std::string realTarget = targetName;
  196. bool clean = false;
  197. if ( realTarget == "clean" )
  198. {
  199. clean = true;
  200. realTarget = "ALL_BUILD";
  201. }
  202. if(clean)
  203. {
  204. makeCommand.push_back("/clean");
  205. }
  206. else
  207. {
  208. makeCommand.push_back("/build");
  209. }
  210. if(!config.empty())
  211. {
  212. makeCommand.push_back(config);
  213. }
  214. else
  215. {
  216. makeCommand.push_back("Debug");
  217. }
  218. makeCommand.push_back("/project");
  219. if (!realTarget.empty())
  220. {
  221. makeCommand.push_back(realTarget);
  222. }
  223. else
  224. {
  225. makeCommand.push_back("ALL_BUILD");
  226. }
  227. makeCommand.insert(makeCommand.end(),
  228. makeOptions.begin(), makeOptions.end());
  229. }
  230. ///! Create a local generator appropriate to this Global Generator
  231. cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
  232. {
  233. cmLocalVisualStudio7Generator *lg =
  234. new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS7);
  235. lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
  236. lg->SetGlobalGenerator(this);
  237. return lg;
  238. }
  239. //----------------------------------------------------------------------------
  240. bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s,
  241. cmMakefile* mf)
  242. {
  243. if(this->PlatformName == "x64")
  244. {
  245. mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
  246. }
  247. else if(this->PlatformName == "Itanium")
  248. {
  249. mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
  250. }
  251. mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str());
  252. mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION",
  253. this->GetIntelProjectVersion());
  254. return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf);
  255. }
  256. void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
  257. {
  258. // process the configurations
  259. const char* ct
  260. = this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
  261. if ( ct )
  262. {
  263. std::vector<std::string> argsOut;
  264. cmSystemTools::ExpandListArgument(ct, argsOut);
  265. for(std::vector<std::string>::iterator i = argsOut.begin();
  266. i != argsOut.end(); ++i)
  267. {
  268. if(std::find(this->Configurations.begin(),
  269. this->Configurations.end(),
  270. *i) == this->Configurations.end())
  271. {
  272. this->Configurations.push_back(*i);
  273. }
  274. }
  275. }
  276. // default to at least Debug and Release
  277. if(this->Configurations.size() == 0)
  278. {
  279. this->Configurations.push_back("Debug");
  280. this->Configurations.push_back("Release");
  281. }
  282. // Reset the entry to have a semi-colon separated list.
  283. std::string configs = this->Configurations[0];
  284. for(unsigned int i=1; i < this->Configurations.size(); ++i)
  285. {
  286. configs += ";";
  287. configs += this->Configurations[i];
  288. }
  289. mf->AddCacheDefinition(
  290. "CMAKE_CONFIGURATION_TYPES",
  291. configs.c_str(),
  292. "Semicolon separated list of supported configuration types, "
  293. "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
  294. "anything else will be ignored.",
  295. cmCacheManager::STRING);
  296. }
  297. void cmGlobalVisualStudio7Generator::Generate()
  298. {
  299. // first do the superclass method
  300. this->cmGlobalVisualStudioGenerator::Generate();
  301. // Now write out the DSW
  302. this->OutputSLNFile();
  303. // If any solution or project files changed during the generation,
  304. // tell Visual Studio to reload them...
  305. if(!cmSystemTools::GetErrorOccuredFlag())
  306. {
  307. this->CallVisualStudioMacro(MacroReload);
  308. }
  309. }
  310. void cmGlobalVisualStudio7Generator
  311. ::OutputSLNFile(cmLocalGenerator* root,
  312. std::vector<cmLocalGenerator*>& generators)
  313. {
  314. if(generators.size() == 0)
  315. {
  316. return;
  317. }
  318. this->CurrentProject = root->GetMakefile()->GetProjectName();
  319. std::string fname = root->GetMakefile()->GetStartOutputDirectory();
  320. fname += "/";
  321. fname += root->GetMakefile()->GetProjectName();
  322. fname += ".sln";
  323. cmGeneratedFileStream fout(fname.c_str());
  324. fout.SetCopyIfDifferent(true);
  325. if(!fout)
  326. {
  327. return;
  328. }
  329. this->WriteSLNFile(fout, root, generators);
  330. if (fout.Close())
  331. {
  332. this->FileReplacedDuringGenerate(fname);
  333. }
  334. }
  335. // output the SLN file
  336. void cmGlobalVisualStudio7Generator::OutputSLNFile()
  337. {
  338. std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
  339. for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
  340. {
  341. this->OutputSLNFile(it->second[0], it->second);
  342. }
  343. }
  344. void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
  345. std::ostream& fout,
  346. OrderedTargetDependSet const& projectTargets)
  347. {
  348. // loop over again and write out configurations for each target
  349. // in the solution
  350. for(OrderedTargetDependSet::const_iterator tt =
  351. projectTargets.begin(); tt != projectTargets.end(); ++tt)
  352. {
  353. cmTarget const* target = *tt;
  354. if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
  355. {
  356. continue;
  357. }
  358. const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
  359. if(expath)
  360. {
  361. std::set<std::string> allConfigurations(this->Configurations.begin(),
  362. this->Configurations.end());
  363. const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING");
  364. this->WriteProjectConfigurations(
  365. fout, target->GetName().c_str(), target->GetType(),
  366. allConfigurations, mapping ? mapping : "");
  367. }
  368. else
  369. {
  370. const std::set<std::string>& configsPartOfDefaultBuild =
  371. this->IsPartOfDefaultBuild(projectTargets, target);
  372. const char *vcprojName =
  373. target->GetProperty("GENERATOR_FILE_NAME");
  374. if (vcprojName)
  375. {
  376. this->WriteProjectConfigurations(fout, vcprojName, target->GetType(),
  377. configsPartOfDefaultBuild);
  378. }
  379. }
  380. }
  381. }
  382. void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
  383. std::ostream& fout,
  384. cmLocalGenerator* root,
  385. OrderedTargetDependSet const& projectTargets)
  386. {
  387. VisualStudioFolders.clear();
  388. for(OrderedTargetDependSet::const_iterator tt =
  389. projectTargets.begin(); tt != projectTargets.end(); ++tt)
  390. {
  391. cmTarget const* target = *tt;
  392. if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
  393. {
  394. continue;
  395. }
  396. bool written = false;
  397. // handle external vc project files
  398. const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
  399. if(expath)
  400. {
  401. std::string project = target->GetName();
  402. std::string location = expath;
  403. this->WriteExternalProject(fout,
  404. project.c_str(),
  405. location.c_str(),
  406. target->GetProperty("VS_PROJECT_TYPE"),
  407. target->GetUtilities());
  408. written = true;
  409. }
  410. else
  411. {
  412. const char *vcprojName =
  413. target->GetProperty("GENERATOR_FILE_NAME");
  414. if(vcprojName)
  415. {
  416. cmMakefile* tmf = target->GetMakefile();
  417. std::string dir = tmf->GetStartOutputDirectory();
  418. dir = root->Convert(dir.c_str(),
  419. cmLocalGenerator::START_OUTPUT);
  420. if(dir == ".")
  421. {
  422. dir = ""; // msbuild cannot handle ".\" prefix
  423. }
  424. this->WriteProject(fout, vcprojName, dir.c_str(),
  425. *target);
  426. written = true;
  427. }
  428. }
  429. // Create "solution folder" information from FOLDER target property
  430. //
  431. if (written && this->UseFolderProperty())
  432. {
  433. const char *targetFolder = target->GetProperty("FOLDER");
  434. if (targetFolder)
  435. {
  436. std::vector<cmsys::String> tokens =
  437. cmSystemTools::SplitString(targetFolder, '/', false);
  438. std::string cumulativePath = "";
  439. for(std::vector<cmsys::String>::iterator iter = tokens.begin();
  440. iter != tokens.end(); ++iter)
  441. {
  442. if(!iter->size())
  443. {
  444. continue;
  445. }
  446. if (cumulativePath.empty())
  447. {
  448. cumulativePath = "CMAKE_FOLDER_GUID_" + *iter;
  449. }
  450. else
  451. {
  452. VisualStudioFolders[cumulativePath].insert(
  453. cumulativePath + "/" + *iter);
  454. cumulativePath = cumulativePath + "/" + *iter;
  455. }
  456. this->CreateGUID(cumulativePath.c_str());
  457. }
  458. if (!cumulativePath.empty())
  459. {
  460. VisualStudioFolders[cumulativePath].insert(target->GetName());
  461. }
  462. }
  463. }
  464. }
  465. }
  466. void cmGlobalVisualStudio7Generator::WriteTargetDepends(
  467. std::ostream& fout,
  468. OrderedTargetDependSet const& projectTargets
  469. )
  470. {
  471. for(OrderedTargetDependSet::const_iterator tt =
  472. projectTargets.begin(); tt != projectTargets.end(); ++tt)
  473. {
  474. cmTarget const* target = *tt;
  475. if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
  476. {
  477. continue;
  478. }
  479. cmMakefile* mf = target->GetMakefile();
  480. const char *vcprojName =
  481. target->GetProperty("GENERATOR_FILE_NAME");
  482. if (vcprojName)
  483. {
  484. std::string dir = mf->GetStartDirectory();
  485. this->WriteProjectDepends(fout, vcprojName,
  486. dir.c_str(), *target);
  487. }
  488. }
  489. }
  490. //----------------------------------------------------------------------------
  491. // Write a SLN file to the stream
  492. void cmGlobalVisualStudio7Generator
  493. ::WriteSLNFile(std::ostream& fout,
  494. cmLocalGenerator* root,
  495. std::vector<cmLocalGenerator*>& generators)
  496. {
  497. // Write out the header for a SLN file
  498. this->WriteSLNHeader(fout);
  499. // Collect all targets under this root generator and the transitive
  500. // closure of their dependencies.
  501. TargetDependSet projectTargets;
  502. TargetDependSet originalTargets;
  503. this->GetTargetSets(projectTargets, originalTargets, root, generators);
  504. OrderedTargetDependSet orderedProjectTargets(projectTargets);
  505. this->WriteTargetsToSolution(fout, root, orderedProjectTargets);
  506. bool useFolderProperty = this->UseFolderProperty();
  507. if (useFolderProperty)
  508. {
  509. this->WriteFolders(fout);
  510. }
  511. // Write out the configurations information for the solution
  512. fout << "Global\n"
  513. << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
  514. int c = 0;
  515. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  516. i != this->Configurations.end(); ++i)
  517. {
  518. fout << "\t\tConfigName." << c << " = " << *i << "\n";
  519. c++;
  520. }
  521. fout << "\tEndGlobalSection\n";
  522. // Write out project(target) depends
  523. fout << "\tGlobalSection(ProjectDependencies) = postSolution\n";
  524. this->WriteTargetDepends(fout, orderedProjectTargets);
  525. fout << "\tEndGlobalSection\n";
  526. if (useFolderProperty)
  527. {
  528. // Write out project folders
  529. fout << "\tGlobalSection(NestedProjects) = preSolution\n";
  530. this->WriteFoldersContent(fout);
  531. fout << "\tEndGlobalSection\n";
  532. }
  533. // Write out the configurations for all the targets in the project
  534. fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n";
  535. this->WriteTargetConfigurations(fout, orderedProjectTargets);
  536. fout << "\tEndGlobalSection\n";
  537. // Write out global sections
  538. this->WriteSLNGlobalSections(fout, root);
  539. // Write the footer for the SLN file
  540. this->WriteSLNFooter(fout);
  541. }
  542. //----------------------------------------------------------------------------
  543. void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
  544. {
  545. const char *prefix = "CMAKE_FOLDER_GUID_";
  546. const std::string::size_type skip_prefix = strlen(prefix);
  547. std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
  548. for(std::map<std::string,std::set<std::string> >::iterator iter =
  549. VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
  550. {
  551. std::string fullName = iter->first;
  552. std::string guid = this->GetGUID(fullName.c_str());
  553. cmSystemTools::ReplaceString(fullName, "/", "\\");
  554. if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix))
  555. {
  556. fullName = fullName.substr(skip_prefix);
  557. }
  558. std::string nameOnly = cmSystemTools::GetFilenameName(fullName);
  559. fout << "Project(\"{" <<
  560. guidProjectTypeFolder << "}\") = \"" <<
  561. nameOnly << "\", \"" <<
  562. fullName << "\", \"{" <<
  563. guid <<
  564. "}\"\nEndProject\n";
  565. }
  566. }
  567. //----------------------------------------------------------------------------
  568. void cmGlobalVisualStudio7Generator::WriteFoldersContent(std::ostream& fout)
  569. {
  570. for(std::map<std::string,std::set<std::string> >::iterator iter =
  571. VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
  572. {
  573. std::string key(iter->first);
  574. std::string guidParent(this->GetGUID(key.c_str()));
  575. for(std::set<std::string>::iterator it = iter->second.begin();
  576. it != iter->second.end(); ++it)
  577. {
  578. std::string value(*it);
  579. std::string guid(this->GetGUID(value.c_str()));
  580. fout << "\t\t{" << guid << "} = {" << guidParent << "}\n";
  581. }
  582. }
  583. }
  584. //----------------------------------------------------------------------------
  585. std::string
  586. cmGlobalVisualStudio7Generator::ConvertToSolutionPath(const char* path)
  587. {
  588. // Convert to backslashes. Do not use ConvertToOutputPath because
  589. // we will add quoting ourselves, and we know these projects always
  590. // use windows slashes.
  591. std::string d = path;
  592. std::string::size_type pos = 0;
  593. while((pos = d.find('/', pos)) != d.npos)
  594. {
  595. d[pos++] = '\\';
  596. }
  597. return d;
  598. }
  599. // Write a dsp file into the SLN file,
  600. // Note, that dependencies from executables to
  601. // the libraries it uses are also done here
  602. void cmGlobalVisualStudio7Generator::WriteProject(std::ostream& fout,
  603. const std::string& dspname,
  604. const char* dir, cmTarget const& target)
  605. {
  606. // check to see if this is a fortran build
  607. const char* ext = ".vcproj";
  608. const char* project =
  609. "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"";
  610. if(this->TargetIsFortranOnly(target))
  611. {
  612. ext = ".vfproj";
  613. project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
  614. }
  615. fout << project
  616. << dspname << "\", \""
  617. << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
  618. << dspname << ext << "\", \"{"
  619. << this->GetGUID(dspname) << "}\"\nEndProject\n";
  620. UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
  621. if(ui != this->UtilityDepends.end())
  622. {
  623. const char* uname = ui->second.c_str();
  624. fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
  625. << uname << "\", \""
  626. << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
  627. << uname << ".vcproj" << "\", \"{"
  628. << this->GetGUID(uname) << "}\"\n"
  629. << "EndProject\n";
  630. }
  631. }
  632. // Write a dsp file into the SLN file,
  633. // Note, that dependencies from executables to
  634. // the libraries it uses are also done here
  635. void
  636. cmGlobalVisualStudio7Generator
  637. ::WriteProjectDepends(std::ostream& fout,
  638. const std::string& dspname,
  639. const char*, cmTarget const& target)
  640. {
  641. int depcount = 0;
  642. std::string dspguid = this->GetGUID(dspname);
  643. VSDependSet const& depends = this->VSTargetDepends[&target];
  644. for(VSDependSet::const_iterator di = depends.begin();
  645. di != depends.end(); ++di)
  646. {
  647. const char* name = di->c_str();
  648. std::string guid = this->GetGUID(name);
  649. if(guid.size() == 0)
  650. {
  651. std::string m = "Target: ";
  652. m += target.GetName();
  653. m += " depends on unknown target: ";
  654. m += name;
  655. cmSystemTools::Error(m.c_str());
  656. }
  657. fout << "\t\t{" << dspguid << "}." << depcount << " = {" << guid << "}\n";
  658. depcount++;
  659. }
  660. UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
  661. if(ui != this->UtilityDepends.end())
  662. {
  663. const char* uname = ui->second.c_str();
  664. fout << "\t\t{" << this->GetGUID(uname) << "}.0 = {" << dspguid << "}\n";
  665. }
  666. }
  667. // Write a dsp file into the SLN file, Note, that dependencies from
  668. // executables to the libraries it uses are also done here
  669. void cmGlobalVisualStudio7Generator
  670. ::WriteProjectConfigurations(
  671. std::ostream& fout, const std::string& name, cmTarget::TargetType,
  672. const std::set<std::string>& configsPartOfDefaultBuild,
  673. const std::string& platformMapping)
  674. {
  675. const std::string& platformName =
  676. !platformMapping.empty() ? platformMapping : this->GetPlatformName();
  677. std::string guid = this->GetGUID(name);
  678. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  679. i != this->Configurations.end(); ++i)
  680. {
  681. fout << "\t\t{" << guid << "}." << *i
  682. << ".ActiveCfg = " << *i << "|" << platformName << "\n";
  683. std::set<std::string>::const_iterator
  684. ci = configsPartOfDefaultBuild.find(*i);
  685. if(!(ci == configsPartOfDefaultBuild.end()))
  686. {
  687. fout << "\t\t{" << guid << "}." << *i
  688. << ".Build.0 = " << *i << "|" << platformName << "\n";
  689. }
  690. }
  691. }
  692. // Write a dsp file into the SLN file,
  693. // Note, that dependencies from executables to
  694. // the libraries it uses are also done here
  695. void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
  696. const std::string& name,
  697. const char* location,
  698. const char* typeGuid,
  699. const std::set<std::string>&)
  700. {
  701. std::string d = cmSystemTools::ConvertToOutputPath(location);
  702. fout << "Project("
  703. << "\"{"
  704. << (typeGuid ? typeGuid : this->ExternalProjectType(location))
  705. << "}\") = \""
  706. << name << "\", \""
  707. << this->ConvertToSolutionPath(location) << "\", \"{"
  708. << this->GetGUID(name)
  709. << "}\"\n";
  710. fout << "EndProject\n";
  711. }
  712. void cmGlobalVisualStudio7Generator
  713. ::WriteSLNGlobalSections(std::ostream& fout,
  714. cmLocalGenerator* root)
  715. {
  716. bool extensibilityGlobalsOverridden = false;
  717. bool extensibilityAddInsOverridden = false;
  718. const cmPropertyMap& props = root->GetMakefile()->GetProperties();
  719. for(cmPropertyMap::const_iterator itProp = props.begin();
  720. itProp != props.end(); ++itProp)
  721. {
  722. if(itProp->first.find("VS_GLOBAL_SECTION_") == 0)
  723. {
  724. std::string sectionType;
  725. std::string name = itProp->first.substr(18);
  726. if(name.find("PRE_") == 0)
  727. {
  728. name = name.substr(4);
  729. sectionType = "preSolution";
  730. }
  731. else if(name.find("POST_") == 0)
  732. {
  733. name = name.substr(5);
  734. sectionType = "postSolution";
  735. }
  736. else
  737. continue;
  738. if(!name.empty())
  739. {
  740. if(name == "ExtensibilityGlobals" && sectionType == "postSolution")
  741. extensibilityGlobalsOverridden = true;
  742. else if(name == "ExtensibilityAddIns" && sectionType == "postSolution")
  743. extensibilityAddInsOverridden = true;
  744. fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
  745. std::vector<std::string> keyValuePairs;
  746. cmSystemTools::ExpandListArgument(itProp->second.GetValue(),
  747. keyValuePairs);
  748. for(std::vector<std::string>::const_iterator itPair =
  749. keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair)
  750. {
  751. const std::string::size_type posEqual = itPair->find('=');
  752. if(posEqual != std::string::npos)
  753. {
  754. const std::string key =
  755. cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
  756. const std::string value =
  757. cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
  758. fout << "\t\t" << key << " = " << value << "\n";
  759. }
  760. }
  761. fout << "\tEndGlobalSection\n";
  762. }
  763. }
  764. }
  765. if(!extensibilityGlobalsOverridden)
  766. fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
  767. << "\tEndGlobalSection\n";
  768. if(!extensibilityAddInsOverridden)
  769. fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
  770. << "\tEndGlobalSection\n";
  771. }
  772. // Standard end of dsw file
  773. void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
  774. {
  775. fout << "EndGlobal\n";
  776. }
  777. // ouput standard header for dsw file
  778. void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout)
  779. {
  780. fout << "Microsoft Visual Studio Solution File, Format Version 7.00\n";
  781. }
  782. //----------------------------------------------------------------------------
  783. std::string
  784. cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget const* target)
  785. {
  786. std::string pname = target->GetName();
  787. pname += "_UTILITY";
  788. std::string fname = target->GetMakefile()->GetStartOutputDirectory();
  789. fname += "/";
  790. fname += pname;
  791. fname += ".vcproj";
  792. cmGeneratedFileStream fout(fname.c_str());
  793. fout.SetCopyIfDifferent(true);
  794. this->CreateGUID(pname.c_str());
  795. std::string guid = this->GetGUID(pname.c_str());
  796. fout <<
  797. "<?xml version=\"1.0\" encoding = \""
  798. << this->Encoding() << "\"?>\n"
  799. "<VisualStudioProject\n"
  800. "\tProjectType=\"Visual C++\"\n"
  801. "\tVersion=\"" << this->GetIDEVersion() << "0\"\n"
  802. "\tName=\"" << pname << "\"\n"
  803. "\tProjectGUID=\"{" << guid << "}\"\n"
  804. "\tKeyword=\"Win32Proj\">\n"
  805. "\t<Platforms><Platform Name=\"Win32\"/></Platforms>\n"
  806. "\t<Configurations>\n"
  807. ;
  808. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  809. i != this->Configurations.end(); ++i)
  810. {
  811. fout <<
  812. "\t\t<Configuration\n"
  813. "\t\t\tName=\"" << *i << "|Win32\"\n"
  814. "\t\t\tOutputDirectory=\"" << *i << "\"\n"
  815. "\t\t\tIntermediateDirectory=\"" << pname << ".dir\\" << *i << "\"\n"
  816. "\t\t\tConfigurationType=\"10\"\n"
  817. "\t\t\tUseOfMFC=\"0\"\n"
  818. "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n"
  819. "\t\t\tCharacterSet=\"2\">\n"
  820. "\t\t</Configuration>\n"
  821. ;
  822. }
  823. fout <<
  824. "\t</Configurations>\n"
  825. "\t<Files></Files>\n"
  826. "\t<Globals></Globals>\n"
  827. "</VisualStudioProject>\n"
  828. ;
  829. if(fout.Close())
  830. {
  831. this->FileReplacedDuringGenerate(fname);
  832. }
  833. return pname;
  834. }
  835. std::string cmGlobalVisualStudio7Generator::GetGUID(const std::string& name)
  836. {
  837. std::string guidStoreName = name;
  838. guidStoreName += "_GUID_CMAKE";
  839. const char* storedGUID =
  840. this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
  841. if(storedGUID)
  842. {
  843. return std::string(storedGUID);
  844. }
  845. cmSystemTools::Error("Unknown Target referenced : ",
  846. name.c_str());
  847. return "";
  848. }
  849. void cmGlobalVisualStudio7Generator::CreateGUID(const std::string& name)
  850. {
  851. std::string guidStoreName = name;
  852. guidStoreName += "_GUID_CMAKE";
  853. if(this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str()))
  854. {
  855. return;
  856. }
  857. std::string ret;
  858. UUID uid;
  859. unsigned short *uidstr;
  860. UuidCreate(&uid);
  861. UuidToStringW(&uid,&uidstr);
  862. ret = cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(uidstr));
  863. RpcStringFreeW(&uidstr);
  864. ret = cmSystemTools::UpperCase(ret);
  865. this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
  866. ret.c_str(), "Stored GUID",
  867. cmCacheManager::INTERNAL);
  868. }
  869. std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations()
  870. {
  871. return &this->Configurations;
  872. };
  873. //----------------------------------------------------------------------------
  874. void cmGlobalVisualStudio7Generator
  875. ::GetDocumentation(cmDocumentationEntry& entry)
  876. {
  877. entry.Name = cmGlobalVisualStudio7Generator::GetActualName();
  878. entry.Brief = "Generates Visual Studio .NET 2002 project files.";
  879. }
  880. //----------------------------------------------------------------------------
  881. void
  882. cmGlobalVisualStudio7Generator
  883. ::AppendDirectoryForConfig(const std::string& prefix,
  884. const std::string& config,
  885. const std::string& suffix,
  886. std::string& dir)
  887. {
  888. if(!config.empty())
  889. {
  890. dir += prefix;
  891. dir += config;
  892. dir += suffix;
  893. }
  894. }
  895. std::set<std::string>
  896. cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
  897. OrderedTargetDependSet const& projectTargets, cmTarget const* target)
  898. {
  899. std::set<std::string> activeConfigs;
  900. // if it is a utilitiy target then only make it part of the
  901. // default build if another target depends on it
  902. int type = target->GetType();
  903. if (type == cmTarget::GLOBAL_TARGET)
  904. {
  905. return activeConfigs;
  906. }
  907. if(type == cmTarget::UTILITY && !this->IsDependedOn(projectTargets, target))
  908. {
  909. return activeConfigs;
  910. }
  911. // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
  912. for(std::vector<std::string>::iterator i = this->Configurations.begin();
  913. i != this->Configurations.end(); ++i)
  914. {
  915. const char* propertyValue =
  916. target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str());
  917. if(cmSystemTools::IsOff(propertyValue))
  918. {
  919. activeConfigs.insert(*i);
  920. }
  921. }
  922. return activeConfigs;
  923. }
  924. bool
  925. cmGlobalVisualStudio7Generator
  926. ::IsDependedOn(OrderedTargetDependSet const& projectTargets,
  927. cmTarget const* targetIn)
  928. {
  929. for (OrderedTargetDependSet::const_iterator l = projectTargets.begin();
  930. l != projectTargets.end(); ++l)
  931. {
  932. cmTarget const& target = **l;
  933. TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
  934. if(tgtdeps.count(targetIn))
  935. {
  936. return true;
  937. }
  938. }
  939. return false;
  940. }
  941. //----------------------------------------------------------------------------
  942. static cmVS7FlagTable cmVS7ExtraFlagTable[] =
  943. {
  944. // Precompiled header and related options. Note that the
  945. // UsePrecompiledHeader entries are marked as "Continue" so that the
  946. // corresponding PrecompiledHeaderThrough entry can be found.
  947. {"UsePrecompiledHeader", "YX", "Automatically Generate", "2",
  948. cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
  949. {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "",
  950. cmVS7FlagTable::UserValueRequired},
  951. {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3",
  952. cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
  953. {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
  954. cmVS7FlagTable::UserValueRequired},
  955. {"WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true", 0},
  956. // Exception handling mode. If no entries match, it will be FALSE.
  957. {"ExceptionHandling", "GX", "enable c++ exceptions", "true", 0},
  958. {"ExceptionHandling", "EHsc", "enable c++ exceptions", "true", 0},
  959. // The EHa option does not have an IDE setting. Let it go to false,
  960. // and have EHa passed on the command line by leaving out the table
  961. // entry.
  962. {0,0,0,0,0}
  963. };
  964. cmIDEFlagTable const* cmGlobalVisualStudio7Generator::GetExtraFlagTableVS7()
  965. {
  966. return cmVS7ExtraFlagTable;
  967. }
  968. std::string cmGlobalVisualStudio7Generator::Encoding()
  969. {
  970. std::ostringstream encoding;
  971. #ifdef CMAKE_ENCODING_UTF8
  972. encoding << "UTF-8";
  973. #else
  974. encoding << "Windows-1252";
  975. #endif
  976. return encoding.str();
  977. }