cmGlobalVisualStudioGenerator.cxx 26 KB

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