cmLocalVisualStudio6Generator.cxx 46.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
12
13
14
15
16
17
18
19
20
21
22

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "cmGlobalGenerator.h"
#include "cmLocalVisualStudio6Generator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmCacheManager.h"
23
#include "cmake.h"
Ken Martin's avatar
Ken Martin committed
24

25
26
#include <cmsys/RegularExpression.hxx>

Ken Martin's avatar
Ken Martin committed
27
28
29
30
31
32
33
34
35
cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
{
}

cmLocalVisualStudio6Generator::~cmLocalVisualStudio6Generator()
{
}


36
void cmLocalVisualStudio6Generator::Generate()
37
38
39
40
41
{ 
  std::set<cmStdString> lang;
  lang.insert("C");
  lang.insert("CXX");
  this->CreateCustomTargetsAndCommands(lang);
Ken Martin's avatar
Ken Martin committed
42
43
44
45
46
47
  this->OutputDSPFile();
}

void cmLocalVisualStudio6Generator::OutputDSPFile()
{ 
  // If not an in source build, then create the output directory
Ken Martin's avatar
Ken Martin committed
48
49
  if(strcmp(this->Makefile->GetStartOutputDirectory(),
            this->Makefile->GetHomeDirectory()) != 0)
Ken Martin's avatar
Ken Martin committed
50
    {
Ken Martin's avatar
Ken Martin committed
51
    if(!cmSystemTools::MakeDirectory(this->Makefile->GetStartOutputDirectory()))
Ken Martin's avatar
Ken Martin committed
52
53
      {
      cmSystemTools::Error("Error creating directory ",
Ken Martin's avatar
Ken Martin committed
54
                           this->Makefile->GetStartOutputDirectory());
Ken Martin's avatar
Ken Martin committed
55
56
57
      }
    }

58
59
60
61
62
63
  // Setup /I and /LIBPATH options for the resulting DSP file.  VS 6
  // truncates long include paths so make it as short as possible if
  // the length threatents this problem.
  unsigned int maxIncludeLength = 3000;
  bool useShortPath = false;
  for(int j=0; j < 2; ++j)
Ken Martin's avatar
Ken Martin committed
64
    {
65
66
67
68
69
    std::vector<std::string> includes;
    this->GetIncludeDirectories(includes);
    std::vector<std::string>::iterator i;
    for(i = includes.begin(); i != includes.end(); ++i)
      {
Ken Martin's avatar
Ken Martin committed
70
71
      std::string tmp = 
        this->ConvertToOptionallyRelativeOutputPath(i->c_str());
72
73
74
75
      if(useShortPath)
        {
        cmSystemTools::GetShortPath(tmp.c_str(), tmp);
        }
Ken Martin's avatar
Ken Martin committed
76
      this->IncludeOptions +=  " /I ";
Ken Martin's avatar
Ken Martin committed
77

78
79
80
      // quote if not already quoted
      if (tmp[0] != '"')
        {
Ken Martin's avatar
Ken Martin committed
81
82
83
        this->IncludeOptions += "\"";
        this->IncludeOptions += tmp;
        this->IncludeOptions += "\"";
84
85
86
        }
      else
        {
Ken Martin's avatar
Ken Martin committed
87
        this->IncludeOptions += tmp;
88
89
        }
      }
Ken Martin's avatar
Ken Martin committed
90
    if(j == 0 && this->IncludeOptions.size() > maxIncludeLength)
Ken Martin's avatar
Ken Martin committed
91
      {
Ken Martin's avatar
Ken Martin committed
92
      this->IncludeOptions = "";
93
      useShortPath = true;
Ken Martin's avatar
Ken Martin committed
94
95
96
      }
    else
      {
97
      break;
Ken Martin's avatar
Ken Martin committed
98
99
100
101
102
103
      }
    }
  
  // Create the DSP or set of DSP's for libraries and executables

  // clear project names
Ken Martin's avatar
Ken Martin committed
104
  this->CreatedProjectNames.clear();
105
  // Call TraceVSDependencies on all targets
Ken Martin's avatar
Ken Martin committed
106
  cmTargets &tgts = this->Makefile->GetTargets(); 
107
108
109
  for(cmTargets::iterator l = tgts.begin(); 
      l != tgts.end(); l++)
    {
110
111
112
    // Add a rule to regenerate the build system when the target
    // specification source changes.
    const char* suppRegenRule =
Ken Martin's avatar
Ken Martin committed
113
      this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
114
115
116
117
118
    if (!cmSystemTools::IsOn(suppRegenRule))
      {
      this->AddDSPBuildRule(l->second);
      }

119
120
121
122
123
124
125
    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
    // so don't build a projectfile for it
    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
      {
      cmTarget& target = l->second;
Ken Martin's avatar
Ken Martin committed
126
      target.TraceVSDependencies(target.GetName(), this->Makefile);
127
128
      }
    }
129

Ken Martin's avatar
Ken Martin committed
130
131
132
133
134
135
136
  // build any targets
  for(cmTargets::iterator l = tgts.begin(); 
      l != tgts.end(); l++)
    {
    switch(l->second.GetType())
      {
      case cmTarget::STATIC_LIBRARY:
Brad King's avatar
Brad King committed
137
        this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
Ken Martin's avatar
Ken Martin committed
138
139
        break;
      case cmTarget::SHARED_LIBRARY:
Ken Martin's avatar
Ken Martin committed
140
      case cmTarget::MODULE_LIBRARY:
Brad King's avatar
Brad King committed
141
        this->SetBuildType(DLL, l->first.c_str(), l->second);
Ken Martin's avatar
Ken Martin committed
142
143
        break;
      case cmTarget::EXECUTABLE:
Brad King's avatar
Brad King committed
144
        this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
Ken Martin's avatar
Ken Martin committed
145
146
        break;
      case cmTarget::UTILITY:
147
      case cmTarget::GLOBAL_TARGET:
Brad King's avatar
Brad King committed
148
        this->SetBuildType(UTILITY, l->first.c_str(), l->second);
Ken Martin's avatar
Ken Martin committed
149
150
        break;
      case cmTarget::INSTALL_FILES:
151
        break;
Ken Martin's avatar
Ken Martin committed
152
      case cmTarget::INSTALL_PROGRAMS:
153
        break;
Ken Martin's avatar
Ken Martin committed
154
      default:
155
156
        cmSystemTools::Error("Bad target type", l->first.c_str());
        break;
Ken Martin's avatar
Ken Martin committed
157
158
159
160
161
162
163
164
165
166
167
      }
    // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
    // so don't build a projectfile for it
    if ((l->second.GetType() != cmTarget::INSTALL_FILES)
        && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS)
        && (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0))
      {
      // check to see if the dsp is going into a sub-directory
      std::string::size_type pos = l->first.rfind('/');
      if(pos != std::string::npos)
        {
Ken Martin's avatar
Ken Martin committed
168
        std::string dir = this->Makefile->GetStartOutputDirectory();
Ken Martin's avatar
Ken Martin committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
        dir += "/";
        dir += l->first.substr(0, pos);
        if(!cmSystemTools::MakeDirectory(dir.c_str()))
          {
          cmSystemTools::Error("Error creating directory ", dir.c_str());
          }
        }
      this->CreateSingleDSP(l->first.c_str(),l->second);
      }
    }
}

