cmGlobalVisualStudio7Generator.cxx 24.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

     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.

=========================================================================*/
17
#include "windows.h" // this must be first to define GetCurrentDirectory
Ken Martin's avatar
Ken Martin committed
18
19
#include "cmGlobalVisualStudio7Generator.h"
#include "cmLocalVisualStudio7Generator.h"
20
#include "cmGeneratedFileStream.h"
Ken Martin's avatar
Ken Martin committed
21
22
23
#include "cmMakefile.h"
#include "cmake.h"

24
25
26
27
28
29
30

cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator()
{
  m_FindMakeProgramFile = "CMakeVS7FindMake.cmake";
}


31
void cmGlobalVisualStudio7Generator::EnableLanguage(std::vector<std::string>const &  lang, 
Ken Martin's avatar
Ken Martin committed
32
                                                    cmMakefile *mf)
Ken Martin's avatar
Ken Martin committed
33
{
34
  mf->AddDefinition("CMAKE_CFG_INTDIR","$(OutDir)");
35
36
  mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
  mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
37
  mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
38
  mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
39
  mf->AddDefinition("CMAKE_GENERATOR_Fortran", "ifort");
40
41
  
  // Create list of configurations requested by user's cache, if any.
42
  this->cmGlobalGenerator::EnableLanguage(lang, mf);
43
  this->GenerateConfigurations(mf);
Ken Martin's avatar
Ken Martin committed
44
45
}

46
std::string cmGlobalVisualStudio7Generator::GenerateBuildCommand(const char* makeProgram,
47
48
  const char *projectName, const char* additionalOptions, const char *targetName,
  const char* config, bool ignoreErrors)
Ken Martin's avatar
Ken Martin committed
49
{
50
51
52
  // Ingoring errors is not implemented in visual studio 6
  (void) ignoreErrors;

Ken Martin's avatar
Ken Martin committed
53
54
  // now build the test
  std::string makeCommand = 
55
    cmSystemTools::ConvertToOutputPath(makeProgram);
Ken Martin's avatar
Ken Martin committed
56
57
58
59
60
  std::string lowerCaseCommand = makeCommand;
  cmSystemTools::LowerCase(lowerCaseCommand);

  // if there are spaces in the makeCommand, assume a full path
  // and convert it to a path with no spaces in it as the
Andy Cedilnik's avatar
Andy Cedilnik committed
61
  // RunSingleCommand does not like spaces
Ken Martin's avatar
Ken Martin committed
62
63
64
65
66
67
68
69
#if defined(_WIN32) && !defined(__CYGWIN__)      
  if(makeCommand.find(' ') != std::string::npos)
    {
    cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
    }
#endif
  makeCommand += " ";
  makeCommand += projectName;
70
  makeCommand += ".sln ";
71
72
73
74
75
76
  bool clean = false;
  if ( targetName && strcmp(targetName, "clean") == 0 )
    {
    clean = true;
    targetName = "ALL_BUILD";
    }
77
78
  if(clean)
    {
79
    makeCommand += "/clean ";
80
81
82
83
84
85
86
    }
  else
    {
    makeCommand += "/build ";
    }

  if(config && strlen(config))
87
    {
88
    makeCommand += config;
89
90
91
92
93
94
    }
  else
    {
    makeCommand += "Debug";
    }
  makeCommand += " /project ";
95
96

  if (targetName && strlen(targetName))
Ken Martin's avatar
Ken Martin committed
97
98
99
100
101
102
103
    {
    makeCommand += targetName;
    }
  else
    {
    makeCommand += "ALL_BUILD";
    }
104
105
106
107
108
  if ( additionalOptions )
    {
    makeCommand += " ";
    makeCommand += additionalOptions;
    }
109
  return makeCommand;
Ken Martin's avatar
Ken Martin committed
110
111
112
113
114
115
116
117
118
119
}

///! Create a local generator appropriate to this Global Generator
cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
{
  cmLocalGenerator *lg = new cmLocalVisualStudio7Generator;
  lg->SetGlobalGenerator(this);
  return lg;
}

