ENH: fix uppercase version so defines are not upper as well
[cmake.git] / Source / cmGlobalVisualStudioGenerator.cxx
blob7c1c1ae9908a177449aa2a4e0348b11179b1e2fd
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalVisualStudioGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-07-30 19:26:34 $
7 Version: $Revision: 1.14 $
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 void cmGlobalVisualStudioGenerator::Generate()
37 // Add a special target that depends on ALL projects for easy build
38 // of one configuration only.
39 const char* no_working_dir = 0;
40 std::vector<std::string> no_depends;
41 cmCustomCommandLines no_commands;
42 std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
43 for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
45 std::vector<cmLocalGenerator*>& gen = it->second;
46 // add the ALL_BUILD to the first local generator of each project
47 if(gen.size())
49 // Use no actual command lines so that the target itself is not
50 // considered always out of date.
51 gen[0]->GetMakefile()->
52 AddUtilityCommand("ALL_BUILD", true, no_working_dir,
53 no_depends, no_commands, false,
54 "Build all projects");
58 // Fix utility dependencies to avoid linking to libraries.
59 this->FixUtilityDepends();
61 // Configure CMake Visual Studio macros, for this user on this version
62 // of Visual Studio.
63 this->ConfigureCMakeVisualStudioMacros();
65 // Run all the local generators.
66 this->cmGlobalGenerator::Generate();
69 //----------------------------------------------------------------------------
70 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
71 const std::string& regKeyBase,
72 std::string& nextAvailableSubKeyName);
74 void RegisterVisualStudioMacros(const std::string& macrosFile,
75 const std::string& regKeyBase);
77 //----------------------------------------------------------------------------
78 #define CMAKE_VSMACROS_FILENAME \
79 "CMakeVSMacros2.vsmacros"
81 #define CMAKE_VSMACROS_RELOAD_MACRONAME \
82 "Macros.CMakeVSMacros2.Macros.ReloadProjects"
84 #define CMAKE_VSMACROS_STOP_MACRONAME \
85 "Macros.CMakeVSMacros2.Macros.StopBuild"
87 //----------------------------------------------------------------------------
88 void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
90 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
91 std::string dir = this->GetUserMacrosDirectory();
93 if (mf != 0 && dir != "")
95 std::string src = mf->GetRequiredDefinition("CMAKE_ROOT");
96 src += "/Templates/" CMAKE_VSMACROS_FILENAME;
98 std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
100 // Copy the macros file to the user directory only if the
101 // destination does not exist or the source location is newer.
102 // This will allow the user to edit the macros for development
103 // purposes but newer versions distributed with CMake will replace
104 // older versions in user directories.
105 int res;
106 if(!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) ||
107 res > 0)
109 if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str()))
111 std::ostringstream oss;
112 oss << "Could not copy from: " << src << std::endl;
113 oss << " to: " << dst << std::endl;
114 cmSystemTools::Message(oss.str().c_str(), "Warning");
118 RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase());
122 //----------------------------------------------------------------------------
123 void
124 cmGlobalVisualStudioGenerator
125 ::CallVisualStudioMacro(MacroName m,
126 const char* vsSolutionFile)
128 // If any solution or project files changed during the generation,
129 // tell Visual Studio to reload them...
130 cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
131 std::string dir = this->GetUserMacrosDirectory();
133 // Only really try to call the macro if:
134 // - mf is non-NULL
135 // - there is a UserMacrosDirectory
136 // - the CMake vsmacros file exists
137 // - the CMake vsmacros file is registered
138 // - there were .sln/.vcproj files changed during generation
140 if (mf != 0 && dir != "")
142 std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
143 std::string nextSubkeyName;
144 if (cmSystemTools::FileExists(macrosFile.c_str()) &&
145 IsVisualStudioMacrosFileRegistered(macrosFile,
146 this->GetUserMacrosRegKeyBase(), nextSubkeyName)
149 std::string topLevelSlnName;
150 if(vsSolutionFile)
152 topLevelSlnName = vsSolutionFile;
154 else
156 topLevelSlnName = mf->GetStartOutputDirectory();
157 topLevelSlnName += "/";
158 topLevelSlnName += mf->GetProjectName();
159 topLevelSlnName += ".sln";
162 if(m == MacroReload)
164 std::vector<std::string> filenames;
165 this->GetFilesReplacedDuringGenerate(filenames);
166 if (filenames.size() > 0)
168 // Convert vector to semi-colon delimited string of filenames:
169 std::string projects;
170 std::vector<std::string>::iterator it = filenames.begin();
171 if (it != filenames.end())
173 projects = *it;
174 ++it;
176 for (; it != filenames.end(); ++it)
178 projects += ";";
179 projects += *it;
181 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
182 CMAKE_VSMACROS_RELOAD_MACRONAME, projects,
183 this->GetCMakeInstance()->GetDebugOutput());
186 else if(m == MacroStop)
188 cmCallVisualStudioMacro::CallMacro(topLevelSlnName,
189 CMAKE_VSMACROS_STOP_MACRONAME, "",
190 this->GetCMakeInstance()->GetDebugOutput());
196 //----------------------------------------------------------------------------
197 std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory()
199 return "";
202 //----------------------------------------------------------------------------
203 std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase()
205 return "";
208 //----------------------------------------------------------------------------
209 void cmGlobalVisualStudioGenerator::FixUtilityDepends()
211 // Skip for VS versions 8 and above.
212 if(!this->VSLinksDependencies())
214 return;
217 // For VS versions before 8:
219 // When a target that links contains a project-level dependency on a
220 // library target that library is automatically linked. In order to
221 // allow utility-style project-level dependencies that do not
222 // actually link we need to automatically insert an intermediate
223 // custom target.
225 // Here we edit the utility dependencies of a target to add the
226 // intermediate custom target when necessary.
227 for(unsigned i = 0; i < this->LocalGenerators.size(); ++i)
229 cmTargets* targets =
230 &(this->LocalGenerators[i]->GetMakefile()->GetTargets());
231 for(cmTargets::iterator tarIt = targets->begin();
232 tarIt != targets->end(); ++tarIt)
234 this->FixUtilityDependsForTarget(tarIt->second);
239 //----------------------------------------------------------------------------
240 void
241 cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
243 // Only targets that link need to be fixed.
244 if(target.GetType() != cmTarget::STATIC_LIBRARY &&
245 target.GetType() != cmTarget::SHARED_LIBRARY &&
246 target.GetType() != cmTarget::MODULE_LIBRARY &&
247 target.GetType() != cmTarget::EXECUTABLE)
249 return;
252 #if 0
253 // This feature makes a mess in SLN files for VS 7.1 and below. It
254 // creates an extra target for every target that is "linked" by a
255 // static library. Without this feature static libraries do not
256 // wait until their "link" dependencies are built to build. This is
257 // not a problem 99.9% of the time, and projects that do have the
258 // problem can enable this work-around by using add_dependencies.
260 // Static libraries cannot depend directly on the targets to which
261 // they link because VS will copy those targets into the library
262 // (for VS < 8). To work around the problem we copy the
263 // dependencies to be utility dependencies so that the work-around
264 // below is used.
265 if(target.GetType() == cmTarget::STATIC_LIBRARY)
267 cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
268 for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin();
269 i != libs.end(); ++i)
271 if(cmTarget* depTarget = this->FindTarget(0, i->first.c_str(), false))
273 target.AddUtility(depTarget->GetName());
277 #endif
279 // Look at each utility dependency.
280 for(std::set<cmStdString>::const_iterator ui =
281 target.GetUtilities().begin();
282 ui != target.GetUtilities().end(); ++ui)
284 if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
286 if(depTarget->GetType() == cmTarget::STATIC_LIBRARY ||
287 depTarget->GetType() == cmTarget::SHARED_LIBRARY ||
288 depTarget->GetType() == cmTarget::MODULE_LIBRARY)
290 // This utility dependency will cause an attempt to link. If
291 // the depender does not already link the dependee we need an
292 // intermediate target.
293 if(!this->CheckTargetLinks(target, ui->c_str()))
295 this->CreateUtilityDependTarget(*depTarget);
302 //----------------------------------------------------------------------------
303 void
304 cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target)
306 // This target is a library on which a utility dependency exists.
307 // We need to create an intermediate custom target to hook up the
308 // dependency without causing a link.
309 const char* altName = target.GetProperty("ALTERNATIVE_DEPENDENCY_NAME");
310 if(!altName)
312 // Create the intermediate utility target.
313 std::string altNameStr = target.GetName();
314 altNameStr += "_UTILITY";
315 const std::vector<std::string> no_depends;
316 cmCustomCommandLines no_commands;
317 const char* no_working_dir = 0;
318 const char* no_comment = 0;
319 target.GetMakefile()->AddUtilityCommand(altNameStr.c_str(), true,
320 no_working_dir, no_depends,
321 no_commands, false, no_comment);
322 target.SetProperty("ALTERNATIVE_DEPENDENCY_NAME", altNameStr.c_str());
324 // Most targets have a GUID created in ConfigureFinalPass. Since
325 // that has already been called, create one for this target now.
326 this->CreateGUID(altNameStr.c_str());
328 // The intermediate target should depend on the original target.
329 if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str()))
331 alt->AddUtility(target.GetName());
336 //----------------------------------------------------------------------------
337 bool cmGlobalVisualStudioGenerator::CheckTargetLinks(cmTarget& target,
338 const char* name)
340 // Return whether the given target links to a target with the given name.
341 if(target.GetType() == cmTarget::STATIC_LIBRARY)
343 // Static libraries never link to anything.
344 return false;
346 cmTarget::LinkLibraryVectorType const& libs = target.GetLinkLibraries();
347 for(cmTarget::LinkLibraryVectorType::const_iterator i = libs.begin();
348 i != libs.end(); ++i)
350 if(i->first == name)
352 return true;
355 return false;
358 //----------------------------------------------------------------------------
359 const char*
360 cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target,
361 const char* name)
363 // Handle the external MS project special case.
364 if(strncmp(name, "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
366 // Note from Ken:
367 // kind of weird removing the first 27 letters. my
368 // recommendatsions: use cmCustomCommand::GetCommand() to get the
369 // project name or get rid of the target name starting with
370 // "INCLUDE_EXTERNAL_MSPROJECT_" and use another indicator/flag
371 // somewhere. These external project names shouldn't conflict
372 // with cmake target names anyways.
373 return name+27;
376 // Possibly depend on an intermediate utility target to avoid
377 // linking.
378 if(target.GetType() == cmTarget::STATIC_LIBRARY ||
379 target.GetType() == cmTarget::SHARED_LIBRARY ||
380 target.GetType() == cmTarget::MODULE_LIBRARY ||
381 target.GetType() == cmTarget::EXECUTABLE)
383 // The depender is a target that links. Lookup the dependee to
384 // see if it provides an alternative dependency name.
385 if(cmTarget* depTarget = this->FindTarget(0, name))
387 // Check for an alternative name created by FixUtilityDepends.
388 if(const char* altName =
389 depTarget->GetProperty("ALTERNATIVE_DEPENDENCY_NAME"))
391 // The alternative name is needed only if the depender does
392 // not really link to the dependee.
393 if(!this->CheckTargetLinks(target, name))
395 return altName;
401 // No special case. Just use the original dependency name.
402 return name;
405 //----------------------------------------------------------------------------
406 #include <windows.h>
408 //----------------------------------------------------------------------------
409 bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
410 const std::string& regKeyBase,
411 std::string& nextAvailableSubKeyName)
413 bool macrosRegistered = false;
415 std::string s1;
416 std::string s2;
418 // Make lowercase local copies, convert to Unix slashes, and
419 // see if the resulting strings are the same:
420 s1 = cmSystemTools::LowerCase(macrosFile);
421 cmSystemTools::ConvertToUnixSlashes(s1);
423 std::string keyname;
424 HKEY hkey = NULL;
425 LONG result = ERROR_SUCCESS;
426 DWORD index = 0;
428 keyname = regKeyBase + "\\OtherProjects7";
429 hkey = NULL;
430 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
431 0, KEY_READ, &hkey);
432 if (ERROR_SUCCESS == result)
434 // Iterate the subkeys and look for the values of interest in each subkey:
435 CHAR subkeyname[256];
436 DWORD cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
437 CHAR keyclass[256];
438 DWORD cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
439 FILETIME lastWriteTime;
440 lastWriteTime.dwHighDateTime = 0;
441 lastWriteTime.dwLowDateTime = 0;
443 while (ERROR_SUCCESS == RegEnumKeyEx(hkey, index, subkeyname,
444 &cch_subkeyname,
445 0, keyclass, &cch_keyclass, &lastWriteTime))
447 // Open the subkey and query the values of interest:
448 HKEY hsubkey = NULL;
449 result = RegOpenKeyEx(hkey, subkeyname, 0, KEY_READ, &hsubkey);
450 if (ERROR_SUCCESS == result)
452 DWORD valueType = REG_SZ;
453 CHAR data1[256];
454 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
455 RegQueryValueEx(hsubkey, "Path", 0, &valueType,
456 (LPBYTE) &data1[0], &cch_data1);
458 DWORD data2 = 0;
459 DWORD cch_data2 = sizeof(data2);
460 RegQueryValueEx(hsubkey, "Security", 0, &valueType,
461 (LPBYTE) &data2, &cch_data2);
463 DWORD data3 = 0;
464 DWORD cch_data3 = sizeof(data3);
465 RegQueryValueEx(hsubkey, "StorageFormat", 0, &valueType,
466 (LPBYTE) &data3, &cch_data3);
468 s2 = cmSystemTools::LowerCase(data1);
469 cmSystemTools::ConvertToUnixSlashes(s2);
470 if (s2 == s1)
472 macrosRegistered = true;
475 std::string fullname(data1);
476 std::string filename;
477 std::string filepath;
478 std::string filepathname;
479 std::string filepathpath;
480 if (cmSystemTools::FileExists(fullname.c_str()))
482 filename = cmSystemTools::GetFilenameName(fullname);
483 filepath = cmSystemTools::GetFilenamePath(fullname);
484 filepathname = cmSystemTools::GetFilenameName(filepath);
485 filepathpath = cmSystemTools::GetFilenamePath(filepath);
488 //std::cout << keyname << "\\" << subkeyname << ":" << std::endl;
489 //std::cout << " Path: " << data1 << std::endl;
490 //std::cout << " Security: " << data2 << std::endl;
491 //std::cout << " StorageFormat: " << data3 << std::endl;
492 //std::cout << " filename: " << filename << std::endl;
493 //std::cout << " filepath: " << filepath << std::endl;
494 //std::cout << " filepathname: " << filepathname << std::endl;
495 //std::cout << " filepathpath: " << filepathpath << std::endl;
496 //std::cout << std::endl;
498 RegCloseKey(hsubkey);
500 else
502 std::cout << "error opening subkey: " << subkeyname << std::endl;
503 std::cout << std::endl;
506 ++index;
507 cch_subkeyname = sizeof(subkeyname)/sizeof(subkeyname[0]);
508 cch_keyclass = sizeof(keyclass)/sizeof(keyclass[0]);
509 lastWriteTime.dwHighDateTime = 0;
510 lastWriteTime.dwLowDateTime = 0;
513 RegCloseKey(hkey);
515 else
517 std::cout << "error opening key: " << keyname << std::endl;
518 std::cout << std::endl;
522 // Pass back next available sub key name, assuming sub keys always
523 // follow the expected naming scheme. Expected naming scheme is that
524 // the subkeys of OtherProjects7 is 0 to n-1, so it's ok to use "n"
525 // as the name of the next subkey.
526 std::ostringstream ossNext;
527 ossNext << index;
528 nextAvailableSubKeyName = ossNext.str();
531 keyname = regKeyBase + "\\RecordingProject7";
532 hkey = NULL;
533 result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(),
534 0, KEY_READ, &hkey);
535 if (ERROR_SUCCESS == result)
537 DWORD valueType = REG_SZ;
538 CHAR data1[256];
539 DWORD cch_data1 = sizeof(data1)/sizeof(data1[0]);
540 RegQueryValueEx(hkey, "Path", 0, &valueType,
541 (LPBYTE) &data1[0], &cch_data1);
543 DWORD data2 = 0;
544 DWORD cch_data2 = sizeof(data2);
545 RegQueryValueEx(hkey, "Security", 0, &valueType,
546 (LPBYTE) &data2, &cch_data2);
548 DWORD data3 = 0;
549 DWORD cch_data3 = sizeof(data3);
550 RegQueryValueEx(hkey, "StorageFormat", 0, &valueType,
551 (LPBYTE) &data3, &cch_data3);
553 s2 = cmSystemTools::LowerCase(data1);
554 cmSystemTools::ConvertToUnixSlashes(s2);
555 if (s2 == s1)
557 macrosRegistered = true;
560 //std::cout << keyname << ":" << std::endl;
561 //std::cout << " Path: " << data1 << std::endl;
562 //std::cout << " Security: " << data2 << std::endl;
563 //std::cout << " StorageFormat: " << data3 << std::endl;
564 //std::cout << std::endl;
566 RegCloseKey(hkey);
568 else
570 std::cout << "error opening key: " << keyname << std::endl;
571 std::cout << std::endl;
574 return macrosRegistered;
577 //----------------------------------------------------------------------------
578 void WriteVSMacrosFileRegistryEntry(
579 const std::string& nextAvailableSubKeyName,
580 const std::string& macrosFile,
581 const std::string& regKeyBase)
583 std::string keyname = regKeyBase + "\\OtherProjects7";
584 HKEY hkey = NULL;
585 LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0,
586 KEY_READ|KEY_WRITE, &hkey);
587 if (ERROR_SUCCESS == result)
589 // Create the subkey and set the values of interest:
590 HKEY hsubkey = NULL;
591 result = RegCreateKeyEx(hkey, nextAvailableSubKeyName.c_str(), 0, "", 0,
592 KEY_READ|KEY_WRITE, 0, &hsubkey, 0);
593 if (ERROR_SUCCESS == result)
595 DWORD dw = 0;
597 std::string s(macrosFile);
598 cmSystemTools::ReplaceString(s, "/", "\\");
600 result = RegSetValueEx(hsubkey, "Path", 0, REG_SZ, (LPBYTE) s.c_str(),
601 static_cast<DWORD>(strlen(s.c_str()) + 1));
602 if (ERROR_SUCCESS != result)
604 std::cout << "error result 1: " << result << std::endl;
605 std::cout << std::endl;
608 // Security value is always "1" for sample macros files (seems to be "2"
609 // if you put the file somewhere outside the standard VSMacros folder)
610 dw = 1;
611 result = RegSetValueEx(hsubkey, "Security",
612 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
613 if (ERROR_SUCCESS != result)
615 std::cout << "error result 2: " << result << std::endl;
616 std::cout << std::endl;
619 // StorageFormat value is always "0" for sample macros files
620 dw = 0;
621 result = RegSetValueEx(hsubkey, "StorageFormat",
622 0, REG_DWORD, (LPBYTE) &dw, sizeof(DWORD));
623 if (ERROR_SUCCESS != result)
625 std::cout << "error result 3: " << result << std::endl;
626 std::cout << std::endl;
629 RegCloseKey(hsubkey);
631 else
633 std::cout << "error creating subkey: "
634 << nextAvailableSubKeyName << std::endl;
635 std::cout << std::endl;
637 RegCloseKey(hkey);
639 else
641 std::cout << "error opening key: " << keyname << std::endl;
642 std::cout << std::endl;
646 //----------------------------------------------------------------------------
647 void RegisterVisualStudioMacros(const std::string& macrosFile,
648 const std::string& regKeyBase)
650 bool macrosRegistered;
651 std::string nextAvailableSubKeyName;
653 macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile,
654 regKeyBase, nextAvailableSubKeyName);
656 if (!macrosRegistered)
658 int count = cmCallVisualStudioMacro::
659 GetNumberOfRunningVisualStudioInstances("ALL");
661 // Only register the macros file if there are *no* instances of Visual
662 // Studio running. If we register it while one is running, first, it has
663 // no effect on the running instance; second, and worse, Visual Studio
664 // removes our newly added registration entry when it quits. Instead,
665 // emit a warning asking the user to exit all running Visual Studio
666 // instances...
668 if (0 != count)
670 std::ostringstream oss;
671 oss << "Could not register CMake's Visual Studio macros file '"
672 << CMAKE_VSMACROS_FILENAME "' while Visual Studio is running."
673 << " Please exit all running instances of Visual Studio before"
674 << " continuing." << std::endl
675 << std::endl
676 << "CMake needs to register Visual Studio macros when its macros"
677 << " file is updated or when it detects that its current macros file"
678 << " is no longer registered with Visual Studio."
679 << std::endl;
680 cmSystemTools::Message(oss.str().c_str(), "Warning");
682 // Count them again now that the warning is over. In the case of a GUI
683 // warning, the user may have gone to close Visual Studio and then come
684 // back to the CMake GUI and clicked ok on the above warning. If so,
685 // then register the macros *now* if the count is *now* 0...
687 count = cmCallVisualStudioMacro::
688 GetNumberOfRunningVisualStudioInstances("ALL");
690 // Also re-get the nextAvailableSubKeyName in case Visual Studio
691 // wrote out new registered macros information as it was exiting:
693 if (0 == count)
695 IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase,
696 nextAvailableSubKeyName);
700 // Do another if check - 'count' may have changed inside the above if:
702 if (0 == count)
704 WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile,
705 regKeyBase);
709 bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget& target)
711 // check to see if this is a fortran build
712 std::set<cmStdString> languages;
713 target.GetLanguages(languages);
714 if(languages.size() == 1)
716 if(*languages.begin() == "Fortran")
718 return true;
721 return false;