void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname, cmTarget &target)
{
  // add to the list of projects
  std::string pname = lname;
Ken Martin's avatar
Ken Martin committed
185
  this->CreatedProjectNames.push_back(pname);
Ken Martin's avatar
Ken Martin committed
186
187
  // create the dsp.cmake file
  std::string fname;
Ken Martin's avatar
Ken Martin committed
188
  fname = this->Makefile->GetStartOutputDirectory();
Ken Martin's avatar
Ken Martin committed
189
190
191
192
193
194
195
196
197
198
  fname += "/";
  fname += lname;
  fname += ".dsp";
  // save the name of the real dsp file
  std::string realDSP = fname;
  fname += ".cmake";
  std::ofstream fout(fname.c_str());
  if(!fout)
    {
    cmSystemTools::Error("Error Writing ", fname.c_str());
199
    cmSystemTools::ReportLastSystemError("");
Ken Martin's avatar
Ken Martin committed
200
201
202
203
204
205
206
207
    }
  this->WriteDSPFile(fout,lname,target);
  fout.close();
  // if the dsp file has changed, then write it.
  cmSystemTools::CopyFileIfDifferent(fname.c_str(), realDSP.c_str());
}


208
void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt)
Ken Martin's avatar
Ken Martin committed
209
{
210
  std::string dspname = tgt.GetName();
Ken Martin's avatar
Ken Martin committed
211
  dspname += ".dsp.cmake";
Ken Martin's avatar
Ken Martin committed
212
  const char* dsprule = this->Makefile->GetRequiredDefinition("CMAKE_COMMAND");
213
214
  cmCustomCommandLine commandLine;
  commandLine.push_back(dsprule);
Ken Martin's avatar
Ken Martin committed
215
  std::string makefileIn = this->Makefile->GetStartDirectory();
216
217
  makefileIn += "/";
  makefileIn += "CMakeLists.txt";
218
219
  std::string comment = "Building Custom Rule ";
  comment += makefileIn;
220
221
  std::string args;
  args = "-H";
Ken Martin's avatar
Ken Martin committed
222
  args +=
Ken Martin's avatar
Ken Martin committed
223
    this->Convert(this->Makefile->GetHomeDirectory(),START_OUTPUT, SHELL, true);
224
  commandLine.push_back(args);
225
  args = "-B";
Ken Martin's avatar
Ken Martin committed
226
  args += 
Ken Martin's avatar
Ken Martin committed
227
    this->Convert(this->Makefile->GetHomeOutputDirectory(), 
Ken Martin's avatar
Ken Martin committed
228
                  START_OUTPUT, SHELL, true);
229
  commandLine.push_back(args);
Ken Martin's avatar
Ken Martin committed
230
231

  std::string configFile = 
Ken Martin's avatar
Ken Martin committed
232
    this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
Ken Martin's avatar
Ken Martin committed
233
  configFile += "/Templates/CMakeWindowsSystemConfig.cmake";
Ken Martin's avatar
Ken Martin committed
234
  std::vector<std::string> listFiles = this->Makefile->GetListFiles();
Ken Martin's avatar
Ken Martin committed
235
236
237
238
239
240
241
242
243
244
245
246
247
  bool found = false;
  for(std::vector<std::string>::iterator i = listFiles.begin();
      i != listFiles.end(); ++i)
    {
    if(*i == configFile)
      {
      found  = true;
      }
    }
  if(!found)
    {
    listFiles.push_back(configFile);
    }
248
249
250

  cmCustomCommandLines commandLines;
  commandLines.push_back(commandLine);
251
  const char* no_working_directory = 0;
252
253
254
255
  this->Makefile->AddCustomCommandToOutput(dspname.c_str(), listFiles,
                                           makefileIn.c_str(), commandLines,
                                           comment.c_str(),
                                           no_working_directory, true);
Ken Martin's avatar
Ken Martin committed
256
  if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
257
258
259
260
261
262
263
    {
    tgt.GetSourceFiles().push_back(file);
    }
  else
    {
    cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
    }
Ken Martin's avatar
Ken Martin committed
264
265
266
267
}


void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, 
Bill Hoffman's avatar
Bill Hoffman committed
268
269
                                                 const char *libName,
                                                 cmTarget &target)
