Skip implicit link info for multiple OS X archs
[cmake.git] / Source / cmGlobalVisualStudioGenerator.cxx
blobbff7c9a5e611e7eada4d8547d057d02155ec261f
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalVisualStudioGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-09-16 15:44:08 $
7 Version: $Revision: 1.17 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalVisualStudioGenerator.h"
19 #include "cmCallVisualStudioMacro.h"
20 #include "cmLocalGenerator.h"
21 #include "cmMakefile.h"
22 #include "cmTarget.h"
24 //----------------------------------------------------------------------------
25 cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
29 //----------------------------------------------------------------------------
30 cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
34 //----------------------------------------------------------------------------
35 std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
37 std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\";
38 key += this->GetIDEVersion();
39 return key;
42 //----------------------------------------------------------------------------
43 void cmGlobalVisualStudioGenerator::Generate()
45 // Add a special target that depends on ALL projects for easy build
46 // of one configuration only.
47 const char* no_working_dir = 0;
48 std::vector<std::string> no_depends;
49 cmCustomCommandLines no_commands;
50 std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
51 for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
53 std::vector<cmLocalGenerator*>& gen = it->second;
54 // add the ALL_BUILD to the first local generator of each project
55 if(gen.size())
57 // Use no actual command lines so that the target itself is not
58 // considered always out of date.
59 cmTarget* allBuild =
60 gen[0]->GetMakefile()->
61 AddUtilityCommand("ALL_BUILD", true, no_working_dir,
62 no_depends, no_commands, false,
63 "Build all projects");
64 // Now make all targets depend on the ALL_BUILD target
65 cmTargets targets;
66 for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
67 i != gen.end(); ++i)
69 cmTargets& targets = (*i)->GetMakefile()->GetTargets();
70 for(cmTargets::iterator t = targets.begin();
71 t != targets.end(); ++t)
73 if(!this->IsExcluded(gen[0], t->second))
75 allBuild->AddUtility(t->second.GetName());
82 // Fix utility dependencies to avoid linking to libraries.
83 this->FixUtilityDepends();
85 // Configure CMake Visual Studio macros, for this user on this version
86 // of Visual Studio.
87 this->ConfigureCMakeVisualStudioMacros();
89 // Run all the local generators.
90 this->cmGlobalGenerator::Generate();
93 //----------------------------------------------------------------------------
94 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
95 const std::string& regKeyBase,
96 std::string& nextAvailableSubKeyName);
98 void RegisterVisualStudioMacros(const std::string& macrosFile,
99 const std::string& regKeyBase);
101 //----------------------------------------------------------------------------
102 #define CMAKE_VSMACROS_FILENAME \
103 "CMakeVSMacros2.vsmacros"
105 #define CMAKE_VSMACROS_RELOAD_MACRONAME \
106 "Macros.CMakeVSMacros2.Macros.ReloadProjects"
108 #define CMAKE_VSMACROS_STOP_MACRONAME \
109 "Macros.CMakeVSMacros2.Macros.StopBuild"
111 //----------------------------------------------------------------------------
112 void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
114 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
115 std::string dir = this->GetUserMacrosDirectory();
117 if (mf != 0 && dir != "")
119 std::string src = mf->GetRequiredDefinition("CMAKE_ROOT");
120 src += "/Templates/" CMAKE_VSMACROS_FILENAME;
122 std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
124 // Copy the macros file to the user directory only if the
125 // destination does not exist or the source location is newer.
126 // This will allow the user to edit the macros for development
127 // purposes but newer versions distributed with CMake will replace
128 // older versions in user directories.
129 int res;
130 if(!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) ||
131 res > 0)
133 if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str()))
135 std::ostringstream oss;
136 oss << "Could not copy from: " << src << std::endl;
137 oss << " to: " << dst << std::endl;
138 cmSystemTools::Message(oss.str().c_str(), "Warning");
142 RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase());
146 //----------------------------------------------------------------------------
147 void
148 cmGlobalVisualStudioGenerator
149 ::CallVisualStudioMacro(MacroName m,
150 const char* vsSolutionFile)
152 // If any solution or project files changed during the generation,
153 // tell Visual Studio to reload them...
154 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
155 std::string dir = this->GetUserMacrosDirectory();
157 // Only really try to call the macro if:
158 // - mf is non-NULL
159 // - there is a UserMacrosDirectory
160 // - the CMake vsmacros file exists
161 // - the CMake vsmacros file is registered
162 // - there were .sln/.vcproj files changed during generation
164 if (mf != 0 && dir != "")
166 std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
167 std::string nextSubkeyName;
168 if (cmSystemTools::FileExists(macrosFile.c_str()) &&
169 IsVisualStudioMacrosFileRegistered(macrosFile,
170 this->GetUserMacrosRegKeyBase(), nextSubkeyName)
173 std::string topLevelSlnName;
174 if(vsSolutionFile)
176 topLevelSlnName = vsSolutionFile;
178 else
180 topLevelSlnName = mf->GetStartOutputDirectory();
181 topLevelSlnName += "/";
182 topLevelSlnName += mf->GetProjectName();
183 topLevelSlnName += ".sln";
186 if(m == MacroReload)
188 std::vector<std::string> filenames;
189 this->GetFilesReplacedDuringGenerate(filenames);
190 if (filenames.size() > 0)
192 // Convert vector to semi-colon delimited string of filenames:
193 std::string projects;
194 std::vector<std::string>::iterator it = filenames.begin();
195 if (it != filenames.end())
197 projects = *it;
198 ++it;
200 for (; it != filenames.end(); ++it)
202 projects += ";";
203 projects += *it;
205 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
206 CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
207 this->GetCMakeInstance()->GetDebugOutput());
210 else if(m == MacroStop)
212 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
213 CMAKE_VSMACROS_STOP_MACRONAME, "",
214 this->GetCMakeInstance()->GetDebugOutput());
220 //----------------------------------------------------------------------------
221 std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
223 return "";
226 //----------------------------------------------------------------------------
227 std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase()
229 return "";
232 //----------------------------------------------------------------------------
233 void cmGlobalVisualStudioGenerator::FixUtilityDepends()
235 // Skip for VS versions 8 and above.
236 if(!this->VSLinksDependencies())
238 return;
241 // For VS versions before 8:
243 // When a target that links contains a project-level dependency on a
244 // library target that library is automatically linked. In order to
245 // allow utility-style project-level dependencies that do not
246 // actually link we need to automatically insert an intermediate
247 // custom target.
249 // Here we edit the utility dependencies of a target to add the
250 // intermediate custom target when necessary.
251 for(unsigned i = 0; i < this->LocalGenerators.size(); ++i)
253 cmTargets* targets =
254 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
255 for(cmTargets::iterator tarIt = targets->begin();
256 tarIt != targets->end(); ++tarIt)
258 this->FixUtilityDependsForTarget(tarIt->second);
263 //----------------------------------------------------------------------------
264 void
265 cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
267 // Only targets that link need to be fixed.
268 if(target.GetType() != cmTarget::STATIC_LIBRARY &&
269 target.GetType() != cmTarget::SHARED_LIBRARY &&
270 target.GetType() != cmTarget::MODULE_LIBRARY &&
271 target.GetType() != cmTarget::EXECUTABLE)
273 return;
276 #if 0
277 // This feature makes a mess in SLN files for VS 7.1 and below. It
278 // creates an extra target for every target that is "linked" by a
279 // static library. Without this feature static libraries do not
280 // wait until their "link" dependencies are built to build. This is
281 // not a problem 99.9% of the time, and projects that do have the
282 // problem can enable this work-around by using add_dependencies.
284 // Static libraries cannot depend directly on the targets to which
285 // they link because VS will copy those targets into the library
286 // (for VS < 8). To work around the problem we copy the
287 // dependencies to be utility dependencies so that the work-around
288 // below is used.
289 if(target.GetType() == cmTarget::STATIC_LIBRARY)
291 cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
292 for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin();
293 i != libs.end(); ++i)
295 if(cmTarget* depTarget = this->FindTarget(0, i->first.c_str(), false))
297 target.AddUtility(depTarget->GetName());
301 #endif
303 // Look at each utility dependency.
304 for(std::set<cmStdString>::const_iterator ui =
305 target.GetUtilities().begin();
306 ui != target.GetUtilities().end(); ++ui)
308 if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
310 if(depTarget->GetType() == cmTarget::STATIC_LIBRARY ||
311 depTarget->GetType() == cmTarget::SHARED_LIBRARY ||
312 depTarget->GetType() == cmTarget::MODULE_LIBRARY)
314 // This utility dependency will cause an attempt to link. If
315 // the depender does not already link the dependee we need an
316 // intermediate target.
317 if(!this->CheckTargetLinks(target, ui->c_str()))
319 this->CreateUtilityDependTarget(*depTarget);
326 //----------------------------------------------------------------------------
327 void
328 cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target)
330 // This target is a library on which a utility dependency exists.
331 // We need to create an intermediate custom target to hook up the
332 // dependency without causing a link.
333 const char* altName = target.GetProperty("ALTERNATIVE_DEPENDENCY_NAME");
334 if(!altName)
336 // Create the intermediate utility target.
337 std::string altNameStr = target.GetName();
338 altNameStr += "_UTILITY";
339 const std::vector<std::string> no_depends;
340 cmCustomCommandLines no_commands;
341 const char* no_working_dir = 0;
342 const char* no_comment = 0;
343 target.GetMakefile()->AddUtilityCommand(altNameStr.c_str(), true,
344 no_working_dir, no_depends,
345 no_commands, false, no_comment);
346 target.SetProperty("ALTERNATIVE_DEPENDENCY_NAME", altNameStr.c_str());
348 // Most targets have a GUID created in ConfigureFinalPass. Since
349 // that has already been called, create one for this target now.
350 this->CreateGUID(altNameStr.c_str());
352 // The intermediate target should depend on the original target.
353 if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str()))
355 alt->AddUtility(target.GetName());
360 //----------------------------------------------------------------------------
361 bool cmGlobalVisualStudioGenerator::CheckTargetLinks(cmTarget& target,
362 const char* name)
364 // Return whether the given target links to a target with the given name.
365 if(target.GetType() == cmTarget::STATIC_LIBRARY)
367 // Static libraries never link to anything.
368 return false;
370 cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
371 for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin();
372 i != libs.end(); ++i)
374 if(i->first == name)
376 return true;
379 return false;
382 //----------------------------------------------------------------------------
383 const char*
384 cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target,
385 const char* name)
387 // Possibly depend on an intermediate utility target to avoid
388 // linking.
389 if(target.GetType() == cmTarget::STATIC_LIBRARY ||
390 target.GetType() == cmTarget::SHARED_LIBRARY ||
391 target.GetType() == cmTarget::MODULE_LIBRARY ||
392 target.GetType() == cmTarget::EXECUTABLE)
394 // The depender is a target that links. Lookup the dependee to
395 // see if it provides an alternative dependency name.
396 if(cmTarget* depTarget = this->FindTarget(0, name))
398 // Check for an alternative name created by FixUtilityDepends.
399 if(const char* altName =
400 depTarget->GetProperty("ALTERNATIVE_DEPENDENCY_NAME"))
402 // The alternative name is needed only if the depender does
403 // not really link to the dependee.
404 if(!this->CheckTargetLinks(target, name))
406 return altName;
412 // No special case. Just use the original dependency name.
413 return name;
416 //----------------------------------------------------------------------------
417 #include <windows.h>
419 //----------------------------------------------------------------------------
420 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
421 const std::string& regKeyBase,
422 std::string& nextAvailableSubKeyName)
424 bool macrosRegistered = false;
426 std::string s1;
427 std::string s2;
429 // Make lowercase local copies, convert to Unix slashes, and
430 // see if the resulting strings are the same:
431 s1 = cmSystemTools::LowerCase(macrosFile);
432 cmSystemTools::ConvertToUnixSlashes(s1);
434 std::string keyname;
435 HKEY hkey = NULL;
436 LONG result = ERROR_SUCCESS;
437 DWORD index = 0;
439 keyname = regKeyBase + "\\OtherProjects7";
440 hkey = NULL;
441 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
442 0, KEY_READ, &hkey);
443 if (ERROR_SUCCESS == result)
445 // Iterate the subkeys and look for the values of interest in each subkey:
446 CHAR subkeyname[256];
447 DWORD cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
448 CHAR keyclass[256];
449 DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
450 FILETIME lastWriteTime;
451 lastWriteTime.dwHighDateTime = 0;
452 lastWriteTime.dwLowDateTime = 0;
454 while (ERROR_SUCCESS == RegEnumKeyEx(hkey, index, subkeyname,
455 &cch_subkeyname,
456 0, keyclass, &cch_keyclass, &lastWriteTime))
458 // Open the subkey and query the values of interest:
459 HKEY hsubkey = NULL;
460 result = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
461 if (ERROR_SUCCESS == result)
463 DWORD valueType = REG_SZ;
464 CHAR data1[256];
465 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
466 RegQueryValueEx(hsubkey, "Path", 0, &valueType,
467 (LPBYTE) &data1[0], &cch_data1);
469 DWORD data2 = 0;
470 DWORD cch_data2 = sizeof(data2);
471 RegQueryValueEx(hsubkey, "Security", 0, &valueType,
472 (LPBYTE) &data2, &cch_data2);
474 DWORD data3 = 0;
475 DWORD cch_data3 = sizeof(data3);
476 RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
477 (LPBYTE) &data3, &cch_data3);
479 s2 = cmSystemTools::LowerCase(data1);
480 cmSystemTools::ConvertToUnixSlashes(s2);
481 if (s2 == s1)
483 macrosRegistered = true;
486 std::string fullname(data1);
487 std::string filename;
488 std::string filepath;
489 std::string filepathname;
490 std::string filepathpath;
491 if (cmSystemTools::FileExists(fullname.c_str()))
493 filename = cmSystemTools::GetFilenameName(fullname);
494 filepath = cmSystemTools::GetFilenamePath(fullname);
495 filepathname = cmSystemTools::GetFilenameName(filepath);
496 filepathpath = cmSystemTools::GetFilenamePath(filepath);
499 //std::cout << keyname << "\\" << subkeyname << ":" << std::endl;
500 //std::cout << " Path: " << data1 << std::endl;
501 //std::cout << " Security: " << data2 << std::endl;
502 //std::cout << " StorageFormat: " << data3 << std::endl;
503 //std::cout << " filename: " << filename << std::endl;
504 //std::cout << " filepath: " << filepath << std::endl;
505 //std::cout << " filepathname: " << filepathname << std::endl;
506 //std::cout << " filepathpath: " << filepathpath << std::endl;
507 //std::cout << std::endl;
509 RegCloseKey(hsubkey);
511 else
513 std::cout << "error opening subkey: " << subkeyname << std::endl;
514 std::cout << std::endl;
517 ++index;
518 cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
519 cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
520 lastWriteTime.dwHighDateTime = 0;
521 lastWriteTime.dwLowDateTime = 0;
524 RegCloseKey(hkey);
526 else
528 std::cout << "error opening key: " << keyname << std::endl;
529 std::cout << std::endl;
533 // Pass back next available sub key name, assuming sub keys always
534 // follow the expected naming scheme. Expected naming scheme is that
535 // the subkeys of OtherProjects7 is 0 to n-1, so it's ok to use "n"
536 // as the name of the next subkey.
537 std::ostringstream ossNext;
538 ossNext << index;
539 nextAvailableSubKeyName = ossNext.str();
542 keyname = regKeyBase + "\\RecordingProject7";
543 hkey = NULL;
544 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
545 0, KEY_READ, &hkey);
546 if (ERROR_SUCCESS == result)
548 DWORD valueType = REG_SZ;
549 CHAR data1[256];
550 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
551 RegQueryValueEx(hkey, "Path", 0, &valueType,
552 (LPBYTE) &data1[0], &cch_data1);
554 DWORD data2 = 0;
555 DWORD cch_data2 = sizeof(data2);
556 RegQueryValueEx(hkey, "Security", 0, &valueType,
557 (LPBYTE) &data2, &cch_data2);
559 DWORD data3 = 0;
560 DWORD cch_data3 = sizeof(data3);
561 RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
562 (LPBYTE) &data3, &cch_data3);
564 s2 = cmSystemTools::LowerCase(data1);
565 cmSystemTools::ConvertToUnixSlashes(s2);
566 if (s2 == s1)
568 macrosRegistered = true;
571 //std::cout << keyname << ":" << std::endl;
572 //std::cout << " Path: " << data1 << std::endl;
573 //std::cout << " Security: " << data2 << std::endl;
574 //std::cout << " StorageFormat: " << data3 << std::endl;
575 //std::cout << std::endl;
577 RegCloseKey(hkey);
579 else
581 std::cout << "error opening key: " << keyname << std::endl;
582 std::cout << std::endl;
585 return macrosRegistered;
588 //----------------------------------------------------------------------------
589 void WriteVSMacrosFileRegistryEntry(
590 const std::string& nextAvailableSubKeyName,
591 const std::string& macrosFile,
592 const std::string& regKeyBase)
594 std::string keyname = regKeyBase + "\\OtherProjects7";
595 HKEY hkey = NULL;
596 LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
597 KEY_READ|KEY_WRITE, &hkey);
598 if (ERROR_SUCCESS == result)
600 // Create the subkey and set the values of interest:
601 HKEY hsubkey = NULL;
602 result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0, "", 0,
603 KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
604 if (ERROR_SUCCESS == result)
606 DWORD dw = 0;
608 std::string s(macrosFile);
609 cmSystemTools::ReplaceString(s, "/", "\\");
611 result = RegSetValueEx(hsubkey, "Path", 0, REG_SZ, (LPBYTE) s.c_str(),
612 static_cast<DWORD>(strlen(s.c_str()) + 1));
613 if (ERROR_SUCCESS != result)
615 std::cout << "error result 1: " << result << std::endl;
616 std::cout << std::endl;
619 // Security value is always "1" for sample macros files (seems to be "2"
620 // if you put the file somewhere outside the standard VSMacros folder)
621 dw = 1;
622 result = RegSetValueEx(hsubkey, "Security",
623 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
624 if (ERROR_SUCCESS != result)
626 std::cout << "error result 2: " << result << std::endl;
627 std::cout << std::endl;
630 // StorageFormat value is always "0" for sample macros files
631 dw = 0;
632 result = RegSetValueEx(hsubkey, "StorageFormat",
633 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
634 if (ERROR_SUCCESS != result)
636 std::cout << "error result 3: " << result << std::endl;
637 std::cout << std::endl;
640 RegCloseKey(hsubkey);
642 else
644 std::cout << "error creating subkey: "
645 << nextAvailableSubKeyName << std::endl;
646 std::cout << std::endl;
648 RegCloseKey(hkey);
650 else
652 std::cout << "error opening key: " << keyname << std::endl;
653 std::cout << std::endl;
657 //----------------------------------------------------------------------------
658 void RegisterVisualStudioMacros(const std::string& macrosFile,
659 const std::string& regKeyBase)
661 bool macrosRegistered;
662 std::string nextAvailableSubKeyName;
664 macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile,
665 regKeyBase, nextAvailableSubKeyName);
667 if (!macrosRegistered)
669 int count = cmCallVisualStudioMacro::
670 GetNumberOfRunningVisualStudioInstances("ALL");
672 // Only register the macros file if there are *no* instances of Visual
673 // Studio running. If we register it while one is running, first, it has
674 // no effect on the running instance; second, and worse, Visual Studio
675 // removes our newly added registration entry when it quits. Instead,
676 // emit a warning asking the user to exit all running Visual Studio
677 // instances...
679 if (0 != count)
681 std::ostringstream oss;
682 oss << "Could not register CMake's Visual Studio macros file '"
683 << CMAKE_VSMACROS_FILENAME "' while Visual Studio is running."
684 << " Please exit all running instances of Visual Studio before"
685 << " continuing." << std::endl
686 << std::endl
687 << "CMake needs to register Visual Studio macros when its macros"
688 << " file is updated or when it detects that its current macros file"
689 << " is no longer registered with Visual Studio."
690 << std::endl;
691 cmSystemTools::Message(oss.str().c_str(), "Warning");
693 // Count them again now that the warning is over. In the case of a GUI
694 // warning, the user may have gone to close Visual Studio and then come
695 // back to the CMake GUI and clicked ok on the above warning. If so,
696 // then register the macros *now* if the count is *now* 0...
698 count = cmCallVisualStudioMacro::
699 GetNumberOfRunningVisualStudioInstances("ALL");
701 // Also re-get the nextAvailableSubKeyName in case Visual Studio
702 // wrote out new registered macros information as it was exiting:
704 if (0 == count)
706 IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase,
707 nextAvailableSubKeyName);
711 // Do another if check - 'count' may have changed inside the above if:
713 if (0 == count)
715 WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile,
716 regKeyBase);
720 bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget& target)
722 // check to see if this is a fortran build
723 std::set<cmStdString> languages;
724 target.GetLanguages(languages);
725 if(languages.size() == 1)
727 if(*languages.begin() == "Fortran")
729 return true;
732 return false;