cmLocalVisualStudio7Generator.cxx 77.2 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 (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
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
  std::string comment = "Building Custom Rule ";
  comment += makefileIn;
251
252
  std::string args;
  args = "-H";
Ken Martin's avatar
Ken Martin committed
253
  args += this->Convert(this->Makefile->GetHomeDirectory(), 
254
                        START_OUTPUT, UNCHANGED, true);
255
  commandLine.push_back(args);
256
  args = "-B";
Andy Cedilnik's avatar
Andy Cedilnik committed
257
  args +=
Ken Martin's avatar
Ken Martin committed
258
    this->Convert(this->Makefile->GetHomeOutputDirectory(),
259
                  START_OUTPUT, UNCHANGED, true);
260
  commandLine.push_back(args);
261
262
  commandLine.push_back("--check-stamp-file");
  commandLine.push_back(stampName.c_str());
Andy Cedilnik's avatar
Andy Cedilnik committed
263

264
  std::vector<std::string> const& listFiles = this->Makefile->GetListFiles();
265
266
267

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

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

Ken Martin's avatar
Ken Martin committed
292
293
294
295
296
297
298
299
  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";
}
300
301
302
303
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
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
355
356
357
// fill the table here currently the comment field is not used for
// anything other than documentation NOTE: Make sure the longer
// commandFlag comes FIRST!
358
359
cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
{
Andy Cedilnik's avatar
Andy Cedilnik committed
360
  // option flags (some flags map to the same option)
361
362
363
364
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
  {"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},
402
  {"WarningLevel", "W0", "Warning level", "0", 0},
403
404
405
406
  {"WarningLevel", "W1", "Warning level", "1", 0},
  {"WarningLevel", "W2", "Warning level", "2", 0},
  {"WarningLevel", "W3", "Warning level", "3", 0},
  {"WarningLevel", "W4", "Warning level", "4", 0},
407
408
  {"DisableSpecificWarnings", "wd", "Disable specific warnings", "",
   cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
409
410
411
412
413
414
415
416
417
418

  // 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},
419
420
  // The YX and Yu options are in a per-global-generator table because
  // their values differ based on the VS IDE version.
421
422
  {"ForcedIncludeFiles", "FI", "Forced include files", "",
   cmVS7FlagTable::UserValueRequired},
423

Andy Cedilnik's avatar
Andy Cedilnik committed
424
  // boolean flags
425
  {"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
426
  {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
427
428
  {"Detect64BitPortabilityProblems", "Wp64", 
   "Detect 64-bit Portability Problems", "TRUE", 0},
Bill Hoffman's avatar
Bill Hoffman committed
429
  {"EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations",
Bill Hoffman's avatar
Bill Hoffman committed
430
   "TRUE", 0},
431
432
433
434
435
436
437
438
439
440
441
  {"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
442
443
  {"RuntimeTypeInfo", "GR-",
   "Turn off Run time type information for c++", "FALSE", 0},
444
445
446
447
  {"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}
448
449
};

450
451


Bill Hoffman's avatar
Bill Hoffman committed
452
453
cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] =
{
Andy Cedilnik's avatar
Andy Cedilnik committed
454
  // option flags (some flags map to the same option)
455
456
457
458
459
460
  {"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", "",
461
  cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
462
  {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs",
463
   "TRUE", 0},
464
  {"FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0},
Bill Hoffman's avatar
Bill Hoffman committed
465
466
467
468
  {"FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address",
   "2", 0},
  {"EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs",
   "1", 0},
469
470
471
472
473
474
  {"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},
475
  {"ModuleDefinitionFile", "DEF:", "add an export def file", "",
476
477
   cmVS7FlagTable::UserValue}, 
  {"GenerateMapFile", "MAP", "enable generation of map file", "TRUE", 0},
478
  {0,0,0,0,0}
Bill Hoffman's avatar
Bill Hoffman committed
479
480
};

481
482
483
484
485
486
487
488
//----------------------------------------------------------------------------
class cmLocalVisualStudio7GeneratorOptions
{
public:
  // Construct an options table for a given tool.
  enum Tool
  {
    Compiler,
489
490
    Linker,
    FortranCompiler
491
  };
492
  cmLocalVisualStudio7GeneratorOptions(cmLocalVisualStudio7Generator* lg,
493
                                       int version,
494
                                       Tool tool,
495
                                       cmVS7FlagTable const* extraTable = 0);
496
497
498
499

  // Store options from command line flags.
  void Parse(const char* flags);

500
501
502
  // Fix the ExceptionHandling option to default to off.
  void FixExceptionHandlingDefault();

503
504
505
506
507
  // Store options for verbose builds.
  void SetVerboseMakefile(bool verbose);

  // Store definitions and flags.
  void AddDefine(const std::string& define);
508
  void AddDefines(const char* defines);
509
510
511
512
513
  void AddFlag(const char* flag, const char* value);

  // Check for specific options.
  bool UsingUnicode();

514
  bool IsDebug();
515
516
517
518
519
520
521
522
523
524
  // Write options to output.
  void OutputPreprocessorDefinitions(std::ostream& fout,
                                     const char* prefix,
                                     const char* suffix);
  void OutputFlagMap(std::ostream& fout, const char* indent);
  void OutputAdditionalOptions(std::ostream& fout,
                               const char* prefix,
                               const char* suffix);

private:
525
  cmLocalVisualStudio7Generator* LocalGenerator;
526
  int Version;
527

528
529
530
531
532
533
534
535
  // create a map of xml tags to the values they should have in the output
  // for example, "BufferSecurityCheck" = "TRUE"
  // first fill this table with the values for the configuration
  // Debug, Release, etc,
  // Then parse the command line flags specified in CMAKE_CXX_FLAGS
  // and CMAKE_C_FLAGS
  // and overwrite or add new values to this map
  std::map<cmStdString, cmStdString> FlagMap;
536

537
  // Preprocessor definitions.
538
  std::vector<std::string> Defines;
539

540
541
  // Unrecognized flags that get no special handling.
  cmStdString FlagString;
542

543
  Tool CurrentTool;
544
545
  bool DoingDefine;
  cmVS7FlagTable const* FlagTable;
546
  cmVS7FlagTable const* ExtraFlagTable;
547
  void HandleFlag(const char* flag);
548
549
  bool CheckFlagTable(cmVS7FlagTable const* table, const char* flag,
                      bool& flag_handled);
550
};
Andy Cedilnik's avatar
Andy Cedilnik committed
551

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
//----------------------------------------------------------------------------
// 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
610
void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
Bill Hoffman's avatar
Bill Hoffman committed
611
612
613
                                                       const char* configName,
                                                       const char *libName,
                                                       cmTarget &target)
Andy Cedilnik's avatar
Andy Cedilnik committed
614
{
Ken Martin's avatar
Ken Martin committed
615
  const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
Ken Martin's avatar
Ken Martin committed
616
617
618
619
620
  if(!mfcFlag)
    {
    mfcFlag = "0";
    }
  fout << "\t\t<Configuration\n"
621
       << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n"
Ken Martin's avatar
Ken Martin committed
622
623
624
625
626
       << "\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
627
  // 10 == utility
Ken Martin's avatar
Ken Martin committed
628
  const char* configType = "10";
629
  const char* projectType = 0;
630
  bool targetBuilds = true;
Ken Martin's avatar
Ken Martin committed
631
  switch(target.GetType())
Andy Cedilnik's avatar
Andy Cedilnik committed
632
    {
Ken Martin's avatar
Ken Martin committed
633
    case cmTarget::STATIC_LIBRARY:
634
      projectType = "typeStaticLibrary";
Ken Martin's avatar
Ken Martin committed
635
636
637
638
      configType = "4";
      break;
    case cmTarget::SHARED_LIBRARY:
    case cmTarget::MODULE_LIBRARY:
639
      projectType = "typeDynamicLibrary";
Ken Martin's avatar
Ken Martin committed
640
641
      configType = "2";
      break;
Andy Cedilnik's avatar
Andy Cedilnik committed
642
    case cmTarget::EXECUTABLE:
Ken Martin's avatar
Ken Martin committed
643
      configType = "1";
Andy Cedilnik's avatar
Andy Cedilnik committed
644
      break;
Ken Martin's avatar
Ken Martin committed
645
    case cmTarget::UTILITY:
646
    case cmTarget::GLOBAL_TARGET:
Ken Martin's avatar
Ken Martin committed
647
648
      configType = "10";
    default:
649
      targetBuilds = false;
Ken Martin's avatar
Ken Martin committed
650
651
      break;
    }
652
653
654
655
  if(this->FortranProject && projectType)
    {
    configType = projectType;
    }
656
  std::string flags;
657
658
  if(strcmp(configType, "10") != 0)
    {
659
    const char* linkLanguage = target.GetLinkerLanguage(configName);
660
661
    if(!linkLanguage)
      {
Ken Martin's avatar
Ken Martin committed
662
663
664
      cmSystemTools::Error
        ("CMake can not determine linker language for target:",
         target.GetName());
665
666
      return;
      }
667
668
    if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
      || strcmp(linkLanguage, "Fortran") == 0)
Andy Cedilnik's avatar
Andy Cedilnik committed
669
      {
Bill Hoffman's avatar
Bill Hoffman committed
670
671
672
      std::string baseFlagVar = "CMAKE_";
      baseFlagVar += linkLanguage;
      baseFlagVar += "_FLAGS";
Ken Martin's avatar
Ken Martin committed
673
      flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
674
675
676
      std::string flagVar = baseFlagVar + std::string("_") +
        cmSystemTools::UpperCase(configName);
      flags += " ";
Ken Martin's avatar
Ken Martin committed
677
      flags += this->Makefile->GetRequiredDefinition(flagVar.c_str());
Bill Hoffman's avatar
Bill Hoffman committed
678
      }
679
680
681
682
683
684
685
686
687
    // set the correct language
    if(strcmp(linkLanguage, "C") == 0)
      {
      flags += " /TC ";
      }
    if(strcmp(linkLanguage, "CXX") == 0)
      {
      flags += " /TP ";
      }
688
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
689

690
691
692
693
694
695
696
  // Add the target-specific flags.
  if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
    {
    flags += " ";
    flags += targetFlags;
    }

697
  std::string configUpper = cmSystemTools::UpperCase(configName);
698
699
  std::string defPropName = "COMPILE_DEFINITIONS_";
  defPropName += configUpper;
700

701
702
  // Get preprocessor definitions for this directory.
  std::string defineFlags = this->Makefile->GetDefineFlags();
703
704
705
706
707
708
  Options::Tool t = Options::Compiler;
  if(this->FortranProject)
    {
    t = Options::FortranCompiler;
    }
  Options targetOptions(this, this->Version, t, this->ExtraFlagTable);
709
  targetOptions.FixExceptionHandlingDefault();
710
711
  targetOptions.Parse(flags.c_str());
  targetOptions.Parse(defineFlags.c_str());
712
713
  targetOptions.AddDefines
    (this->Makefile->GetProperty("COMPILE_DEFINITIONS"));
714
  targetOptions.AddDefines(target.GetProperty("COMPILE_DEFINITIONS"));
715
  targetOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str()));
716
  targetOptions.AddDefines(target.GetProperty(defPropName.c_str()));
717
718
719
720
  targetOptions.SetVerboseMakefile(
    this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

  // Add a definition for the configuration name.
721
  std::string configDefine = "CMAKE_INTDIR=\"";
722
  configDefine += configName;
723
  configDefine += "\"";
724
725
  targetOptions.AddDefine(configDefine);

726
727
  // Add the export symbol definition for shared library objects.
  if(const char* exportMacro = target.GetExportMacro())
728
    {
729
    targetOptions.AddDefine(exportMacro);
730
731
    }

732
733
734
735
736
737
738
739
  // 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"
740
741
742
       << "\t\t\tConfigurationType=\"" << configType << "\"\n"
       << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n"
       << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n";
743
744
745
746

  // If unicode is enabled change the character set to unicode, if not
  // then default to MBCS.
  if(targetOptions.UsingUnicode())
747
748
749
750
751
752
753
    {
    fout << "\t\t\tCharacterSet=\"1\">\n";
    }
  else
    {
    fout << "\t\t\tCharacterSet=\"2\">\n";
    }
754
755
756
757
758
  const char* tool = "VCCLCompilerTool";
  if(this->FortranProject)
    {
    tool = "VFFortranCompilerTool";
    }
759
  fout << "\t\t\t<Tool\n"
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
       << "\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=\"" 
777
778
         << this->ConvertToXMLOutputPath(modDir.c_str())
         << "\\$(ConfigurationName)\"\n";
779
    }
780
  targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
781
  fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
782
783
  std::vector<std::string> includes;
  this->GetIncludeDirectories(includes);
784
785
786
  std::vector<std::string>::iterator i = includes.begin();
  for(;i != includes.end(); ++i)
    {
787
    // output the include path
788
789
    std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
    fout << ipath << ";";
790
791
792
793
794
795
796
797
798
    // 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 << ";";
      }
799
800
    }
  fout << "\"\n";
801
802
  targetOptions.OutputFlagMap(fout, "\t\t\t\t");
  targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
Ken Martin's avatar
Ken Martin committed
803
  fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n";
804
  fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
805
  if(targetBuilds)
Andy Cedilnik's avatar
Andy Cedilnik committed
806
    {
807
808
    // We need to specify a program database file name even for
    // non-debug configurations because VS still creates .idb files.
809
    fout <<  "\t\t\t\tProgramDataBaseFileName=\""
810
         << target.GetDirectory(configName) << "/"
811
         << target.GetPDBName(configName) << "\"\n";
Bill Hoffman's avatar
Bill Hoffman committed
812
    }
Ken Martin's avatar
Ken Martin committed
813
  fout << "/>\n";  // end of <Tool Name=VCCLCompilerTool
814
815
816
817
818
819
820
821
822
823
824
825
  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"
826
       << "\t\t\t\tAdditionalIncludeDirectories=\"";
Ken Martin's avatar
Ken Martin committed
827
828
829
830
831
  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
832
  // add the -D flags to the RC tool
833
834
835
  fout << "\"";
  targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "");
  fout << "/>\n";
836
837
838
839
840
841
  tool = "VCMIDLTool";
  if(this->FortranProject)
    {
    tool = "VFMIDLTool";
    }
  fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
842
  targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
843
  fout << "\t\t\t\tMkTypLibCompatible=\"FALSE\"\n";
844
845
846
847
848
849
850
851
852
853
854
855
  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";
    }
856
857
858
859
860
861
862
863
  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
864
865

  // Check if we need the FAT32 workaround.
866
  if(targetBuilds && this->Version >= 8)
867
    {
868
    // Check the filesystem type where the target will be written.
869
    if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str()))
870
871
872
873
      {
      // 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
874
875
876
877
878
879
880
      // bug #2617. 
      const char* tool  = "VCManifestTool";
      if(this->FortranProject)
        {
        tool = "VFManifestTool";
        }
      fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
881
882
883
           << "\t\t\t\tUseFAT32Workaround=\"true\"\n"
           << "\t\t\t/>\n";
      }
884
    }
885

Alexander Neundorf's avatar
   
Alexander Neundorf committed
886
  this->OutputTargetRules(fout, configName, target, libName);
887
  this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug());