Ken Martin's avatar
Ken Martin committed
270
{
271
272
273
274
275
276
  // For utility targets need custom command since pre- and post-
  // build does not do anything in Visual Studio 6.  In order for the
  // rules to run in the correct order as custom commands, we need
  // special care for dependencies.  The first rule must depend on all
  // the dependencies of all the rules.  The later rules must each
  // depend only on the previous rule.
277
278
  if ((target.GetType() == cmTarget::UTILITY ||
      target.GetType() == cmTarget::GLOBAL_TARGET) &&
279
280
      (!target.GetPreBuildCommands().empty() ||
       !target.GetPostBuildCommands().empty()))
281
    {
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    // Accumulate the dependencies of all the commands.
    std::vector<std::string> depends;
    for (std::vector<cmCustomCommand>::const_iterator cr =
           target.GetPreBuildCommands().begin();
         cr != target.GetPreBuildCommands().end(); ++cr)
      {
      depends.insert(depends.end(),
                     cr->GetDepends().begin(), cr->GetDepends().end());
      }
    for (std::vector<cmCustomCommand>::const_iterator cr =
           target.GetPostBuildCommands().begin();
         cr != target.GetPostBuildCommands().end(); ++cr)
      {
      depends.insert(depends.end(),
                     cr->GetDepends().begin(), cr->GetDepends().end());
      }

    // Add the pre- and post-build commands in order.
300
    int count = 1;
301
302
303
304
    for (std::vector<cmCustomCommand>::const_iterator cr =
           target.GetPreBuildCommands().begin();
         cr != target.GetPreBuildCommands().end(); ++cr)
      {
305
      this->AddUtilityCommandHack(target, count++, depends, *cr);
306
307
308
      }
    for (std::vector<cmCustomCommand>::const_iterator cr =
           target.GetPostBuildCommands().begin();
309
310
         cr != target.GetPostBuildCommands().end(); ++cr)
      {
311
      this->AddUtilityCommandHack(target, count++, depends, *cr);
312
313
      }
    }
Ken Martin's avatar
Ken Martin committed
314
315
316
317
  
  // trace the visual studio dependencies
  std::string name = libName;
  name += ".dsp.cmake";
318

Ken Martin's avatar
Ken Martin committed
319
  // We may be modifying the source groups temporarily, so make a copy.
Ken Martin's avatar
Ken Martin committed
320
  std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
Ken Martin's avatar
Ken Martin committed
321
  
Ken Martin's avatar
Ken Martin committed
322
  // get the classes from the source lists then add them to the groups
323
324
  std::vector<cmSourceFile*> & classes = target.GetSourceFiles();

Ken Martin's avatar
Ken Martin committed
325
326
  // now all of the source files have been properly assigned to the target
  // now stick them into source groups using the reg expressions
Ken Martin's avatar
Ken Martin committed
327
328
329
330
331
  for(std::vector<cmSourceFile*>::iterator i = classes.begin(); 
      i != classes.end(); i++)
    {
    // Add the file to the list of sources.
    std::string source = (*i)->GetFullPath();
Ken Martin's avatar
Ken Martin committed
332
    cmSourceGroup& sourceGroup = this->Makefile->FindSourceGroup(source.c_str(),
Ken Martin's avatar
Ken Martin committed
333
                                                             sourceGroups);
334
    sourceGroup.AssignSource(*i);
Ken Martin's avatar
Ken Martin committed
335
336
337
338
339
340
    // while we are at it, if it is a .rule file then for visual studio 6 we
    // must generate it
    if ((*i)->GetSourceExtension() == "rule")
      {
      if(!cmSystemTools::FileExists(source.c_str()))
        {
341
        cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
Ken Martin's avatar
Ken Martin committed
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#if defined(_WIN32) || defined(__CYGWIN__)
        std::ofstream fout(source.c_str(), 
                           std::ios::binary | std::ios::out | std::ios::trunc);
#else
        std::ofstream fout(source.c_str(), 
                           std::ios::out | std::ios::trunc);
#endif
        if(fout)
          {
          fout.write("# generated from CMake",22);
          fout.flush();
          fout.close();
          }
        }
      }
Ken Martin's avatar
Ken Martin committed
357
358
359
360
361
    }
  
  // Write the DSP file's header.
  this->WriteDSPHeader(fout, libName, target, sourceGroups);
  
362

Ken Martin's avatar
Ken Martin committed
363
364
365
366
  // Loop through every source group.
  for(std::vector<cmSourceGroup>::const_iterator sg = sourceGroups.begin();
      sg != sourceGroups.end(); ++sg)
    {
Bill Hoffman's avatar
Bill Hoffman committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    this->WriteGroup(&(*sg), target, fout, libName);
    }  

  // Write the DSP file's footer.
  this->WriteDSPFooter(fout);
}

