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