cmLocalVisualStudio7Generator.cxx 65.8 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1
2
/*=========================================================================

3
  Program:   CMake - Cross-Platform Makefile Generator
Ken Martin's avatar
Ken Martin committed
4
5
6
7
8
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

9
10
  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
Ken Martin's avatar
Ken Martin committed
11

Andy Cedilnik's avatar
Andy Cedilnik committed
12
13
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Ken Martin's avatar
Ken Martin committed
14
15
16
17
18
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmGlobalVisualStudio7Generator.h"
#include "cmLocalVisualStudio7Generator.h"
19
20
#include "cmXMLParser.h"
#include <cm_expat.h>
Ken Martin's avatar
Ken Martin committed
21
22
23
24
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmCacheManager.h"
Ken Martin's avatar
Ken Martin committed
25
#include "cmake.h"
Ken Martin's avatar
Ken Martin committed
26

27
#include "cmComputeLinkInformation.h"
28
29
#include "cmGeneratedFileStream.h"

30
31
#include <cmsys/System.h>

32
33
#include <ctype.h> // for isspace

34
35
static bool cmLVS6G_IsFAT(const char* dir);

36
37
38
39
40
41
42
43
44
45
46
class cmLocalVisualStudio7GeneratorInternals
{
public:
  cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e):
    LocalGenerator(e) {}
  typedef cmComputeLinkInformation::ItemVector ItemVector;
  void OutputLibraries(std::ostream& fout, ItemVector const& libs);
private:
  cmLocalVisualStudio7Generator* LocalGenerator;
};

47
48
extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];

49
//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
50
51
cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator()
{
Ken Martin's avatar
Ken Martin committed
52
  this->Version = 7;
53
  this->PlatformName = "Win32";
54
  this->ExtraFlagTable = 0;
55
  this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);
Ken Martin's avatar
Ken Martin committed
56
57
58
59
}

cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
{
60
  delete this->Internal;
Ken Martin's avatar
Ken Martin committed
61
62
}

Alexander Neundorf's avatar
   
Alexander Neundorf committed
63
void cmLocalVisualStudio7Generator::AddHelperCommands()
Ken Martin's avatar
Ken Martin committed
64
{
65
66
67
  std::set<cmStdString> lang;
  lang.insert("C");
  lang.insert("CXX");
Bill Hoffman's avatar
Bill Hoffman committed
68
69
70
  lang.insert("RC");
  lang.insert("IDL");
  lang.insert("DEF");
71
  lang.insert("Fortran");
72
  this->CreateCustomTargetsAndCommands(lang);
73
  this->FixGlobalTargets();
Alexander Neundorf's avatar
   
Alexander Neundorf committed
74
75
76
77
}

void cmLocalVisualStudio7Generator::Generate()
{
78
79
  this->WriteProjectFiles();
  this->WriteStampFiles();
Ken Martin's avatar
Ken Martin committed
80
81
}

82
void cmLocalVisualStudio7Generator::FixGlobalTargets()
83
84
85
86
87
88
89
90
91
{
  // Visual Studio .NET 2003 Service Pack 1 will not run post-build
  // commands for targets in which no sources are built.  Add dummy
  // rules to force these targets to build.
  cmTargets &tgts = this->Makefile->GetTargets();
  for(cmTargets::iterator l = tgts.begin();
      l != tgts.end(); l++)
    {
    cmTarget& tgt = l->second;
92
    if(tgt.GetType() == cmTarget::GLOBAL_TARGET)
93
94
95
      {
      std::vector<std::string> no_depends;
      cmCustomCommandLine force_command;
96
97
      force_command.push_back("cd");
      force_command.push_back(".");
98
99
100
101
102
103
104
105
106
107
108
109
110
111
      cmCustomCommandLines force_commands;
      force_commands.push_back(force_command);
      const char* no_main_dependency = 0;
      std::string force = this->Makefile->GetStartOutputDirectory();
      force += cmake::GetCMakeFilesDirectory();
      force += "/";
      force += tgt.GetName();
      force += "_force";
      this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends,
                                               no_main_dependency,
                                               force_commands, " ", 0, true);
      if(cmSourceFile* file =
         this->Makefile->GetSourceFileWithOutput(force.c_str()))
        {
112
        tgt.AddSourceFile(file);
113
114
115
116
117
        }
      }
    }
}

Ken Martin's avatar
Ken Martin committed
118
119
120
// TODO
// for CommandLine= need to repleace quotes with &quot
// write out configurations
121
void cmLocalVisualStudio7Generator::WriteProjectFiles()
Andy Cedilnik's avatar
Andy Cedilnik committed
122
{
Ken Martin's avatar
Ken Martin committed
123
  // If not an in source build, then create the output directory
Ken Martin's avatar
Ken Martin committed
124
125
  if(strcmp(this->Makefile->GetStartOutputDirectory(),
            this->Makefile->GetHomeDirectory()) != 0)
Ken Martin's avatar
Ken Martin committed
126
    {
Ken Martin's avatar
Ken Martin committed
127
128
    if(!cmSystemTools::MakeDirectory
       (this->Makefile->GetStartOutputDirectory()))
Ken Martin's avatar
Ken Martin committed
129
130
      {
      cmSystemTools::Error("Error creating directory ",
Ken Martin's avatar
Ken Martin committed
131
                           this->Makefile->GetStartOutputDirectory());
Ken Martin's avatar
Ken Martin committed
132
133
      }
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
134

135
  // Get the set of targets in this directory.
Ken Martin's avatar
Ken Martin committed
136
  cmTargets &tgts = this->Makefile->GetTargets();
137
138
139

  // Create the regeneration custom rule.
  if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
140
    {
141
    // Create a rule to regenerate the build system when the target
142
    // specification source changes.
143
    if(cmSourceFile* sf = this->CreateVCProjBuildRule())
144
      {
145
146
147
148
149
150
151
152
      // Add the rule to targets that need it.
      for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
        {
        if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
          {
          l->second.AddSourceFile(sf);
          }
        }
153
      }
154
    }
155

156
  // Create the project file for each target.
Andy Cedilnik's avatar
Andy Cedilnik committed
157
  for(cmTargets::iterator l = tgts.begin();
Ken Martin's avatar
Ken Martin committed
158
159
160
161
      l != tgts.end(); l++)
    {
    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
    // so don't build a projectfile for it
162
    if(!l->second.GetProperty("EXTERNAL_MSPROJECT"))
Ken Martin's avatar
Ken Martin committed
163
164
165
166
167
168
      {
      this->CreateSingleVCProj(l->first.c_str(),l->second);
      }
    }
}

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//----------------------------------------------------------------------------
void cmLocalVisualStudio7Generator::WriteStampFiles()
{
  // Touch a timestamp file used to determine when the project file is
  // out of date.
  std::string stampName = this->Makefile->GetStartOutputDirectory();
  stampName += cmake::GetCMakeFilesDirectory();
  cmSystemTools::MakeDirectory(stampName.c_str());
  stampName += "/";
  stampName += "generate.stamp";
  std::ofstream stamp(stampName.c_str());
  stamp << "# CMake generation timestamp file this directory.\n";

  // Create a helper file so CMake can determine when it is run
  // through the rule created by CreateVCProjBuildRule whether it
  // really needs to regenerate the project.  This file lists its own
  // dependencies.  If any file listed in it is newer than itself then
  // CMake must rerun.  Otherwise the project files are up to date and
  // the stamp file can just be touched.
  std::string depName = stampName;
  depName += ".depend";
  std::ofstream depFile(depName.c_str());
  depFile << "# CMake generation dependency list for this directory.\n";
  std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
  for(std::vector<std::string>::const_iterator lf = listFiles.begin();
      lf != listFiles.end(); ++lf)
    {
    depFile << *lf << std::endl;
    }
}

//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
201
202
void cmLocalVisualStudio7Generator
::CreateSingleVCProj(const char *lname, cmTarget &target)
Ken Martin's avatar
Ken Martin committed
203
{
204
205
206
  this->FortranProject =
    static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
    ->TargetIsFortranOnly(target);
Ken Martin's avatar
Ken Martin committed
207
208
  // add to the list of projects
  std::string pname = lname;
209
  target.SetProperty("GENERATOR_FILE_NAME",lname);
Ken Martin's avatar
Ken Martin committed
210
211
  // create the dsp.cmake file
  std::string fname;
Ken Martin's avatar
Ken Martin committed
212
  fname = this->Makefile->GetStartOutputDirectory();
Ken Martin's avatar
Ken Martin committed
213
214
  fname += "/";
  fname += lname;
215
216
217
218
219
220
221
222
  if(this->FortranProject)
    {
    fname += ".vfproj";
    }
  else
    {
    fname += ".vcproj";
    }
223
224
225
226
227
228

  // Generate the project file and replace it atomically with
  // copy-if-different.  We use a separate timestamp so that the IDE
  // does not reload project files unnecessarily.
  cmGeneratedFileStream fout(fname.c_str());
  fout.SetCopyIfDifferent(true);
Ken Martin's avatar
Ken Martin committed
229
  this->WriteVCProjFile(fout,lname,target);
230
231
232
233
  if (fout.Close())
    {
    this->GlobalGenerator->FileReplacedDuringGenerate(fname);
    }
Ken Martin's avatar
Ken Martin committed
234
235
}

236
237
//----------------------------------------------------------------------------
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
Ken Martin's avatar
Ken Martin committed
238
{
239
  std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash();
240
  stampName += "generate.stamp";
Ken Martin's avatar
Ken Martin committed
241
242
  const char* dsprule = 
    this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
243
244
  cmCustomCommandLine commandLine;
  commandLine.push_back(dsprule);
Ken Martin's avatar
Ken Martin committed
245
  std::string makefileIn = this->Makefile->GetStartDirectory();
246
247
  makefileIn += "/";
  makefileIn += "CMakeLists.txt";
248
  makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str());
249
250
251
252
  if(!cmSystemTools::FileExists(makefileIn.c_str()))
    {
    return 0;
    }
253
254
  std::string comment = "Building Custom Rule ";
  comment += makefileIn;
255
256
  std::string args;
  args = "-H";
Ken Martin's avatar
Ken Martin committed
257
  args += this->Convert(this->Makefile->GetHomeDirectory(), 
258
                        START_OUTPUT, UNCHANGED, true);
259
  commandLine.push_back(args);
260
  args = "-B";
Andy Cedilnik's avatar
Andy Cedilnik committed
261
  args +=
Ken Martin's avatar
Ken Martin committed
262
    this->Convert(this->Makefile->GetHomeOutputDirectory(),
263
                  START_OUTPUT, UNCHANGED, true);
264
  commandLine.push_back(args);
265
266
  commandLine.push_back("--check-stamp-file");
  commandLine.push_back(stampName.c_str());
Andy Cedilnik's avatar
Andy Cedilnik committed
267

268
  std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
269
270
271

  cmCustomCommandLines commandLines;
  commandLines.push_back(commandLine);
272
  const char* no_working_directory = 0;
273
  this->Makefile->AddCustomCommandToOutput(stampName.c_str(), listFiles,
274
275
276
                                           makefileIn.c_str(), commandLines,
                                           comment.c_str(),
                                           no_working_directory, true);
Ken Martin's avatar
Ken Martin committed
277
  if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
278
    {
279
    return file;
280
281
282
283
    }
  else
    {
    cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
284
    return 0;
285
    }
Ken Martin's avatar
Ken Martin committed
286
287
}

Andy Cedilnik's avatar
Andy Cedilnik committed
288
void cmLocalVisualStudio7Generator::WriteConfigurations(std::ostream& fout,
Ken Martin's avatar
Ken Martin committed
289
                                                        const char *libName,
290
                                                        cmTarget &target)
Ken Martin's avatar
Ken Martin committed
291
{
Andy Cedilnik's avatar
Andy Cedilnik committed
292
  std::vector<std::string> *configs =
Ken Martin's avatar
Ken Martin committed
293
294
295
    static_cast<cmGlobalVisualStudio7Generator *>
    (this->GlobalGenerator)->GetConfigurations();

Ken Martin's avatar
Ken Martin committed
296
297
298
299
300
301
302
303
  fout << "\t<Configurations>\n";
  for( std::vector<std::string>::iterator i = configs->begin();
       i != configs->end(); ++i)
    {
    this->WriteConfiguration(fout, i->c_str(), libName, target);
    }
  fout << "\t</Configurations>\n";
}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] =
{ 
  {"Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0}, 
  {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0},
  {"DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0},
  {"DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0},
  {"DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0},
  {"DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0},
  {"Optimization", "Od", "disable optimization", "optimizeDisabled", 0},
  {"Optimization", "O1", "min space", "optimizeMinSpace", 0},
  {"Optimization", "O3", "full optimize", "optimizeFull", 0},
  {"GlobalOptimizations", "Og", "global optimize", "true", 0},
  {"InlineFunctionExpansion", "Ob0", "", "expandDisable", 0},
  {"InlineFunctionExpansion", "Ob1", "", "expandOnlyInline", 0},
  {"FavorSizeOrSpeed", "Os", "", "favorSize", 0},
  {"OmitFramePointers", "Oy-", "", "false", 0},
  {"OptimizeForProcessor", "GB", "", "procOptimizeBlended", 0},
  {"OptimizeForProcessor", "G5", "", "procOptimizePentium", 0},
  {"OptimizeForProcessor", "G6", "", "procOptimizePentiumProThruIII", 0},
  {"UseProcessorExtensions", "QzxK", "", "codeForStreamingSIMD", 0},
  {"OptimizeForProcessor", "QaxN", "", "codeForPentium4", 0},
  {"OptimizeForProcessor", "QaxB", "", "codeForPentiumM", 0},
  {"OptimizeForProcessor", "QaxP", "", "codeForCodeNamedPrescott", 0},
  {"OptimizeForProcessor", "QaxT", "", "codeForCore2Duo", 0},
  {"OptimizeForProcessor", "QxK", "", "codeExclusivelyStreamingSIMD", 0},
  {"OptimizeForProcessor", "QxN", "", "codeExclusivelyPentium4", 0},
  {"OptimizeForProcessor", "QxB", "", "codeExclusivelyPentiumM", 0},
  {"OptimizeForProcessor", "QxP", "", "codeExclusivelyCodeNamedPrescott", 0},
  {"OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0},
  {"OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD", 0},
  {"OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4", 0},

  {"ModulePath", "module:", "", "", 
   cmVS7FlagTable::UserValueRequired},
  {"LoopUnrolling", "Qunroll:", "", "", 
   cmVS7FlagTable::UserValueRequired},
  {"AutoParallelThreshold", "Qpar-threshold:", "", "", 
   cmVS7FlagTable::UserValueRequired},
  {"HeapArrays", "heap-arrays:", "", "", 
   cmVS7FlagTable::UserValueRequired},
  {"ObjectText", "bintext:", "", "", 
   cmVS7FlagTable::UserValueRequired},
  {"Parallelization", "Qparallel", "", "true", 0},
  {"PrefetchInsertion", "Qprefetch-", "", "false", 0},
  {"BufferedIO", "assume:buffered_io", "", "true", 0},
  {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
  {"CallingConvention", "iface:cref", "", "callConventionCRef", 0},
  {"CallingConvention", "iface:stdref", "", "callConventionStdRef", 0},
  {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0},
  {"CallingConvention", "iface:cvf", "", "callConventionCVF", 0},
  {"EnableRecursion", "recursive", "", "true", 0},
  {"ReentrantCode", "reentrancy", "", "true", 0},
  // done up to Language
  {0,0,0,0,0}
};
Ken Martin's avatar
Ken Martin committed
359
360
361
// fill the table here currently the comment field is not used for
// anything other than documentation NOTE: Make sure the longer
// commandFlag comes FIRST!
362
363
cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
{
Andy Cedilnik's avatar
Andy Cedilnik committed
364
  // option flags (some flags map to the same option)
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  {"BasicRuntimeChecks", "GZ", "Stack frame checks", "1", 0},
  {"BasicRuntimeChecks", "RTCsu",
   "Both stack and uninitialized checks", "3", 0},
  {"BasicRuntimeChecks", "RTCs", "Stack frame checks", "1", 0},
  {"BasicRuntimeChecks", "RTCu", "Uninitialized Variables ", "2", 0},
  {"BasicRuntimeChecks", "RTC1",
   "Both stack and uninitialized checks", "3", 0},
  {"DebugInformationFormat", "Z7", "debug format", "1", 0},
  {"DebugInformationFormat", "Zd", "debug format", "2", 0},
  {"DebugInformationFormat", "Zi", "debug format", "3", 0},
  {"DebugInformationFormat", "ZI", "debug format", "4", 0},
  {"EnableEnhancedInstructionSet", "arch:SSE2",
   "Use sse2 instructions", "2", 0},
  {"EnableEnhancedInstructionSet", "arch:SSE",
   "Use sse instructions",   "1", 0},
  {"FavorSizeOrSpeed",  "Ot", "Favor fast code",  "1", 0},
  {"FavorSizeOrSpeed",  "Os", "Favor small code", "2", 0},
  {"CompileAs", "TC", "Compile as c code",        "1", 0},
  {"CompileAs", "TP", "Compile as c++ code",      "2", 0},
  {"Optimization", "Od", "Non Debug",        "0", 0},
  {"Optimization", "O1", "Min Size",         "1", 0},
  {"Optimization", "O2", "Max Speed",        "2", 0},
  {"Optimization", "Ox", "Max Optimization", "3", 0},
  {"OptimizeForProcessor", "GB", "Blended processor mode", "0", 0},
  {"OptimizeForProcessor", "G5", "Pentium",                "1", 0},
  {"OptimizeForProcessor", "G6", "PPro PII PIII",          "2", 0},
  {"OptimizeForProcessor", "G7", "Pentium 4 or Athlon",    "3", 0},
  {"InlineFunctionExpansion", "Ob0", "no inlines",              "0", 0},
  {"InlineFunctionExpansion", "Ob1", "when inline keyword",     "1", 0},
  {"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0},
  {"RuntimeLibrary", "MTd", "Multithreded debug",     "1", 0},
  {"RuntimeLibrary", "MT", "Multithreded", "0", 0},
  {"RuntimeLibrary", "MDd", "Multithreded dll debug", "3", 0},
  {"RuntimeLibrary", "MD", "Multithreded dll",        "2", 0},
  {"RuntimeLibrary", "MLd", "Sinble Thread debug",    "5", 0},
  {"RuntimeLibrary", "ML", "Sinble Thread",           "4", 0},
  {"StructMemberAlignment", "Zp16", "struct align 16 byte ",   "5", 0},
  {"StructMemberAlignment", "Zp1", "struct align 1 byte ",     "1", 0},
  {"StructMemberAlignment", "Zp2", "struct align 2 byte ",     "2", 0},
  {"StructMemberAlignment", "Zp4", "struct align 4 byte ",     "3", 0},
  {"StructMemberAlignment", "Zp8", "struct align 8 byte ",     "4", 0},
406
  {"WarningLevel", "W0", "Warning level", "0", 0},
407
408
409
410
  {"WarningLevel", "W1", "Warning level", "1", 0},
  {"WarningLevel", "W2", "Warning level", "2", 0},
  {"WarningLevel", "W3", "Warning level", "3", 0},
  {"WarningLevel", "W4", "Warning level", "4", 0},
411
412
  {"DisableSpecificWarnings", "wd", "Disable specific warnings", "",
   cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
413
414
415
416
417
418
419
420
421
422

  // Precompiled header and related options.  Note that the
  // UsePrecompiledHeader entries are marked as "Continue" so that the
  // corresponding PrecompiledHeaderThrough entry can be found.
  {"UsePrecompiledHeader", "Yc", "Create Precompiled Header", "1",
   cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
  {"PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "",
   cmVS7FlagTable::UserValueRequired},
  {"PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "",
   cmVS7FlagTable::UserValue},
423
424
  // The YX and Yu options are in a per-global-generator table because
  // their values differ based on the VS IDE version.
425
426
  {"ForcedIncludeFiles", "FI", "Forced include files", "",
   cmVS7FlagTable::UserValueRequired},
427

Andy Cedilnik's avatar
Andy Cedilnik committed
428
  // boolean flags
429
  {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
430
  {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
431
432
  {"Detect64BitPortabilityProblems", "Wp64", 
   "Detect 64-bit Portability Problems", "TRUE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
433
  {"EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations",
Bill Hoffman's avatar
Bill Hoffman committed
434
   "TRUE", 0},
435
436
437
438
439
440
441
442
443
444
445
  {"EnableFunctionLevelLinking", "Gy",
   "EnableFunctionLevelLinking", "TRUE", 0},
  {"EnableIntrinsicFunctions", "Oi", "EnableIntrinsicFunctions", "TRUE", 0},
  {"GlobalOptimizations", "Og", "Global Optimize", "TRUE", 0},
  {"ImproveFloatingPointConsistency", "Op",
   "ImproveFloatingPointConsistency", "TRUE", 0},
  {"MinimalRebuild", "Gm", "minimal rebuild", "TRUE", 0},
  {"OmitFramePointers", "Oy", "OmitFramePointers", "TRUE", 0},
  {"OptimizeForWindowsApplication", "GA", "Optimize for windows", "TRUE", 0},
  {"RuntimeTypeInfo", "GR",
   "Turn on Run time type information for c++", "TRUE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
446
447
  {"RuntimeTypeInfo", "GR-",
   "Turn off Run time type information for c++", "FALSE", 0},
448
449
450
451
  {"SmallerTypeCheck", "RTCc", "smaller type check", "TRUE", 0},
  {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "TRUE", 0},
  {"WarnAsError", "WX", "Treat warnings as errors", "TRUE", 0},
  {0,0,0,0,0}
452
453
};

454
455


Bill Hoffman's avatar
Bill Hoffman committed
456
457
cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] =
{
Andy Cedilnik's avatar
Andy Cedilnik committed
458
  // option flags (some flags map to the same option)
459
460
461
462
463
464
  {"GenerateManifest", "MANIFEST:NO",
   "disable manifest generation", "FALSE", 0},
  {"GenerateManifest", "MANIFEST", "enable manifest generation", "TRUE", 0},
  {"LinkIncremental", "INCREMENTAL:NO", "link incremental", "1", 0},
  {"LinkIncremental", "INCREMENTAL:YES", "link incremental", "2", 0},
  {"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore", "",
465
  cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
466
  {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs",
467
   "TRUE", 0},
468
  {"FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0},
Bill Hoffman's avatar
Bill Hoffman committed
469
470
471
472
  {"FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address",
   "2", 0},
  {"EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs",
   "1", 0},
473
474
475
476
477
478
  {"EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "2", 0},
  {"OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", "1", 0},
  {"OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", "2", 0},
  {"TargetMachine", "MACHINE:I386", "Machine x86", "1", 0},
  {"TargetMachine", "MACHINE:X86", "Machine x86", "1", 0},
  {"TargetMachine", "MACHINE:X64", "Machine x64", "17", 0},
479
  {"ModuleDefinitionFile", "DEF:", "add an export def file", "",
480
481
   cmVS7FlagTable::UserValue}, 
  {"GenerateMapFile", "MAP", "enable generation of map file", "TRUE", 0},
482
  {0,0,0,0,0}
Bill Hoffman's avatar
Bill Hoffman committed
483
484
};

485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
//----------------------------------------------------------------------------
// Helper class to write build event <Tool .../> elements.
class cmLocalVisualStudio7Generator::EventWriter
{
public:
  EventWriter(cmLocalVisualStudio7Generator* lg,
              const char* config, std::ostream& os):
    LG(lg), Config(config), Stream(os), First(true) {}
  void Start(const char* tool)
    {
    this->First = true;
    this->Stream << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"";
    }
  void Finish()
    {
    this->Stream << (this->First? "" : "\"") << "/>\n";
    }
  void Write(std::vector<cmCustomCommand> const& ccs)
    {
    for(std::vector<cmCustomCommand>::const_iterator ci = ccs.begin();
        ci != ccs.end(); ++ci)
      {
      this->Write(*ci);
      }
    }
  void Write(cmCustomCommand const& cc)
    {
    if(this->First)
      {
      const char* comment = cc.GetComment();
      if(comment && *comment)
        {
        this->Stream << "\nDescription=\""
                     << this->LG->EscapeForXML(comment) << "\"";
        }
      this->Stream << "\nCommandLine=\"";
      this->First = false;
      }
    else
      {
      this->Stream << this->LG->EscapeForXML("\n");
      }
    std::string script =
      this->LG->ConstructScript(cc.GetCommandLines(),
                                cc.GetWorkingDirectory(),
                                this->Config,
                                cc.GetEscapeOldStyle(),
                                cc.GetEscapeAllowMakeVars());
    this->Stream << this->LG->EscapeForXML(script.c_str());
    }
private:
  cmLocalVisualStudio7Generator* LG;
  const char* Config;
  std::ostream& Stream;
  bool First;
};

//----------------------------------------------------------------------------
Andy Cedilnik's avatar
Andy Cedilnik committed
543
void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
Bill Hoffman's avatar
Bill Hoffman committed
544
545
546
                                                       const char* configName,
                                                       const char *libName,
                                                       cmTarget &target)
Andy Cedilnik's avatar
Andy Cedilnik committed
547
{
Ken Martin's avatar
Ken Martin committed
548
  const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
Ken Martin's avatar
Ken Martin committed
549
550
551
552
553
  if(!mfcFlag)
    {
    mfcFlag = "0";
    }
  fout << "\t\t<Configuration\n"
554
       << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n"
Ken Martin's avatar
Ken Martin committed
555
556
557
558
559
       << "\t\t\tOutputDirectory=\"" << configName << "\"\n";
  // This is an internal type to Visual Studio, it seems that:
  // 4 == static library
  // 2 == dll
  // 1 == executable
Andy Cedilnik's avatar
Andy Cedilnik committed
560
  // 10 == utility
Ken Martin's avatar
Ken Martin committed
561
  const char* configType = "10";
562
  const char* projectType = 0;
563
  bool targetBuilds = true;
Ken Martin's avatar
Ken Martin committed
564
  switch(target.GetType())
Andy Cedilnik's avatar
Andy Cedilnik committed
565
    {
Ken Martin's avatar
Ken Martin committed
566
    case cmTarget::STATIC_LIBRARY:
567
      projectType = "typeStaticLibrary";
Ken Martin's avatar
Ken Martin committed
568
569
570
571
      configType = "4";
      break;
    case cmTarget::SHARED_LIBRARY:
    case cmTarget::MODULE_LIBRARY:
572
      projectType = "typeDynamicLibrary";
Ken Martin's avatar
Ken Martin committed
573
574
      configType = "2";
      break;
Andy Cedilnik's avatar
Andy Cedilnik committed
575
    case cmTarget::EXECUTABLE:
Ken Martin's avatar
Ken Martin committed
576
      configType = "1";
Andy Cedilnik's avatar
Andy Cedilnik committed
577
      break;
Ken Martin's avatar
Ken Martin committed
578
    case cmTarget::UTILITY:
579
    case cmTarget::GLOBAL_TARGET:
Ken Martin's avatar
Ken Martin committed
580
581
      configType = "10";
    default:
582
      targetBuilds = false;
Ken Martin's avatar
Ken Martin committed
583
584
      break;
    }
585
586
587
588
  if(this->FortranProject && projectType)
    {
    configType = projectType;
    }
589
  std::string flags;
590
591
  if(strcmp(configType, "10") != 0)
    {
592
    const char* linkLanguage = target.GetLinkerLanguage(configName);
593
594
    if(!linkLanguage)
      {
Ken Martin's avatar
Ken Martin committed
595
596
597
      cmSystemTools::Error
        ("CMake can not determine linker language for target:",
         target.GetName());
598
599
      return;
      }
600
601
    if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
      || strcmp(linkLanguage, "Fortran") == 0)
Andy Cedilnik's avatar
Andy Cedilnik committed
602
      {
Bill Hoffman's avatar
Bill Hoffman committed
603
604
605
      std::string baseFlagVar = "CMAKE_";
      baseFlagVar += linkLanguage;
      baseFlagVar += "_FLAGS";
Ken Martin's avatar
Ken Martin committed
606
      flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
607
608
609
      std::string flagVar = baseFlagVar + std::string("_") +
        cmSystemTools::UpperCase(configName);
      flags += " ";
Ken Martin's avatar
Ken Martin committed
610
      flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
Bill Hoffman's avatar
Bill Hoffman committed
611
      }
612
613
614
615
616
617
618
619
620
    // set the correct language
    if(strcmp(linkLanguage, "C") == 0)
      {
      flags += " /TC ";
      }
    if(strcmp(linkLanguage, "CXX") == 0)
      {
      flags += " /TP ";
      }
621
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
622

623
624
625
626
627
628
629
  // Add the target-specific flags.
  if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
    {
    flags += " ";
    flags += targetFlags;
    }

630
  std::string configUpper = cmSystemTools::UpperCase(configName);
631
632
  std::string defPropName = "COMPILE_DEFINITIONS_";
  defPropName += configUpper;
633

634
635
  // Get preprocessor definitions for this directory.
  std::string defineFlags = this->Makefile->GetDefineFlags();
636
  Options::Tool t = Options::Compiler;
637
  cmVS7FlagTable const* table = cmLocalVisualStudio7GeneratorFlagTable;
638
639
640
  if(this->FortranProject)
    {
    t = Options::FortranCompiler;
641
    table = cmLocalVisualStudio7GeneratorFortranFlagTable;
642
    }
643
644
645
  Options targetOptions(this, this->Version, t, 
                        table,
                        this->ExtraFlagTable);
646
  targetOptions.FixExceptionHandlingDefault();
647
648
  targetOptions.Parse(flags.c_str());
  targetOptions.Parse(defineFlags.c_str());
649
650
  targetOptions.AddDefines
    (this->Makefile->GetProperty("COMPILE_DEFINITIONS"));
651
  targetOptions.AddDefines(target.GetProperty("COMPILE_DEFINITIONS"));
652
  targetOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str()));
653
  targetOptions.AddDefines(target.GetProperty(defPropName.c_str()));
654
655
656
657
  targetOptions.SetVerboseMakefile(
    this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

  // Add a definition for the configuration name.
658
  std::string configDefine = "CMAKE_INTDIR=\"";
659
  configDefine += configName;
660
  configDefine += "\"";
661
662
  targetOptions.AddDefine(configDefine);

663
664
  // Add the export symbol definition for shared library objects.
  if(const char* exportMacro = target.GetExportMacro())
665
    {
666
    targetOptions.AddDefine(exportMacro);
667
668
    }

669
670
671
672
673
674
675
676
  // The intermediate directory name consists of a directory for the
  // target and a subdirectory for the configuration name.
  std::string intermediateDir = this->GetTargetDirectory(target);
  intermediateDir += "/";
  intermediateDir += configName;
  fout << "\t\t\tIntermediateDirectory=\""
       << this->ConvertToXMLOutputPath(intermediateDir.c_str())
       << "\"\n"
677
678
679
       << "\t\t\tConfigurationType=\"" << configType << "\"\n"
       << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n"
       << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n";
680
681
682
683

  // If unicode is enabled change the character set to unicode, if not
  // then default to MBCS.
  if(targetOptions.UsingUnicode())
684
685
686
687
688
689
690
    {
    fout << "\t\t\tCharacterSet=\"1\">\n";
    }
  else
    {
    fout << "\t\t\tCharacterSet=\"2\">\n";
    }
691
692
693
694
695
  const char* tool = "VCCLCompilerTool";
  if(this->FortranProject)
    {
    tool = "VFFortranCompilerTool";
    }
696
  fout << "\t\t\t<Tool\n"
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
       << "\t\t\t\tName=\"" << tool << "\"\n";
  if(this->FortranProject)
    {
    const char* target_mod_dir =
      target.GetProperty("Fortran_MODULE_DIRECTORY"); 
    std::string modDir;
    if(target_mod_dir)
      {
      modDir = this->Convert(target_mod_dir,
                             cmLocalGenerator::START_OUTPUT,
                             cmLocalGenerator::UNCHANGED);
      }
    else
      {
      modDir = ".";
      }
    fout << "\t\t\t\tModulePath=\"" 
714
715
         << this->ConvertToXMLOutputPath(modDir.c_str())
         << "\\$(ConfigurationName)\"\n";
716
    }
717
  targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
718
  fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
719
720
  std::vector<std::string> includes;
  this->GetIncludeDirectories(includes);
721
722
723
  std::vector<std::string>::iterator i = includes.begin();
  for(;i != includes.end(); ++i)
    {
724
    // output the include path
725
726
    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
    fout << ipath << ";";
727
728
729
730
731
732
733
734
735
    // if this is fortran then output the include with 
    // a ConfigurationName on the end of it.
    if(this->FortranProject)
      {
      ipath = i->c_str();
      ipath += "/$(ConfigurationName)";
      ipath = this->ConvertToXMLOutputPath(ipath.c_str());
      fout << ipath << ";";
      }
736
737
    }
  fout << "\"\n";
738
739
  targetOptions.OutputFlagMap(fout, "\t\t\t\t");
  targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
Ken Martin's avatar
Ken Martin committed
740
  fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n";
741
  fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
742
  if(targetBuilds)
Andy Cedilnik's avatar
Andy Cedilnik committed
743
    {
744
745
    // We need to specify a program database file name even for
    // non-debug configurations because VS still creates .idb files.
746
    fout <<  "\t\t\t\tProgramDataBaseFileName=\""
747
         << target.GetDirectory(configName) << "/"
748
         << target.GetPDBName(configName) << "\"\n";
Bill Hoffman's avatar
Bill Hoffman committed
749
    }
Ken Martin's avatar
Ken Martin committed
750
  fout << "/>\n";  // end of <Tool Name=VCCLCompilerTool
751
752
753
754
755
756
757
758
759
760
761
762
  tool = "VCCustomBuildTool";
  if(this->FortranProject)
    {
    tool = "VFCustomBuildTool";
    }
  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"/>\n";
  tool = "VCResourceCompilerTool";
  if(this->FortranProject)
    {
    tool = "VFResourceCompilerTool";
    }
  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
763
       << "\t\t\t\tAdditionalIncludeDirectories=\"";
Ken Martin's avatar
Ken Martin committed
764
765
766
767
768
  for(i = includes.begin();i != includes.end(); ++i)
    {
    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
    fout << ipath << ";";
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
769
  // add the -D flags to the RC tool
770
771
772
  fout << "\"";
  targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "");
  fout << "/>\n";
773
774
775
776
777
778
  tool = "VCMIDLTool";
  if(this->FortranProject)
    {
    tool = "VFMIDLTool";
    }
  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
779
  targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
780
  fout << "\t\t\t\tMkTypLibCompatible=\"FALSE\"\n";
781
782
783
784
785
786
787
788
789
790
791
792
  if( this->PlatformName == "x64" )
    {
    fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
    }
  else if( this->PlatformName == "ia64" )
    {
    fout << "\t\t\t\tTargetEnvironment=\"2\"\n";
    }
  else
    {
    fout << "\t\t\t\tTargetEnvironment=\"1\"\n";
    }
793
794
795
796
797
798
799
800
  fout << "\t\t\t\tGenerateStublessProxies=\"TRUE\"\n";
  fout << "\t\t\t\tTypeLibraryName=\"$(InputName).tlb\"\n";
  fout << "\t\t\t\tOutputDirectory=\"$(IntDir)\"\n";
  fout << "\t\t\t\tHeaderFileName=\"$(InputName).h\"\n";
  fout << "\t\t\t\tDLLDataFileName=\"\"\n";
  fout << "\t\t\t\tInterfaceIdentifierFileName=\"$(InputName)_i.c\"\n";
  fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n";
  // end of <Tool Name=VCMIDLTool
801
802

  // Check if we need the FAT32 workaround.
803
  if(targetBuilds && this->Version >= 8)
804
    {
805
    // Check the filesystem type where the target will be written.
806
    if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
807
808
809
810
      {
      // Add a flag telling the manifest tool to use a workaround
      // for FAT32 file systems, which can cause an empty manifest
      // to be embedded into the resulting executable.  See CMake
811
812
813
814
815
816
817
      // bug #2617. 
      const char* tool  = "VCManifestTool";
      if(this->FortranProject)
        {
        tool = "VFManifestTool";
        }
      fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
818
819
820
           << "\t\t\t\tUseFAT32Workaround=\"true\"\n"
           << "\t\t\t/>\n";
      }
821
    }
822

Alexander Neundorf's avatar
   
Alexander Neundorf committed
823
  this->OutputTargetRules(fout, configName, target, libName);
824
  this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug());
Ken Martin's avatar
Ken Martin committed
825
826
  fout << "\t\t</Configuration>\n";
}
827

828
829
830
831
832
833
//----------------------------------------------------------------------------
std::string
cmLocalVisualStudio7Generator
::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const char* configName)
{
  std::string configTypeUpper = cmSystemTools::UpperCase(configName);
Ken Martin's avatar
Ken Martin committed
834
835
  std::string extraLinkOptionsBuildTypeDef = 
    rootLinkerFlags + "_" + configTypeUpper;
836
837

  std::string extraLinkOptionsBuildType =
Ken Martin's avatar
Ken Martin committed
838
839
    this->Makefile->GetRequiredDefinition
    (extraLinkOptionsBuildTypeDef.c_str());
840

841
842
  return extraLinkOptionsBuildType;
}
Bill Hoffman's avatar
Bill Hoffman committed
843

Ken Martin's avatar
Ken Martin committed
844
void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
Bill Hoffman's avatar
Bill Hoffman committed
845
                                                    const char* configName,
846
847
                                                    cmTarget &target,
                                                    bool isDebug)
848
{
Ken Martin's avatar
Ken Martin committed
849
  std::string temp;
Bill Hoffman's avatar
Bill Hoffman committed
850
  std::string extraLinkOptions;
851
  if(target.GetType() == cmTarget::EXECUTABLE)
Bill Hoffman's avatar
Bill Hoffman committed
852
    {
Ken Martin's avatar
Ken Martin committed
853
854
855
856
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
Bill Hoffman's avatar
Bill Hoffman committed
857
858
859
    }
  if(target.GetType() == cmTarget::SHARED_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
860
861
862
863
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
Bill Hoffman's avatar
Bill Hoffman committed
864
865
866
    }
  if(target.GetType() == cmTarget::MODULE_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
867
868
869
870
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
Ken Martin's avatar
Ken Martin committed
871
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
872

Brad King's avatar
Brad King committed
873
  const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
Bill Hoffman's avatar
Bill Hoffman committed
874
875
876
877
878
  if(targetLinkFlags)
    {
    extraLinkOptions += " ";
    extraLinkOptions += targetLinkFlags;
    }
879
880
881
882
883
884
885
886
887
  std::string configTypeUpper = cmSystemTools::UpperCase(configName);
  std::string linkFlagsConfig = "LINK_FLAGS_";
  linkFlagsConfig += configTypeUpper;
  targetLinkFlags = target.GetProperty(linkFlagsConfig.c_str());
  if(targetLinkFlags)
    {
    extraLinkOptions += " ";
    extraLinkOptions += targetLinkFlags;
    }
888
889
  Options linkOptions(this, this->Version, Options::Linker,
                      cmLocalVisualStudio7GeneratorLinkFlagTable);
890
  linkOptions.Parse(extraLinkOptions.c_str());
Ken Martin's avatar
Ken Martin committed
891
892
893
894
  switch(target.GetType())
    {
    case cmTarget::STATIC_LIBRARY:
    {
895
    std::string targetNameFull = target.GetFullName(configName);
896
897
    std::string libpath = target.GetDirectory(configName);
    libpath += "/";
898
    libpath += targetNameFull;
899
900
901
902
903
    const char* tool = "VCLibrarianTool";
    if(this->FortranProject)
      {
      tool = "VFLibrarianTool";
      }
Bill Hoffman's avatar
Bill Hoffman committed
904
    fout << "\t\t\t<Tool\n"
905
         << "\t\t\t\tName=\"" << tool << "\"\n";
Bill Hoffman's avatar
Bill Hoffman committed
906
907
908
909
    if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
      {
      fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
      }
Andy Cedilnik's avatar
Andy Cedilnik committed
910
    fout << "\t\t\t\tOutputFile=\""
911
         << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
Bill Hoffman's avatar
Bill Hoffman committed
912
    break;
Ken Martin's avatar
Ken Martin committed
913
914
915
    }
    case cmTarget::SHARED_LIBRARY:
    case cmTarget::MODULE_LIBRARY:
Bill Hoffman's avatar
Bill Hoffman committed
916
    {
917
918
919
920
921
922
923
924
    std::string targetName;
    std::string targetNameSO;
    std::string targetNameFull;
    std::string targetNameImport;
    std::string targetNamePDB;
    target.GetLibraryNames(targetName, targetNameSO, targetNameFull,
                           targetNameImport, targetNamePDB, configName);

925
    // Compute the link library and directory information.
926
927
    cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
    if(!pcli)
928
929
930
      {
      return;
      }
931
    cmComputeLinkInformation& cli = *pcli;
932
    const char* linkLanguage = cli.GetLinkLanguage();
933
934
935
936
937
938

    // Compute the variable name to lookup standard libraries for this
    // language.
    std::string standardLibsVar = "CMAKE_";
    standardLibsVar += linkLanguage;
    standardLibsVar += "_STANDARD_LIBRARIES";
939
940
941
942
943
    const char* tool = "VCLinkerTool";
    if(this->FortranProject)
      {
      tool = "VFLinkerTool";
      }
Bill Hoffman's avatar
Bill Hoffman committed
944
    fout << "\t\t\t<Tool\n"
945
         << "\t\t\t\tName=\"" << tool << "\"\n";
946
    linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
947
948
    // Use the NOINHERIT macro to avoid getting VS project default
    // libraries which may be set by the user to something bad.
949
    fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
950
         << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
951
         << " ";
952
    this->Internal->OutputLibraries(fout, cli.GetItems());
Bill Hoffman's avatar
Bill Hoffman committed
953
    fout << "\"\n";
954
    temp = target.GetDirectory(configName);
Bill Hoffman's avatar
Bill Hoffman committed
955
    temp += "/";
956
    temp += targetNameFull;
Andy Cedilnik's avatar
Andy Cedilnik committed
957
    fout << "\t\t\t\tOutputFile=\""
Bill Hoffman's avatar
Bill Hoffman committed
958
         << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
959
    this->WriteTargetVersionAttribute(fout, target);
960
    linkOptions.OutputFlagMap(fout, "\t\t\t\t");
Bill Hoffman's avatar
Bill Hoffman committed
961
    fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
962
    this->OutputLibraryDirectories(fout, cli.GetDirectories());
Bill Hoffman's avatar
Bill Hoffman committed
963
964
    fout << "\"\n";
    this->OutputModuleDefinitionFile(fout, target);
965
966
    temp = target.GetDirectory(configName);
    temp += "/";
967
    temp += targetNamePDB;
Bill Hoffman's avatar
Bill Hoffman committed
968
    fout << "\t\t\t\tProgramDataBaseFile=\"" <<
Bill Hoffman's avatar
Bill Hoffman committed
969
      this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
970
    if(isDebug)
Bill Hoffman's avatar
Bill Hoffman committed
971
972
      {
      fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
973
      }
Bill Hoffman's avatar
Bill Hoffman committed
974
975
976
    std::string stackVar = "CMAKE_";
    stackVar += linkLanguage;
    stackVar += "_STACK_SIZE";
Ken Martin's avatar
Ken Martin committed
977
    const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
Bill Hoffman's avatar
Bill Hoffman committed
978
    if(stackVal)
979
      {
Bill Hoffman's avatar
Bill Hoffman committed
980
981
      fout << "\t\t\t\tStackReserveSize=\"" << stackVal  << "\"\n";
      }
982
    temp = target.GetDirectory(configName, true);
Bill Hoffman's avatar
Bill Hoffman committed
983
    temp += "/";
984
985
    temp += targetNameImport;
    fout << "\t\t\t\tImportLibrary=\""
Ken Martin's avatar
Ken Martin committed
986
         << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
Bill Hoffman's avatar
Bill Hoffman committed
987
988
989
990
    }
    break;
    case cmTarget::EXECUTABLE:
    {
991
992
    std::string targetName;
    std::string targetNameFull;
993
    std::string targetNameImport;
994
995
    std::string targetNamePDB;
    target.GetExecutableNames(targetName, targetNameFull,
996
                              targetNameImport, targetNamePDB, configName);
997

998
    // Compute the link library and directory information.
999
1000
    cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
    if(!pcli)
1001
1002
1003
      {
      return;
      }
1004
    cmComputeLinkInformation& cli = *pcli;
1005
    const char* linkLanguage = cli.GetLinkLanguage();
1006
1007
1008
1009
1010
1011

    // Compute the variable name to lookup standard libraries for this
    // language.
    std::string standardLibsVar = "CMAKE_";
    standardLibsVar += linkLanguage;
    standardLibsVar += "_STANDARD_LIBRARIES";
1012
1013
1014
1015
1016
    const char* tool = "VCLinkerTool";
    if(this->FortranProject)
      {
      tool = "VFLinkerTool";
      }
Bill Hoffman's avatar
Bill Hoffman committed
1017
    fout << "\t\t\t<Tool\n"
1018
         << "\t\t\t\tName=\"" << tool << "\"\n";
1019
    linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
1020
1021
    // Use the NOINHERIT macro to avoid getting VS project default
    // libraries which may be set by the user to something bad.
1022
    fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
1023
         << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
Bill Hoffman's avatar
Bill Hoffman committed
1024
         << " ";
1025
    this->Internal->OutputLibraries(fout, cli.GetItems());
Bill Hoffman's avatar
Bill Hoffman committed
1026
    fout << "\"\n";
1027
    temp = target.GetDirectory(configName);
Bill Hoffman's avatar
Bill Hoffman committed
1028
    temp += "/";
1029
    temp += targetNameFull;
Ken Martin's avatar
Ken Martin committed
1030
1031
    fout << "\t\t\t\tOutputFile=\"" 
         << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
1032
    this->WriteTargetVersionAttribute(fout, target);
1033
    linkOptions.OutputFlagMap(fout, "\t\t\t\t");
Bill Hoffman's avatar
Bill Hoffman committed
1034
    fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
1035
    this->OutputLibraryDirectories(fout, cli.GetDirectories());
Bill Hoffman's avatar
Bill Hoffman committed
1036
    fout << "\"\n";
1037
    fout << "\t\t\t\tProgramDataBaseFile=\""
1038
         << target.GetDirectory(configName) << "/" << targetNamePDB
1039
         << "\"\n";
1040
    if(isDebug)
Bill Hoffman's avatar
Bill Hoffman committed
1041
1042
      {
      fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
1043
      }
Bill Hoffman's avatar
Bill Hoffman committed
1044
1045
1046
1047
1048
    if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
      {
      fout << "\t\t\t\tSubSystem=\"2\"\n";
      }
    else
Andy Cedilnik's avatar
Andy Cedilnik committed
1049
      {
Bill Hoffman's avatar
Bill Hoffman committed
1050
      fout << "\t\t\t\tSubSystem=\"