void cmLocalVisualStudio6Generator::WriteGroup(const cmSourceGroup *sg, cmTarget target, std::ostream &fout, const char *libName)
{
  const std::vector<const cmSourceFile *> &sourceFiles = 
    sg->GetSourceFiles();
  // If the group is empty, don't write it at all.
        
  if(sourceFiles.empty())
    { 
    return; 
    }
    
  // If the group has a name, write the header.
  std::string name = sg->GetName();
  if(name != "")
    {
    this->WriteDSPBeginGroup(fout, name.c_str(), "");
    }
Ken Martin's avatar
Ken Martin committed
391
    
Bill Hoffman's avatar
Bill Hoffman committed
392
393
394
395
396
397
398
399
400
  // Loop through each source in the source group.
  for(std::vector<const cmSourceFile *>::const_iterator sf =
        sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
    {
    std::string source = (*sf)->GetFullPath();
    const cmCustomCommand *command = 
      (*sf)->GetCustomCommand();
    std::string compileFlags;
    std::vector<std::string> depends;
401
402
403

    // Add per-source file flags.
    if(const char* cflags = (*sf)->GetProperty("COMPILE_FLAGS"))
404
      {
405
      compileFlags += cflags;
406
407
      }

Bill Hoffman's avatar
Bill Hoffman committed
408
    const char* lang = 
Ken Martin's avatar
Ken Martin committed
409
      this->GlobalGenerator->GetLanguageFromExtension((*sf)->GetSourceExtension().c_str());
Bill Hoffman's avatar
Bill Hoffman committed
410
    if(lang && strcmp(lang, "CXX") == 0)
Ken Martin's avatar
Ken Martin committed
411
      {
Bill Hoffman's avatar
Bill Hoffman committed
412
413
414
415
416
417
418
419
420
421
      // force a C++ file type
      compileFlags += " /TP ";
      }
      
    // Check for extra object-file dependencies.
    const char* dependsValue = (*sf)->GetProperty("OBJECT_DEPENDS");
    if(dependsValue)
      {
      cmSystemTools::ExpandListArgument(dependsValue, depends);
      }
422
423
    if (source != libName || target.GetType() == cmTarget::UTILITY ||
      target.GetType() == cmTarget::GLOBAL_TARGET)
Bill Hoffman's avatar
Bill Hoffman committed
424
425
426
427
428
429
430
431
      {
      fout << "# Begin Source File\n\n";
        
      // Tell MS-Dev what the source is.  If the compiler knows how to
      // build it, then it will.
      fout << "SOURCE=" << 
        this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n";
      if(!depends.empty())
432
        {
Bill Hoffman's avatar
Bill Hoffman committed
433
434
435
436
437
438
439
440
441
        // Write out the dependencies for the rule.
        fout << "USERDEP__HACK=";
        for(std::vector<std::string>::const_iterator d = depends.begin();
            d != depends.end(); ++d)
          { 
          fout << "\\\n\t" << 
            this->ConvertToOptionallyRelativeOutputPath(d->c_str());
          }
        fout << "\n";
442
        }
Bill Hoffman's avatar
Bill Hoffman committed
443
      if (command)
444
        {
Bill Hoffman's avatar
Bill Hoffman committed
445
        std::string script =
446
447
448
          this->ConstructScript(command->GetCommandLines(), 
                                command->GetWorkingDirectory(),
                                "\\\n\t");
449
450
451
452
453
454
455
        std::string comment =
          this->ConstructComment(*command,
                                 "Building Custom Rule $(InputPath)");
        if(comment == "<hack>")
          {
          comment = "";
          }
Bill Hoffman's avatar
Bill Hoffman committed
456
        const char* flags = compileFlags.size() ? compileFlags.c_str(): 0;
457
458
459
        this->WriteCustomRule(fout, source.c_str(), script.c_str(),
                              comment.c_str(), command->GetDepends(),
                              command->GetOutputs(), flags);
Ken Martin's avatar
Ken Martin committed
460
        }
Bill Hoffman's avatar
Bill Hoffman committed
461
      else if(compileFlags.size())
Ken Martin's avatar
Ken Martin committed
462
        {
Bill Hoffman's avatar
Bill Hoffman committed
463
        for(std::vector<std::string>::iterator i
Ken Martin's avatar
Ken Martin committed
464
              = this->Configurations.begin(); i != this->Configurations.end(); ++i)
Bill Hoffman's avatar
Bill Hoffman committed
465
          { 
Ken Martin's avatar
Ken Martin committed
466
          if (i == this->Configurations.begin())
Bill Hoffman's avatar
Bill Hoffman committed
467
468
            {
            fout << "!IF  \"$(CFG)\" == " << i->c_str() << std::endl;
469
            }
Bill Hoffman's avatar
Bill Hoffman committed
470
471
472
473
474
475
476
          else 
            {
            fout << "!ELSEIF  \"$(CFG)\" == " << i->c_str() << std::endl;
            }
          fout << "\n# ADD CPP " << compileFlags << "\n\n";
          } 
        fout << "!ENDIF\n\n";
Ken Martin's avatar
Ken Martin committed
477
        }
Bill Hoffman's avatar
Bill Hoffman committed
478
      fout << "# End Source File\n";
Ken Martin's avatar
Ken Martin committed
479
      }
Bill Hoffman's avatar
Bill Hoffman committed
480
481
482
483
484
485
486
487
488
489
490
    }

  std::vector<cmSourceGroup> children  = sg->GetGroupChildren();

  for(unsigned int i=0;i<children.size();++i)
    {
    this->WriteGroup(&children[i], target, fout, libName);
    }



Ken Martin's avatar
Ken Martin committed
491
    
Bill Hoffman's avatar
Bill Hoffman committed
492
493
494
495
496
  // If the group has a name, write the footer.
  if(name != "")
    {
    this->WriteDSPEndGroup(fout);
    }
Ken Martin's avatar
Ken Martin committed
497
498
499
500

}


501
502
503
504
void
cmLocalVisualStudio6Generator
::AddUtilityCommandHack(cmTarget& target, int count,
                        std::vector<std::string>& depends,
505
                        const cmCustomCommand& origCommand)
506
507
{
  // Create a fake output that forces the rule to run.
Ken Martin's avatar
Ken Martin committed
508
  char* output = new char[(strlen(this->Makefile->GetStartOutputDirectory()) +
509
                           strlen(target.GetName()) + 30)];
Ken Martin's avatar
Ken Martin committed
510
  sprintf(output,"%s/%s_force_%i", this->Makefile->GetStartOutputDirectory(),
511
          target.GetName(), count);
512
  std::string comment = this->ConstructComment(origCommand, "<hack>");
513
514
515

  // Add the rule with the given dependencies and commands.
  const char* no_main_dependency = 0;
Ken Martin's avatar
Ken Martin committed
516
  this->Makefile->AddCustomCommandToOutput(output,
517
518
                                       depends,
                                       no_main_dependency,
519
                                       origCommand.GetCommandLines(),
520
                                       comment.c_str(),
521
                                       origCommand.GetWorkingDirectory());
522
523
524
525
526
527
528

  // Replace the dependencies with the output of this rule so that the
  // next rule added will run after this one.
  depends.clear();
  depends.push_back(output);

  // Add a source file representing this output to the project.
Ken Martin's avatar
Ken Martin committed
529
  cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output);
530
531
532
533
534
535
  target.GetSourceFiles().push_back(outsf);

  // Free the fake output name.
  delete [] output;
}

536
537
538
539
540
541
542
543
544
void
cmLocalVisualStudio6Generator
::WriteCustomRule(std::ostream& fout,
                  const char* source,
                  const char* command,
                  const char* comment,
                  const std::vector<std::string>& depends,
                  const std::vector<std::string>& outputs,
                  const char* flags)
Ken Martin's avatar
Ken Martin committed
545
{
546
  // Write the rule for each configuration.
Ken Martin's avatar
Ken Martin committed
547
  std::vector<std::string>::iterator i;
Ken Martin's avatar
Ken Martin committed
548
  for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
Ken Martin's avatar
Ken Martin committed
549
    {
Ken Martin's avatar
Ken Martin committed
550
    if (i == this->Configurations.begin())
Ken Martin's avatar
Ken Martin committed
551
552
553
554
555
556
557
558
559
560
561
562
563
      {
      fout << "!IF  \"$(CFG)\" == " << i->c_str() << std::endl;
      }
    else 
      {
      fout << "!ELSEIF  \"$(CFG)\" == " << i->c_str() << std::endl;
      }
    if(flags)
      {
      fout << "\n# ADD CPP " << flags << "\n\n";
      }
    // Write out the dependencies for the rule.
    fout << "USERDEP__HACK=";
564
    for(std::vector<std::string>::const_iterator d = depends.begin();
565
        d != depends.end(); ++d)
Ken Martin's avatar
Ken Martin committed
566
      {
567
568
569
570
      // Lookup the real name of the dependency in case it is a CMake target.
      std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
      fout << "\\\n\t" <<
        this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
Ken Martin's avatar
Ken Martin committed
571
572
573
574
      }
    fout << "\n";

    fout << "# PROP Ignore_Default_Tool 1\n";
575
576
577
578
579
580
581
    fout << "# Begin Custom Build -";
    if(comment && *comment)
      {
      fout << " " << comment;
      }
    fout << "\n\n";
    if(outputs.empty())
Ken Martin's avatar
Ken Martin committed
582
      {
Bill Hoffman's avatar
bug fix    
Bill Hoffman committed
583
      fout << source << "_force :  \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
Ken Martin's avatar
Ken Martin committed
584
585
      fout << command << "\n\n";
      }
586
587
588
589
590
591
592
593
594
595
596
    else
      {
      for(std::vector<std::string>::const_iterator o = outputs.begin();
          o != outputs.end(); ++o)
        {
        // Write a rule for every output generated by this command.
        fout << this->ConvertToOptionallyRelativeOutputPath(o->c_str())
             << " :  \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
        fout << command << "\n\n";
        }
      }
Ken Martin's avatar
Ken Martin committed
597
598
599
600
601
602
603
604
    fout << "# End Custom Build\n\n";
    }
  
  fout << "!ENDIF\n\n";
}


