Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmLocalVisualStudio7Generator.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 "cmGlobalVisualStudio7Generator.h"
13 #include "cmLocalVisualStudio7Generator.h"
14 #include "cmXMLParser.h"
15 #include <cm_expat.h>
16 #include "cmMakefile.h"
17 #include "cmSystemTools.h"
18 #include "cmSourceFile.h"
19 #include "cmCacheManager.h"
20 #include "cmGeneratorTarget.h"
21 #include "cmake.h"
22
23 #include "cmComputeLinkInformation.h"
24 #include "cmGeneratedFileStream.h"
25
26 #include <cmsys/System.h>
27
28 #include <ctype.h> // for isspace
29
30 // Package GUID of Intel Visual Fortran plugin to VS IDE
31 #define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}"
32
33 static bool cmLVS6G_IsFAT(const char* dir);
34
35 class cmLocalVisualStudio7GeneratorInternals
36 {
37 public:
38   cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e):
39     LocalGenerator(e) {}
40   typedef cmComputeLinkInformation::ItemVector ItemVector;
41   void OutputLibraries(std::ostream& fout, ItemVector const& libs);
42   void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0);
43 private:
44   cmLocalVisualStudio7Generator* LocalGenerator;
45 };
46
47 extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
48
49 //----------------------------------------------------------------------------
50 cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(VSVersion v):
51   cmLocalVisualStudioGenerator(v)
52 {
53   this->PlatformName = "Win32";
54   this->ExtraFlagTable = 0;
55   this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);
56 }
57
58 cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
59 {
60   delete this->Internal;
61 }
62
63 void cmLocalVisualStudio7Generator::AddHelperCommands()
64 {
65   std::set<cmStdString> lang;
66   lang.insert("C");
67   lang.insert("CXX");
68   lang.insert("RC");
69   lang.insert("IDL");
70   lang.insert("DEF");
71   lang.insert("Fortran");
72   this->CreateCustomTargetsAndCommands(lang);
73
74   // Now create GUIDs for targets
75   cmTargets &tgts = this->Makefile->GetTargets();
76
77   cmGlobalVisualStudio7Generator* gg =
78     static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
79   for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
80     {
81     const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT");
82     if(path)
83       {
84       this->ReadAndStoreExternalGUID(
85         l->second.GetName(), path);
86       }
87     else
88       {
89       gg->CreateGUID(l->first.c_str());
90       }
91     }
92
93
94   this->FixGlobalTargets();
95 }
96
97 void cmLocalVisualStudio7Generator::Generate()
98 {
99   this->WriteProjectFiles();
100   this->WriteStampFiles();
101 }
102
103 void cmLocalVisualStudio7Generator::AddCMakeListsRules()
104 {
105   cmTargets &tgts = this->Makefile->GetTargets();
106   // Create the regeneration custom rule.
107   if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
108     {
109     // Create a rule to regenerate the build system when the target
110     // specification source changes.
111     if(cmSourceFile* sf = this->CreateVCProjBuildRule())
112       {
113       // Add the rule to targets that need it.
114       for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
115         {
116         if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
117           {
118           l->second.AddSourceFile(sf);
119           }
120         }
121       }
122     }
123 }
124
125 void cmLocalVisualStudio7Generator::FixGlobalTargets()
126 {
127   // Visual Studio .NET 2003 Service Pack 1 will not run post-build
128   // commands for targets in which no sources are built.  Add dummy
129   // rules to force these targets to build.
130   cmTargets &tgts = this->Makefile->GetTargets();
131   for(cmTargets::iterator l = tgts.begin();
132       l != tgts.end(); l++)
133     {
134     cmTarget& tgt = l->second;
135     if(tgt.GetType() == cmTarget::GLOBAL_TARGET)
136       {
137       std::vector<std::string> no_depends;
138       cmCustomCommandLine force_command;
139       force_command.push_back("cd");
140       force_command.push_back(".");
141       cmCustomCommandLines force_commands;
142       force_commands.push_back(force_command);
143       const char* no_main_dependency = 0;
144       std::string force = this->Makefile->GetStartOutputDirectory();
145       force += cmake::GetCMakeFilesDirectory();
146       force += "/";
147       force += tgt.GetName();
148       force += "_force";
149       if(cmSourceFile* file =
150          this->Makefile->AddCustomCommandToOutput(
151            force.c_str(), no_depends, no_main_dependency,
152            force_commands, " ", 0, true))
153         {
154         tgt.AddSourceFile(file);
155         }
156       }
157     }
158 }
159
160 // TODO
161 // for CommandLine= need to repleace quotes with &quot
162 // write out configurations
163 void cmLocalVisualStudio7Generator::WriteProjectFiles()
164 {
165   // If not an in source build, then create the output directory
166   if(strcmp(this->Makefile->GetStartOutputDirectory(),
167             this->Makefile->GetHomeDirectory()) != 0)
168     {
169     if(!cmSystemTools::MakeDirectory
170        (this->Makefile->GetStartOutputDirectory()))
171       {
172       cmSystemTools::Error("Error creating directory ",
173                            this->Makefile->GetStartOutputDirectory());
174       }
175     }
176
177   // Get the set of targets in this directory.
178   cmTargets &tgts = this->Makefile->GetTargets();
179
180   // Create the project file for each target.
181   for(cmTargets::iterator l = tgts.begin();
182       l != tgts.end(); l++)
183     {
184     // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
185     // so don't build a projectfile for it
186     if(!l->second.GetProperty("EXTERNAL_MSPROJECT"))
187       {
188       this->CreateSingleVCProj(l->first.c_str(),l->second);
189       }
190     }
191 }
192
193 //----------------------------------------------------------------------------
194 void cmLocalVisualStudio7Generator::WriteStampFiles()
195 {
196   // Touch a timestamp file used to determine when the project file is
197   // out of date.
198   std::string stampName = this->Makefile->GetStartOutputDirectory();
199   stampName += cmake::GetCMakeFilesDirectory();
200   cmSystemTools::MakeDirectory(stampName.c_str());
201   stampName += "/";
202   stampName += "generate.stamp";
203   std::ofstream stamp(stampName.c_str());
204   stamp << "# CMake generation timestamp file for this directory.\n";
205
206   // Create a helper file so CMake can determine when it is run
207   // through the rule created by CreateVCProjBuildRule whether it
208   // really needs to regenerate the project.  This file lists its own
209   // dependencies.  If any file listed in it is newer than itself then
210   // CMake must rerun.  Otherwise the project files are up to date and
211   // the stamp file can just be touched.
212   std::string depName = stampName;
213   depName += ".depend";
214   std::ofstream depFile(depName.c_str());
215   depFile << "# CMake generation dependency list for this directory.\n";
216   std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
217   for(std::vector<std::string>::const_iterator lf = listFiles.begin();
218       lf != listFiles.end(); ++lf)
219     {
220     depFile << *lf << std::endl;
221     }
222 }
223
224 //----------------------------------------------------------------------------
225 void cmLocalVisualStudio7Generator
226 ::CreateSingleVCProj(const char *lname, cmTarget &target)
227 {
228   this->FortranProject =
229     static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
230     ->TargetIsFortranOnly(target);
231   this->WindowsCEProject =
232     static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
233     ->TargetsWindowsCE();
234
235   // Intel Fortran for VS10 uses VS9 format ".vfproj" files.
236   VSVersion realVersion = this->Version;
237   if(this->FortranProject && this->Version >= VS10)
238     {
239     this->Version = VS9;
240     }
241
242   // add to the list of projects
243   std::string pname = lname;
244   target.SetProperty("GENERATOR_FILE_NAME",lname);
245   // create the dsp.cmake file
246   std::string fname;
247   fname = this->Makefile->GetStartOutputDirectory();
248   fname += "/";
249   fname += lname;
250   if(this->FortranProject)
251     {
252     fname += ".vfproj";
253     }
254   else
255     {
256     fname += ".vcproj";
257     }
258
259   // Generate the project file and replace it atomically with
260   // copy-if-different.  We use a separate timestamp so that the IDE
261   // does not reload project files unnecessarily.
262   cmGeneratedFileStream fout(fname.c_str());
263   fout.SetCopyIfDifferent(true);
264   this->WriteVCProjFile(fout,lname,target);
265   if (fout.Close())
266     {
267     this->GlobalGenerator->FileReplacedDuringGenerate(fname);
268     }
269
270   this->Version = realVersion;
271 }
272
273 //----------------------------------------------------------------------------
274 cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
275 {
276   std::string stampName = this->Makefile->GetCurrentOutputDirectory();
277   stampName += "/";
278   stampName += cmake::GetCMakeFilesDirectoryPostSlash();
279   stampName += "generate.stamp";
280   const char* dsprule =
281     this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
282   cmCustomCommandLine commandLine;
283   commandLine.push_back(dsprule);
284   std::string makefileIn = this->Makefile->GetStartDirectory();
285   makefileIn += "/";
286   makefileIn += "CMakeLists.txt";
287   makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str());
288   if(!cmSystemTools::FileExists(makefileIn.c_str()))
289     {
290     return 0;
291     }
292   std::string comment = "Building Custom Rule ";
293   comment += makefileIn;
294   std::string args;
295   args = "-H";
296   args += this->Convert(this->Makefile->GetHomeDirectory(),
297                         START_OUTPUT, UNCHANGED, true);
298   commandLine.push_back(args);
299   args = "-B";
300   args +=
301     this->Convert(this->Makefile->GetHomeOutputDirectory(),
302                   START_OUTPUT, UNCHANGED, true);
303   commandLine.push_back(args);
304   commandLine.push_back("--check-stamp-file");
305   std::string stampFilename = this->Convert(stampName.c_str(), FULL,
306                                             SHELL);
307   commandLine.push_back(stampFilename.c_str());
308
309   std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
310
311   cmCustomCommandLines commandLines;
312   commandLines.push_back(commandLine);
313   const char* no_working_directory = 0;
314   std::string fullpathStampName = this->Convert(stampName.c_str(), FULL,
315                                             UNCHANGED);
316   this->Makefile->AddCustomCommandToOutput(fullpathStampName.c_str(),
317                                            listFiles, makefileIn.c_str(),
318                                            commandLines, comment.c_str(),
319                                            no_working_directory, true);
320   if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
321     {
322     return file;
323     }
324   else
325     {
326     cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
327     return 0;
328     }
329 }
330
331 void cmLocalVisualStudio7Generator::WriteConfigurations(std::ostream& fout,
332                                                         const char *libName,
333                                                         cmTarget &target)
334 {
335   std::vector<std::string> *configs =
336     static_cast<cmGlobalVisualStudio7Generator *>
337     (this->GlobalGenerator)->GetConfigurations();
338
339   fout << "\t<Configurations>\n";
340   for( std::vector<std::string>::iterator i = configs->begin();
341        i != configs->end(); ++i)
342     {
343     this->WriteConfiguration(fout, i->c_str(), libName, target);
344     }
345   fout << "\t</Configurations>\n";
346 }
347 cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] =
348 {
349   {"Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0},
350   {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0},
351   {"SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0},
352   {"SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0},
353   {"DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0},
354   {"DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0},
355   {"DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0},
356   {"DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0},
357   {"Optimization", "Od", "disable optimization", "optimizeDisabled", 0},
358   {"Optimization", "O1", "min space", "optimizeMinSpace", 0},
359   {"Optimization", "O3", "full optimize", "optimizeFull", 0},
360   {"GlobalOptimizations", "Og", "global optimize", "true", 0},
361   {"InlineFunctionExpansion", "Ob0", "", "expandDisable", 0},
362   {"InlineFunctionExpansion", "Ob1", "", "expandOnlyInline", 0},
363   {"FavorSizeOrSpeed", "Os", "", "favorSize", 0},
364   {"OmitFramePointers", "Oy-", "", "false", 0},
365   {"OptimizeForProcessor", "GB", "", "procOptimizeBlended", 0},
366   {"OptimizeForProcessor", "G5", "", "procOptimizePentium", 0},
367   {"OptimizeForProcessor", "G6", "", "procOptimizePentiumProThruIII", 0},
368   {"UseProcessorExtensions", "QzxK", "", "codeForStreamingSIMD", 0},
369   {"OptimizeForProcessor", "QaxN", "", "codeForPentium4", 0},
370   {"OptimizeForProcessor", "QaxB", "", "codeForPentiumM", 0},
371   {"OptimizeForProcessor", "QaxP", "", "codeForCodeNamedPrescott", 0},
372   {"OptimizeForProcessor", "QaxT", "", "codeForCore2Duo", 0},
373   {"OptimizeForProcessor", "QxK", "", "codeExclusivelyStreamingSIMD", 0},
374   {"OptimizeForProcessor", "QxN", "", "codeExclusivelyPentium4", 0},
375   {"OptimizeForProcessor", "QxB", "", "codeExclusivelyPentiumM", 0},
376   {"OptimizeForProcessor", "QxP", "", "codeExclusivelyCodeNamedPrescott", 0},
377   {"OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0},
378   {"OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD", 0},
379   {"OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4", 0},
380
381   {"ModulePath", "module:", "", "",
382    cmVS7FlagTable::UserValueRequired},
383   {"LoopUnrolling", "Qunroll:", "", "",
384    cmVS7FlagTable::UserValueRequired},
385   {"AutoParallelThreshold", "Qpar-threshold:", "", "",
386    cmVS7FlagTable::UserValueRequired},
387   {"HeapArrays", "heap-arrays:", "", "",
388    cmVS7FlagTable::UserValueRequired},
389   {"ObjectText", "bintext:", "", "",
390    cmVS7FlagTable::UserValueRequired},
391   {"Parallelization", "Qparallel", "", "true", 0},
392   {"PrefetchInsertion", "Qprefetch-", "", "false", 0},
393   {"BufferedIO", "assume:buffered_io", "", "true", 0},
394   {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
395   {"CallingConvention", "iface:cref", "", "callConventionCRef", 0},
396   {"CallingConvention", "iface:stdref", "", "callConventionStdRef", 0},
397   {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
398   {"CallingConvention", "iface:cvf", "", "callConventionCVF", 0},
399   {"EnableRecursion", "recursive", "", "true", 0},
400   {"ReentrantCode", "reentrancy", "", "true", 0},
401   // done up to Language
402   {0,0,0,0,0}
403 };
404 // fill the table here currently the comment field is not used for
405 // anything other than documentation NOTE: Make sure the longer
406 // commandFlag comes FIRST!
407 cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
408 {
409   // option flags (some flags map to the same option)
410   {"BasicRuntimeChecks", "GZ", "Stack frame checks", "1", 0},
411   {"BasicRuntimeChecks", "RTCsu",
412    "Both stack and uninitialized checks", "3", 0},
413   {"BasicRuntimeChecks", "RTCs", "Stack frame checks", "1", 0},
414   {"BasicRuntimeChecks", "RTCu", "Uninitialized Variables ", "2", 0},
415   {"BasicRuntimeChecks", "RTC1",
416    "Both stack and uninitialized checks", "3", 0},
417   {"DebugInformationFormat", "Z7", "debug format", "1", 0},
418   {"DebugInformationFormat", "Zd", "debug format", "2", 0},
419   {"DebugInformationFormat", "Zi", "debug format", "3", 0},
420   {"DebugInformationFormat", "ZI", "debug format", "4", 0},
421   {"EnableEnhancedInstructionSet", "arch:SSE2",
422    "Use sse2 instructions", "2", 0},
423   {"EnableEnhancedInstructionSet", "arch:SSE",
424    "Use sse instructions",   "1", 0},
425   {"FloatingPointModel", "fp:precise",
426    "Use precise floating point model", "0", 0},
427   {"FloatingPointModel", "fp:strict",
428    "Use strict floating point model", "1", 0},
429   {"FloatingPointModel", "fp:fast", "Use fast floating point model", "2", 0},
430   {"FavorSizeOrSpeed",  "Ot", "Favor fast code",  "1", 0},
431   {"FavorSizeOrSpeed",  "Os", "Favor small code", "2", 0},
432   {"CompileAs", "TC", "Compile as c code",        "1", 0},
433   {"CompileAs", "TP", "Compile as c++ code",      "2", 0},
434   {"Optimization", "Od", "Non Debug",        "0", 0},
435   {"Optimization", "O1", "Min Size",         "1", 0},
436   {"Optimization", "O2", "Max Speed",        "2", 0},
437   {"Optimization", "Ox", "Max Optimization", "3", 0},
438   {"OptimizeForProcessor", "GB", "Blended processor mode", "0", 0},
439   {"OptimizeForProcessor", "G5", "Pentium",                "1", 0},
440   {"OptimizeForProcessor", "G6", "PPro PII PIII",          "2", 0},
441   {"OptimizeForProcessor", "G7", "Pentium 4 or Athlon",    "3", 0},
442   {"InlineFunctionExpansion", "Ob0", "no inlines",              "0", 0},
443   {"InlineFunctionExpansion", "Ob1", "when inline keyword",     "1", 0},
444   {"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0},
445   {"RuntimeLibrary", "MTd", "Multithreaded debug",     "1", 0},
446   {"RuntimeLibrary", "MT", "Multithreaded", "0", 0},
447   {"RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0},
448   {"RuntimeLibrary", "MD", "Multithreaded dll",        "2", 0},
449   {"RuntimeLibrary", "MLd", "Single Thread debug",    "5", 0},
450   {"RuntimeLibrary", "ML", "Single Thread",           "4", 0},
451   {"StructMemberAlignment", "Zp16", "struct align 16 byte ",   "5", 0},
452   {"StructMemberAlignment", "Zp1", "struct align 1 byte ",     "1", 0},
453   {"StructMemberAlignment", "Zp2", "struct align 2 byte ",     "2", 0},
454   {"StructMemberAlignment", "Zp4", "struct align 4 byte ",     "3", 0},
455   {"StructMemberAlignment", "Zp8", "struct align 8 byte ",     "4", 0},
456   {"WarningLevel", "W0", "Warning level", "0", 0},
457   {"WarningLevel", "W1", "Warning level", "1", 0},
458   {"WarningLevel", "W2", "Warning level", "2", 0},
459   {"WarningLevel", "W3", "Warning level", "3", 0},
460   {"WarningLevel", "W4", "Warning level", "4", 0},
461   {"DisableSpecificWarnings", "wd", "Disable specific warnings", "",
462    cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
463
464   // Precompiled header and related options.  Note that the
465   // UsePrecompiledHeader entries are marked as "Continue" so that the
466   // corresponding PrecompiledHeaderThrough entry can be found.
467   {"UsePrecompiledHeader", "Yc", "Create Precompiled Header", "1",
468    cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
469   {"PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "",
470    cmVS7FlagTable::UserValueRequired},
471   {"PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "",
472    cmVS7FlagTable::UserValue},
473   // The YX and Yu options are in a per-global-generator table because
474   // their values differ based on the VS IDE version.
475   {"ForcedIncludeFiles", "FI", "Forced include files", "",
476    cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable},
477
478   {"AssemblerListingLocation", "Fa", "ASM List Location", "",
479    cmVS7FlagTable::UserValue},
480   {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
481    cmVS7FlagTable::UserValue},
482
483   // boolean flags
484   {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0},
485   {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0},
486   {"Detect64BitPortabilityProblems", "Wp64",
487    "Detect 64-bit Portability Problems", "TRUE", 0},
488   {"EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations",
489    "TRUE", 0},
490   {"EnableFunctionLevelLinking", "Gy",
491    "EnableFunctionLevelLinking", "TRUE", 0},
492   {"EnableIntrinsicFunctions", "Oi", "EnableIntrinsicFunctions", "TRUE", 0},
493   {"GlobalOptimizations", "Og", "Global Optimize", "TRUE", 0},
494   {"ImproveFloatingPointConsistency", "Op",
495    "ImproveFloatingPointConsistency", "TRUE", 0},
496   {"MinimalRebuild", "Gm", "minimal rebuild", "TRUE", 0},
497   {"OmitFramePointers", "Oy", "OmitFramePointers", "TRUE", 0},
498   {"OptimizeForWindowsApplication", "GA", "Optimize for windows", "TRUE", 0},
499   {"RuntimeTypeInfo", "GR",
500    "Turn on Run time type information for c++", "TRUE", 0},
501   {"RuntimeTypeInfo", "GR-",
502    "Turn off Run time type information for c++", "FALSE", 0},
503   {"SmallerTypeCheck", "RTCc", "smaller type check", "TRUE", 0},
504   {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "TRUE", 0},
505   {"WholeProgramOptimization", "GL",
506    "Enables whole program optimization", "TRUE", 0},
507   {"WholeProgramOptimization", "GL-",
508    "Disables whole program optimization", "FALSE", 0},
509   {"WarnAsError", "WX", "Treat warnings as errors", "TRUE", 0},
510   {"BrowseInformation", "FR", "Generate browse information", "1", 0},
511   {"StringPooling", "GF", "Enable StringPooling", "TRUE", 0},
512   {0,0,0,0,0}
513 };
514
515
516
517 cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] =
518 {
519   // option flags (some flags map to the same option)
520   {"GenerateManifest", "MANIFEST:NO",
521    "disable manifest generation", "FALSE", 0},
522   {"GenerateManifest", "MANIFEST", "enable manifest generation", "TRUE", 0},
523   {"LinkIncremental", "INCREMENTAL:NO", "link incremental", "1", 0},
524   {"LinkIncremental", "INCREMENTAL:YES", "link incremental", "2", 0},
525   {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0},
526   {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0},
527   {"DataExecutionPrevention", "NXCOMPAT:NO",
528    "Not known to work with Windows Data Execution Prevention", "1", 0},
529   {"DataExecutionPrevention", "NXCOMPAT",
530    "Known to work with Windows Data Execution Prevention", "2", 0},
531   {"DelaySign", "DELAYSIGN:NO", "", "false", 0},
532   {"DelaySign", "DELAYSIGN", "", "true", 0},
533   {"EntryPointSymbol", "ENTRY:", "sets the starting address", "",
534    cmVS7FlagTable::UserValue},
535   {"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore", "",
536   cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
537   {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs",
538    "TRUE", 0},
539   {"FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0},
540   {"FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address",
541    "2", 0},
542   {"EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs",
543    "1", 0},
544   {"EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "2", 0},
545   {"ResourceOnlyDLL", "NOENTRY", "Create DLL with no entry point", "true", 0},
546   {"OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", "1", 0},
547   {"OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", "2", 0},
548   {"Profile", "PROFILE", "", "true", 0},
549   {"RandomizedBaseAddress", "DYNAMICBASE:NO",
550    "Image may not be rebased at load-time", "1", 0},
551   {"RandomizedBaseAddress", "DYNAMICBASE",
552    "Image may be rebased at load-time", "2", 0},
553   {"SetChecksum", "RELEASE", "Enable setting checksum in header", "true", 0},
554   {"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0},
555   {"TargetMachine", "MACHINE:I386", "Machine x86", "1", 0},
556   {"TargetMachine", "MACHINE:X86", "Machine x86", "1", 0},
557   {"TargetMachine", "MACHINE:AM33", "Machine AM33", "2", 0},
558   {"TargetMachine", "MACHINE:ARM", "Machine ARM", "3", 0},
559   {"TargetMachine", "MACHINE:EBC", "Machine EBC", "4", 0},
560   {"TargetMachine", "MACHINE:IA64", "Machine IA64", "5", 0},
561   {"TargetMachine", "MACHINE:M32R", "Machine M32R", "6", 0},
562   {"TargetMachine", "MACHINE:MIPS", "Machine MIPS", "7", 0},
563   {"TargetMachine", "MACHINE:MIPS16", "Machine MIPS16", "8", 0},
564   {"TargetMachine", "MACHINE:MIPSFPU)", "Machine MIPSFPU", "9", 0},
565   {"TargetMachine", "MACHINE:MIPSFPU16", "Machine MIPSFPU16", "10", 0},
566   {"TargetMachine", "MACHINE:MIPSR41XX", "Machine MIPSR41XX", "11", 0},
567   {"TargetMachine", "MACHINE:SH3", "Machine SH3", "12", 0},
568   {"TargetMachine", "MACHINE:SH3DSP", "Machine SH3DSP", "13", 0},
569   {"TargetMachine", "MACHINE:SH4", "Machine SH4", "14", 0},
570   {"TargetMachine", "MACHINE:SH5", "Machine SH5", "15", 0},
571   {"TargetMachine", "MACHINE:THUMB", "Machine THUMB", "16", 0},
572   {"TargetMachine", "MACHINE:X64", "Machine x64", "17", 0},
573   {"TurnOffAssemblyGeneration", "NOASSEMBLY",
574    "No assembly even if CLR information is present in objects.", "true", 0},
575   {"ModuleDefinitionFile", "DEF:", "add an export def file", "",
576    cmVS7FlagTable::UserValue},
577   {"GenerateMapFile", "MAP", "enable generation of map file", "TRUE", 0},
578   {0,0,0,0,0}
579 };
580
581 //----------------------------------------------------------------------------
582 // Helper class to write build event <Tool .../> elements.
583 class cmLocalVisualStudio7Generator::EventWriter
584 {
585 public:
586   EventWriter(cmLocalVisualStudio7Generator* lg,
587               const char* config, std::ostream& os):
588     LG(lg), Config(config), Stream(os), First(true) {}
589   void Start(const char* tool)
590     {
591     this->First = true;
592     this->Stream << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"";
593     }
594   void Finish()
595     {
596     this->Stream << (this->First? "" : "\"") << "/>\n";
597     }
598   void Write(std::vector<cmCustomCommand> const& ccs)
599     {
600     for(std::vector<cmCustomCommand>::const_iterator ci = ccs.begin();
601         ci != ccs.end(); ++ci)
602       {
603       this->Write(*ci);
604       }
605     }
606   void Write(cmCustomCommand const& cc)
607     {
608     if(this->First)
609       {
610       const char* comment = cc.GetComment();
611       if(comment && *comment)
612         {
613         this->Stream << "\nDescription=\""
614                      << this->LG->EscapeForXML(comment) << "\"";
615         }
616       this->Stream << "\nCommandLine=\"";
617       this->First = false;
618       }
619     else
620       {
621       this->Stream << this->LG->EscapeForXML("\n");
622       }
623     std::string script = this->LG->ConstructScript(cc, this->Config);
624     this->Stream << this->LG->EscapeForXML(script.c_str());
625     }
626 private:
627   cmLocalVisualStudio7Generator* LG;
628   const char* Config;
629   std::ostream& Stream;
630   bool First;
631 };
632
633 //----------------------------------------------------------------------------
634 void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
635                                                        const char* configName,
636                                                        const char *libName,
637                                                        cmTarget &target)
638 {
639   const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
640   if(!mfcFlag)
641     {
642     mfcFlag = "0";
643     }
644   fout << "\t\t<Configuration\n"
645        << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n"
646        << "\t\t\tOutputDirectory=\"" << configName << "\"\n";
647   // This is an internal type to Visual Studio, it seems that:
648   // 4 == static library
649   // 2 == dll
650   // 1 == executable
651   // 10 == utility
652   const char* configType = "10";
653   const char* projectType = 0;
654   bool targetBuilds = true;
655   switch(target.GetType())
656     {
657     case cmTarget::OBJECT_LIBRARY:
658       targetBuilds = false; // TODO: PDB for object library?
659     case cmTarget::STATIC_LIBRARY:
660       projectType = "typeStaticLibrary";
661       configType = "4";
662       break;
663     case cmTarget::SHARED_LIBRARY:
664     case cmTarget::MODULE_LIBRARY:
665       projectType = "typeDynamicLibrary";
666       configType = "2";
667       break;
668     case cmTarget::EXECUTABLE:
669       configType = "1";
670       break;
671     case cmTarget::UTILITY:
672     case cmTarget::GLOBAL_TARGET:
673       configType = "10";
674     default:
675       targetBuilds = false;
676       break;
677     }
678   if(this->FortranProject && projectType)
679     {
680     configType = projectType;
681     }
682   std::string flags;
683   if(strcmp(configType, "10") != 0)
684     {
685     const char* linkLanguage = (this->FortranProject? "Fortran":
686                                 target.GetLinkerLanguage(configName));
687     if(!linkLanguage)
688       {
689       cmSystemTools::Error
690         ("CMake can not determine linker language for target: ",
691          target.GetName());
692       return;
693       }
694     if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
695       || strcmp(linkLanguage, "Fortran") == 0)
696       {
697       std::string baseFlagVar = "CMAKE_";
698       baseFlagVar += linkLanguage;
699       baseFlagVar += "_FLAGS";
700       flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
701       std::string flagVar = baseFlagVar + std::string("_") +
702         cmSystemTools::UpperCase(configName);
703       flags += " ";
704       flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
705       }
706     // set the correct language
707     if(strcmp(linkLanguage, "C") == 0)
708       {
709       flags += " /TC ";
710       }
711     if(strcmp(linkLanguage, "CXX") == 0)
712       {
713       flags += " /TP ";
714       }
715
716     // Add the target-specific flags.
717     this->AddCompileOptions(flags, &target, linkLanguage, configName);
718     }
719
720   if(this->FortranProject)
721     {
722     switch(this->GetFortranFormat(target.GetProperty("Fortran_FORMAT")))
723       {
724       case FortranFormatFixed: flags += " -fixed"; break;
725       case FortranFormatFree: flags += " -free"; break;
726       default: break;
727       }
728     }
729
730   // Get preprocessor definitions for this directory.
731   std::string defineFlags = this->Makefile->GetDefineFlags();
732   Options::Tool t = Options::Compiler;
733   cmVS7FlagTable const* table = cmLocalVisualStudio7GeneratorFlagTable;
734   if(this->FortranProject)
735     {
736     t = Options::FortranCompiler;
737     table = cmLocalVisualStudio7GeneratorFortranFlagTable;
738     }
739   Options targetOptions(this, t,
740                         table,
741                         this->ExtraFlagTable);
742   targetOptions.FixExceptionHandlingDefault();
743   std::string asmLocation = std::string(configName) + "/";
744   targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
745   targetOptions.Parse(flags.c_str());
746   targetOptions.Parse(defineFlags.c_str());
747   targetOptions.ParseFinish();
748   cmGeneratorTarget* gt =
749     this->GlobalGenerator->GetGeneratorTarget(&target);
750   std::vector<std::string> targetDefines;
751   target.GetCompileDefinitions(targetDefines, configName);
752   targetOptions.AddDefines(targetDefines);
753   targetOptions.SetVerboseMakefile(
754     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
755
756   // Add a definition for the configuration name.
757   std::string configDefine = "CMAKE_INTDIR=\"";
758   configDefine += configName;
759   configDefine += "\"";
760   targetOptions.AddDefine(configDefine);
761
762   // Add the export symbol definition for shared library objects.
763   if(const char* exportMacro = target.GetExportMacro())
764     {
765     targetOptions.AddDefine(exportMacro);
766     }
767
768   // The intermediate directory name consists of a directory for the
769   // target and a subdirectory for the configuration name.
770   std::string intermediateDir = this->GetTargetDirectory(target);
771   intermediateDir += "/";
772   intermediateDir += configName;
773   fout << "\t\t\tIntermediateDirectory=\""
774        << this->ConvertToXMLOutputPath(intermediateDir.c_str())
775        << "\"\n"
776        << "\t\t\tConfigurationType=\"" << configType << "\"\n"
777        << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n"
778        << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n";
779
780   // If unicode is enabled change the character set to unicode, if not
781   // then default to MBCS.
782   if(targetOptions.UsingUnicode())
783     {
784     fout << "\t\t\tCharacterSet=\"1\">\n";
785     }
786   else if(targetOptions.UsingSBCS())
787     {
788     fout << "\t\t\tCharacterSet=\"0\">\n";
789     }
790   else
791     {
792     fout << "\t\t\tCharacterSet=\"2\">\n";
793     }
794   const char* tool = "VCCLCompilerTool";
795   if(this->FortranProject)
796     {
797     tool = "VFFortranCompilerTool";
798     }
799   fout << "\t\t\t<Tool\n"
800        << "\t\t\t\tName=\"" << tool << "\"\n";
801   if(this->FortranProject)
802     {
803     const char* target_mod_dir =
804       target.GetProperty("Fortran_MODULE_DIRECTORY");
805     std::string modDir;
806     if(target_mod_dir)
807       {
808       modDir = this->Convert(target_mod_dir,
809                              cmLocalGenerator::START_OUTPUT,
810                              cmLocalGenerator::UNCHANGED);
811       }
812     else
813       {
814       modDir = ".";
815       }
816     fout << "\t\t\t\tModulePath=\""
817          << this->ConvertToXMLOutputPath(modDir.c_str())
818          << "\\$(ConfigurationName)\"\n";
819     }
820   targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
821   fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
822   std::vector<std::string> includes;
823   this->GetIncludeDirectories(includes, gt, "C", configName);
824   std::vector<std::string>::iterator i = includes.begin();
825   for(;i != includes.end(); ++i)
826     {
827     // output the include path
828     std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
829     fout << ipath << ";";
830     // if this is fortran then output the include with
831     // a ConfigurationName on the end of it.
832     if(this->FortranProject)
833       {
834       ipath = i->c_str();
835       ipath += "/$(ConfigurationName)";
836       ipath = this->ConvertToXMLOutputPath(ipath.c_str());
837       fout << ipath << ";";
838       }
839     }
840   fout << "\"\n";
841   targetOptions.OutputFlagMap(fout, "\t\t\t\t");
842   targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX");
843   fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
844   fout << "/>\n";  // end of <Tool Name=VCCLCompilerTool
845   tool = "VCCustomBuildTool";
846   if(this->FortranProject)
847     {
848     tool = "VFCustomBuildTool";
849     }
850   fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"/>\n";
851   tool = "VCResourceCompilerTool";
852   if(this->FortranProject)
853     {
854     tool = "VFResourceCompilerTool";
855     }
856   fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
857        << "\t\t\t\tAdditionalIncludeDirectories=\"";
858   for(i = includes.begin();i != includes.end(); ++i)
859     {
860     std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
861     fout << ipath << ";";
862     }
863   // add the -D flags to the RC tool
864   fout << "\"";
865   targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
866   fout << "/>\n";
867   tool = "VCMIDLTool";
868   if(this->FortranProject)
869     {
870     tool = "VFMIDLTool";
871     }
872   fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
873   fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
874   for(i = includes.begin(); i != includes.end(); ++i)
875     {
876     std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
877     fout << ipath << ";";
878     }
879   fout << "\"\n";
880   fout << "\t\t\t\tMkTypLibCompatible=\"FALSE\"\n";
881   if( this->PlatformName == "x64" )
882     {
883     fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
884     }
885   else if( this->PlatformName == "ia64" )
886     {
887     fout << "\t\t\t\tTargetEnvironment=\"2\"\n";
888     }
889   else
890     {
891     fout << "\t\t\t\tTargetEnvironment=\"1\"\n";
892     }
893   fout << "\t\t\t\tGenerateStublessProxies=\"TRUE\"\n";
894   fout << "\t\t\t\tTypeLibraryName=\"$(InputName).tlb\"\n";
895   fout << "\t\t\t\tOutputDirectory=\"$(IntDir)\"\n";
896   fout << "\t\t\t\tHeaderFileName=\"$(InputName).h\"\n";
897   fout << "\t\t\t\tDLLDataFileName=\"\"\n";
898   fout << "\t\t\t\tInterfaceIdentifierFileName=\"$(InputName)_i.c\"\n";
899   fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n";
900   // end of <Tool Name=VCMIDLTool
901
902   // Check if we need the FAT32 workaround.
903   if(targetBuilds && this->Version >= VS8)
904     {
905     // Check the filesystem type where the target will be written.
906     if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
907       {
908       // Add a flag telling the manifest tool to use a workaround
909       // for FAT32 file systems, which can cause an empty manifest
910       // to be embedded into the resulting executable.  See CMake
911       // bug #2617.
912       const char* manifestTool  = "VCManifestTool";
913       if(this->FortranProject)
914         {
915         manifestTool = "VFManifestTool";
916         }
917       fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n"
918            << "\t\t\t\tUseFAT32Workaround=\"true\"\n"
919            << "\t\t\t/>\n";
920       }
921     }
922
923   this->OutputTargetRules(fout, configName, target, libName);
924   this->OutputBuildTool(fout, configName, target, targetOptions);
925   fout << "\t\t</Configuration>\n";
926 }
927
928 //----------------------------------------------------------------------------
929 std::string
930 cmLocalVisualStudio7Generator
931 ::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const char* configName)
932 {
933   std::string configTypeUpper = cmSystemTools::UpperCase(configName);
934   std::string extraLinkOptionsBuildTypeDef =
935     rootLinkerFlags + "_" + configTypeUpper;
936
937   std::string extraLinkOptionsBuildType =
938     this->Makefile->GetRequiredDefinition
939     (extraLinkOptionsBuildTypeDef.c_str());
940
941   return extraLinkOptionsBuildType;
942 }
943
944 void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
945   const char* configName, cmTarget &target, const Options& targetOptions)
946 {
947   cmGlobalVisualStudio7Generator* gg =
948     static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
949   std::string temp;
950   std::string extraLinkOptions;
951   if(target.GetType() == cmTarget::EXECUTABLE)
952     {
953     extraLinkOptions =
954       this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS")
955       + std::string(" ")
956       + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
957     }
958   if(target.GetType() == cmTarget::SHARED_LIBRARY)
959     {
960     extraLinkOptions =
961       this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS")
962       + std::string(" ")
963       + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
964     }
965   if(target.GetType() == cmTarget::MODULE_LIBRARY)
966     {
967     extraLinkOptions =
968       this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS")
969       + std::string(" ")
970       + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
971     }
972
973   const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
974   if(targetLinkFlags)
975     {
976     extraLinkOptions += " ";
977     extraLinkOptions += targetLinkFlags;
978     }
979   std::string configTypeUpper = cmSystemTools::UpperCase(configName);
980   std::string linkFlagsConfig = "LINK_FLAGS_";
981   linkFlagsConfig += configTypeUpper;
982   targetLinkFlags = target.GetProperty(linkFlagsConfig.c_str());
983   if(targetLinkFlags)
984     {
985     extraLinkOptions += " ";
986     extraLinkOptions += targetLinkFlags;
987     }
988   Options linkOptions(this, Options::Linker,
989                       cmLocalVisualStudio7GeneratorLinkFlagTable);
990   linkOptions.Parse(extraLinkOptions.c_str());
991   if(!this->ModuleDefinitionFile.empty())
992     {
993     std::string defFile =
994       this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str());
995     linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
996     }
997   switch(target.GetType())
998     {
999     case cmTarget::UNKNOWN_LIBRARY:
1000       break;
1001     case cmTarget::OBJECT_LIBRARY:
1002       {
1003       std::string libpath = this->GetTargetDirectory(target);
1004       libpath += "/";
1005       libpath += configName;
1006       libpath += "/";
1007       libpath += target.GetName();
1008       libpath += ".lib";
1009       const char* tool =
1010         this->FortranProject? "VFLibrarianTool":"VCLibrarianTool";
1011       fout << "\t\t\t<Tool\n"
1012            << "\t\t\t\tName=\"" << tool << "\"\n";
1013       fout << "\t\t\t\tOutputFile=\""
1014            << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
1015       break;
1016       }
1017     case cmTarget::STATIC_LIBRARY:
1018     {
1019     std::string targetNameFull = target.GetFullName(configName);
1020     std::string libpath = target.GetDirectory(configName);
1021     libpath += "/";
1022     libpath += targetNameFull;
1023     const char* tool = "VCLibrarianTool";
1024     if(this->FortranProject)
1025       {
1026       tool = "VFLibrarianTool";
1027       }
1028     fout << "\t\t\t<Tool\n"
1029          << "\t\t\t\tName=\"" << tool << "\"\n";
1030
1031     if(this->GetVersion() < VS8)
1032       {
1033       cmOStringStream libdeps;
1034       this->Internal->OutputObjects(libdeps, &target);
1035       if(!libdeps.str().empty())
1036         {
1037         fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n";
1038         }
1039       }
1040     std::string libflags;
1041     this->GetStaticLibraryFlags(libflags, configTypeUpper, &target);
1042     if(!libflags.empty())
1043       {
1044       fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
1045       }
1046     fout << "\t\t\t\tOutputFile=\""
1047          << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
1048     break;
1049     }
1050     case cmTarget::SHARED_LIBRARY:
1051     case cmTarget::MODULE_LIBRARY:
1052     {
1053     std::string targetName;
1054     std::string targetNameSO;
1055     std::string targetNameFull;
1056     std::string targetNameImport;
1057     std::string targetNamePDB;
1058     target.GetLibraryNames(targetName, targetNameSO, targetNameFull,
1059                            targetNameImport, targetNamePDB, configName);
1060
1061     // Compute the link library and directory information.
1062     cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
1063     if(!pcli)
1064       {
1065       return;
1066       }
1067     cmComputeLinkInformation& cli = *pcli;
1068     const char* linkLanguage = cli.GetLinkLanguage();
1069
1070     // Compute the variable name to lookup standard libraries for this
1071     // language.
1072     std::string standardLibsVar = "CMAKE_";
1073     standardLibsVar += linkLanguage;
1074     standardLibsVar += "_STANDARD_LIBRARIES";
1075     const char* tool = "VCLinkerTool";
1076     if(this->FortranProject)
1077       {
1078       tool = "VFLinkerTool";
1079       }
1080     fout << "\t\t\t<Tool\n"
1081          << "\t\t\t\tName=\"" << tool << "\"\n";
1082     if(!gg->NeedLinkLibraryDependencies(target))
1083       {
1084       fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
1085       }
1086     linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
1087     // Use the NOINHERIT macro to avoid getting VS project default
1088     // libraries which may be set by the user to something bad.
1089     fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
1090          << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
1091     if(this->GetVersion() < VS8)
1092       {
1093       this->Internal->OutputObjects(fout, &target, " ");
1094       }
1095     fout << " ";
1096     this->Internal->OutputLibraries(fout, cli.GetItems());
1097     fout << "\"\n";
1098     temp = target.GetDirectory(configName);
1099     temp += "/";
1100     temp += targetNameFull;
1101     fout << "\t\t\t\tOutputFile=\""
1102          << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
1103     this->WriteTargetVersionAttribute(fout, target);
1104     linkOptions.OutputFlagMap(fout, "\t\t\t\t");
1105     fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
1106     this->OutputLibraryDirectories(fout, cli.GetDirectories());
1107     fout << "\"\n";
1108     temp = target.GetPDBDirectory(configName);
1109     temp += "/";
1110     temp += targetNamePDB;
1111     fout << "\t\t\t\tProgramDatabaseFile=\"" <<
1112       this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
1113     if(targetOptions.IsDebug())
1114       {
1115       fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
1116       }
1117     if(this->WindowsCEProject)
1118       {
1119       if(this->GetVersion() < VS9)
1120         {
1121         fout << "\t\t\t\tSubSystem=\"9\"\n";
1122         }
1123       else
1124         {
1125         fout << "\t\t\t\tSubSystem=\"8\"\n";
1126         }
1127       }
1128     std::string stackVar = "CMAKE_";
1129     stackVar += linkLanguage;
1130     stackVar += "_STACK_SIZE";
1131     const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
1132     if(stackVal)
1133       {
1134       fout << "\t\t\t\tStackReserveSize=\"" << stackVal  << "\"\n";
1135       }
1136     temp = target.GetDirectory(configName, true);
1137     temp += "/";
1138     temp += targetNameImport;
1139     fout << "\t\t\t\tImportLibrary=\""
1140          << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
1141     if(this->FortranProject)
1142       {
1143       fout << "\n\t\t\t\tLinkDLL=\"true\"";
1144       }
1145     fout << "/>\n";
1146     }
1147     break;
1148     case cmTarget::EXECUTABLE:
1149     {
1150     std::string targetName;
1151     std::string targetNameFull;
1152     std::string targetNameImport;
1153     std::string targetNamePDB;
1154     target.GetExecutableNames(targetName, targetNameFull,
1155                               targetNameImport, targetNamePDB, configName);
1156
1157     // Compute the link library and directory information.
1158     cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
1159     if(!pcli)
1160       {
1161       return;
1162       }
1163     cmComputeLinkInformation& cli = *pcli;
1164     const char* linkLanguage = cli.GetLinkLanguage();
1165
1166     bool isWin32Executable = target.GetPropertyAsBool("WIN32_EXECUTABLE");
1167
1168     // Compute the variable name to lookup standard libraries for this
1169     // language.
1170     std::string standardLibsVar = "CMAKE_";
1171     standardLibsVar += linkLanguage;
1172     standardLibsVar += "_STANDARD_LIBRARIES";
1173     const char* tool = "VCLinkerTool";
1174     if(this->FortranProject)
1175       {
1176       tool = "VFLinkerTool";
1177       }
1178     fout << "\t\t\t<Tool\n"
1179          << "\t\t\t\tName=\"" << tool << "\"\n";
1180     if(!gg->NeedLinkLibraryDependencies(target))
1181       {
1182       fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n";
1183       }
1184     linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
1185     // Use the NOINHERIT macro to avoid getting VS project default
1186     // libraries which may be set by the user to something bad.
1187     fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
1188          << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
1189     if(this->GetVersion() < VS8)
1190       {
1191       this->Internal->OutputObjects(fout, &target, " ");
1192       }
1193     fout << " ";
1194     this->Internal->OutputLibraries(fout, cli.GetItems());
1195     fout << "\"\n";
1196     temp = target.GetDirectory(configName);
1197     temp += "/";
1198     temp += targetNameFull;
1199     fout << "\t\t\t\tOutputFile=\""
1200          << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
1201     this->WriteTargetVersionAttribute(fout, target);
1202     linkOptions.OutputFlagMap(fout, "\t\t\t\t");
1203     fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
1204     this->OutputLibraryDirectories(fout, cli.GetDirectories());
1205     fout << "\"\n";
1206     std::string path = this->ConvertToXMLOutputPathSingle(
1207       target.GetPDBDirectory(configName).c_str());
1208     fout << "\t\t\t\tProgramDatabaseFile=\""
1209          << path << "/" << targetNamePDB
1210          << "\"\n";
1211     if(targetOptions.IsDebug())
1212       {
1213       fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
1214       }
1215     if ( this->WindowsCEProject )
1216       {
1217       if(this->GetVersion() < VS9)
1218         {
1219         fout << "\t\t\t\tSubSystem=\"9\"\n";
1220         }
1221       else
1222         {
1223         fout << "\t\t\t\tSubSystem=\"8\"\n";
1224         }
1225
1226       if(!linkOptions.GetFlag("EntryPointSymbol"))
1227         {
1228         const char* entryPointSymbol = targetOptions.UsingUnicode() ?
1229           (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") :
1230           (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup");
1231         fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n";
1232         }
1233       }
1234     else if ( this->FortranProject )
1235       {
1236       fout << "\t\t\t\tSubSystem=\""
1237            << (isWin32Executable ? "subSystemWindows" : "subSystemConsole")
1238            << "\"\n";
1239       }
1240     else
1241       {
1242       fout << "\t\t\t\tSubSystem=\""
1243            << (isWin32Executable ? "2" : "1")
1244            << "\"\n";
1245       }
1246     std::string stackVar = "CMAKE_";
1247     stackVar += linkLanguage;
1248     stackVar += "_STACK_SIZE";
1249     const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
1250     if(stackVal)
1251       {
1252       fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
1253       }
1254     temp = target.GetDirectory(configName, true);
1255     temp += "/";
1256     temp += targetNameImport;
1257     fout << "\t\t\t\tImportLibrary=\""
1258          << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
1259     break;
1260     }
1261     case cmTarget::UTILITY:
1262     case cmTarget::GLOBAL_TARGET:
1263       break;
1264     }
1265 }
1266
1267 //----------------------------------------------------------------------------
1268 void
1269 cmLocalVisualStudio7Generator
1270 ::WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target)
1271 {
1272   int major;
1273   int minor;
1274   target.GetTargetVersion(major, minor);
1275   fout << "\t\t\t\tVersion=\"" << major << "." << minor << "\"\n";
1276 }
1277
1278 //----------------------------------------------------------------------------
1279 void
1280 cmLocalVisualStudio7GeneratorInternals
1281 ::OutputLibraries(std::ostream& fout, ItemVector const& libs)
1282 {
1283   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
1284   for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
1285     {
1286     if(l->IsPath)
1287       {
1288       std::string rel = lg->Convert(l->Value.c_str(),
1289                                     cmLocalGenerator::START_OUTPUT,
1290                                     cmLocalGenerator::UNCHANGED);
1291       fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
1292       }
1293     else
1294       {
1295       fout << l->Value << " ";
1296       }
1297     }
1298 }
1299
1300 //----------------------------------------------------------------------------
1301 void
1302 cmLocalVisualStudio7GeneratorInternals
1303 ::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep)
1304 {
1305   // VS < 8 does not support per-config source locations so we
1306   // list object library content on the link line instead.
1307   cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
1308   cmGeneratorTarget* gt =
1309     lg->GetGlobalGenerator()->GetGeneratorTarget(t);
1310   std::vector<std::string> objs;
1311   gt->UseObjectLibraries(objs);
1312   const char* sep = isep? isep : "";
1313   for(std::vector<std::string>::const_iterator
1314         oi = objs.begin(); oi != objs.end(); ++oi)
1315     {
1316     std::string rel = lg->Convert(oi->c_str(),
1317                                   cmLocalGenerator::START_OUTPUT,
1318                                   cmLocalGenerator::UNCHANGED);
1319     fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
1320     sep = " ";
1321     }
1322 }
1323
1324 //----------------------------------------------------------------------------
1325 void
1326 cmLocalVisualStudio7Generator
1327 ::OutputLibraryDirectories(std::ostream& fout,
1328                            std::vector<std::string> const& dirs)
1329 {
1330   const char* comma = "";
1331   for(std::vector<std::string>::const_iterator d = dirs.begin();
1332       d != dirs.end(); ++d)
1333     {
1334     // Remove any trailing slash and skip empty paths.
1335     std::string dir = *d;
1336     if(dir[dir.size()-1] == '/')
1337       {
1338       dir = dir.substr(0, dir.size()-1);
1339       }
1340     if(dir.empty())
1341       {
1342       continue;
1343       }
1344
1345     // Switch to a relative path specification if it is shorter.
1346     if(cmSystemTools::FileIsFullPath(dir.c_str()))
1347       {
1348       std::string rel = this->Convert(dir.c_str(), START_OUTPUT, UNCHANGED);
1349       if(rel.size() < dir.size())
1350         {
1351         dir = rel;
1352         }
1353       }
1354
1355     // First search a configuration-specific subdirectory and then the
1356     // original directory.
1357     fout << comma << this->ConvertToXMLOutputPath((dir+"/$(OutDir)").c_str())
1358          << "," << this->ConvertToXMLOutputPath(dir.c_str());
1359     comma = ",";
1360     }
1361 }
1362
1363 void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
1364                                                     const char *libName,
1365                                                     cmTarget &target)
1366 {
1367   // get the configurations
1368   std::vector<std::string> *configs =
1369     static_cast<cmGlobalVisualStudio7Generator *>
1370     (this->GlobalGenerator)->GetConfigurations();
1371
1372   // We may be modifying the source groups temporarily, so make a copy.
1373   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
1374
1375   // get the classes from the source lists then add them to the groups
1376   this->ModuleDefinitionFile = "";
1377   std::vector<cmSourceFile*>const & classes = target.GetSourceFiles();
1378   for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
1379       i != classes.end(); i++)
1380     {
1381     // Add the file to the list of sources.
1382     std::string source = (*i)->GetFullPath();
1383     if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF")
1384       {
1385       this->ModuleDefinitionFile = (*i)->GetFullPath();
1386       }
1387     cmSourceGroup& sourceGroup =
1388       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
1389     sourceGroup.AssignSource(*i);
1390     }
1391
1392   // open the project
1393   this->WriteProjectStart(fout, libName, target, sourceGroups);
1394   // write the configuration information
1395   this->WriteConfigurations(fout, libName, target);
1396
1397   fout << "\t<Files>\n";
1398
1399
1400   // Loop through every source group.
1401   for(unsigned int i = 0; i < sourceGroups.size(); ++i)
1402     {
1403     cmSourceGroup sg = sourceGroups[i];
1404     this->WriteGroup(&sg, target, fout, libName, configs);
1405     }
1406
1407   if(this->GetVersion() >= VS8)
1408     {
1409     // VS >= 8 support per-config source locations so we
1410     // list object library content as external objects.
1411     cmGeneratorTarget* gt =
1412       this->GlobalGenerator->GetGeneratorTarget(&target);
1413     std::vector<std::string> objs;
1414     gt->UseObjectLibraries(objs);
1415     if(!objs.empty())
1416       {
1417       // TODO: Separate sub-filter for each object library used?
1418       fout << "\t\t<Filter Name=\"Object Libraries\">\n";
1419       for(std::vector<std::string>::const_iterator
1420             oi = objs.begin(); oi != objs.end(); ++oi)
1421         {
1422         std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str());
1423         fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n";
1424         }
1425       fout << "\t\t</Filter>\n";
1426       }
1427     }
1428
1429   fout << "\t</Files>\n";
1430
1431   // Write the VCProj file's footer.
1432   this->WriteVCProjFooter(fout, target);
1433 }
1434
1435 struct cmLVS7GFileConfig
1436 {
1437   std::string ObjectName;
1438   std::string CompileFlags;
1439   std::string CompileDefs;
1440   std::string CompileDefsConfig;
1441   std::string AdditionalDeps;
1442   bool ExcludedFromBuild;
1443 };
1444
1445 class cmLocalVisualStudio7GeneratorFCInfo
1446 {
1447 public:
1448   cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
1449                                       cmTarget& target,
1450                                       cmSourceFile const& sf,
1451                                       std::vector<std::string>* configs);
1452   std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
1453 };
1454
1455 cmLocalVisualStudio7GeneratorFCInfo
1456 ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
1457                                       cmTarget& target,
1458                                       cmSourceFile const& sf,
1459                                       std::vector<std::string>* configs)
1460 {
1461   cmGeneratorTarget* gt =
1462     lg->GetGlobalGenerator()->GetGeneratorTarget(&target);
1463   std::string objectName;
1464   if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end())
1465     {
1466     objectName = gt->Objects[&sf];
1467     }
1468
1469   // Compute per-source, per-config information.
1470   for(std::vector<std::string>::iterator i = configs->begin();
1471       i != configs->end(); ++i)
1472     {
1473     std::string configUpper = cmSystemTools::UpperCase(*i);
1474     cmLVS7GFileConfig fc;
1475     bool needfc = false;
1476     if(!objectName.empty())
1477       {
1478       fc.ObjectName = objectName;
1479       needfc = true;
1480       }
1481     if(const char* cflags = sf.GetProperty("COMPILE_FLAGS"))
1482       {
1483       fc.CompileFlags = cflags;
1484       needfc = true;
1485       }
1486     if(lg->FortranProject)
1487       {
1488       switch(lg->GetFortranFormat(sf.GetProperty("Fortran_FORMAT")))
1489         {
1490         case cmLocalGenerator::FortranFormatFixed:
1491           fc.CompileFlags = "-fixed " + fc.CompileFlags;
1492           needfc = true;
1493           break;
1494         case cmLocalGenerator::FortranFormatFree:
1495           fc.CompileFlags = "-free " + fc.CompileFlags;
1496           needfc = true;
1497           break;
1498         default: break;
1499         }
1500       }
1501     if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS"))
1502       {
1503       fc.CompileDefs = cdefs;
1504       needfc = true;
1505       }
1506     std::string defPropName = "COMPILE_DEFINITIONS_";
1507     defPropName += configUpper;
1508     if(const char* ccdefs = sf.GetProperty(defPropName.c_str()))
1509       {
1510       fc.CompileDefsConfig = ccdefs;
1511       needfc = true;
1512       }
1513
1514     // Check for extra object-file dependencies.
1515     if(const char* deps = sf.GetProperty("OBJECT_DEPENDS"))
1516       {
1517       std::vector<std::string> depends;
1518       cmSystemTools::ExpandListArgument(deps, depends);
1519       const char* sep = "";
1520       for(std::vector<std::string>::iterator j = depends.begin();
1521           j != depends.end(); ++j)
1522         {
1523         fc.AdditionalDeps += sep;
1524         fc.AdditionalDeps += lg->ConvertToXMLOutputPath(j->c_str());
1525         sep = ";";
1526         needfc = true;
1527         }
1528       }
1529
1530     const char* lang =
1531       lg->GlobalGenerator->GetLanguageFromExtension
1532       (sf.GetExtension().c_str());
1533     const char* sourceLang = lg->GetSourceFileLanguage(sf);
1534     const char* linkLanguage = target.GetLinkerLanguage(i->c_str());
1535     bool needForceLang = false;
1536     // source file does not match its extension language
1537     if(lang && sourceLang && strcmp(lang, sourceLang) != 0)
1538       {
1539       needForceLang = true;
1540       lang = sourceLang;
1541       }
1542     // If HEADER_FILE_ONLY is set, we must suppress this generation in
1543     // the project file
1544     fc.ExcludedFromBuild =
1545       (sf.GetPropertyAsBool("HEADER_FILE_ONLY"));
1546     if(fc.ExcludedFromBuild)
1547       {
1548       needfc = true;
1549       }
1550
1551     // if the source file does not match the linker language
1552     // then force c or c++
1553     if(needForceLang || (linkLanguage && lang
1554                          && strcmp(lang, linkLanguage) != 0))
1555       {
1556       if(strcmp(lang, "CXX") == 0)
1557         {
1558         // force a C++ file type
1559         fc.CompileFlags += " /TP ";
1560         needfc = true;
1561         }
1562       else if(strcmp(lang, "C") == 0)
1563         {
1564         // force to c
1565         fc.CompileFlags += " /TC ";
1566         needfc = true;
1567         }
1568       }
1569
1570     if(needfc)
1571       {
1572       this->FileConfigMap[*i] = fc;
1573       }
1574     }
1575 }
1576
1577 //----------------------------------------------------------------------------
1578 std::string
1579 cmLocalVisualStudio7Generator
1580 ::ComputeLongestObjectDirectory(cmTarget& target) const
1581 {
1582   std::vector<std::string> *configs =
1583     static_cast<cmGlobalVisualStudio7Generator *>
1584     (this->GlobalGenerator)->GetConfigurations();
1585   // Compute the maximum length configuration name.
1586   std::string config_max;
1587   for(std::vector<std::string>::iterator i = configs->begin();
1588       i != configs->end(); ++i)
1589     {
1590     if(i->size() > config_max.size())
1591       {
1592       config_max = *i;
1593       }
1594     }
1595
1596   // Compute the maximum length full path to the intermediate
1597   // files directory for any configuration.  This is used to construct
1598   // object file names that do not produce paths that are too long.
1599   std::string dir_max;
1600   dir_max += this->Makefile->GetCurrentOutputDirectory();
1601   dir_max += "/";
1602   dir_max += this->GetTargetDirectory(target);
1603   dir_max += "/";
1604   dir_max += config_max;
1605   dir_max += "/";
1606   return dir_max;
1607 }
1608
1609 bool cmLocalVisualStudio7Generator
1610 ::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
1611              std::ostream &fout, const char *libName,
1612              std::vector<std::string> *configs)
1613 {
1614   const std::vector<const cmSourceFile *> &sourceFiles =
1615     sg->GetSourceFiles();
1616   std::vector<cmSourceGroup> const& children  = sg->GetGroupChildren();
1617
1618   // Write the children to temporary output.
1619   bool hasChildrenWithSources = false;
1620   cmOStringStream tmpOut;
1621   for(unsigned int i=0;i<children.size();++i)
1622     {
1623     if(this->WriteGroup(&children[i], target, tmpOut, libName, configs))
1624       {
1625       hasChildrenWithSources = true;
1626       }
1627     }
1628
1629   // If the group is empty, don't write it at all.
1630   if(sourceFiles.empty() && !hasChildrenWithSources)
1631     {
1632     return false;
1633     }
1634
1635   // If the group has a name, write the header.
1636   std::string name = sg->GetName();
1637   if(name != "")
1638     {
1639     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
1640     }
1641
1642   // Loop through each source in the source group.
1643   std::string objectName;
1644   for(std::vector<const cmSourceFile *>::const_iterator sf =
1645         sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
1646     {
1647     std::string source = (*sf)->GetFullPath();
1648     FCInfo fcinfo(this, target, *(*sf), configs);
1649
1650     if (source != libName || target.GetType() == cmTarget::UTILITY ||
1651       target.GetType() == cmTarget::GLOBAL_TARGET )
1652       {
1653       fout << "\t\t\t<File\n";
1654       std::string d = this->ConvertToXMLOutputPathSingle(source.c_str());
1655       // Tell MS-Dev what the source is.  If the compiler knows how to
1656       // build it, then it will.
1657       fout << "\t\t\t\tRelativePath=\"" << d << "\">\n";
1658       if(cmCustomCommand const* command = (*sf)->GetCustomCommand())
1659         {
1660         this->WriteCustomRule(fout, source.c_str(), *command, fcinfo);
1661         }
1662       else if(!fcinfo.FileConfigMap.empty())
1663         {
1664         const char* aCompilerTool = "VCCLCompilerTool";
1665         const char* lang = "CXX";
1666         if(this->FortranProject)
1667           {
1668           aCompilerTool = "VFFortranCompilerTool";
1669           }
1670         std::string ext = (*sf)->GetExtension();
1671         ext = cmSystemTools::LowerCase(ext);
1672         if(ext == "idl")
1673           {
1674           aCompilerTool = "VCMIDLTool";
1675           if(this->FortranProject)
1676             {
1677             aCompilerTool = "VFMIDLTool";
1678             }
1679           }
1680         if(ext == "rc")
1681           {
1682           aCompilerTool = "VCResourceCompilerTool";
1683           lang = "RC";
1684           if(this->FortranProject)
1685             {
1686             aCompilerTool = "VFResourceCompilerTool";
1687             }
1688           }
1689         if(ext == "def")
1690           {
1691           aCompilerTool = "VCCustomBuildTool";
1692           if(this->FortranProject)
1693             {
1694             aCompilerTool = "VFCustomBuildTool";
1695             }
1696           }
1697         for(std::map<cmStdString, cmLVS7GFileConfig>::const_iterator
1698               fci = fcinfo.FileConfigMap.begin();
1699             fci != fcinfo.FileConfigMap.end(); ++fci)
1700           {
1701           cmLVS7GFileConfig const& fc = fci->second;
1702           fout << "\t\t\t\t<FileConfiguration\n"
1703                << "\t\t\t\t\tName=\""  << fci->first
1704                << "|" << this->PlatformName << "\"";
1705           if(fc.ExcludedFromBuild)
1706             {
1707             fout << " ExcludedFromBuild=\"true\"";
1708             }
1709           fout << ">\n";
1710           fout << "\t\t\t\t\t<Tool\n"
1711                << "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n";
1712           if(!fc.CompileFlags.empty() ||
1713              !fc.CompileDefs.empty() ||
1714              !fc.CompileDefsConfig.empty())
1715             {
1716             Options::Tool tool = Options::Compiler;
1717             cmVS7FlagTable const* table =
1718               cmLocalVisualStudio7GeneratorFlagTable;
1719             if(this->FortranProject)
1720               {
1721               tool = Options::FortranCompiler;
1722               table = cmLocalVisualStudio7GeneratorFortranFlagTable;
1723               }
1724             Options fileOptions(this, tool, table,
1725                                 this->ExtraFlagTable);
1726             fileOptions.Parse(fc.CompileFlags.c_str());
1727             fileOptions.AddDefines(fc.CompileDefs.c_str());
1728             fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
1729             fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
1730             fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
1731             fileOptions.OutputPreprocessorDefinitions(fout,
1732                                                       "\t\t\t\t\t", "\n",
1733                                                       lang);
1734             }
1735           if(!fc.AdditionalDeps.empty())
1736             {
1737             fout << "\t\t\t\t\tAdditionalDependencies=\""
1738                  << fc.AdditionalDeps.c_str() << "\"\n";
1739             }
1740           if(!fc.ObjectName.empty())
1741             {
1742             fout << "\t\t\t\t\tObjectFile=\"$(IntDir)/"
1743                  << fc.ObjectName.c_str() << "\"\n";
1744             }
1745           fout << "\t\t\t\t\t/>\n"
1746                << "\t\t\t\t</FileConfiguration>\n";
1747           }
1748         }
1749       fout << "\t\t\t</File>\n";
1750       }
1751     }
1752
1753   // If the group has children with source files, write the children.
1754   if(hasChildrenWithSources)
1755     {
1756     fout << tmpOut.str();
1757     }
1758
1759   // If the group has a name, write the footer.
1760   if(name != "")
1761     {
1762     this->WriteVCProjEndGroup(fout);
1763     }
1764
1765   return true;
1766 }
1767
1768 void cmLocalVisualStudio7Generator::
1769 WriteCustomRule(std::ostream& fout,
1770                 const char* source,
1771                 const cmCustomCommand& command,
1772                 FCInfo& fcinfo)
1773 {
1774   std::string comment = this->ConstructComment(command);
1775
1776   // Write the rule for each configuration.
1777   std::vector<std::string>::iterator i;
1778   std::vector<std::string> *configs =
1779     static_cast<cmGlobalVisualStudio7Generator *>
1780     (this->GlobalGenerator)->GetConfigurations();
1781   const char* compileTool = "VCCLCompilerTool";
1782   if(this->FortranProject)
1783     {
1784     compileTool = "VFCLCompilerTool";
1785     }
1786   const char* customTool = "VCCustomBuildTool";
1787   if(this->FortranProject)
1788     {
1789     customTool = "VFCustomBuildTool";
1790     }
1791   for(i = configs->begin(); i != configs->end(); ++i)
1792     {
1793     cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i];
1794     fout << "\t\t\t\t<FileConfiguration\n";
1795     fout << "\t\t\t\t\tName=\"" << *i << "|" << this->PlatformName << "\">\n";
1796     if(!fc.CompileFlags.empty())
1797       {
1798       fout << "\t\t\t\t\t<Tool\n"
1799            << "\t\t\t\t\tName=\"" << compileTool << "\"\n"
1800            << "\t\t\t\t\tAdditionalOptions=\""
1801            << this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
1802       }
1803
1804     std::string script = this->ConstructScript(command, i->c_str());
1805     if(this->FortranProject)
1806       {
1807       cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str());
1808       }
1809     fout << "\t\t\t\t\t<Tool\n"
1810          << "\t\t\t\t\tName=\"" << customTool << "\"\n"
1811          << "\t\t\t\t\tDescription=\""
1812          << this->EscapeForXML(comment.c_str()) << "\"\n"
1813          << "\t\t\t\t\tCommandLine=\""
1814          << this->EscapeForXML(script.c_str()) << "\"\n"
1815          << "\t\t\t\t\tAdditionalDependencies=\"";
1816     if(command.GetDepends().empty())
1817       {
1818       // There are no real dependencies.  Produce an artificial one to
1819       // make sure the rule runs reliably.
1820       if(!cmSystemTools::FileExists(source))
1821         {
1822         std::ofstream depout(source);
1823         depout << "Artificial dependency for a custom command.\n";
1824         }
1825       fout << this->ConvertToXMLOutputPath(source);
1826       }
1827     else
1828       {
1829       // Write out the dependencies for the rule.
1830       for(std::vector<std::string>::const_iterator d =
1831           command.GetDepends().begin();
1832           d != command.GetDepends().end();
1833           ++d)
1834         {
1835         // Get the real name of the dependency in case it is a CMake target.
1836         std::string dep;
1837         if(this->GetRealDependency(d->c_str(), i->c_str(), dep))
1838           {
1839           fout << this->ConvertToXMLOutputPath(dep.c_str())
1840                << ";";
1841           }
1842         }
1843       }
1844     fout << "\"\n";
1845     fout << "\t\t\t\t\tOutputs=\"";
1846     if(command.GetOutputs().empty())
1847       {
1848       fout << source << "_force";
1849       }
1850     else
1851       {
1852       // Write a rule for the output generated by this command.
1853       const char* sep = "";
1854       for(std::vector<std::string>::const_iterator o =
1855           command.GetOutputs().begin();
1856           o != command.GetOutputs().end();
1857           ++o)
1858         {
1859         fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str());
1860         sep = ";";
1861         }
1862       }
1863     fout << "\"/>\n";
1864     fout << "\t\t\t\t</FileConfiguration>\n";
1865     }
1866 }
1867
1868
1869 void cmLocalVisualStudio7Generator::WriteVCProjBeginGroup(std::ostream& fout,
1870                                                           const char* group,
1871                                                           const char* )
1872 {
1873   fout << "\t\t<Filter\n"
1874        << "\t\t\tName=\"" << group << "\"\n"
1875        << "\t\t\tFilter=\"\">\n";
1876 }
1877
1878
1879 void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout)
1880 {
1881   fout << "\t\t</Filter>\n";
1882 }
1883
1884
1885 // look for custom rules on a target and collect them together
1886 void cmLocalVisualStudio7Generator
1887 ::OutputTargetRules(std::ostream& fout,
1888                     const char* configName,
1889                     cmTarget &target,
1890                     const char * /*libName*/)
1891 {
1892   if (target.GetType() > cmTarget::GLOBAL_TARGET)
1893     {
1894     return;
1895     }
1896   EventWriter event(this, configName, fout);
1897
1898   // Add pre-build event.
1899   const char* tool =
1900     this->FortranProject? "VFPreBuildEventTool":"VCPreBuildEventTool";
1901   event.Start(tool);
1902   event.Write(target.GetPreBuildCommands());
1903   event.Finish();
1904
1905   // Add pre-link event.
1906   tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool";
1907   event.Start(tool);
1908   event.Write(target.GetPreLinkCommands());
1909   cmsys::auto_ptr<cmCustomCommand> pcc(
1910     this->MaybeCreateImplibDir(target, configName, this->FortranProject));
1911   if(pcc.get())
1912     {
1913     event.Write(*pcc);
1914     }
1915   event.Finish();
1916
1917   // Add post-build event.
1918   tool = this->FortranProject? "VFPostBuildEventTool":"VCPostBuildEventTool";
1919   event.Start(tool);
1920   event.Write(target.GetPostBuildCommands());
1921   event.Finish();
1922 }
1923
1924 void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout,
1925                                                     cmTarget& target)
1926 {
1927   // if we have all the required Source code control tags
1928   // then add that to the project
1929   const char* vsProjectname = target.GetProperty("VS_SCC_PROJECTNAME");
1930   const char* vsLocalpath = target.GetProperty("VS_SCC_LOCALPATH");
1931   const char* vsProvider = target.GetProperty("VS_SCC_PROVIDER");
1932
1933   if(vsProvider && vsLocalpath && vsProjectname)
1934     {
1935     fout << "\tSccProjectName=\"" << vsProjectname << "\"\n"
1936          << "\tSccLocalPath=\"" << vsLocalpath << "\"\n"
1937          << "\tSccProvider=\"" << vsProvider << "\"\n";
1938
1939     const char* vsAuxPath = target.GetProperty("VS_SCC_AUXPATH");
1940     if(vsAuxPath)
1941       {
1942       fout << "\tSccAuxPath=\"" << vsAuxPath << "\"\n";
1943       }
1944     }
1945 }
1946
1947 void
1948 cmLocalVisualStudio7Generator
1949 ::WriteProjectStartFortran(std::ostream& fout,
1950                            const char *libName,
1951                            cmTarget & target)
1952 {
1953
1954   cmGlobalVisualStudio7Generator* gg =
1955     static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
1956
1957   // Compute the version of the Intel plugin to the VS IDE.
1958   // If the key does not exist then use a default guess.
1959   std::string intelVersion;
1960   std::string vskey = gg->GetRegistryBase();
1961   vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
1962   cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion,
1963                                    cmSystemTools::KeyWOW64_32);
1964   unsigned int intelVersionNumber = ~0u;
1965   sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
1966   if(intelVersionNumber >= 11)
1967     {
1968     // Default to latest known project file version.
1969     intelVersion = "11.0";
1970     }
1971   else if(intelVersionNumber == 10)
1972     {
1973     // Version 10.x actually uses 9.10 in project files!
1974     intelVersion = "9.10";
1975     }
1976   else
1977     {
1978     // Version <= 9: use ProductVersion from registry.
1979     }
1980
1981   fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
1982        << "<VisualStudioProject\n"
1983        << "\tProjectCreator=\"Intel Fortran\"\n"
1984        << "\tVersion=\"" << intelVersion << "\"\n";
1985   const char* keyword = target.GetProperty("VS_KEYWORD");
1986   if(!keyword)
1987     {
1988     keyword = "Console Application";
1989     }
1990   const char* projectType = 0;
1991   switch(target.GetType())
1992     {
1993     case cmTarget::STATIC_LIBRARY:
1994       projectType = "typeStaticLibrary";
1995       if(keyword)
1996         {
1997         keyword = "Static Library";
1998         }
1999       break;
2000     case cmTarget::SHARED_LIBRARY:
2001     case cmTarget::MODULE_LIBRARY:
2002       projectType = "typeDynamicLibrary";
2003       if(!keyword)
2004         {
2005         keyword = "Dll";
2006         }
2007       break;
2008     case cmTarget::EXECUTABLE:
2009       if(!keyword)
2010         {
2011         keyword = "Console Application";
2012         }
2013       projectType = 0;
2014       break;
2015     case cmTarget::UTILITY:
2016     case cmTarget::GLOBAL_TARGET:
2017     default:
2018       break;
2019     }
2020   if(projectType)
2021     {
2022     fout << "\tProjectType=\"" << projectType << "\"\n";
2023     }
2024   this->WriteProjectSCC(fout, target);
2025   fout<< "\tKeyword=\"" << keyword << "\">\n"
2026        << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\">\n"
2027        << "\t<Platforms>\n"
2028        << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n"
2029        << "\t</Platforms>\n";
2030 }
2031
2032
2033 void
2034 cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout,
2035                                                  const char *libName,
2036                                                  cmTarget & target,
2037                                                  std::vector<cmSourceGroup> &)
2038 {
2039   if(this->FortranProject)
2040     {
2041     this->WriteProjectStartFortran(fout, libName, target);
2042     return;
2043     }
2044   fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
2045        << "<VisualStudioProject\n"
2046        << "\tProjectType=\"Visual C++\"\n";
2047   if(this->Version == VS71)
2048     {
2049     fout << "\tVersion=\"7.10\"\n";
2050     }
2051   else
2052     {
2053     fout <<  "\tVersion=\"" << (this->Version/10) << ".00\"\n";
2054     }
2055   const char* projLabel = target.GetProperty("PROJECT_LABEL");
2056   if(!projLabel)
2057     {
2058     projLabel = libName;
2059     }
2060   const char* keyword = target.GetProperty("VS_KEYWORD");
2061   if(!keyword)
2062     {
2063     keyword = "Win32Proj";
2064     }
2065   cmGlobalVisualStudio7Generator* gg =
2066     static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
2067   fout << "\tName=\"" << projLabel << "\"\n";
2068   if(this->Version >= VS8)
2069     {
2070     fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n";
2071     }
2072   this->WriteProjectSCC(fout, target);
2073   fout << "\tKeyword=\"" << keyword << "\">\n"
2074        << "\t<Platforms>\n"
2075        << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n"
2076        << "\t</Platforms>\n";
2077 }
2078
2079
2080 void cmLocalVisualStudio7Generator::WriteVCProjFooter(std::ostream& fout,
2081                                                       cmTarget &target)
2082 {
2083   fout << "\t<Globals>\n";
2084
2085   cmPropertyMap const& props = target.GetProperties();
2086   for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i)
2087     {
2088     if(i->first.find("VS_GLOBAL_") == 0)
2089       {
2090       std::string name = i->first.substr(10);
2091       if(name != "")
2092         {
2093         fout << "\t\t<Global\n"
2094              << "\t\t\tName=\"" << name << "\"\n"
2095              << "\t\t\tValue=\"" << i->second.GetValue() << "\"\n"
2096              << "\t\t/>\n";
2097         }
2098       }
2099     }
2100
2101   fout << "\t</Globals>\n"
2102        << "</VisualStudioProject>\n";
2103 }
2104
2105 std::string cmLocalVisualStudio7GeneratorEscapeForXML(const char* s)
2106 {
2107   std::string ret = s;
2108   cmSystemTools::ReplaceString(ret, "&", "&amp;");
2109   cmSystemTools::ReplaceString(ret, "\"", "&quot;");
2110   cmSystemTools::ReplaceString(ret, "<", "&lt;");
2111   cmSystemTools::ReplaceString(ret, ">", "&gt;");
2112   cmSystemTools::ReplaceString(ret, "\n", "&#x0D;&#x0A;");
2113   return ret;
2114 }
2115
2116 std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
2117 {
2118   return cmLocalVisualStudio7GeneratorEscapeForXML(s);
2119 }
2120
2121 std::string cmLocalVisualStudio7Generator
2122 ::ConvertToXMLOutputPath(const char* path)
2123 {
2124   std::string ret = this->ConvertToOptionallyRelativeOutputPath(path);
2125   cmSystemTools::ReplaceString(ret, "&", "&amp;");
2126   cmSystemTools::ReplaceString(ret, "\"", "&quot;");
2127   cmSystemTools::ReplaceString(ret, "<", "&lt;");
2128   cmSystemTools::ReplaceString(ret, ">", "&gt;");
2129   return ret;
2130 }
2131
2132 std::string cmLocalVisualStudio7Generator
2133 ::ConvertToXMLOutputPathSingle(const char* path)
2134 {
2135   std::string ret = this->ConvertToOptionallyRelativeOutputPath(path);
2136   cmSystemTools::ReplaceString(ret, "\"", "");
2137   cmSystemTools::ReplaceString(ret, "&", "&amp;");
2138   cmSystemTools::ReplaceString(ret, "<", "&lt;");
2139   cmSystemTools::ReplaceString(ret, ">", "&gt;");
2140   return ret;
2141 }
2142
2143
2144 // This class is used to parse an existing vs 7 project
2145 // and extract the GUID
2146 class cmVS7XMLParser : public cmXMLParser
2147 {
2148 public:
2149   virtual void EndElement(const char* /* name */)
2150     {
2151     }
2152   virtual void StartElement(const char* name, const char** atts)
2153     {
2154       // once the GUID is found do nothing
2155       if(this->GUID.size())
2156         {
2157         return;
2158         }
2159       int i =0;
2160       if(strcmp("VisualStudioProject", name) == 0)
2161         {
2162         while(atts[i])
2163           {
2164           if(strcmp(atts[i], "ProjectGUID") == 0)
2165             {
2166             if(atts[i+1])
2167               {
2168               this->GUID =  atts[i+1];
2169               this->GUID = this->GUID.substr(1, this->GUID.size()-2);
2170               }
2171             else
2172               {
2173               this->GUID = "";
2174               }
2175             return;
2176             }
2177           ++i;
2178           }
2179         }
2180     }
2181   int InitializeParser()
2182     {
2183       int ret = cmXMLParser::InitializeParser();
2184       if(ret == 0)
2185         {
2186         return ret;
2187         }
2188       // visual studio projects have a strange encoding, but it is
2189       // really utf-8
2190       XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8");
2191       return 1;
2192     }
2193   std::string GUID;
2194 };
2195
2196 void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
2197   const char* name,
2198   const char* path)
2199 {
2200   cmVS7XMLParser parser;
2201   parser.ParseFile(path);
2202   // if we can not find a GUID then create one
2203   if(parser.GUID.size() == 0)
2204     {
2205     cmGlobalVisualStudio7Generator* gg =
2206       static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
2207     gg->CreateGUID(name);
2208     return;
2209     }
2210   std::string guidStoreName = name;
2211   guidStoreName += "_GUID_CMAKE";
2212   // save the GUID in the cache
2213   this->GlobalGenerator->GetCMakeInstance()->
2214     AddCacheEntry(guidStoreName.c_str(),
2215                   parser.GUID.c_str(),
2216                   "Stored GUID",
2217                   cmCacheManager::INTERNAL);
2218 }
2219
2220
2221 //----------------------------------------------------------------------------
2222 std::string cmLocalVisualStudio7Generator
2223 ::GetTargetDirectory(cmTarget const& target) const
2224 {
2225   std::string dir;
2226   dir += target.GetName();
2227   dir += ".dir";
2228   return dir;
2229 }
2230
2231 //----------------------------------------------------------------------------
2232 #include <windows.h>
2233 static bool cmLVS6G_IsFAT(const char* dir)
2234 {
2235   if(dir[0] && dir[1] == ':')
2236     {
2237     char volRoot[4] = "_:/";
2238     volRoot[0] = dir[0];
2239     char fsName[16];
2240     if(GetVolumeInformation(volRoot, 0, 0, 0, 0, 0, fsName, 16) &&
2241        strstr(fsName, "FAT") != 0)
2242       {
2243       return true;
2244       }
2245     }
2246   return false;
2247 }