120
void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
Ken Martin's avatar
Ken Martin committed
121
122
{
  // process the configurations
123
124
125
  const char* ct 
    = m_CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
  if ( ct )
Ken Martin's avatar
Ken Martin committed
126
    {
127
128
129
130
131
    std::string configTypes = ct;
    
    std::string::size_type start = 0;
    std::string::size_type endpos = 0;
    while(endpos != std::string::npos)
Ken Martin's avatar
Ken Martin committed
132
      {
133
      endpos = configTypes.find_first_of(" ;", start);
134
135
136
      std::string config;
      std::string::size_type len;
      if(endpos != std::string::npos)
Ken Martin's avatar
Ken Martin committed
137
        {
138
        len = endpos - start;
Ken Martin's avatar
Ken Martin committed
139
        }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
      else
        {
        len = configTypes.size() - start;
        }
      config = configTypes.substr(start, len);
      if(config == "Debug" || config == "Release" ||
         config == "MinSizeRel" || config == "RelWithDebInfo")
        {
        // only add unique configurations
        if(std::find(m_Configurations.begin(),
                     m_Configurations.end(), config) == m_Configurations.end())
          {
          m_Configurations.push_back(config);
          }
        }
      else
        {
        cmSystemTools::Error(
          "Invalid configuration type in CMAKE_CONFIGURATION_TYPES: ",
          config.c_str(),
          " (Valid types are Debug,Release,MinSizeRel,RelWithDebInfo)");
        }
      start = endpos+1;
Ken Martin's avatar
Ken Martin committed
163
164
165
166
167
168
169
      }
    }
  if(m_Configurations.size() == 0)
    {
    m_Configurations.push_back("Debug");
    m_Configurations.push_back("Release");
    }
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  
  // Reset the entry to have a semi-colon separated list.
  std::string configs = m_Configurations[0];
  for(unsigned int i=1; i < m_Configurations.size(); ++i)
    {
    configs += ";";
    configs += m_Configurations[i];
    }
  
  mf->AddCacheDefinition(
    "CMAKE_CONFIGURATION_TYPES",
    configs.c_str(),
    "Semicolon separated list of supported configuration types, "
    "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
    "anything else will be ignored.",
    cmCacheManager::STRING);
Ken Martin's avatar
Ken Martin committed
186
187
188
189
190
}

void cmGlobalVisualStudio7Generator::Generate()
{
  // add a special target that depends on ALL projects for easy build
191
192
  // of one configuration only.
  const char* no_output = 0;
193
  const char* no_working_dir = 0;
194
  std::vector<std::string> no_depends;
195
  std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
196
  for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
197
198
199
200
201
202
    {
    std::vector<cmLocalGenerator*>& gen = it->second;
    // add the ALL_BUILD to the first local generator of each project
    if(gen.size())
      {
      gen[0]->GetMakefile()->
203
        AddUtilityCommand("ALL_BUILD", false, no_output, no_depends,
204
                          no_working_dir,
205
                          "echo", "Build all projects");
206
      std::string cmake_command = 
207
        m_LocalGenerators[0]->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND");
208
      gen[0]->GetMakefile()->
209
        AddUtilityCommand("INSTALL", false, no_output, no_depends,
210
                          no_working_dir,
211
                          cmake_command.c_str(),
212
                          "-DBUILD_TYPE=$(OutDir)", "-P", "cmake_install.cmake");
Andy Cedilnik's avatar
Andy Cedilnik committed
213
214
215
216
217
      gen[0]->GetMakefile()->
        AddUtilityCommand("preinstall", false, no_output, no_depends,
                          no_working_dir,
                          cmake_command.c_str(),
                          "-E", "echo", "preinstall");
218
219
220
221
222
223
224
225
226
227
228

      // Make the INSTALL target depend on ALL_BUILD unless the
      // project says to not do so.
      const char* noall =
        gen[0]->GetMakefile()
        ->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
      if(!noall || cmSystemTools::IsOff(noall))
        {
        cmTarget* install = gen[0]->GetMakefile()->FindTarget("INSTALL");
        install->AddUtility("ALL_BUILD");
        }
229
230
      }
    }
231

Ken Martin's avatar
Ken Martin committed
232
233
234
235
236
237
238
239
240
241
  // add the Run Tests command
  this->SetupTests();
  
  // first do the superclass method
  this->cmGlobalGenerator::Generate();
  
  // Now write out the DSW
  this->OutputSLNFile();
}