void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream& fout, 
Bill Hoffman's avatar
Bill Hoffman committed
605
606
                                                       const char* group,
                                                       const char* filter)
Ken Martin's avatar
Ken Martin committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
{
  fout << "# Begin Group \"" << group << "\"\n"
    "# PROP Default_Filter \"" << filter << "\"\n";
}


void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream& fout)
{
  fout << "# End Group\n";
}




Brad King's avatar
Brad King committed
621
622
void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
                                                 const char* libName,
623
                                                 cmTarget& target)
Ken Martin's avatar
Ken Martin committed
624
{
Ken Martin's avatar
Ken Martin committed
625
626
  std::string root= this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
  const char *def= this->Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
Ken Martin's avatar
Ken Martin committed
627
628
629
630
631
632
633
634
635
636
637
638
639

  if( def)
    {
    root = def;
    }
  else
    {
    root += "/Templates";
    }
  
  switch(b)
    {
    case STATIC_LIBRARY:
Ken Martin's avatar
Ken Martin committed
640
641
642
643
      this->DSPHeaderTemplate = root;
      this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
      this->DSPFooterTemplate = root;
      this->DSPFooterTemplate += "/staticLibFooter.dsptemplate";
Ken Martin's avatar
Ken Martin committed
644
645
      break;
    case DLL:
Ken Martin's avatar
Ken Martin committed
646
647
648
649
      this->DSPHeaderTemplate =  root;
      this->DSPHeaderTemplate += "/DLLHeader.dsptemplate";
      this->DSPFooterTemplate =  root;
      this->DSPFooterTemplate += "/DLLFooter.dsptemplate";
Ken Martin's avatar
Ken Martin committed
650
651
      break;
    case EXECUTABLE:
652
653
      if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
        {
Ken Martin's avatar
Ken Martin committed
654
655
656
657
        this->DSPHeaderTemplate = root;
        this->DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
        this->DSPFooterTemplate = root;
        this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
658
659
660
        }
      else
        {
Ken Martin's avatar
Ken Martin committed
661
662
663
664
        this->DSPHeaderTemplate = root;
        this->DSPHeaderTemplate += "/EXEHeader.dsptemplate";
        this->DSPFooterTemplate = root;
        this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
665
        }
Ken Martin's avatar
Ken Martin committed
666
667
      break;
    case UTILITY:
Ken Martin's avatar
Ken Martin committed
668
669
670
671
      this->DSPHeaderTemplate = root;
      this->DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
      this->DSPFooterTemplate = root;
      this->DSPFooterTemplate += "/UtilityFooter.dsptemplate";
Ken Martin's avatar
Ken Martin committed
672
673
674
675
676
      break;
    }

  // once the build type is set, determine what configurations are
  // possible
Ken Martin's avatar
Ken Martin committed
677
  std::ifstream fin(this->DSPHeaderTemplate.c_str());
Ken Martin's avatar
Ken Martin committed
678

679
  cmsys::RegularExpression reg("# Name ");
Ken Martin's avatar
Ken Martin committed
680
681
  if(!fin)
    {
Ken Martin's avatar
Ken Martin committed
682
    cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
Ken Martin's avatar
Ken Martin committed
683
684
    }

Ken Martin's avatar
Ken Martin committed
685
686
  // reset this->Configurations
  this->Configurations.erase(this->Configurations.begin(), this->Configurations.end());
Ken Martin's avatar
Ken Martin committed
687
  // now add all the configurations possible
688
689
  std::string line;
  while(cmSystemTools::GetLineFromStream(fin, line))
Ken Martin's avatar
Ken Martin committed
690
691
692
693
    {
    cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
    if (reg.find(line))
      {
Ken Martin's avatar
Ken Martin committed
694
      this->Configurations.push_back(line.substr(reg.end()));
Ken Martin's avatar
Ken Martin committed
695
696
697
698
699
700
      }
    }
}

// look for custom rules on a target and collect them together
std::string 
701
cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget &target, 
Ken Martin's avatar
Ken Martin committed
702
                                                 const char * /* libName */)
