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