Ken Martin's avatar
Ken Martin committed
888
889
  fout << "\t\t</Configuration>\n";
}
890

891
892
893
894
895
896
//----------------------------------------------------------------------------
std::string
cmLocalVisualStudio7Generator
::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const char* configName)
{
  std::string configTypeUpper = cmSystemTools::UpperCase(configName);
Ken Martin's avatar
Ken Martin committed
897
898
  std::string extraLinkOptionsBuildTypeDef = 
    rootLinkerFlags + "_" + configTypeUpper;
899
900

  std::string extraLinkOptionsBuildType =
Ken Martin's avatar
Ken Martin committed
901
902
    this->Makefile->GetRequiredDefinition
    (extraLinkOptionsBuildTypeDef.c_str());
903

904
905
  return extraLinkOptionsBuildType;
}
Bill Hoffman's avatar
Bill Hoffman committed
906

Ken Martin's avatar
Ken Martin committed
907
void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
Bill Hoffman's avatar
Bill Hoffman committed
908
                                                    const char* configName,
909
910
                                                    cmTarget &target,
                                                    bool isDebug)
911
{
Ken Martin's avatar
Ken Martin committed
912
  std::string temp;
Bill Hoffman's avatar
Bill Hoffman committed
913
  std::string extraLinkOptions;
914
  if(target.GetType() == cmTarget::EXECUTABLE)
Bill Hoffman's avatar
Bill Hoffman committed
915
    {
Ken Martin's avatar
Ken Martin committed
916
917
918
919
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName);
Bill Hoffman's avatar
Bill Hoffman committed
920
921
922
    }
  if(target.GetType() == cmTarget::SHARED_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
923
924
925
926
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName);
Bill Hoffman's avatar
Bill Hoffman committed
927
928
929
    }
  if(target.GetType() == cmTarget::MODULE_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
930
931
932
933
    extraLinkOptions = 
      this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") 
      + std::string(" ") 
      + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName);