Ken Martin's avatar
Ken Martin committed
703
704
705
{
  std::string customRuleCode = "";

706
  if (target.GetType() >= cmTarget::UTILITY )
Ken Martin's avatar
Ken Martin committed
707
708
709
    {
    return customRuleCode;
    }
710
711
712
713
714
715
716
717
718
719

  // are there any rules?
  if (target.GetPreBuildCommands().size() + 
      target.GetPreLinkCommands().size() + 
      target.GetPostBuildCommands().size() == 0)
    {
    return customRuleCode;
    }
    
  customRuleCode = "# Begin Special Build Tool\n";
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

  // Write the pre-build and pre-link together (VS6 does not support
  // both).  Make sure no continuation character is put on the last
  // line.
  int prelink_total = (static_cast<int>(target.GetPreBuildCommands().size())+
                       static_cast<int>(target.GetPreLinkCommands().size()));
  int prelink_count = 0;
  if(prelink_total > 0)
    {
    // header stuff
    customRuleCode += "PreLink_Cmds=";
    }
  const char* prelink_newline = "\\\n\t";
  for (std::vector<cmCustomCommand>::const_iterator cr =
         target.GetPreBuildCommands().begin();
735
       cr != target.GetPreBuildCommands().end(); ++cr)
Ken Martin's avatar
Ken Martin committed
736
    {
737
    if(++prelink_count == prelink_total)
Ken Martin's avatar
Ken Martin committed
738
      {
739
      prelink_newline = "";
740
      }
741
    customRuleCode += this->ConstructScript(cr->GetCommandLines(),
742
                                            cr->GetWorkingDirectory(),
743
                                            prelink_newline);
Ken Martin's avatar
Ken Martin committed
744
    }
745
746
  for (std::vector<cmCustomCommand>::const_iterator cr =
         target.GetPreLinkCommands().begin();
747
       cr != target.GetPreLinkCommands().end(); ++cr)
Ken Martin's avatar
Ken Martin committed
748
    {
749
    if(++prelink_count == prelink_total)
750
      {
751
      prelink_newline = "";
752
      }
753
    customRuleCode += this->ConstructScript(cr->GetCommandLines(),
754
                                            cr->GetWorkingDirectory(),
755
                                            prelink_newline);
Ken Martin's avatar
Ken Martin committed
756
    }
757
  if(prelink_total > 0)
Ken Martin's avatar
Ken Martin committed
758
759
760
    {
    customRuleCode += "\n";
    }
761
762
763
764
765
766
767
768
769
770
771
772

  // Write the post-build rules.  Make sure no continuation character
  // is put on the last line.
  int postbuild_total = static_cast<int>(target.GetPostBuildCommands().size());
  int postbuild_count = 0;
  const char* postbuild_newline = "\\\n\t";
  if(postbuild_total > 0)
    {
    customRuleCode += "PostBuild_Cmds=";
    }
  for (std::vector<cmCustomCommand>::const_iterator cr =
         target.GetPostBuildCommands().begin();
773
774
       cr != target.GetPostBuildCommands().end(); ++cr)
    {
775
    if(++postbuild_count == postbuild_total)
776
      {
777
      postbuild_newline = "";
778
      }
779
    customRuleCode += this->ConstructScript(cr->GetCommandLines(),
780
                                            cr->GetWorkingDirectory(),
781
782
783
784
785
                                            postbuild_newline);
    }
  if(postbuild_total > 0)
    {
    customRuleCode += "\n";
786
787
    }

788
  customRuleCode += "# End Special Build Tool\n";
Ken Martin's avatar
Ken Martin committed
789
790
791
792
793
794
795
796
797
798
799
800
801
  return customRuleCode;
}


inline std::string removeQuotes(const std::string& s)
{
  if(s[0] == '\"' && s[s.size()-1] == '\"')
    {
    return s.substr(1, s.size()-2);
    }
  return s;
}

802
803
804
805
806
// Code in blocks surrounded by a test for this definition is needed
// only for compatibility with user project's replacement DSP
// templates.  The CMake templates no longer use them.
#define CM_USE_OLD_VS6

807
808
void cmLocalVisualStudio6Generator
::WriteDSPHeader(std::ostream& fout, 
809
                 const char *libName, cmTarget &target, 
810
                 std::vector<cmSourceGroup> &)