242
243
void cmGlobalVisualStudio7Generator::OutputSLNFile(cmLocalGenerator* root,
                                                   std::vector<cmLocalGenerator*>& generators)
244
245
{
  if(generators.size() == 0)
Ken Martin's avatar
Ken Martin committed
246
    {
247
    return;
Ken Martin's avatar
Ken Martin committed
248
    }
249
  m_CurrentProject = root->GetMakefile()->GetProjectName();
250
  std::string fname = root->GetMakefile()->GetStartOutputDirectory();
Ken Martin's avatar
Ken Martin committed
251
  fname += "/";
252
  fname += root->GetMakefile()->GetProjectName();
Ken Martin's avatar
Ken Martin committed
253
  fname += ".sln";
254
255
  cmGeneratedFileStream fout(fname.c_str());
  fout.SetCopyIfDifferent(true);
Ken Martin's avatar
Ken Martin committed
256
257
258
259
  if(!fout)
    {
    return;
    }
260
  this->WriteSLNFile(fout, root, generators);
261
262
263
264
265
266
}

// output the SLN file
void cmGlobalVisualStudio7Generator::OutputSLNFile()
{ 
  std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
267
  for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
268
    {
269
    this->OutputSLNFile(it->second[0], it->second);
270
    }
Ken Martin's avatar
Ken Martin committed
271
272
273
274
}


// Write a SLN file to the stream
275
void cmGlobalVisualStudio7Generator::WriteSLNFile(std::ostream& fout,
276
                                                  cmLocalGenerator* root,
277
                                                  std::vector<cmLocalGenerator*>& generators)
