cmGlobalVisualStudioGenerator.cxx 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  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 "cmGlobalVisualStudioGenerator.h"
  11. #include "cmCallVisualStudioMacro.h"
  12. #include "cmGeneratorTarget.h"
  13. #include "cmLocalVisualStudioGenerator.h"
  14. #include "cmMakefile.h"
  15. #include "cmSourceFile.h"
  16. #include "cmTarget.h"
  17. //----------------------------------------------------------------------------
  18. cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
  19. {
  20. this->ArchitectureId = "X86";
  21. this->VersionId = 0;
  22. }
  23. //----------------------------------------------------------------------------
  24. cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
  25. {
  26. }
  27. //----------------------------------------------------------------------------
  28. std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
  29. {
  30. std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\";
  31. key += this->GetIDEVersion();
  32. return key;
  33. }
  34. //----------------------------------------------------------------------------
  35. void cmGlobalVisualStudioGenerator::Generate()
  36. {
  37. // Add a special target that depends on ALL projects for easy build
  38. // of one configuration only.
  39. const char* no_working_dir = 0;
  40. std::vector<std::string> no_depends;
  41. cmCustomCommandLines no_commands;
  42. std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
  43. for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
  44. {
  45. std::vector<cmLocalGenerator*>& gen = it->second;
  46. // add the ALL_BUILD to the first local generator of each project
  47. if(gen.size())
  48. {
  49. // Use no actual command lines so that the target itself is not
  50. // considered always out of date.
  51. cmTarget* allBuild =
  52. gen[0]->GetMakefile()->
  53. AddUtilityCommand("ALL_BUILD", true, no_working_dir,
  54. no_depends, no_commands, false,
  55. "Build all projects");
  56. #if 0
  57. // Can't activate this code because we want ALL_BUILD
  58. // selected as the default "startup project" when first
  59. // opened in Visual Studio... And if it's nested in a
  60. // folder, then that doesn't happen.
  61. //
  62. // Organize in the "predefined targets" folder:
  63. //
  64. if (this->UseFolderProperty())
  65. {
  66. allBuild->SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
  67. }
  68. #endif
  69. // Now make all targets depend on the ALL_BUILD target
  70. cmTargets targets;
  71. for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
  72. i != gen.end(); ++i)
  73. {
  74. cmTargets& targets = (*i)->GetMakefile()->GetTargets();
  75. for(cmTargets::iterator t = targets.begin();
  76. t != targets.end(); ++t)
  77. {
  78. if(!this->IsExcluded(gen[0], t->second))
  79. {
  80. allBuild->AddUtility(t->second.GetName());
  81. }
  82. }
  83. }
  84. }
  85. }
  86. // Configure CMake Visual Studio macros, for this user on this version
  87. // of Visual Studio.
  88. this->ConfigureCMakeVisualStudioMacros();
  89. // Add CMakeLists.txt with custom command to rerun CMake.
  90. for(std::vector<cmLocalGenerator*>::const_iterator
  91. lgi = this->LocalGenerators.begin();
  92. lgi != this->LocalGenerators.end(); ++lgi)
  93. {
  94. cmLocalVisualStudioGenerator* lg =
  95. static_cast<cmLocalVisualStudioGenerator*>(*lgi);
  96. lg->AddCMakeListsRules();
  97. }
  98. // Run all the local generators.
  99. this->cmGlobalGenerator::Generate();
  100. }
  101. //----------------------------------------------------------------------------
  102. void
  103. cmGlobalVisualStudioGenerator
  104. ::ComputeTargetObjects(cmGeneratorTarget* gt) const
  105. {
  106. cmLocalVisualStudioGenerator* lg =
  107. static_cast<cmLocalVisualStudioGenerator*>(gt->LocalGenerator);
  108. std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target);
  109. // Count the number of object files with each name. Note that
  110. // windows file names are not case sensitive.
  111. std::map<cmStdString, int> counts;
  112. for(std::vector<cmSourceFile*>::const_iterator
  113. si = gt->ObjectSources.begin();
  114. si != gt->ObjectSources.end(); ++si)
  115. {
  116. cmSourceFile* sf = *si;
  117. std::string objectNameLower = cmSystemTools::LowerCase(
  118. cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
  119. objectNameLower += ".obj";
  120. counts[objectNameLower] += 1;
  121. }
  122. // For all source files producing duplicate names we need unique
  123. // object name computation.
  124. for(std::vector<cmSourceFile*>::const_iterator
  125. si = gt->ObjectSources.begin();
  126. si != gt->ObjectSources.end(); ++si)
  127. {
  128. cmSourceFile* sf = *si;
  129. std::string objectName =
  130. cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
  131. objectName += ".obj";
  132. if(counts[cmSystemTools::LowerCase(objectName)] > 1)
  133. {
  134. gt->ExplicitObjectName.insert(sf);
  135. objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max);
  136. }
  137. gt->Objects[sf] = objectName;
  138. }
  139. std::string dir = gt->Makefile->GetCurrentOutputDirectory();
  140. dir += "/";
  141. std::string tgtDir = lg->GetTargetDirectory(*gt->Target);
  142. if(!tgtDir.empty())
  143. {
  144. dir += tgtDir;
  145. dir += "/";
  146. }
  147. const char* cd = this->GetCMakeCFGIntDir();
  148. if(cd && *cd)
  149. {
  150. dir += cd;
  151. dir += "/";
  152. }
  153. gt->ObjectDirectory = dir;
  154. }
  155. //----------------------------------------------------------------------------
  156. bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
  157. const std::string& regKeyBase,
  158. std::string& nextAvailableSubKeyName);
  159. void RegisterVisualStudioMacros(const std::string& macrosFile,
  160. const std::string& regKeyBase);
  161. //----------------------------------------------------------------------------
  162. #define CMAKE_VSMACROS_FILENAME \
  163. "CMakeVSMacros2.vsmacros"
  164. #define CMAKE_VSMACROS_RELOAD_MACRONAME \
  165. "Macros.CMakeVSMacros2.Macros.ReloadProjects"
  166. #define CMAKE_VSMACROS_STOP_MACRONAME \
  167. "Macros.CMakeVSMacros2.Macros.StopBuild"
  168. //----------------------------------------------------------------------------
  169. void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
  170. {
  171. cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
  172. std::string dir = this->GetUserMacrosDirectory();
  173. if (mf != 0 && dir != "")
  174. {
  175. std::string src = mf->GetRequiredDefinition("CMAKE_ROOT");
  176. src += "/Templates/" CMAKE_VSMACROS_FILENAME;
  177. std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
  178. // Copy the macros file to the user directory only if the
  179. // destination does not exist or the source location is newer.
  180. // This will allow the user to edit the macros for development
  181. // purposes but newer versions distributed with CMake will replace
  182. // older versions in user directories.
  183. int res;
  184. if(!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) ||
  185. res > 0)
  186. {
  187. if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str()))
  188. {
  189. std::ostringstream oss;
  190. oss << "Could not copy from: " << src << std::endl;
  191. oss << " to: " << dst << std::endl;
  192. cmSystemTools::Message(oss.str().c_str(), "Warning");
  193. }
  194. }
  195. RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase());
  196. }
  197. }
  198. //----------------------------------------------------------------------------
  199. void
  200. cmGlobalVisualStudioGenerator
  201. ::CallVisualStudioMacro(MacroName m,
  202. const char* vsSolutionFile)
  203. {
  204. // If any solution or project files changed during the generation,
  205. // tell Visual Studio to reload them...
  206. cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
  207. std::string dir = this->GetUserMacrosDirectory();
  208. // Only really try to call the macro if:
  209. // - mf is non-NULL
  210. // - there is a UserMacrosDirectory
  211. // - the CMake vsmacros file exists
  212. // - the CMake vsmacros file is registered
  213. // - there were .sln/.vcproj files changed during generation
  214. //
  215. if (mf != 0 && dir != "")
  216. {
  217. std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
  218. std::string nextSubkeyName;
  219. if (cmSystemTools::FileExists(macrosFile.c_str()) &&
  220. IsVisualStudioMacrosFileRegistered(macrosFile,
  221. this->GetUserMacrosRegKeyBase(), nextSubkeyName)
  222. )
  223. {
  224. std::string topLevelSlnName;
  225. if(vsSolutionFile)
  226. {
  227. topLevelSlnName = vsSolutionFile;
  228. }
  229. else
  230. {
  231. topLevelSlnName = mf->GetStartOutputDirectory();
  232. topLevelSlnName += "/";
  233. topLevelSlnName += mf->GetProjectName();
  234. topLevelSlnName += ".sln";
  235. }
  236. if(m == MacroReload)
  237. {
  238. std::vector<std::string> filenames;
  239. this->GetFilesReplacedDuringGenerate(filenames);
  240. if (filenames.size() > 0)
  241. {
  242. // Convert vector to semi-colon delimited string of filenames:
  243. std::string projects;
  244. std::vector<std::string>::iterator it = filenames.begin();
  245. if (it != filenames.end())
  246. {
  247. projects = *it;
  248. ++it;
  249. }
  250. for (; it != filenames.end(); ++it)
  251. {
  252. projects += ";";
  253. projects += *it;
  254. }
  255. cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
  256. CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
  257. this->GetCMakeInstance()->GetDebugOutput());
  258. }
  259. }
  260. else if(m == MacroStop)
  261. {
  262. cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
  263. CMAKE_VSMACROS_STOP_MACRONAME, "",
  264. this->GetCMakeInstance()->GetDebugOutput());
  265. }
  266. }
  267. }
  268. }
  269. //----------------------------------------------------------------------------
  270. std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
  271. {
  272. return "";
  273. }
  274. //----------------------------------------------------------------------------
  275. std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase()
  276. {
  277. return "";
  278. }
  279. //----------------------------------------------------------------------------
  280. void cmGlobalVisualStudioGenerator::FillLinkClosure(cmTarget* target,
  281. TargetSet& linked)
  282. {
  283. if(linked.insert(target).second)
  284. {
  285. TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
  286. for(TargetDependSet::const_iterator di = depends.begin();
  287. di != depends.end(); ++di)
  288. {
  289. if(di->IsLink())
  290. {
  291. this->FillLinkClosure(*di, linked);
  292. }
  293. }
  294. }
  295. }
  296. //----------------------------------------------------------------------------
  297. cmGlobalVisualStudioGenerator::TargetSet const&
  298. cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmTarget* target)
  299. {
  300. TargetSetMap::iterator i = this->TargetLinkClosure.find(target);
  301. if(i == this->TargetLinkClosure.end())
  302. {
  303. TargetSetMap::value_type entry(target, TargetSet());
  304. i = this->TargetLinkClosure.insert(entry).first;
  305. this->FillLinkClosure(target, i->second);
  306. }
  307. return i->second;
  308. }
  309. //----------------------------------------------------------------------------
  310. void cmGlobalVisualStudioGenerator::FollowLinkDepends(
  311. cmTarget* target, std::set<cmTarget*>& linked)
  312. {
  313. if(linked.insert(target).second &&
  314. target->GetType() == cmTarget::STATIC_LIBRARY)
  315. {
  316. // Static library targets do not list their link dependencies so
  317. // we must follow them transitively now.
  318. TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
  319. for(TargetDependSet::const_iterator di = depends.begin();
  320. di != depends.end(); ++di)
  321. {
  322. if(di->IsLink())
  323. {
  324. this->FollowLinkDepends(*di, linked);
  325. }
  326. }
  327. }
  328. }
  329. //----------------------------------------------------------------------------
  330. bool cmGlobalVisualStudioGenerator::ComputeTargetDepends()
  331. {
  332. if(!this->cmGlobalGenerator::ComputeTargetDepends())
  333. {
  334. return false;
  335. }
  336. std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
  337. for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
  338. {
  339. std::vector<cmLocalGenerator*>& gen = it->second;
  340. for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
  341. i != gen.end(); ++i)
  342. {
  343. cmTargets& targets = (*i)->GetMakefile()->GetTargets();
  344. for(cmTargets::iterator ti = targets.begin();
  345. ti != targets.end(); ++ti)
  346. {
  347. this->ComputeVSTargetDepends(ti->second);
  348. }
  349. }
  350. }
  351. return true;
  352. }
  353. //----------------------------------------------------------------------------
  354. static bool VSLinkable(cmTarget* t)
  355. {
  356. return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY;
  357. }
  358. //----------------------------------------------------------------------------
  359. void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
  360. {
  361. if(this->VSTargetDepends.find(&target) != this->VSTargetDepends.end())
  362. {
  363. return;
  364. }
  365. VSDependSet& vsTargetDepend = this->VSTargetDepends[&target];
  366. // VS <= 7.1 has two behaviors that affect solution dependencies.
  367. //
  368. // (1) Solution-level dependencies between a linkable target and a
  369. // library cause that library to be linked. We use an intermedite
  370. // empty utility target to express the dependency. (VS 8 and above
  371. // provide a project file "LinkLibraryDependencies" setting to
  372. // choose whether to activate this behavior. We disable it except
  373. // when linking external project files.)
  374. //
  375. // (2) We cannot let static libraries depend directly on targets to
  376. // which they "link" because the librarian tool will copy the
  377. // targets into the static library. While the work-around for
  378. // behavior (1) would also avoid this, it would create a large
  379. // number of extra utility targets for little gain. Instead, use
  380. // the above work-around only for dependencies explicitly added by
  381. // the add_dependencies() command. Approximate link dependencies by
  382. // leaving them out for the static library itself but following them
  383. // transitively for other targets.
  384. bool allowLinkable = (target.GetType() != cmTarget::STATIC_LIBRARY &&
  385. target.GetType() != cmTarget::SHARED_LIBRARY &&
  386. target.GetType() != cmTarget::MODULE_LIBRARY &&
  387. target.GetType() != cmTarget::EXECUTABLE);
  388. TargetDependSet const& depends = this->GetTargetDirectDepends(target);
  389. // Collect implicit link dependencies (target_link_libraries).
  390. // Static libraries cannot depend on their link implementation
  391. // due to behavior (2), but they do not really need to.
  392. std::set<cmTarget*> linkDepends;
  393. if(target.GetType() != cmTarget::STATIC_LIBRARY)
  394. {
  395. for(TargetDependSet::const_iterator di = depends.begin();
  396. di != depends.end(); ++di)
  397. {
  398. cmTargetDepend dep = *di;
  399. if(dep.IsLink())
  400. {
  401. this->FollowLinkDepends(dep, linkDepends);
  402. }
  403. }
  404. }
  405. // Collext explicit util dependencies (add_dependencies).
  406. std::set<cmTarget*> utilDepends;
  407. for(TargetDependSet::const_iterator di = depends.begin();
  408. di != depends.end(); ++di)
  409. {
  410. cmTargetDepend dep = *di;
  411. if(dep.IsUtil())
  412. {
  413. this->FollowLinkDepends(dep, utilDepends);
  414. }
  415. }
  416. // Collect all targets linked by this target so we can avoid
  417. // intermediate targets below.
  418. TargetSet linked;
  419. if(target.GetType() != cmTarget::STATIC_LIBRARY)
  420. {
  421. linked = this->GetTargetLinkClosure(&target);
  422. }
  423. // Emit link dependencies.
  424. for(std::set<cmTarget*>::iterator di = linkDepends.begin();
  425. di != linkDepends.end(); ++di)
  426. {
  427. cmTarget* dep = *di;
  428. vsTargetDepend.insert(dep->GetName());
  429. }
  430. // Emit util dependencies. Possibly use intermediate targets.
  431. for(std::set<cmTarget*>::iterator di = utilDepends.begin();
  432. di != utilDepends.end(); ++di)
  433. {
  434. cmTarget* dep = *di;
  435. if(allowLinkable || !VSLinkable(dep) || linked.count(dep))
  436. {
  437. // Direct dependency allowed.
  438. vsTargetDepend.insert(dep->GetName());
  439. }
  440. else
  441. {
  442. // Direct dependency on linkable target not allowed.
  443. // Use an intermediate utility target.
  444. vsTargetDepend.insert(this->GetUtilityDepend(dep));
  445. }
  446. }
  447. }
  448. //----------------------------------------------------------------------------
  449. void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf)
  450. {
  451. mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId);
  452. mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId);
  453. if (this->VersionId)
  454. {
  455. mf->AddDefinition(this->VersionId, "1");
  456. }
  457. }
  458. //----------------------------------------------------------------------------
  459. std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(cmTarget* target)
  460. {
  461. UtilityDependsMap::iterator i = this->UtilityDepends.find(target);
  462. if(i == this->UtilityDepends.end())
  463. {
  464. std::string name = this->WriteUtilityDepend(target);
  465. UtilityDependsMap::value_type entry(target, name);
  466. i = this->UtilityDepends.insert(entry).first;
  467. }
  468. return i->second;
  469. }
  470. //----------------------------------------------------------------------------
  471. #include <windows.h>
  472. //----------------------------------------------------------------------------
  473. bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
  474. const std::string& regKeyBase,
  475. std::string& nextAvailableSubKeyName)
  476. {
  477. bool macrosRegistered = false;
  478. std::string s1;
  479. std::string s2;
  480. // Make lowercase local copies, convert to Unix slashes, and
  481. // see if the resulting strings are the same:
  482. s1 = cmSystemTools::LowerCase(macrosFile);
  483. cmSystemTools::ConvertToUnixSlashes(s1);
  484. std::string keyname;
  485. HKEY hkey = NULL;
  486. LONG result = ERROR_SUCCESS;
  487. DWORD index = 0;
  488. keyname = regKeyBase + "\\OtherProjects7";
  489. hkey = NULL;
  490. result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
  491. 0, KEY_READ, &hkey);
  492. if (ERROR_SUCCESS == result)
  493. {
  494. // Iterate the subkeys and look for the values of interest in each subkey:
  495. CHAR subkeyname[256];
  496. DWORD cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
  497. CHAR keyclass[256];
  498. DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
  499. FILETIME lastWriteTime;
  500. lastWriteTime.dwHighDateTime = 0;
  501. lastWriteTime.dwLowDateTime = 0;
  502. while (ERROR_SUCCESS == RegEnumKeyEx(hkey, index, subkeyname,
  503. &cch_subkeyname,
  504. 0, keyclass, &cch_keyclass, &lastWriteTime))
  505. {
  506. // Open the subkey and query the values of interest:
  507. HKEY hsubkey = NULL;
  508. result = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
  509. if (ERROR_SUCCESS == result)
  510. {
  511. DWORD valueType = REG_SZ;
  512. CHAR data1[256];
  513. DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
  514. RegQueryValueEx(hsubkey, "Path", 0, &valueType,
  515. (LPBYTE) &data1[0], &cch_data1);
  516. DWORD data2 = 0;
  517. DWORD cch_data2 = sizeof(data2);
  518. RegQueryValueEx(hsubkey, "Security", 0, &valueType,
  519. (LPBYTE) &data2, &cch_data2);
  520. DWORD data3 = 0;
  521. DWORD cch_data3 = sizeof(data3);
  522. RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
  523. (LPBYTE) &data3, &cch_data3);
  524. s2 = cmSystemTools::LowerCase(data1);
  525. cmSystemTools::ConvertToUnixSlashes(s2);
  526. if (s2 == s1)
  527. {
  528. macrosRegistered = true;
  529. }
  530. std::string fullname(data1);
  531. std::string filename;
  532. std::string filepath;
  533. std::string filepathname;
  534. std::string filepathpath;
  535. if (cmSystemTools::FileExists(fullname.c_str()))
  536. {
  537. filename = cmSystemTools::GetFilenameName(fullname);
  538. filepath = cmSystemTools::GetFilenamePath(fullname);
  539. filepathname = cmSystemTools::GetFilenameName(filepath);
  540. filepathpath = cmSystemTools::GetFilenamePath(filepath);
  541. }
  542. //std::cout << keyname << "\\" << subkeyname << ":" << std::endl;
  543. //std::cout << " Path: " << data1 << std::endl;
  544. //std::cout << " Security: " << data2 << std::endl;
  545. //std::cout << " StorageFormat: " << data3 << std::endl;
  546. //std::cout << " filename: " << filename << std::endl;
  547. //std::cout << " filepath: " << filepath << std::endl;
  548. //std::cout << " filepathname: " << filepathname << std::endl;
  549. //std::cout << " filepathpath: " << filepathpath << std::endl;
  550. //std::cout << std::endl;
  551. RegCloseKey(hsubkey);
  552. }
  553. else
  554. {
  555. std::cout << "error opening subkey: " << subkeyname << std::endl;
  556. std::cout << std::endl;
  557. }
  558. ++index;
  559. cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
  560. cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
  561. lastWriteTime.dwHighDateTime = 0;
  562. lastWriteTime.dwLowDateTime = 0;
  563. }
  564. RegCloseKey(hkey);
  565. }
  566. else
  567. {
  568. std::cout << "error opening key: " << keyname << std::endl;
  569. std::cout << std::endl;
  570. }
  571. // Pass back next available sub key name, assuming sub keys always
  572. // follow the expected naming scheme. Expected naming scheme is that
  573. // the subkeys of OtherProjects7 is 0 to n-1, so it's ok to use "n"
  574. // as the name of the next subkey.
  575. std::ostringstream ossNext;
  576. ossNext << index;
  577. nextAvailableSubKeyName = ossNext.str();
  578. keyname = regKeyBase + "\\RecordingProject7";
  579. hkey = NULL;
  580. result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
  581. 0, KEY_READ, &hkey);
  582. if (ERROR_SUCCESS == result)
  583. {
  584. DWORD valueType = REG_SZ;
  585. CHAR data1[256];
  586. DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
  587. RegQueryValueEx(hkey, "Path", 0, &valueType,
  588. (LPBYTE) &data1[0], &cch_data1);
  589. DWORD data2 = 0;
  590. DWORD cch_data2 = sizeof(data2);
  591. RegQueryValueEx(hkey, "Security", 0, &valueType,
  592. (LPBYTE) &data2, &cch_data2);
  593. DWORD data3 = 0;
  594. DWORD cch_data3 = sizeof(data3);
  595. RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
  596. (LPBYTE) &data3, &cch_data3);
  597. s2 = cmSystemTools::LowerCase(data1);
  598. cmSystemTools::ConvertToUnixSlashes(s2);
  599. if (s2 == s1)
  600. {
  601. macrosRegistered = true;
  602. }
  603. //std::cout << keyname << ":" << std::endl;
  604. //std::cout << " Path: " << data1 << std::endl;
  605. //std::cout << " Security: " << data2 << std::endl;
  606. //std::cout << " StorageFormat: " << data3 << std::endl;
  607. //std::cout << std::endl;
  608. RegCloseKey(hkey);
  609. }
  610. else
  611. {
  612. std::cout << "error opening key: " << keyname << std::endl;
  613. std::cout << std::endl;
  614. }
  615. return macrosRegistered;
  616. }
  617. //----------------------------------------------------------------------------
  618. void WriteVSMacrosFileRegistryEntry(
  619. const std::string& nextAvailableSubKeyName,
  620. const std::string& macrosFile,
  621. const std::string& regKeyBase)
  622. {
  623. std::string keyname = regKeyBase + "\\OtherProjects7";
  624. HKEY hkey = NULL;
  625. LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
  626. KEY_READ|KEY_WRITE, &hkey);
  627. if (ERROR_SUCCESS == result)
  628. {
  629. // Create the subkey and set the values of interest:
  630. HKEY hsubkey = NULL;
  631. char lpClass[] = "";
  632. result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0,
  633. lpClass, 0, KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
  634. if (ERROR_SUCCESS == result)
  635. {
  636. DWORD dw = 0;
  637. std::string s(macrosFile);
  638. cmSystemTools::ReplaceString(s, "/", "\\");
  639. result = RegSetValueEx(hsubkey, "Path", 0, REG_SZ, (LPBYTE) s.c_str(),
  640. static_cast<DWORD>(strlen(s.c_str()) + 1));
  641. if (ERROR_SUCCESS != result)
  642. {
  643. std::cout << "error result 1: " << result << std::endl;
  644. std::cout << std::endl;
  645. }
  646. // Security value is always "1" for sample macros files (seems to be "2"
  647. // if you put the file somewhere outside the standard VSMacros folder)
  648. dw = 1;
  649. result = RegSetValueEx(hsubkey, "Security",
  650. 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
  651. if (ERROR_SUCCESS != result)
  652. {
  653. std::cout << "error result 2: " << result << std::endl;
  654. std::cout << std::endl;
  655. }
  656. // StorageFormat value is always "0" for sample macros files
  657. dw = 0;
  658. result = RegSetValueEx(hsubkey, "StorageFormat",
  659. 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
  660. if (ERROR_SUCCESS != result)
  661. {
  662. std::cout << "error result 3: " << result << std::endl;
  663. std::cout << std::endl;
  664. }
  665. RegCloseKey(hsubkey);
  666. }
  667. else
  668. {
  669. std::cout << "error creating subkey: "
  670. << nextAvailableSubKeyName << std::endl;
  671. std::cout << std::endl;
  672. }
  673. RegCloseKey(hkey);
  674. }
  675. else
  676. {
  677. std::cout << "error opening key: " << keyname << std::endl;
  678. std::cout << std::endl;
  679. }
  680. }
  681. //----------------------------------------------------------------------------
  682. void RegisterVisualStudioMacros(const std::string& macrosFile,
  683. const std::string& regKeyBase)
  684. {
  685. bool macrosRegistered;
  686. std::string nextAvailableSubKeyName;
  687. macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile,
  688. regKeyBase, nextAvailableSubKeyName);
  689. if (!macrosRegistered)
  690. {
  691. int count = cmCallVisualStudioMacro::
  692. GetNumberOfRunningVisualStudioInstances("ALL");
  693. // Only register the macros file if there are *no* instances of Visual
  694. // Studio running. If we register it while one is running, first, it has
  695. // no effect on the running instance; second, and worse, Visual Studio
  696. // removes our newly added registration entry when it quits. Instead,
  697. // emit a warning asking the user to exit all running Visual Studio
  698. // instances...
  699. //
  700. if (0 != count)
  701. {
  702. std::ostringstream oss;
  703. oss << "Could not register CMake's Visual Studio macros file '"
  704. << CMAKE_VSMACROS_FILENAME "' while Visual Studio is running."
  705. << " Please exit all running instances of Visual Studio before"
  706. << " continuing." << std::endl
  707. << std::endl
  708. << "CMake needs to register Visual Studio macros when its macros"
  709. << " file is updated or when it detects that its current macros file"
  710. << " is no longer registered with Visual Studio."
  711. << std::endl;
  712. cmSystemTools::Message(oss.str().c_str(), "Warning");
  713. // Count them again now that the warning is over. In the case of a GUI
  714. // warning, the user may have gone to close Visual Studio and then come
  715. // back to the CMake GUI and clicked ok on the above warning. If so,
  716. // then register the macros *now* if the count is *now* 0...
  717. //
  718. count = cmCallVisualStudioMacro::
  719. GetNumberOfRunningVisualStudioInstances("ALL");
  720. // Also re-get the nextAvailableSubKeyName in case Visual Studio
  721. // wrote out new registered macros information as it was exiting:
  722. //
  723. if (0 == count)
  724. {
  725. IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase,
  726. nextAvailableSubKeyName);
  727. }
  728. }
  729. // Do another if check - 'count' may have changed inside the above if:
  730. //
  731. if (0 == count)
  732. {
  733. WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile,
  734. regKeyBase);
  735. }
  736. }
  737. }
  738. bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget& target)
  739. {
  740. // check to see if this is a fortran build
  741. std::set<cmStdString> languages;
  742. target.GetLanguages(languages);
  743. if(languages.size() == 1)
  744. {
  745. if(*languages.begin() == "Fortran")
  746. {
  747. return true;
  748. }
  749. }
  750. return false;
  751. }
  752. //----------------------------------------------------------------------------
  753. bool
  754. cmGlobalVisualStudioGenerator::TargetCompare
  755. ::operator()(cmTarget const* l, cmTarget const* r) const
  756. {
  757. // Make sure ALL_BUILD is first so it is the default active project.
  758. if(strcmp(r->GetName(), "ALL_BUILD") == 0)
  759. {
  760. return false;
  761. }
  762. if(strcmp(l->GetName(), "ALL_BUILD") == 0)
  763. {
  764. return true;
  765. }
  766. return strcmp(l->GetName(), r->GetName()) < 0;
  767. }
  768. //----------------------------------------------------------------------------
  769. cmGlobalVisualStudioGenerator::OrderedTargetDependSet
  770. ::OrderedTargetDependSet(TargetDependSet const& targets)
  771. {
  772. for(TargetDependSet::const_iterator ti =
  773. targets.begin(); ti != targets.end(); ++ti)
  774. {
  775. this->insert(*ti);
  776. }
  777. }
  778. //----------------------------------------------------------------------------
  779. cmGlobalVisualStudioGenerator::OrderedTargetDependSet
  780. ::OrderedTargetDependSet(TargetSet const& targets)
  781. {
  782. for(TargetSet::const_iterator ti = targets.begin();
  783. ti != targets.end(); ++ti)
  784. {
  785. this->insert(*ti);
  786. }
  787. }