1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
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"
14 #include "cmCallVisualStudioMacro.h"
15 #include "cmGeneratorTarget.h"
16 #include "cmLocalVisualStudioGenerator.h"
17 #include "cmMakefile.h"
18 #include "cmSourceFile.h"
21 //----------------------------------------------------------------------------
22 cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
26 //----------------------------------------------------------------------------
27 cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
31 //----------------------------------------------------------------------------
32 std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
34 std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\";
35 key += this->GetIDEVersion();
39 //----------------------------------------------------------------------------
40 void cmGlobalVisualStudioGenerator::Generate()
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)
50 std::vector<cmLocalGenerator*>& gen = it->second;
51 // add the ALL_BUILD to the first local generator of each project
54 // Use no actual command lines so that the target itself is not
55 // considered always out of date.
57 gen[0]->GetMakefile()->
58 AddUtilityCommand("ALL_BUILD", true, no_working_dir,
59 no_depends, no_commands, false,
60 "Build all projects");
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.
68 // Organize in the "predefined targets" folder:
70 if (this->UseFolderProperty())
72 allBuild->SetProperty("FOLDER", this->GetPredefinedTargetsFolder());
76 // Now make all targets depend on the ALL_BUILD target
78 for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
81 cmTargets& targets = (*i)->GetMakefile()->GetTargets();
82 for(cmTargets::iterator t = targets.begin();
83 t != targets.end(); ++t)
85 if(!this->IsExcluded(gen[0], t->second))
87 allBuild->AddUtility(t->second.GetName());
94 // Configure CMake Visual Studio macros, for this user on this version
96 this->ConfigureCMakeVisualStudioMacros();
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)
103 cmLocalVisualStudioGenerator* lg =
104 static_cast<cmLocalVisualStudioGenerator*>(*lgi);
105 lg->AddCMakeListsRules();
108 // Run all the local generators.
109 this->cmGlobalGenerator::Generate();
112 //----------------------------------------------------------------------------
114 cmGlobalVisualStudioGenerator
115 ::ComputeTargetObjects(cmGeneratorTarget* gt) const
117 cmLocalVisualStudioGenerator* lg =
118 static_cast<cmLocalVisualStudioGenerator*>(gt->LocalGenerator);
119 std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target);
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)
128 cmSourceFile* sf = *si;
129 std::string objectNameLower = cmSystemTools::LowerCase(
130 cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
131 objectNameLower += ".obj";
132 counts[objectNameLower] += 1;
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)
141 cmSourceFile* sf = *si;
142 std::string objectName =
143 cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
144 objectName += ".obj";
145 if(counts[cmSystemTools::LowerCase(objectName)] > 1)
147 gt->ExplicitObjectName.insert(sf);
148 objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max);
150 gt->Objects[sf] = objectName;
153 std::string dir = gt->Makefile->GetCurrentOutputDirectory();
155 std::string tgtDir = lg->GetTargetDirectory(*gt->Target);
161 const char* cd = this->GetCMakeCFGIntDir();
167 gt->ObjectDirectory = dir;
170 //----------------------------------------------------------------------------
171 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
172 const std::string& regKeyBase,
173 std::string& nextAvailableSubKeyName);
175 void RegisterVisualStudioMacros(const std::string& macrosFile,
176 const std::string& regKeyBase);
178 //----------------------------------------------------------------------------
179 #define CMAKE_VSMACROS_FILENAME \
180 "CMakeVSMacros2.vsmacros"
182 #define CMAKE_VSMACROS_RELOAD_MACRONAME \
183 "Macros.CMakeVSMacros2.Macros.ReloadProjects"
185 #define CMAKE_VSMACROS_STOP_MACRONAME \
186 "Macros.CMakeVSMacros2.Macros.StopBuild"
188 //----------------------------------------------------------------------------
189 void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
191 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
192 std::string dir = this->GetUserMacrosDirectory();
194 if (mf != 0 && dir != "")
196 std::string src = mf->GetRequiredDefinition("CMAKE_ROOT");
197 src += "/Templates/" CMAKE_VSMACROS_FILENAME;
199 std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
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.
207 if(!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) ||
210 if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str()))
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");
219 RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase());
223 //----------------------------------------------------------------------------
225 cmGlobalVisualStudioGenerator
226 ::CallVisualStudioMacro(MacroName m,
227 const char* vsSolutionFile)
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();
234 // Only really try to call the macro if:
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
241 if (mf != 0 && dir != "")
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)
250 std::string topLevelSlnName;
253 topLevelSlnName = vsSolutionFile;
257 topLevelSlnName = mf->GetStartOutputDirectory();
258 topLevelSlnName += "/";
259 topLevelSlnName += mf->GetProjectName();
260 topLevelSlnName += ".sln";
265 std::vector<std::string> filenames;
266 this->GetFilesReplacedDuringGenerate(filenames);
267 if (filenames.size() > 0)
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())
277 for (; it != filenames.end(); ++it)
282 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
283 CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
284 this->GetCMakeInstance()->GetDebugOutput());
287 else if(m == MacroStop)
289 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
290 CMAKE_VSMACROS_STOP_MACRONAME, "",
291 this->GetCMakeInstance()->GetDebugOutput());
297 //----------------------------------------------------------------------------
298 std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
303 //----------------------------------------------------------------------------
304 std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase()
309 //----------------------------------------------------------------------------
310 void cmGlobalVisualStudioGenerator::FillLinkClosure(cmTarget* target,
313 if(linked.insert(target).second)
315 TargetDependSet const& depends = this->GetTargetDirectDepends(*target);
316 for(TargetDependSet::const_iterator di = depends.begin();
317 di != depends.end(); ++di)
321 this->FillLinkClosure(*di, linked);
327 //----------------------------------------------------------------------------
328 cmGlobalVisualStudioGenerator::TargetSet const&
329 cmGlobalVisualStudioGenerator::GetTargetLinkClosure(cmTarget* target)
331 TargetSetMap::iterator i = this->TargetLinkClosure.find(target);
332 if(i == this->TargetLinkClosure.end())
334 TargetSetMap::value_type entry(target, TargetSet());
335 i = this->TargetLinkClosure.insert(entry).first;
336 this->FillLinkClosure(target, i->second);
341 //----------------------------------------------------------------------------
342 void cmGlobalVisualStudioGenerator::FollowLinkDepends(
343 cmTarget* target, std::set<cmTarget*>& linked)
345 if(linked.insert(target).second &&
346 target->GetType() == cmTarget::STATIC_LIBRARY)
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)
356 this->FollowLinkDepends(*di, linked);
362 //----------------------------------------------------------------------------
363 bool cmGlobalVisualStudioGenerator::ComputeTargetDepends()
365 if(!this->cmGlobalGenerator::ComputeTargetDepends())
369 std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
370 for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
372 std::vector<cmLocalGenerator*>& gen = it->second;
373 for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
376 cmTargets& targets = (*i)->GetMakefile()->GetTargets();
377 for(cmTargets::iterator ti = targets.begin();
378 ti != targets.end(); ++ti)
380 this->ComputeVSTargetDepends(ti->second);
387 //----------------------------------------------------------------------------
388 static bool VSLinkable(cmTarget* t)
390 return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY;
393 //----------------------------------------------------------------------------
394 void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
396 if(this->VSTargetDepends.find(&target) != this->VSTargetDepends.end())
400 VSDependSet& vsTargetDepend = this->VSTargetDepends[&target];
401 // VS <= 7.1 has two behaviors that affect solution dependencies.
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.)
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.
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);
425 TargetDependSet const& depends = this->GetTargetDirectDepends(target);
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)
433 for(TargetDependSet::const_iterator di = depends.begin();
434 di != depends.end(); ++di)
436 cmTargetDepend dep = *di;
439 this->FollowLinkDepends(dep, linkDepends);
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)
449 cmTargetDepend dep = *di;
452 this->FollowLinkDepends(dep, utilDepends);
456 // Collect all targets linked by this target so we can avoid
457 // intermediate targets below.
459 if(target.GetType() != cmTarget::STATIC_LIBRARY)
461 linked = this->GetTargetLinkClosure(&target);
464 // Emit link dependencies.
465 for(std::set<cmTarget*>::iterator di = linkDepends.begin();
466 di != linkDepends.end(); ++di)
469 vsTargetDepend.insert(dep->GetName());
472 // Emit util dependencies. Possibly use intermediate targets.
473 for(std::set<cmTarget*>::iterator di = utilDepends.begin();
474 di != utilDepends.end(); ++di)
477 if(allowLinkable || !VSLinkable(dep) || linked.count(dep))
479 // Direct dependency allowed.
480 vsTargetDepend.insert(dep->GetName());
484 // Direct dependency on linkable target not allowed.
485 // Use an intermediate utility target.
486 vsTargetDepend.insert(this->GetUtilityDepend(dep));
491 //----------------------------------------------------------------------------
492 std::string cmGlobalVisualStudioGenerator::GetUtilityDepend(cmTarget* target)
494 UtilityDependsMap::iterator i = this->UtilityDepends.find(target);
495 if(i == this->UtilityDepends.end())
497 std::string name = this->WriteUtilityDepend(target);
498 UtilityDependsMap::value_type entry(target, name);
499 i = this->UtilityDepends.insert(entry).first;
504 //----------------------------------------------------------------------------
507 //----------------------------------------------------------------------------
508 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
509 const std::string& regKeyBase,
510 std::string& nextAvailableSubKeyName)
512 bool macrosRegistered = false;
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);
524 LONG result = ERROR_SUCCESS;
527 keyname = regKeyBase + "\\OtherProjects7";
529 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
531 if (ERROR_SUCCESS == result)
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]);
537 DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
538 FILETIME lastWriteTime;
539 lastWriteTime.dwHighDateTime = 0;
540 lastWriteTime.dwLowDateTime = 0;
542 while (ERROR_SUCCESS == RegEnumKeyEx(hkey, index, subkeyname,
544 0, keyclass, &cch_keyclass, &lastWriteTime))
546 // Open the subkey and query the values of interest:
548 result = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
549 if (ERROR_SUCCESS == result)
551 DWORD valueType = REG_SZ;
553 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
554 RegQueryValueEx(hsubkey, "Path", 0, &valueType,
555 (LPBYTE) &data1[0], &cch_data1);
558 DWORD cch_data2 = sizeof(data2);
559 RegQueryValueEx(hsubkey, "Security", 0, &valueType,
560 (LPBYTE) &data2, &cch_data2);
563 DWORD cch_data3 = sizeof(data3);
564 RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
565 (LPBYTE) &data3, &cch_data3);
567 s2 = cmSystemTools::LowerCase(data1);
568 cmSystemTools::ConvertToUnixSlashes(s2);
571 macrosRegistered = true;
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()))
581 filename = cmSystemTools::GetFilenameName(fullname);
582 filepath = cmSystemTools::GetFilenamePath(fullname);
583 filepathname = cmSystemTools::GetFilenameName(filepath);
584 filepathpath = cmSystemTools::GetFilenamePath(filepath);
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;
597 RegCloseKey(hsubkey);
601 std::cout << "error opening subkey: " << subkeyname << std::endl;
602 std::cout << std::endl;
606 cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
607 cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
608 lastWriteTime.dwHighDateTime = 0;
609 lastWriteTime.dwLowDateTime = 0;
616 std::cout << "error opening key: " << keyname << std::endl;
617 std::cout << std::endl;
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;
627 nextAvailableSubKeyName = ossNext.str();
630 keyname = regKeyBase + "\\RecordingProject7";
632 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
634 if (ERROR_SUCCESS == result)
636 DWORD valueType = REG_SZ;
638 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
639 RegQueryValueEx(hkey, "Path", 0, &valueType,
640 (LPBYTE) &data1[0], &cch_data1);
643 DWORD cch_data2 = sizeof(data2);
644 RegQueryValueEx(hkey, "Security", 0, &valueType,
645 (LPBYTE) &data2, &cch_data2);
648 DWORD cch_data3 = sizeof(data3);
649 RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
650 (LPBYTE) &data3, &cch_data3);
652 s2 = cmSystemTools::LowerCase(data1);
653 cmSystemTools::ConvertToUnixSlashes(s2);
656 macrosRegistered = true;
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;
669 std::cout << "error opening key: " << keyname << std::endl;
670 std::cout << std::endl;
673 return macrosRegistered;
676 //----------------------------------------------------------------------------
677 void WriteVSMacrosFileRegistryEntry(
678 const std::string& nextAvailableSubKeyName,
679 const std::string& macrosFile,
680 const std::string& regKeyBase)
682 std::string keyname = regKeyBase + "\\OtherProjects7";
684 LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
685 KEY_READ|KEY_WRITE, &hkey);
686 if (ERROR_SUCCESS == result)
688 // Create the subkey and set the values of interest:
691 result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0,
692 lpClass, 0, KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
693 if (ERROR_SUCCESS == result)
697 std::string s(macrosFile);
698 cmSystemTools::ReplaceString(s, "/", "\\");
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)
704 std::cout << "error result 1: " << result << std::endl;
705 std::cout << std::endl;
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)
711 result = RegSetValueEx(hsubkey, "Security",
712 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
713 if (ERROR_SUCCESS != result)
715 std::cout << "error result 2: " << result << std::endl;
716 std::cout << std::endl;
719 // StorageFormat value is always "0" for sample macros files
721 result = RegSetValueEx(hsubkey, "StorageFormat",
722 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
723 if (ERROR_SUCCESS != result)
725 std::cout << "error result 3: " << result << std::endl;
726 std::cout << std::endl;
729 RegCloseKey(hsubkey);
733 std::cout << "error creating subkey: "
734 << nextAvailableSubKeyName << std::endl;
735 std::cout << std::endl;
741 std::cout << "error opening key: " << keyname << std::endl;
742 std::cout << std::endl;
746 //----------------------------------------------------------------------------
747 void RegisterVisualStudioMacros(const std::string& macrosFile,
748 const std::string& regKeyBase)
750 bool macrosRegistered;
751 std::string nextAvailableSubKeyName;
753 macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile,
754 regKeyBase, nextAvailableSubKeyName);
756 if (!macrosRegistered)
758 int count = cmCallVisualStudioMacro::
759 GetNumberOfRunningVisualStudioInstances("ALL");
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
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
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."
780 cmSystemTools::Message(oss.str().c_str(), "Warning");
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...
787 count = cmCallVisualStudioMacro::
788 GetNumberOfRunningVisualStudioInstances("ALL");
790 // Also re-get the nextAvailableSubKeyName in case Visual Studio
791 // wrote out new registered macros information as it was exiting:
795 IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase,
796 nextAvailableSubKeyName);
800 // Do another if check - 'count' may have changed inside the above if:
804 WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile,
809 bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget& target)
811 // check to see if this is a fortran build
812 std::set<cmStdString> languages;
813 target.GetLanguages(languages);
814 if(languages.size() == 1)
816 if(*languages.begin() == "Fortran")
824 //----------------------------------------------------------------------------
826 cmGlobalVisualStudioGenerator::TargetCompare
827 ::operator()(cmTarget const* l, cmTarget const* r) const
829 // Make sure ALL_BUILD is first so it is the default active project.
830 if(strcmp(r->GetName(), "ALL_BUILD") == 0)
834 if(strcmp(l->GetName(), "ALL_BUILD") == 0)
838 return strcmp(l->GetName(), r->GetName()) < 0;
841 //----------------------------------------------------------------------------
842 cmGlobalVisualStudioGenerator::OrderedTargetDependSet
843 ::OrderedTargetDependSet(TargetDependSet const& targets)
845 for(TargetDependSet::const_iterator ti =
846 targets.begin(); ti != targets.end(); ++ti)
852 //----------------------------------------------------------------------------
853 cmGlobalVisualStudioGenerator::OrderedTargetDependSet
854 ::OrderedTargetDependSet(TargetSet const& targets)
856 for(TargetSet::const_iterator ti = targets.begin();
857 ti != targets.end(); ++ti)