Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmGlobalVisualStudio7Generator.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 "windows.h" // this must be first to define GetCurrentDirectory
13 #include <assert.h>
14 #include "cmGlobalVisualStudio7Generator.h"
15 #include "cmGeneratedFileStream.h"
16 #include "cmLocalVisualStudio7Generator.h"
17 #include "cmMakefile.h"
18 #include "cmake.h"
19
20 cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
21   const char* platformName)
22 {
23   this->FindMakeProgramFile = "CMakeVS7FindMake.cmake";
24
25   if (!platformName)
26     {
27     platformName = "Win32";
28     }
29   this->PlatformName = platformName;
30 }
31
32
33 void cmGlobalVisualStudio7Generator
34 ::EnableLanguage(std::vector<std::string>const &  lang,
35                  cmMakefile *mf, bool optional)
36 {
37   mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
38   mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
39   mf->AddDefinition("CMAKE_GENERATOR_FC", "ifort");
40   this->AddPlatformDefinitions(mf);
41   if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
42     {
43     mf->AddCacheDefinition(
44       "CMAKE_CONFIGURATION_TYPES",
45       "Debug;Release;MinSizeRel;RelWithDebInfo",
46       "Semicolon separated list of supported configuration types, "
47       "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
48       "anything else will be ignored.",
49       cmCacheManager::STRING);
50     }
51
52   // Create list of configurations requested by user's cache, if any.
53   this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
54   this->GenerateConfigurations(mf);
55
56   // if this environment variable is set, then copy it to
57   // a static cache entry.  It will be used by
58   // cmLocalGenerator::ConstructScript, to add an extra PATH
59   // to all custom commands.   This is because the VS IDE
60   // does not use the environment it is run in, and this allows
61   // for running commands and using dll's that the IDE environment
62   // does not know about.
63   const char* extraPath = cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH");
64   if(extraPath)
65     {
66     mf->AddCacheDefinition
67       ("CMAKE_MSVCIDE_RUN_PATH", extraPath,
68        "Saved environment variable CMAKE_MSVCIDE_RUN_PATH",
69        cmCacheManager::STATIC);
70     }
71
72 }
73
74 std::string cmGlobalVisualStudio7Generator
75 ::GenerateBuildCommand(const char* makeProgram,
76                        const char *projectName, const char *projectDir,
77                        const char* additionalOptions, const char *targetName,
78                        const char* config, bool ignoreErrors, bool)
79 {
80   // Visual studio 7 doesn't need project dir
81   (void) projectDir;
82   // Ingoring errors is not implemented in visual studio 6
83   (void) ignoreErrors;
84
85   // now build the test
86   std::string makeCommand =
87     cmSystemTools::ConvertToOutputPath(makeProgram);
88   std::string lowerCaseCommand = makeCommand;
89   cmSystemTools::LowerCase(lowerCaseCommand);
90
91   // if there are spaces in the makeCommand, assume a full path
92   // and convert it to a path with no spaces in it as the
93   // RunSingleCommand does not like spaces
94 #if defined(_WIN32) && !defined(__CYGWIN__)
95   if(makeCommand.find(' ') != std::string::npos)
96     {
97     cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
98     }
99 #endif
100   makeCommand += " ";
101   makeCommand += projectName;
102   makeCommand += ".sln ";
103   bool clean = false;
104   if ( targetName && strcmp(targetName, "clean") == 0 )
105     {
106     clean = true;
107     targetName = "ALL_BUILD";
108     }
109   if(clean)
110     {
111     makeCommand += "/clean ";
112     }
113   else
114     {
115     makeCommand += "/build ";
116     }
117
118   if(config && strlen(config))
119     {
120     makeCommand += config;
121     }
122   else
123     {
124     makeCommand += "Debug";
125     }
126   makeCommand += " /project ";
127
128   if (targetName && strlen(targetName))
129     {
130     makeCommand += targetName;
131     }
132   else
133     {
134     makeCommand += "ALL_BUILD";
135     }
136   if ( additionalOptions )
137     {
138     makeCommand += " ";
139     makeCommand += additionalOptions;
140     }
141   return makeCommand;
142 }
143
144 ///! Create a local generator appropriate to this Global Generator
145 cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
146 {
147   cmLocalVisualStudio7Generator *lg =
148     new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS7);
149   lg->SetExtraFlagTable(this->GetExtraFlagTableVS7());
150   lg->SetGlobalGenerator(this);
151   return lg;
152 }
153
154 //----------------------------------------------------------------------------
155 void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf)
156 {
157   cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
158   mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
159 }
160
161 void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
162 {
163   // process the configurations
164   const char* ct
165     = this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
166   if ( ct )
167     {
168     std::vector<std::string> argsOut;
169     cmSystemTools::ExpandListArgument(ct, argsOut);
170     for(std::vector<std::string>::iterator i = argsOut.begin();
171         i != argsOut.end(); ++i)
172       {
173       if(std::find(this->Configurations.begin(),
174                    this->Configurations.end(),
175                    *i) == this->Configurations.end())
176         {
177         this->Configurations.push_back(*i);
178         }
179       }
180     }
181   // default to at least Debug and Release
182   if(this->Configurations.size() == 0)
183     {
184     this->Configurations.push_back("Debug");
185     this->Configurations.push_back("Release");
186     }
187
188   // Reset the entry to have a semi-colon separated list.
189   std::string configs = this->Configurations[0];
190   for(unsigned int i=1; i < this->Configurations.size(); ++i)
191     {
192     configs += ";";
193     configs += this->Configurations[i];
194     }
195
196   mf->AddCacheDefinition(
197     "CMAKE_CONFIGURATION_TYPES",
198     configs.c_str(),
199     "Semicolon separated list of supported configuration types, "
200     "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
201     "anything else will be ignored.",
202     cmCacheManager::STRING);
203 }
204
205 void cmGlobalVisualStudio7Generator::Generate()
206 {
207   // first do the superclass method
208   this->cmGlobalVisualStudioGenerator::Generate();
209
210   // Now write out the DSW
211   this->OutputSLNFile();
212   // If any solution or project files changed during the generation,
213   // tell Visual Studio to reload them...
214   if(!cmSystemTools::GetErrorOccuredFlag())
215     {
216     this->CallVisualStudioMacro(MacroReload);
217     }
218 }
219
220 void cmGlobalVisualStudio7Generator
221 ::OutputSLNFile(cmLocalGenerator* root,
222                 std::vector<cmLocalGenerator*>& generators)
223 {
224   if(generators.size() == 0)
225     {
226     return;
227     }
228   this->CurrentProject = root->GetMakefile()->GetProjectName();
229   std::string fname = root->GetMakefile()->GetStartOutputDirectory();
230   fname += "/";
231   fname += root->GetMakefile()->GetProjectName();
232   fname += ".sln";
233   cmGeneratedFileStream fout(fname.c_str());
234   fout.SetCopyIfDifferent(true);
235   if(!fout)
236     {
237     return;
238     }
239   this->WriteSLNFile(fout, root, generators);
240   if (fout.Close())
241     {
242     this->FileReplacedDuringGenerate(fname);
243     }
244 }
245
246 // output the SLN file
247 void cmGlobalVisualStudio7Generator::OutputSLNFile()
248 {
249   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
250   for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
251     {
252     this->OutputSLNFile(it->second[0], it->second);
253     }
254 }
255
256
257 void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
258   std::ostream& fout,
259   cmLocalGenerator* root,
260   OrderedTargetDependSet const& projectTargets)
261 {
262   // loop over again and write out configurations for each target
263   // in the solution
264   for(OrderedTargetDependSet::const_iterator tt =
265         projectTargets.begin(); tt != projectTargets.end(); ++tt)
266     {
267     cmTarget* target = *tt;
268     const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
269     if(expath)
270       {
271       std::set<std::string> allConfigurations(this->Configurations.begin(),
272                                               this->Configurations.end());
273       this->WriteProjectConfigurations(
274         fout, target->GetName(), target->GetType(),
275         allConfigurations, target->GetProperty("VS_PLATFORM_MAPPING"));
276       }
277     else
278       {
279       const std::set<std::string>& configsPartOfDefaultBuild =
280         this->IsPartOfDefaultBuild(root->GetMakefile()->GetProjectName(),
281                                    target);
282       const char *vcprojName =
283         target->GetProperty("GENERATOR_FILE_NAME");
284       if (vcprojName)
285         {
286         this->WriteProjectConfigurations(fout, vcprojName, target->GetType(),
287                                          configsPartOfDefaultBuild);
288         }
289       }
290     }
291 }
292
293
294 void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
295     std::ostream& fout,
296     cmLocalGenerator* root,
297     OrderedTargetDependSet const& projectTargets)
298 {
299   VisualStudioFolders.clear();
300
301   for(OrderedTargetDependSet::const_iterator tt =
302         projectTargets.begin(); tt != projectTargets.end(); ++tt)
303     {
304     cmTarget* target = *tt;
305     bool written = false;
306
307     // handle external vc project files
308     const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
309     if(expath)
310       {
311       std::string project = target->GetName();
312       std::string location = expath;
313
314       this->WriteExternalProject(fout,
315                                  project.c_str(),
316                                  location.c_str(),
317                                  target->GetProperty("VS_PROJECT_TYPE"),
318                                  target->GetUtilities());
319       written = true;
320       }
321     else
322       {
323       const char *vcprojName =
324         target->GetProperty("GENERATOR_FILE_NAME");
325       if(vcprojName)
326         {
327         cmMakefile* tmf = target->GetMakefile();
328         std::string dir = tmf->GetStartOutputDirectory();
329         dir = root->Convert(dir.c_str(),
330                             cmLocalGenerator::START_OUTPUT);
331         if(dir == ".")
332           {
333           dir = ""; // msbuild cannot handle ".\" prefix
334           }
335         this->WriteProject(fout, vcprojName, dir.c_str(),
336                            *target);
337         written = true;
338         }
339       }
340
341     // Create "solution folder" information from FOLDER target property
342     //
343     if (written && this->UseFolderProperty())
344       {
345       const char *targetFolder = target->GetProperty("FOLDER");
346       if (targetFolder)
347         {
348         std::vector<cmsys::String> tokens =
349           cmSystemTools::SplitString(targetFolder, '/', false);
350
351         std::string cumulativePath = "";
352
353         for(std::vector<cmsys::String>::iterator iter = tokens.begin();
354             iter != tokens.end(); ++iter)
355           {
356           if(!iter->size())
357             {
358             continue;
359             }
360
361           if (cumulativePath.empty())
362             {
363             cumulativePath = "CMAKE_FOLDER_GUID_" + *iter;
364             }
365           else
366             {
367             VisualStudioFolders[cumulativePath].insert(
368               cumulativePath + "/" + *iter);
369
370             cumulativePath = cumulativePath + "/" + *iter;
371             }
372
373           this->CreateGUID(cumulativePath.c_str());
374           }
375
376         if (!cumulativePath.empty())
377           {
378           VisualStudioFolders[cumulativePath].insert(target->GetName());
379           }
380         }
381       }
382     }
383 }
384
385
386 void cmGlobalVisualStudio7Generator::WriteTargetDepends(
387     std::ostream& fout,
388     OrderedTargetDependSet const& projectTargets
389     )
390 {
391   for(OrderedTargetDependSet::const_iterator tt =
392         projectTargets.begin(); tt != projectTargets.end(); ++tt)
393     {
394     cmTarget* target = *tt;
395     cmMakefile* mf = target->GetMakefile();
396     const char *vcprojName =
397       target->GetProperty("GENERATOR_FILE_NAME");
398     if (vcprojName)
399       {
400       std::string dir = mf->GetStartDirectory();
401       this->WriteProjectDepends(fout, vcprojName,
402                                 dir.c_str(), *target);
403       }
404     }
405 }
406
407 //----------------------------------------------------------------------------
408 // Write a SLN file to the stream
409 void cmGlobalVisualStudio7Generator
410 ::WriteSLNFile(std::ostream& fout,
411                cmLocalGenerator* root,
412                std::vector<cmLocalGenerator*>& generators)
413 {
414   // Write out the header for a SLN file
415   this->WriteSLNHeader(fout);
416
417   // Collect all targets under this root generator and the transitive
418   // closure of their dependencies.
419   TargetDependSet projectTargets;
420   TargetDependSet originalTargets;
421   this->GetTargetSets(projectTargets, originalTargets, root, generators);
422   OrderedTargetDependSet orderedProjectTargets(projectTargets);
423
424   this->WriteTargetsToSolution(fout, root, orderedProjectTargets);
425
426   bool useFolderProperty = this->UseFolderProperty();
427   if (useFolderProperty)
428     {
429     this->WriteFolders(fout);
430     }
431
432   // Write out the configurations information for the solution
433   fout << "Global\n"
434        << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
435
436   int c = 0;
437   for(std::vector<std::string>::iterator i = this->Configurations.begin();
438       i != this->Configurations.end(); ++i)
439     {
440     fout << "\t\tConfigName." << c << " = " << *i << "\n";
441     c++;
442     }
443   fout << "\tEndGlobalSection\n";
444   // Write out project(target) depends
445   fout << "\tGlobalSection(ProjectDependencies) = postSolution\n";
446   this->WriteTargetDepends(fout, orderedProjectTargets);
447   fout << "\tEndGlobalSection\n";
448
449   if (useFolderProperty)
450     {
451     // Write out project folders
452     fout << "\tGlobalSection(NestedProjects) = preSolution\n";
453     this->WriteFoldersContent(fout);
454     fout << "\tEndGlobalSection\n";
455     }
456
457   // Write out the configurations for all the targets in the project
458   fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n";
459   this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
460   fout << "\tEndGlobalSection\n";
461
462   // Write out global sections
463   this->WriteSLNGlobalSections(fout, root);
464
465   // Write the footer for the SLN file
466   this->WriteSLNFooter(fout);
467 }
468
469 //----------------------------------------------------------------------------
470 void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
471 {
472   const char *prefix = "CMAKE_FOLDER_GUID_";
473   const std::string::size_type skip_prefix = strlen(prefix);
474   std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
475   for(std::map<std::string,std::set<std::string> >::iterator iter =
476     VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
477     {
478     std::string fullName = iter->first;
479     std::string guid = this->GetGUID(fullName.c_str());
480
481     cmSystemTools::ReplaceString(fullName, "/", "\\");
482     if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix))
483       {
484       fullName = fullName.substr(skip_prefix);
485       }
486
487     std::string nameOnly = cmSystemTools::GetFilenameName(fullName);
488
489     fout << "Project(\"{" <<
490       guidProjectTypeFolder << "}\") = \"" <<
491       nameOnly << "\", \"" <<
492       fullName << "\", \"{" <<
493       guid <<
494       "}\"\nEndProject\n";
495     }
496 }
497
498 //----------------------------------------------------------------------------
499 void cmGlobalVisualStudio7Generator::WriteFoldersContent(std::ostream& fout)
500 {
501   for(std::map<std::string,std::set<std::string> >::iterator iter =
502     VisualStudioFolders.begin(); iter != VisualStudioFolders.end(); ++iter)
503     {
504     std::string key(iter->first);
505     std::string guidParent(this->GetGUID(key.c_str()));
506
507     for(std::set<std::string>::iterator it = iter->second.begin();
508         it != iter->second.end(); ++it)
509       {
510       std::string value(*it);
511       std::string guid(this->GetGUID(value.c_str()));
512
513       fout << "\t\t{" << guid << "} = {" << guidParent << "}\n";
514       }
515     }
516 }
517
518 //----------------------------------------------------------------------------
519 std::string
520 cmGlobalVisualStudio7Generator::ConvertToSolutionPath(const char* path)
521 {
522   // Convert to backslashes.  Do not use ConvertToOutputPath because
523   // we will add quoting ourselves, and we know these projects always
524   // use windows slashes.
525   std::string d = path;
526   std::string::size_type pos = 0;
527   while((pos = d.find('/', pos)) != d.npos)
528     {
529     d[pos++] = '\\';
530     }
531   return d;
532 }
533
534 // Write a dsp file into the SLN file,
535 // Note, that dependencies from executables to
536 // the libraries it uses are also done here
537 void cmGlobalVisualStudio7Generator::WriteProject(std::ostream& fout,
538                                const char* dspname,
539                                const char* dir, cmTarget& target)
540 {
541    // check to see if this is a fortran build
542   const char* ext = ".vcproj";
543   const char* project =
544     "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"";
545   if(this->TargetIsFortranOnly(target))
546     {
547     ext = ".vfproj";
548     project = "Project(\"{6989167D-11E4-40FE-8C1A-2192A86A7E90}\") = \"";
549     }
550
551   fout << project
552        << dspname << "\", \""
553        << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
554        << dspname << ext << "\", \"{"
555        << this->GetGUID(dspname) << "}\"\nEndProject\n";
556
557   UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
558   if(ui != this->UtilityDepends.end())
559     {
560     const char* uname = ui->second.c_str();
561     fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
562          << uname << "\", \""
563          << this->ConvertToSolutionPath(dir) << (dir[0]? "\\":"")
564          << uname << ".vcproj" << "\", \"{"
565          << this->GetGUID(uname) << "}\"\n"
566          << "EndProject\n";
567     }
568 }
569
570
571
572 // Write a dsp file into the SLN file,
573 // Note, that dependencies from executables to
574 // the libraries it uses are also done here
575 void
576 cmGlobalVisualStudio7Generator
577 ::WriteProjectDepends(std::ostream& fout,
578                       const char* dspname,
579                       const char*, cmTarget& target)
580 {
581   int depcount = 0;
582   std::string dspguid = this->GetGUID(dspname);
583   VSDependSet const& depends = this->VSTargetDepends[&target];
584   for(VSDependSet::const_iterator di = depends.begin();
585       di != depends.end(); ++di)
586     {
587     const char* name = di->c_str();
588     std::string guid = this->GetGUID(name);
589     if(guid.size() == 0)
590       {
591       std::string m = "Target: ";
592       m += target.GetName();
593       m += " depends on unknown target: ";
594       m += name;
595       cmSystemTools::Error(m.c_str());
596       }
597     fout << "\t\t{" << dspguid << "}." << depcount << " = {" << guid << "}\n";
598     depcount++;
599     }
600
601   UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
602   if(ui != this->UtilityDepends.end())
603     {
604     const char* uname = ui->second.c_str();
605     fout << "\t\t{" << this->GetGUID(uname) << "}.0 = {" << dspguid << "}\n";
606     }
607 }
608
609
610 // Write a dsp file into the SLN file, Note, that dependencies from
611 // executables to the libraries it uses are also done here
612 void cmGlobalVisualStudio7Generator
613 ::WriteProjectConfigurations(
614   std::ostream& fout, const char* name, cmTarget::TargetType,
615   const std::set<std::string>& configsPartOfDefaultBuild,
616   const char* platformMapping)
617 {
618   const char* platformName =
619     platformMapping ? platformMapping : this->GetPlatformName();
620   std::string guid = this->GetGUID(name);
621   for(std::vector<std::string>::iterator i = this->Configurations.begin();
622       i != this->Configurations.end(); ++i)
623     {
624     fout << "\t\t{" << guid << "}." << *i
625          << ".ActiveCfg = " << *i << "|" << platformName << "\n";
626       std::set<std::string>::const_iterator
627         ci = configsPartOfDefaultBuild.find(*i);
628       if(!(ci == configsPartOfDefaultBuild.end()))
629       {
630       fout << "\t\t{" << guid << "}." << *i
631            << ".Build.0 = " << *i << "|" << platformName << "\n";
632       }
633     }
634 }
635
636
637
638 // Write a dsp file into the SLN file,
639 // Note, that dependencies from executables to
640 // the libraries it uses are also done here
641 void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
642                                const char* name,
643                                const char* location,
644                                const char* typeGuid,
645                                const std::set<cmStdString>&)
646 {
647   std::string d = cmSystemTools::ConvertToOutputPath(location);
648   fout << "Project("
649        << "\"{"
650        << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
651        << "}\") = \""
652        << name << "\", \""
653        << this->ConvertToSolutionPath(location) << "\", \"{"
654        << this->GetGUID(name)
655        << "}\"\n";
656   fout << "EndProject\n";
657 }
658
659
660
661 void cmGlobalVisualStudio7Generator
662 ::WriteSLNGlobalSections(std::ostream& fout,
663                          cmLocalGenerator* root)
664 {
665   bool extensibilityGlobalsOverridden = false;
666   bool extensibilityAddInsOverridden = false;
667   const cmPropertyMap& props = root->GetMakefile()->GetProperties();
668   for(cmPropertyMap::const_iterator itProp = props.begin();
669       itProp != props.end(); ++itProp)
670     {
671     if(itProp->first.find("VS_GLOBAL_SECTION_") == 0)
672       {
673       std::string sectionType;
674       std::string name = itProp->first.substr(18);
675       if(name.find("PRE_") == 0)
676         {
677         name = name.substr(4);
678         sectionType = "preSolution";
679         }
680       else if(name.find("POST_") == 0)
681         {
682         name = name.substr(5);
683         sectionType = "postSolution";
684         }
685       else
686         continue;
687       if(!name.empty())
688         {
689         if(name == "ExtensibilityGlobals" && sectionType == "postSolution")
690           extensibilityGlobalsOverridden = true;
691         else if(name == "ExtensibilityAddIns" && sectionType == "postSolution")
692           extensibilityAddInsOverridden = true;
693         fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
694         std::vector<std::string> keyValuePairs;
695         cmSystemTools::ExpandListArgument(itProp->second.GetValue(),
696                                           keyValuePairs);
697         for(std::vector<std::string>::const_iterator itPair =
698             keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair)
699           {
700           const std::string::size_type posEqual = itPair->find('=');
701           if(posEqual != std::string::npos)
702             {
703             const std::string key =
704               cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
705             const std::string value =
706               cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
707             fout << "\t\t" << key << " = " << value << "\n";
708             }
709           }
710         fout << "\tEndGlobalSection\n";
711         }
712       }
713     }
714   if(!extensibilityGlobalsOverridden)
715     fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
716          << "\tEndGlobalSection\n";
717   if(!extensibilityAddInsOverridden)
718     fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
719          << "\tEndGlobalSection\n";
720 }
721
722
723
724 // Standard end of dsw file
725 void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
726 {
727   fout << "EndGlobal\n";
728 }
729
730
731 // ouput standard header for dsw file
732 void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout)
733 {
734   fout << "Microsoft Visual Studio Solution File, Format Version 7.00\n";
735 }
736
737 //----------------------------------------------------------------------------
738 std::string
739 cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget* target)
740 {
741   std::string pname = target->GetName();
742   pname += "_UTILITY";
743   std::string fname = target->GetMakefile()->GetStartOutputDirectory();
744   fname += "/";
745   fname += pname;
746   fname += ".vcproj";
747   cmGeneratedFileStream fout(fname.c_str());
748   fout.SetCopyIfDifferent(true);
749   this->CreateGUID(pname.c_str());
750   std::string guid = this->GetGUID(pname.c_str());
751
752   fout <<
753     "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
754     "<VisualStudioProject\n"
755     "\tProjectType=\"Visual C++\"\n"
756     "\tVersion=\"" << this->GetIDEVersion() << "0\"\n"
757     "\tName=\"" << pname << "\"\n"
758     "\tProjectGUID=\"{" << guid << "}\"\n"
759     "\tKeyword=\"Win32Proj\">\n"
760     "\t<Platforms><Platform Name=\"Win32\"/></Platforms>\n"
761     "\t<Configurations>\n"
762     ;
763   for(std::vector<std::string>::iterator i = this->Configurations.begin();
764       i != this->Configurations.end(); ++i)
765     {
766     fout <<
767       "\t\t<Configuration\n"
768       "\t\t\tName=\"" << *i << "|Win32\"\n"
769       "\t\t\tOutputDirectory=\"" << *i << "\"\n"
770       "\t\t\tIntermediateDirectory=\"" << pname << ".dir\\" << *i << "\"\n"
771       "\t\t\tConfigurationType=\"10\"\n"
772       "\t\t\tUseOfMFC=\"0\"\n"
773       "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n"
774       "\t\t\tCharacterSet=\"2\">\n"
775       "\t\t</Configuration>\n"
776       ;
777     }
778   fout <<
779     "\t</Configurations>\n"
780     "\t<Files></Files>\n"
781     "\t<Globals></Globals>\n"
782     "</VisualStudioProject>\n"
783     ;
784
785   if(fout.Close())
786     {
787     this->FileReplacedDuringGenerate(fname);
788     }
789   return pname;
790 }
791
792 std::string cmGlobalVisualStudio7Generator::GetGUID(const char* name)
793 {
794   std::string guidStoreName = name;
795   guidStoreName += "_GUID_CMAKE";
796   const char* storedGUID =
797     this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
798   if(storedGUID)
799     {
800     return std::string(storedGUID);
801     }
802   cmSystemTools::Error("Unknown Target referenced : ",
803                        name);
804   return "";
805 }
806
807
808 void cmGlobalVisualStudio7Generator::CreateGUID(const char* name)
809 {
810   std::string guidStoreName = name;
811   guidStoreName += "_GUID_CMAKE";
812   if(this->CMakeInstance->GetCacheDefinition(guidStoreName.c_str()))
813     {
814     return;
815     }
816   std::string ret;
817   UUID uid;
818   unsigned char *uidstr;
819   UuidCreate(&uid);
820   UuidToString(&uid,&uidstr);
821   ret = reinterpret_cast<char*>(uidstr);
822   RpcStringFree(&uidstr);
823   ret = cmSystemTools::UpperCase(ret);
824   this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(),
825                                      ret.c_str(), "Stored GUID",
826                                      cmCacheManager::INTERNAL);
827 }
828
829 std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations()
830 {
831   return &this->Configurations;
832 };
833
834 //----------------------------------------------------------------------------
835 void cmGlobalVisualStudio7Generator
836 ::GetDocumentation(cmDocumentationEntry& entry)
837 {
838   entry.Name = cmGlobalVisualStudio7Generator::GetActualName();
839   entry.Brief = "Generates Visual Studio .NET 2002 project files.";
840   entry.Full = "";
841 }
842
843 //----------------------------------------------------------------------------
844 void
845 cmGlobalVisualStudio7Generator
846 ::AppendDirectoryForConfig(const char* prefix,
847                            const char* config,
848                            const char* suffix,
849                            std::string& dir)
850 {
851   if(config)
852     {
853     dir += prefix;
854     dir += config;
855     dir += suffix;
856     }
857 }
858
859 std::set<std::string>
860 cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(const char* project,
861                                                      cmTarget* target)
862 {
863   std::set<std::string> activeConfigs;
864   // if it is a utilitiy target then only make it part of the
865   // default build if another target depends on it
866   int type = target->GetType();
867   if (type == cmTarget::GLOBAL_TARGET)
868     {
869     return activeConfigs;
870     }
871   if(type == cmTarget::UTILITY && !this->IsDependedOn(project, target))
872     {
873     return activeConfigs;
874     }
875   // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
876   for(std::vector<std::string>::iterator i = this->Configurations.begin();
877       i != this->Configurations.end(); ++i)
878     {
879     const char* propertyValue =
880       target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str());
881     if(cmSystemTools::IsOff(propertyValue))
882       {
883       activeConfigs.insert(*i);
884       }
885     }
886   return activeConfigs;
887 }
888
889 //----------------------------------------------------------------------------
890 static cmVS7FlagTable cmVS7ExtraFlagTable[] =
891 {
892   // Precompiled header and related options.  Note that the
893   // UsePrecompiledHeader entries are marked as "Continue" so that the
894   // corresponding PrecompiledHeaderThrough entry can be found.
895   {"UsePrecompiledHeader", "YX", "Automatically Generate", "2",
896    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
897   {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "",
898    cmVS7FlagTable::UserValueRequired},
899   {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3",
900    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
901   {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "",
902    cmVS7FlagTable::UserValueRequired},
903   {"WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "TRUE", 0},
904
905   // Exception handling mode.  If no entries match, it will be FALSE.
906   {"ExceptionHandling", "GX", "enable c++ exceptions", "TRUE", 0},
907   {"ExceptionHandling", "EHsc", "enable c++ exceptions", "TRUE", 0},
908   // The EHa option does not have an IDE setting.  Let it go to false,
909   // and have EHa passed on the command line by leaving out the table
910   // entry.
911
912   {0,0,0,0,0}
913 };
914 cmIDEFlagTable const* cmGlobalVisualStudio7Generator::GetExtraFlagTableVS7()
915 {
916   return cmVS7ExtraFlagTable;
917 }