Ken Martin's avatar
Ken Martin committed
934
    }
Andy Cedilnik's avatar
Andy Cedilnik committed
935

Brad King's avatar
Brad King committed
936
  const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
Bill Hoffman's avatar
Bill Hoffman committed
937
938
939
940
941
  if(targetLinkFlags)
    {
    extraLinkOptions += " ";
    extraLinkOptions += targetLinkFlags;
    }
942
943
944
945
946
947
948
949
950
  std::string configTypeUpper = cmSystemTools::UpperCase(configName);
  std::string linkFlagsConfig = "LINK_FLAGS_";
  linkFlagsConfig += configTypeUpper;
  targetLinkFlags = target.GetProperty(linkFlagsConfig.c_str());
  if(targetLinkFlags)
    {
    extraLinkOptions += " ";
    extraLinkOptions += targetLinkFlags;
    }
951
  Options linkOptions(this, this->Version, Options::Linker);
952
  linkOptions.Parse(extraLinkOptions.c_str());
Ken Martin's avatar
Ken Martin committed
953
954
955
956
  switch(target.GetType())
    {
    case cmTarget::STATIC_LIBRARY:
    {
957
    std::string targetNameFull = target.GetFullName(configName);
958
959
    std::string libpath = target.GetDirectory(configName);
    libpath += "/";
960
    libpath += targetNameFull;
961
962
963
964
965
    const char* tool = "VCLibrarianTool";
    if(this->FortranProject)
      {
      tool = "VFLibrarianTool";
      }
Bill Hoffman's avatar
Bill Hoffman committed
966
    fout << "\t\t\t<Tool\n"
967
         << "\t\t\t\tName=\"" << tool << "\"\n";
Bill Hoffman's avatar
Bill Hoffman committed
968
969
970
971
    if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
      {
      fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
      }
Andy Cedilnik's avatar
Andy Cedilnik committed
972
    fout << "\t\t\t\tOutputFile=\""
973
         << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
Bill Hoffman's avatar
Bill Hoffman committed
974
    break;
Ken Martin's avatar
Ken Martin committed
975
976
977
    }
    case cmTarget::SHARED_LIBRARY:
    case cmTarget::MODULE_LIBRARY:
Bill Hoffman's avatar
Bill Hoffman committed
978
    {
979
980
981
982
983
984
985
986
    std::string targetName;
    std::string targetNameSO;
    std::string targetNameFull;
    std::string targetNameImport;
    std::string targetNamePDB;
    target.GetLibraryNames(targetName, targetNameSO, targetNameFull,
                           targetNameImport, targetNamePDB, configName);

987
    // Compute the link library and directory information.
988
989
    cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
    if(!pcli)
990
991
992
      {
      return;
      }
993
    cmComputeLinkInformation& cli = *pcli;
994
    const char* linkLanguage = cli.GetLinkLanguage();
995
996
997
998
999
1000

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