Ken Martin's avatar
Ken Martin committed
278
279
280
281
{
  // Write out the header for a SLN file
  this->WriteSLNHeader(fout);
  
282
283
284
  // Get the start directory with the trailing slash
  std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
  rootdir += "/";
285
286
  bool doneAllBuild = false;
  bool doneRunTests = false;
287
  bool doneInstall  = false;
Andy Cedilnik's avatar
Andy Cedilnik committed
288
289
290
  bool doneEditCache = false;
  bool doneRebuildCache = false;
  bool donePackage = false;
Andy Cedilnik's avatar
Andy Cedilnik committed
291
  bool donePreInstall = false;
292
  
Ken Martin's avatar
Ken Martin committed
293
294
  // For each cmMakefile, create a VCProj for it, and
  // add it to this SLN file
Ken Martin's avatar
Ken Martin committed
295
  unsigned int i;
296
  for(i = 0; i < generators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
297
    {
298
299
300
301
    if(this->IsExcluded(root, generators[i]))
      {
      continue;
      }
302
    cmMakefile* mf = generators[i]->GetMakefile();
Ken Martin's avatar
Ken Martin committed
303
304

    // Get the source directory from the makefile
305
    std::string dir = mf->GetStartOutputDirectory();
Ken Martin's avatar
Ken Martin committed
306
307
    // remove the home directory and / from the source directory
    // this gives a relative path 
308
    cmSystemTools::ReplaceString(dir, rootdir.c_str(), "");
Ken Martin's avatar
Ken Martin committed
309
310
311
312
313

    // Get the list of create dsp files names from the cmVCProjWriter, more
    // than one dsp could have been created per input CMakeLists.txt file
    // for each target
    std::vector<std::string> dspnames = 
314
      static_cast<cmLocalVisualStudio7Generator *>(generators[i])
Ken Martin's avatar
Ken Martin committed
315
      ->GetCreatedProjectNames();
316
    cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
Ken Martin's avatar
Ken Martin committed
317
318
319
320
321
    cmTargets::iterator l = tgts.begin();
    for(std::vector<std::string>::iterator si = dspnames.begin(); 
        l != tgts.end(); ++l)
      {
      // special handling for the current makefile
322
      if(mf == generators[0]->GetMakefile())
Ken Martin's avatar
Ken Martin committed
323
324
325
326
327
328
        {
        dir = "."; // no subdirectory for project generated
        // if this is the special ALL_BUILD utility, then
        // make it depend on every other non UTILITY project.
        // This is done by adding the names to the GetUtilities
        // vector on the makefile
329
        if(l->first == "ALL_BUILD" && !doneAllBuild)
Ken Martin's avatar
Ken Martin committed
330
          {
Ken Martin's avatar
Ken Martin committed
331
          unsigned int j;
332
          for(j = 0; j < generators.size(); ++j)
Ken Martin's avatar
Ken Martin committed
333
            {
334
335
            cmTargets &atgts = generators[j]->GetMakefile()->GetTargets();
            for(cmTargets::iterator al = atgts.begin();
Ken Martin's avatar
Ken Martin committed
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
                al != atgts.end(); ++al)
              {
              if (al->second.IsInAll())
                {
                if (al->second.GetType() == cmTarget::UTILITY)
                  {
                  l->second.AddUtility(al->first.c_str());
                  }
                else
                  {
                  l->second.AddLinkLibrary(al->first,cmTarget::GENERAL);
                  }
                }
              }
            }
          }
        }
      // Write the project into the SLN file
      if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
        {
356
        cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
357
358
359
360
        const cmCustomCommandLines& cmds = cc.GetCommandLines();
        std::string project = cmds[0][0];
        std::string location = cmds[0][1];
        this->WriteExternalProject(fout, project.c_str(), location.c_str(), cc.GetDepends());
Ken Martin's avatar
Ken Martin committed
361
362
363
364
365
366
        }
      else 
        {
        if ((l->second.GetType() != cmTarget::INSTALL_FILES)
            && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
          {
367
          bool skip = false;
Bill Hoffman's avatar
Bill Hoffman committed
368
          if(l->first == "ALL_BUILD" )
369
370
371
372
373
374
375
376
377
378
            {
            if(doneAllBuild)
              {
              skip = true;
              }
            else
              {
              doneAllBuild = true;
              }
            }
379
380
381
382
383
384
385
386
387
388
389
          if(l->first == "INSTALL")
            {
            if(doneInstall)
              {
              skip = true;
              }
            else
              {
              doneInstall = true;
              }
            }
Andy Cedilnik's avatar
Andy Cedilnik committed
390
391
392
393
394
395
396
397
398
399
400
          if(l->first == "preinstall")
            {
            if(donePreInstall)
              {
              skip = true;
              }
            else
              {
              donePreInstall = true;
              }
            }
401
402
403
404
405
406
407
408
409
410
411
          if(l->first == "RUN_TESTS")
            {
            if(doneRunTests)
              {
              skip = true;
              }
            else
              {
              doneRunTests = true;
              }
            }
Andy Cedilnik's avatar
Andy Cedilnik committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
          if(l->first == "EDIT_CACHE")
            {
            if(doneEditCache)
              {
              skip = true;
              }
            else
              {
              doneEditCache = true;
              }
            }
          if(l->first == "REBUILD_CACHE")
            {
            if(doneRebuildCache)
              {
              skip = true;
              }
            else
              {
              doneRebuildCache = true;
              }
            }
          if(l->first == "PACKAGE")
            {
            if(donePackage)
              {
              skip = true;
              }
            else
              {
              donePackage = true;
              }
            }
445
446
447
448
          if(!skip)
            {
            this->WriteProject(fout, si->c_str(), dir.c_str(),l->second);
            }
Ken Martin's avatar
Ken Martin committed
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
          ++si;
          }
        }
      }
    }
  fout << "Global\n"
       << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
  
  int c = 0;
  for(std::vector<std::string>::iterator i = m_Configurations.begin();
      i != m_Configurations.end(); ++i)
    {
    fout << "\t\tConfigName." << c << " = " << *i << "\n";
    c++;
    }
  fout << "\tEndGlobalSection\n"
       << "\tGlobalSection(ProjectDependencies) = postSolution\n";

  // loop over again and compute the depends
468
  for(i = 0; i < generators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
469
    {
470
    cmMakefile* mf = generators[i]->GetMakefile();
Ken Martin's avatar
Ken Martin committed
471
    cmLocalVisualStudio7Generator* pg =  
472
      static_cast<cmLocalVisualStudio7Generator*>(generators[i]);
Ken Martin's avatar
Ken Martin committed
473
474
475
476
477
478
479
480
481
    // Get the list of create dsp files names from the cmVCProjWriter, more
    // than one dsp could have been created per input CMakeLists.txt file
    // for each target
    std::vector<std::string> dspnames = 
      pg->GetCreatedProjectNames();
    cmTargets &tgts = pg->GetMakefile()->GetTargets();
    cmTargets::iterator l = tgts.begin();
    std::string dir = mf->GetStartDirectory();
    for(std::vector<std::string>::iterator si = dspnames.begin(); 
482
        l != tgts.end() && si != dspnames.end(); ++l)
Ken Martin's avatar
Ken Martin committed
483
      {
484
485
486
       if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
         {
         cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
487
488
         const cmCustomCommandLines& cmds = cc.GetCommandLines();
         std::string name = cmds[0][0];
489
490
491
492
493
         std::vector<std::string> depends = cc.GetDepends();
         std::vector<std::string>::iterator iter;
         int depcount = 0;
         for(iter = depends.begin(); iter != depends.end(); ++iter)
           {
494
495
496
497
498
499
500
501
502
503
           std::string guid = this->GetGUID(iter->c_str());
           if(guid.size() == 0)
             {
             std::string m = "Target: ";
             m += l->first;
             m += " depends on unknown target: ";
             m += iter->c_str();
             cmSystemTools::Error(m.c_str());
             }
           
504
           fout << "\t\t{" << this->GetGUID(name.c_str()) << "}." << depcount << " = {"
505
                << guid.c_str() << "}\n";
506
507
508
509
510
           depcount++;
           }
         }
       else if ((l->second.GetType() != cmTarget::INSTALL_FILES)
                && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
Ken Martin's avatar
Ken Martin committed
511
        {
512
        this->WriteProjectDepends(fout, si->c_str(), dir.c_str(), l->second);
Ken Martin's avatar
Ken Martin committed
513
514
515
516
517
518
519
        ++si;
        }
      }
    }
  fout << "\tEndGlobalSection\n";
  fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n";
  // loop over again and compute the depends
520
  for(i = 0; i < generators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
521
    {
522
    cmMakefile* mf = generators[i]->GetMakefile();
Ken Martin's avatar
Ken Martin committed
523
    cmLocalVisualStudio7Generator* pg =  
524
      static_cast<cmLocalVisualStudio7Generator*>(generators[i]);
Ken Martin's avatar
Ken Martin committed
525
526
527
528
529
530
531
532
533
    // Get the list of create dsp files names from the cmVCProjWriter, more
    // than one dsp could have been created per input CMakeLists.txt file
    // for each target
    std::vector<std::string> dspnames = 
      pg->GetCreatedProjectNames();
    cmTargets &tgts = pg->GetMakefile()->GetTargets();
    cmTargets::iterator l = tgts.begin();
    std::string dir = mf->GetStartDirectory();
    for(std::vector<std::string>::iterator si = dspnames.begin(); 
534
        l != tgts.end() && si != dspnames.end(); ++l)
Ken Martin's avatar
Ken Martin committed
535
      {
Bill Hoffman's avatar
Bill Hoffman committed
536
537
538
      if(strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
        {
        cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
539
540
        const cmCustomCommandLines& cmds = cc.GetCommandLines();
        std::string name = cmds[0][0];
Bill Hoffman's avatar
Bill Hoffman committed
541
542
543
        this->WriteProjectConfigurations(fout, name.c_str(), l->second.IsInAll());
        }
      else if ((l->second.GetType() != cmTarget::INSTALL_FILES)
Ken Martin's avatar
Ken Martin committed
544
545
          && (l->second.GetType() != cmTarget::INSTALL_PROGRAMS))
        {
546
        this->WriteProjectConfigurations(fout, si->c_str(), l->second.IsInAll());
Ken Martin's avatar
Ken Martin committed
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
        ++si;
        }
      }
    }
  fout << "\tEndGlobalSection\n";

  // Write the footer for the SLN file
  this->WriteSLNFooter(fout);
}


// Write a dsp file into the SLN file,
// Note, that dependencies from executables to 
// the libraries it uses are also done here
void cmGlobalVisualStudio7Generator::WriteProject(std::ostream& fout, 
                               const char* dspname,
563
                               const char* dir, cmTarget&)
Ken Martin's avatar
Ken Martin committed
564
565
{
  std::string d = cmSystemTools::ConvertToOutputPath(dir);
Bill Hoffman's avatar
Bill Hoffman committed
566
  fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" 
Ken Martin's avatar
Ken Martin committed
567
568
       << dspname << "\", \""
       << d << "\\" << dspname << ".vcproj\", \"{"
569
       << this->GetGUID(dspname) << "}\"\nEndProject\n";
Ken Martin's avatar
Ken Martin committed
570
571
572
573
574
575
576
}



// Write a dsp file into the SLN file,
// Note, that dependencies from executables to 
// the libraries it uses are also done here
577
578
579
580
void
cmGlobalVisualStudio7Generator
::WriteProjectDepends(std::ostream& fout,
                      const char* dspname,
581
                      const char*, cmTarget& target)
Ken Martin's avatar
Ken Martin committed
582
583
584
585
586
587
588
589
590
591
592
{
  int depcount = 0;
  // insert Begin Project Dependency  Project_Dep_Name project stuff here 
  if (target.GetType() != cmTarget::STATIC_LIBRARY)
    {
    cmTarget::LinkLibraries::const_iterator j, jend;
    j = target.GetLinkLibraries().begin();
    jend = target.GetLinkLibraries().end();
    for(;j!= jend; ++j)
      {
      if(j->first != dspname)
593
        {
Ken Martin's avatar
Ken Martin committed
594
        // is the library part of this SLN ? If so add dependency
595
        if(this->FindTarget(m_CurrentProject.c_str(), j->first.c_str()))
Ken Martin's avatar
Ken Martin committed
596
          {
597
598
599
600
601
602
603
604
605
          std::string guid = this->GetGUID(j->first.c_str());
          if(guid.size() == 0)
            {
            std::string m = "Target: ";
            m += dspname;
            m += " depends on unknown target: ";
            m += j->first.c_str();
            cmSystemTools::Error(m.c_str());
            }
606
607
          fout << "\t\t{" << this->GetGUID(dspname) << "}."
               << depcount << " = {" << guid << "}\n";
Ken Martin's avatar
Ken Martin committed
608
609
610
611
612
613
614
615
616
617
618
619
620
621
          depcount++;
          }
        }
      }
    }

  std::set<cmStdString>::const_iterator i, end;
  // write utility dependencies.
  i = target.GetUtilities().begin();
  end = target.GetUtilities().end();
  for(;i!= end; ++i)
    {
    if(*i != dspname)
      {
Bill Hoffman's avatar
Bill Hoffman committed
622
623
624
625
626
627
628
629
630
631
632
      std::string name = *i;
      if(strncmp(name.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
        {
        // kind of weird removing the first 27 letters.
        // my recommendatsions:
        // use cmCustomCommand::GetCommand() to get the project name
        // or get rid of the target name starting with "INCLUDE_EXTERNAL_MSPROJECT_" and use another 
        // indicator/flag somewhere.  These external project names shouldn't conflict with cmake 
        // target names anyways.
        name.erase(name.begin(), name.begin() + 27);
        }
633
634
635
636
637
638
639
640
641
642
      std::string guid = this->GetGUID(name.c_str());
      if(guid.size() == 0)
        {
        std::string m = "Target: ";
        m += dspname;
        m += " depends on unknown target: ";
        m += name.c_str();
        cmSystemTools::Error(m.c_str());
        }
          
643
      fout << "\t\t{" << this->GetGUID(dspname) << "}." << depcount << " = {"
644
           << guid << "}\n";
Ken Martin's avatar
Ken Martin committed
645
646
647
648
649
650
651
652
653
654
655
      depcount++;
      }
    }
}


// Write a dsp file into the SLN file,
// Note, that dependencies from executables to 
// the libraries it uses are also done here
void 
cmGlobalVisualStudio7Generator::WriteProjectConfigurations(std::ostream& fout, 
656
657
                                                           const char* name, 
                                                           bool in_all_build)
Ken Martin's avatar
Ken Martin committed
658
{
659
  std::string guid = this->GetGUID(name);
Ken Martin's avatar
Ken Martin committed
660
661
662
  for(std::vector<std::string>::iterator i = m_Configurations.begin();
      i != m_Configurations.end(); ++i)
    {
663
664
665
666
667
    fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|Win32\n";
    if (in_all_build)
      {
      fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << *i << "|Win32\n";
      }
Ken Martin's avatar
Ken Martin committed
668
669
670
671
672
673
674
675
    }
}



// Write a dsp file into the SLN file,
// Note, that dependencies from executables to 
// the libraries it uses are also done here
676
677
678
void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout, 
                               const char* name,
                               const char* location,
679
                               const std::vector<std::string>&)
680
681
682
683
684
{ 
  std::string d = cmSystemTools::ConvertToOutputPath(location);
  fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"" 
       << name << "\", \""
       << d << "\", \"{"
Bill Hoffman's avatar
Bill Hoffman committed
685
686
687
       << this->GetGUID(name)
       << "}\"\n";
  fout << "EndProject\n";
Ken Martin's avatar
Ken Martin committed
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
}



// Standard end of dsw file
void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
{
  fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
       << "\tEndGlobalSection\n"
       << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
       << "\tEndGlobalSection\n"
       << "EndGlobal\n";
}

  
// ouput standard header for dsw file
void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout)
{
  fout << "Microsoft Visual Studio Solution File, Format Version 7.00\n";
}

709
710
711
712
713
714
715
716
717
std::string cmGlobalVisualStudio7Generator::GetGUID(const char* name)
{
  std::string guidStoreName = name;
  guidStoreName += "_GUID_CMAKE";
  const char* storedGUID = m_CMakeInstance->GetCacheDefinition(guidStoreName.c_str());
  if(storedGUID)
    {
    return std::string(storedGUID);
    }
718
  cmSystemTools::Error("Unknown Target referenced : ",
719
                       name);
720
  return "";
721
722
}

Ken Martin's avatar
Ken Martin committed
723

724
void cmGlobalVisualStudio7Generator::CreateGUID(const char* name)
Ken Martin's avatar
Ken Martin committed
725
{
726
727
728
  std::string guidStoreName = name;
  guidStoreName += "_GUID_CMAKE";
  if(m_CMakeInstance->GetCacheDefinition(guidStoreName.c_str()))
Ken Martin's avatar
Ken Martin committed
729
    {
730
    return;
Ken Martin's avatar
Ken Martin committed
731
732
733
734
735
736
737
738
739
    }
  std::string ret;
  UUID uid;
  unsigned char *uidstr;
  UuidCreate(&uid);
  UuidToString(&uid,&uidstr);
  ret = reinterpret_cast<char*>(uidstr);
  RpcStringFree(&uidstr);
  ret = cmSystemTools::UpperCase(ret);
740
741
  m_CMakeInstance->AddCacheEntry(guidStoreName.c_str(), ret.c_str(), "Stored GUID", 
                                 cmCacheManager::INTERNAL);
Ken Martin's avatar
Ken Martin committed
742
743
}

Ken Martin's avatar
Ken Martin committed
744
745
746
747
std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations()
{
  return &m_Configurations;
};
748
749
750
751
752
753
754
755

//----------------------------------------------------------------------------
void cmGlobalVisualStudio7Generator::GetDocumentation(cmDocumentationEntry& entry) const
{
  entry.name = this->GetName();
  entry.brief = "Generates Visual Studio .NET 2002 project files.";
  entry.full = "";
}
756

757
758
759
760
761
762
// make sure "special" targets have GUID's
void cmGlobalVisualStudio7Generator::Configure()
{
  cmGlobalGenerator::Configure();
  this->CreateGUID("ALL_BUILD");
  this->CreateGUID("INSTALL");
Andy Cedilnik's avatar
Andy Cedilnik committed
763
  this->CreateGUID("preinstall");
764
  this->CreateGUID("RUN_TESTS");
Andy Cedilnik's avatar
Andy Cedilnik committed
765
766
767
  this->CreateGUID("EDIT_CACHE");
  this->CreateGUID("REBUILD_CACHE");
  this->CreateGUID("PACKAGE");
768
}
769
770
771
772
773
774
775
776
777

//----------------------------------------------------------------------------
void
cmGlobalVisualStudio7Generator
::AppendDirectoryForConfig(const char* config, std::string& dir)
{
  if(config)
    {
    dir += config;
778
    dir += "/";
779
780
    }
}