Ken Martin's avatar
Ken Martin committed
811
{
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
  // Lookup the library and executable output directories.
  std::string libPath;
  if(this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
    {
    libPath = this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
    }
  std::string exePath;
  if(this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
    {
    exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
    }

  // Make sure there are trailing slashes.
  if(!libPath.empty())
    {
    if(libPath[libPath.size()-1] != '/')
      {
      libPath += "/";
      }
    }
  if(!exePath.empty())
    {
    if(exePath[exePath.size()-1] != '/')
      {
      exePath += "/";
      }
    }

#ifdef CM_USE_OLD_VS6
Ken Martin's avatar
Ken Martin committed
841
842
843
844
845
846
847
848
  std::set<std::string> pathEmitted;
  
  // determine the link directories
  std::string libOptions;
  std::string libDebugOptions;
  std::string libOptimizedOptions;

  std::string libMultiLineOptions;
849
  std::string libMultiLineOptionsForDebug;
Ken Martin's avatar
Ken Martin committed
850
851
852
853
854
855
  std::string libMultiLineDebugOptions;
  std::string libMultiLineOptimizedOptions;

  if(libPath.size())
    {
    std::string lpath = 
856
      this->ConvertToOptionallyRelativeOutputPath(libPath.c_str());
857
858
859
860
    if(lpath.size() == 0)
      {
      lpath = ".";
      }
Ken Martin's avatar
Ken Martin committed
861
    std::string lpathIntDir = libPath + "$(INTDIR)";
862
    lpathIntDir =  this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
Ken Martin's avatar
Ken Martin committed
863
864
865
866
867
868
869
870
871
872
873
874
875
876
    if(pathEmitted.insert(lpath).second)
      {
      libOptions += " /LIBPATH:";
      libOptions += lpathIntDir;
      libOptions += " ";
      libOptions += " /LIBPATH:";
      libOptions += lpath;
      libOptions += " ";
      libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptions += lpathIntDir;
      libMultiLineOptions += " ";
      libMultiLineOptions += " /LIBPATH:";
      libMultiLineOptions += lpath;
      libMultiLineOptions += " \n";
877
878
879
880
881
882
      libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptionsForDebug += lpathIntDir;
      libMultiLineOptionsForDebug += " ";
      libMultiLineOptionsForDebug += " /LIBPATH:";
      libMultiLineOptionsForDebug += lpath;
      libMultiLineOptionsForDebug += " \n";
Ken Martin's avatar
Ken Martin committed
883
884
885
886
887
      }
    }
  if(exePath.size())
    {
    std::string lpath = 
888
      this->ConvertToOptionallyRelativeOutputPath(exePath.c_str());
889
890
891
892
    if(lpath.size() == 0)
      {
      lpath = ".";
      }
Ken Martin's avatar
Ken Martin committed
893
    std::string lpathIntDir = exePath + "$(INTDIR)";
894
    lpathIntDir =  this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
Ken Martin's avatar
Ken Martin committed
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
    
    if(pathEmitted.insert(lpath).second)
      {
      libOptions += " /LIBPATH:";
      libOptions += lpathIntDir;
      libOptions += " ";
      libOptions += " /LIBPATH:";
      libOptions += lpath;
      libOptions += " ";
      libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptions += lpathIntDir;
      libMultiLineOptions += " ";
      libMultiLineOptions += " /LIBPATH:";
      libMultiLineOptions += lpath;
      libMultiLineOptions += " \n";
910
911
912
913
914
915
      libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptionsForDebug += lpathIntDir;
      libMultiLineOptionsForDebug += " ";
      libMultiLineOptionsForDebug += " /LIBPATH:";
      libMultiLineOptionsForDebug += lpath;
      libMultiLineOptionsForDebug += " \n";
Ken Martin's avatar
Ken Martin committed
916
917
918
919
920
921
922
923
924
925
926
927
      }
    }
  std::vector<std::string>::const_iterator i;
  const std::vector<std::string>& libdirs = target.GetLinkDirectories();
  for(i = libdirs.begin(); i != libdirs.end(); ++i)
    {
    std::string path = *i;
    if(path[path.size()-1] != '/')
      {
      path += "/";
      }
    std::string lpath = 
928
      this->ConvertToOptionallyRelativeOutputPath(path.c_str());
929
930
931
932
    if(lpath.size() == 0)
      {
      lpath = ".";
      }
Ken Martin's avatar
Ken Martin committed
933
    std::string lpathIntDir = path + "$(INTDIR)";
934
    lpathIntDir =  this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
Ken Martin's avatar
Ken Martin committed
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
    if(pathEmitted.insert(lpath).second)
      {
      libOptions += " /LIBPATH:";
      libOptions += lpathIntDir;
      libOptions += " ";
      libOptions += " /LIBPATH:";
      libOptions += lpath;
      libOptions += " ";
      
      libMultiLineOptions += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptions += lpathIntDir;
      libMultiLineOptions += " ";
      libMultiLineOptions += " /LIBPATH:";
      libMultiLineOptions += lpath;
      libMultiLineOptions += " \n";
950
951
952
953
954
955
      libMultiLineOptionsForDebug += "# ADD LINK32 /LIBPATH:";
      libMultiLineOptionsForDebug += lpathIntDir;
      libMultiLineOptionsForDebug += " ";
      libMultiLineOptionsForDebug += " /LIBPATH:";
      libMultiLineOptionsForDebug += lpath;
      libMultiLineOptionsForDebug += " \n";
Ken Martin's avatar
Ken Martin committed
956
957
958
      }
    }
  // find link libraries
Ken Martin's avatar
Ken Martin committed
959
960
  const cmTarget::LinkLibraryVectorType& libs = target.GetLinkLibraries();
  cmTarget::LinkLibraryVectorType::const_iterator j;
Ken Martin's avatar
Ken Martin committed
961
962
963
964
  for(j = libs.begin(); j != libs.end(); ++j)
    {
    // add libraries to executables and dlls (but never include
    // a library in a library, bad recursion)
965
    // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
Ken Martin's avatar
Ken Martin committed
966
    if ((target.GetType() != cmTarget::SHARED_LIBRARY
Ken Martin's avatar
Ken Martin committed
967
968
969
970
         && target.GetType() != cmTarget::STATIC_LIBRARY 
         && target.GetType() != cmTarget::MODULE_LIBRARY) || 
        (target.GetType()==cmTarget::SHARED_LIBRARY && libName != j->first) ||
        (target.GetType()==cmTarget::MODULE_LIBRARY && libName != j->first))
Ken Martin's avatar
Ken Martin committed
971
      {
972
973
974
      // Compute the proper name to use to link this library.
      std::string lib;
      std::string libDebug;
Ken Martin's avatar
Ken Martin committed
975
      cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
976
      if(tgt)
Ken Martin's avatar
Ken Martin committed
977
        {
978
979
        lib = cmSystemTools::GetFilenameWithoutExtension(tgt->GetFullName().c_str());
        libDebug = cmSystemTools::GetFilenameWithoutExtension(tgt->GetFullName("Debug").c_str());
Ken Martin's avatar
Ken Martin committed
980
        lib += ".lib";
981
        libDebug += ".lib";
Ken Martin's avatar
Ken Martin committed
982
        }
983
984
985
986
987
988
989
990
991
992
      else
        {
        lib = j->first.c_str();
        libDebug = j->first.c_str();
        if(j->first.find(".lib") == std::string::npos)
          {
          lib += ".lib";
          libDebug += ".lib";
          }
        }
993
994
      lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
      libDebug = this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
995

Ken Martin's avatar
Ken Martin committed
996
997
998
999
1000
1001
1002
      if (j->second == cmTarget::GENERAL)
        {
        libOptions += " ";
        libOptions += lib;
        libMultiLineOptions += "# ADD LINK32 ";
        libMultiLineOptions +=  lib;
        libMultiLineOptions += "\n";
1003
1004
1005
        libMultiLineOptionsForDebug += "# ADD LINK32 ";
        libMultiLineOptionsForDebug +=  libDebug;
        libMultiLineOptionsForDebug += "\n";
Ken Martin's avatar
Ken Martin committed
1006
1007
1008
1009
1010
1011
1012
        }
      if (j->second == cmTarget::DEBUG)
        {
        libDebugOptions += " ";
        libDebugOptions += lib;

        libMultiLineDebugOptions += "# ADD LINK32 ";
1013
        libMultiLineDebugOptions += libDebug;
Ken Martin's avatar
Ken Martin committed
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
        libMultiLineDebugOptions += "\n";
        }
      if (j->second == cmTarget::OPTIMIZED)
        {
        libOptimizedOptions += " ";
        libOptimizedOptions += lib;

        libMultiLineOptimizedOptions += "# ADD LINK32 ";
        libMultiLineOptimizedOptions += lib;
        libMultiLineOptimizedOptions += "\n";
        }      
      }
    }
1027
#endif
1028
1029

  // Get extra linker options for this target type.
1030
1031
1032
  std::string extraLinkOptions;
  if(target.GetType() == cmTarget::EXECUTABLE)
    {
1033
    extraLinkOptions = this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1034
1035
1036
    }
  if(target.GetType() == cmTarget::SHARED_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
1037
    extraLinkOptions = this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1038
    }
1039
1040
  if(target.GetType() == cmTarget::MODULE_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
1041
    extraLinkOptions = this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1042
    }
1043

1044
1045
  // Get extra linker options for this target.
  if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
1046
    {
1047
1048
    extraLinkOptions += " ";
    extraLinkOptions += targetLinkFlags;
1049
1050
    }

1051
  // Get standard libraries for this language.
1052
1053
  if(target.GetType() >= cmTarget::EXECUTABLE && 
     target.GetType() <= cmTarget::MODULE_LIBRARY)
1054
    {
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
    // Get the language to use for linking.
    const char* linkLanguage = target.GetLinkerLanguage(this->GetGlobalGenerator());
    if(!linkLanguage)
      {
      cmSystemTools::Error("CMake can not determine linker language for target:",
                           target.GetName());
      return;
      }

    // Compute the variable name to lookup standard libraries for this
    // language.
    std::string standardLibsVar = "CMAKE_";
    standardLibsVar += linkLanguage;
    standardLibsVar += "_STANDARD_LIBRARIES";

    // Add standard libraries.
    if(const char* stdLibs =
       this->Makefile->GetDefinition(standardLibsVar.c_str()))
      {
1074
1075
      extraLinkOptions += " ";
      extraLinkOptions += stdLibs;
1076
      }
1077
    }
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

  // Compute the real name of the target.
  std::string outputName = "(OUTPUT_NAME is for libraries and executables only)";
  std::string outputNameDebug = outputName;
  std::string outputNameRelease = outputName;
  std::string outputNameMinSizeRel = outputName;
  std::string outputNameRelWithDebInfo = outputName;
  if(target.GetType() == cmTarget::EXECUTABLE ||
     target.GetType() == cmTarget::STATIC_LIBRARY ||
     target.GetType() == cmTarget::SHARED_LIBRARY ||
     target.GetType() == cmTarget::MODULE_LIBRARY)
    {
    outputName = target.GetFullName();
    outputNameDebug = target.GetFullName("Debug");
    outputNameRelease = target.GetFullName("Release");
    outputNameMinSizeRel = target.GetFullName("MinSizeRel");
    outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
    }

  // Compute the proper link information for the target.
  std::string optionsDebug;
  std::string optionsRelease;
  std::string optionsMinSizeRel;
  std::string optionsRelWithDebInfo;
  if(target.GetType() == cmTarget::EXECUTABLE ||
     target.GetType() == cmTarget::SHARED_LIBRARY ||
     target.GetType() == cmTarget::MODULE_LIBRARY)
    {
    this->ComputeLinkOptions(target, "Debug", extraLinkOptions,
                             optionsDebug);
    this->ComputeLinkOptions(target, "Release", extraLinkOptions,
                             optionsRelease);
    this->ComputeLinkOptions(target, "MinSizeRel", extraLinkOptions,
                             optionsMinSizeRel);
    this->ComputeLinkOptions(target, "RelWithDebInfo", extraLinkOptions,
                             optionsRelWithDebInfo);
    }

#ifdef CM_USE_OLD_VS6
  // Compute link information for the target.
  if(extraLinkOptions.size())
Brad King's avatar
Brad King committed
1119
1120
    {
    libOptions += " ";
1121
    libOptions += extraLinkOptions;
Brad King's avatar
Brad King committed
1122
1123
    libOptions += " ";
    libMultiLineOptions += "# ADD LINK32 ";
1124
    libMultiLineOptions +=  extraLinkOptions;
Brad King's avatar
Brad King committed
1125
    libMultiLineOptions += " \n";
1126
    libMultiLineOptionsForDebug += "# ADD LINK32 ";
1127
    libMultiLineOptionsForDebug +=  extraLinkOptions;
1128
    libMultiLineOptionsForDebug += " \n";
Brad King's avatar
Brad King committed
1129
    }
1130
1131
#endif

Ken Martin's avatar
Ken Martin committed
1132
1133
1134
1135
  // are there any custom rules on the target itself
  // only if the target is a lib or exe
  std::string customRuleCode = this->CreateTargetRules(target, libName);

Ken Martin's avatar
Ken Martin committed
1136
  std::ifstream fin(this->DSPHeaderTemplate.c_str());
Ken Martin's avatar
Ken Martin committed
1137
1138
  if(!fin)
    {
Ken Martin's avatar
Ken Martin committed
1139
    cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
Ken Martin's avatar
Ken Martin committed
1140
    }
1141
1142
1143
1144
1145
1146
1147
1148
  std::string staticLibOptions;
  if(target.GetType() == cmTarget::STATIC_LIBRARY )
    { 
    if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
      {
      staticLibOptions = libflags;
      }
    }
Bill Hoffman's avatar
Bill Hoffman committed
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  std::string exportSymbol;
  if (const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
    {
    exportSymbol = custom_export_name;
    }
  else
    {
    std::string in = libName;
    in += "_EXPORTS";
    exportSymbol = cmSystemTools::MakeCindentifier(in.c_str());
    }


1162
1163
  std::string line;
  while(cmSystemTools::GetLineFromStream(fin, line))
Ken Martin's avatar
Ken Martin committed
1164
    {
Ken Martin's avatar
Ken Martin committed
1165
    const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
1166
1167
1168
1169
    if(!mfcFlag)
      {
      mfcFlag = "0";
      }
Bill Hoffman's avatar
Bill Hoffman committed
1170
1171
    cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
                                 exportSymbol.c_str());
1172
1173
1174
1175
    cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE",
                                 customRuleCode.c_str());
    cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
                                 mfcFlag);
1176
1177
1178
1179
    if(target.GetType() == cmTarget::STATIC_LIBRARY )
      {
      cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS",
                                   staticLibOptions.c_str());
1180
      } 
Ken Martin's avatar
Ken Martin committed
1181
    if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1182
1183
      {
      cmSystemTools::ReplaceString(line, "/nologo", "");
1184
      }
1185
1186

#ifdef CM_USE_OLD_VS6
1187
1188
1189
1190
1191
1192
    cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
                                 libOptions.c_str());
    cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
                                 libDebugOptions.c_str());
    cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
                                 libOptimizedOptions.c_str());
1193
1194
    cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
                                 libMultiLineOptionsForDebug.c_str());
1195
1196
1197
1198
1199
1200
    cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
                                 libMultiLineOptions.c_str());
    cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
                                 libMultiLineDebugOptions.c_str());
    cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
                                 libMultiLineOptimizedOptions.c_str());
1201
#endif
1202

1203
1204
1205
1206
1207
    // Substitute the real output name into the template.
    cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG", outputNameDebug.c_str());
    cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELEASE", outputNameRelease.c_str());
    cmSystemTools::ReplaceString(line, "OUTPUT_NAME_MINSIZEREL", outputNameMinSizeRel.c_str());
    cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELWITHDEBINFO", outputNameRelWithDebInfo.c_str());