cmGlobalUnixMakefileGenerator3.cxx 40.5 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*=========================================================================

  Program:   CMake - Cross-Platform Makefile Generator3
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     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 "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmake.h"
#include "cmGeneratedFileStream.h"
Ken Martin's avatar
Ken Martin committed
23
24
#include "cmSourceFile.h"
#include "cmTarget.h"
Ken Martin's avatar
Ken Martin committed
25
26
27
28

cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
{
  // This type of makefile always requires unix style paths
Ken Martin's avatar
Ken Martin committed
29
30
  this->ForceUnixPaths = true;
  this->FindMakeProgramFile = "CMakeUnixFindMake.cmake";
31
  this->ToolSupportsColor = true;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
32
33
  this->ForceVerboseMakefiles = false;

34
35
36
#ifdef _WIN32
  this->UseLinkScript = false;
#else
37
  this->UseLinkScript = true;
38
#endif
Ken Martin's avatar
Ken Martin committed
39
40
41
}

void cmGlobalUnixMakefileGenerator3
Alexander Neundorf's avatar
   
Alexander Neundorf committed
42
43
44
::EnableLanguage(std::vector<std::string>const& languages, 
                 cmMakefile *mf, 
                 bool optional)
Ken Martin's avatar
Ken Martin committed
45
{
Alexander Neundorf's avatar
   
Alexander Neundorf committed
46
  this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
Ken Martin's avatar
Ken Martin committed
47
48
49
50
  std::string path;
  for(std::vector<std::string>::const_iterator l = languages.begin();
      l != languages.end(); ++l)
    {
Bill Hoffman's avatar
Bill Hoffman committed
51
52
53
54
    if(*l == "NONE")
      {
      continue;
      }
Ken Martin's avatar
Ken Martin committed
55
56
57
58
59
60
61
    const char* lang = l->c_str();
    std::string langComp = "CMAKE_";
    langComp += lang;
    langComp += "_COMPILER";
    
    if(!mf->GetDefinition(langComp.c_str()))
      {
Ken Martin's avatar
Ken Martin committed
62
63
      cmSystemTools::Error(langComp.c_str(), 
                           " not set, after EnableLanguage");
Ken Martin's avatar
Ken Martin committed
64
65
      continue;
      }
66
67
68
69
70
71
72
73
74
    const char* name = mf->GetRequiredDefinition(langComp.c_str());
    if(!cmSystemTools::FileIsFullPath(name))
      {
      path = cmSystemTools::FindProgram(name);
      }
    else
      {
      path = name;
      }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
75
76
    if((path.size() == 0 || !cmSystemTools::FileExists(path.c_str())) 
        && (optional==false))
Ken Martin's avatar
Ken Martin committed
77
78
79
      {
      std::string message = "your ";
      message += lang;
80
81
82
83
84
85
86
      message += " compiler: \"";
      message +=  name;
      message += "\" was not found.   Please set ";
      message += langComp;
      message += " to a valid compiler path or name.";
      cmSystemTools::Error(message.c_str());
      path = name;
Ken Martin's avatar
Ken Martin committed
87
      }
88
89
90
91
    std::string doc = lang;
    doc += " compiler.";
    mf->AddCacheDefinition(langComp.c_str(), path.c_str(),
                           doc.c_str(), cmCacheManager::FILEPATH);
Ken Martin's avatar
Ken Martin committed
92
93
94
95
96
97
98
99
100
101
102
103
    }
}

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

//----------------------------------------------------------------------------
Ken Martin's avatar
Ken Martin committed
104
105
void cmGlobalUnixMakefileGenerator3
::GetDocumentation(cmDocumentationEntry& entry) const
Ken Martin's avatar
Ken Martin committed
106
107
108
109
110
111
112
113
114
{
  entry.name = this->GetName();
  entry.brief = "Generates standard UNIX makefiles.";
  entry.full =
    "A hierarchy of UNIX makefiles is generated into the build tree.  Any "
    "standard UNIX-style make program can build the project through the "
    "default make target.  A \"make install\" target is also provided.";
}

115
116
117
118
119
120
121
122
123
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::AddMultipleOutputPair(const char* depender, const char* dependee)
{
  MultipleOutputPairsType::value_type p(depender, dependee);
  this->MultipleOutputPairs.insert(p);
}

Ken Martin's avatar
Ken Martin committed
124

Ken Martin's avatar
Ken Martin committed
125
126
127
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::Generate() 
{
128
129
130
  // first do superclass method
  this->cmGlobalGenerator::Generate();

131
  // initialize progress
Ken Martin's avatar
Ken Martin committed
132
  unsigned int i;
133
  unsigned long total = 0;
Ken Martin's avatar
Ken Martin committed
134
135
  for (i = 0; i < this->LocalGenerators.size(); ++i)
    {
136
137
138
    cmLocalUnixMakefileGenerator3 *lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
    total += lg->GetNumberOfProgressActions();
Ken Martin's avatar
Ken Martin committed
139
    }
Ken Martin's avatar
Ken Martin committed
140

141
142
143
144
145
146
147
  // write each target's progress.make this loop is done twice. Bascially the
  // Generate pass counts all the actions, the first loop below determines
  // how many actions have progress updates for each target and writes to
  // corrrect variable values for everything except the all targets. The
  // second loop actually writes out correct values for the all targets as
  // well. This is because the all targets require more information that is
  // computed in the first loop.
148
  unsigned long current = 0;
149
  for (i = 0; i < this->LocalGenerators.size(); ++i)
150
151
152
153
154
    {
    cmLocalUnixMakefileGenerator3 *lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
    lg->WriteProgressVariables(total,current);
    }
155
  for (i = 0; i < this->LocalGenerators.size(); ++i)
156
157
    {
    cmLocalUnixMakefileGenerator3 *lg = 
158
159
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
    lg->WriteAllProgressVariable();
160
161
    }
  
Ken Martin's avatar
Ken Martin committed
162
  // write the main makefile
163
  this->WriteMainMakefile2();
Ken Martin's avatar
Ken Martin committed
164
165
166
  this->WriteMainCMakefile();
}

167
168
169
170
171
172
173
void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
{
  // Open the output file.  This should not be copy-if-different
  // because the check-build-system step compares the makefile time to
  // see if the build system must be regenerated.
  std::string makefileName = 
    this->GetCMakeInstance()->GetHomeOutputDirectory();
174
175
  makefileName += cmake::GetCMakeFilesDirectory();
  makefileName += "/Makefile2";
176
177
178
179
180
181
182
183
  cmGeneratedFileStream makefileStream(makefileName.c_str());
  if(!makefileStream)
    {
    return;
    }
 
  // get a local generator for some useful methods
  cmLocalUnixMakefileGenerator3 *lg = 
Ken Martin's avatar
Ken Martin committed
184
    static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
185
186
187
    
  // Write the do not edit header.
  lg->WriteDisclaimer(makefileStream);
188

189
190
191
192
193
194
195
196
197
198
199
200
201
  // Write the main entry point target.  This must be the VERY first
  // target so that make with no arguments will run it.
  // Just depend on the all target to drive the build.
  std::vector<std::string> depends;
  std::vector<std::string> no_commands;
  depends.push_back("all");

  // Write the rule.
  lg->WriteMakeRule(makefileStream,
                    "Default target executed when no arguments are "
                    "given to make.",
                    "default_target",
                    depends,
202
                    no_commands, true);
203

204
  depends.clear();
205

206
207
  // The all and preinstall rules might never have any dependencies
  // added to them.
Ken Martin's avatar
Ken Martin committed
208
  if(this->EmptyRuleHackDepends != "")
209
    {
Ken Martin's avatar
Ken Martin committed
210
    depends.push_back(this->EmptyRuleHackDepends);
211
212
    }

213
214
215
  // Write and empty all:
  lg->WriteMakeRule(makefileStream, 
                    "The main recursive all target", "all", 
216
                    depends, no_commands, true);
217

218
219
220
221
222
  // Write an empty preinstall:
  lg->WriteMakeRule(makefileStream,
                    "The main recursive preinstall target", "preinstall",
                    depends, no_commands, true);

223
224
  // Write out the "special" stuff
  lg->WriteSpecialTargetsTop(makefileStream);
225
226
227
  
  // write the target convenience rules
  unsigned int i;
Ken Martin's avatar
Ken Martin committed
228
  for (i = 0; i < this->LocalGenerators.size(); ++i)
229
    {
Ken Martin's avatar
Ken Martin committed
230
231
    lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
232
233
234
235
236
    // are any parents excluded
    bool exclude = false;
    cmLocalGenerator *lg3 = lg;
    while (lg3)
      {
Ken Martin's avatar
Ken Martin committed
237
      if (lg3->GetMakefile()->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
238
239
240
241
242
243
244
245
246
        {
        exclude = true;
        break;
        }
      lg3 = lg3->GetParent();
      }
    this->WriteConvenienceRules2(makefileStream,lg,exclude);
    }

Ken Martin's avatar
Ken Martin committed
247
  lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
248
249
250
  lg->WriteSpecialTargetsBottom(makefileStream);
}

Ken Martin's avatar
Ken Martin committed
251

Ken Martin's avatar
Ken Martin committed
252
253
254
255
256
257
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
  // Open the output file.  This should not be copy-if-different
  // because the check-build-system step compares the makefile time to
  // see if the build system must be regenerated.
Ken Martin's avatar
Ken Martin committed
258
259
  std::string cmakefileName = 
    this->GetCMakeInstance()->GetHomeOutputDirectory();
260
261
  cmakefileName += cmake::GetCMakeFilesDirectory();
  cmakefileName += "/Makefile.cmake";
Ken Martin's avatar
Ken Martin committed
262
263
264
265
266
  cmGeneratedFileStream cmakefileStream(cmakefileName.c_str());
  if(!cmakefileStream)
    {
    return;
    }
Ken Martin's avatar
Ken Martin committed
267
268
269
270
271

  std::string makefileName = 
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  makefileName += "/Makefile";
  
Ken Martin's avatar
Ken Martin committed
272
273
  // get a local generator for some useful methods
  cmLocalUnixMakefileGenerator3 *lg = 
Ken Martin's avatar
Ken Martin committed
274
    static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
Ken Martin's avatar
Ken Martin committed
275
276
277
278
    
  // Write the do not edit header.
  lg->WriteDisclaimer(cmakefileStream);

Ken Martin's avatar
Ken Martin committed
279
280
281
282
283
  // Save the generator name
  cmakefileStream
    << "# The generator used is:\n"
    << "SET(CMAKE_DEPENDS_GENERATOR \"" << this->GetName() << "\")\n\n";

Ken Martin's avatar
Ken Martin committed
284
285
  // for each cmMakefile get its list of dependencies
  std::vector<std::string> lfiles;
Ken Martin's avatar
Ken Martin committed
286
  for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
287
    {
Ken Martin's avatar
Ken Martin committed
288
289
    lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
Ken Martin's avatar
Ken Martin committed
290
291
292
293
294
295
296
297
298
299
300
301
  
    // Get the list of files contributing to this generation step.
    lfiles.insert(lfiles.end(),lg->GetMakefile()->GetListFiles().begin(),
                  lg->GetMakefile()->GetListFiles().end());
    }
  // Sort the list and remove duplicates.
  std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
  std::vector<std::string>::iterator new_end = 
    std::unique(lfiles.begin(),lfiles.end());
  lfiles.erase(new_end, lfiles.end());

  // reset lg to the first makefile
Ken Martin's avatar
Ken Martin committed
302
  lg = static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[0]);
Ken Martin's avatar
Ken Martin committed
303
304
305
306
307
308
309
310
311

  // Build the path to the cache file.
  std::string cache = this->GetCMakeInstance()->GetHomeOutputDirectory();
  cache += "/CMakeCache.txt";

  // Save the list to the cmake file.
  cmakefileStream
    << "# The top level Makefile was generated from the following files:\n"
    << "SET(CMAKE_MAKEFILE_DEPENDS\n"
Ken Martin's avatar
Ken Martin committed
312
313
314
    << "  \"" 
    << lg->Convert(cache.c_str(),
                   cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
Ken Martin's avatar
Ken Martin committed
315
316
317
318
  for(std::vector<std::string>::const_iterator i = lfiles.begin();
      i !=  lfiles.end(); ++i)
    {
    cmakefileStream
Ken Martin's avatar
Ken Martin committed
319
320
      << "  \"" 
      << lg->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT).c_str()
Ken Martin's avatar
Ken Martin committed
321
322
323
324
325
326
327
      << "\"\n";
    }
  cmakefileStream
    << "  )\n\n";

  // Build the path to the cache check file.
  std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
328
329
  check += cmake::GetCMakeFilesDirectory();
  check += "/cmake.check_cache";
Ken Martin's avatar
Ken Martin committed
330
331
332
333
334

  // Set the corresponding makefile in the cmake file.
  cmakefileStream
    << "# The corresponding makefile is:\n"
    << "SET(CMAKE_MAKEFILE_OUTPUTS\n"
Ken Martin's avatar
Ken Martin committed
335
336
337
338
339
340
    << "  \"" 
    << lg->Convert(makefileName.c_str(),
                   cmLocalGenerator::START_OUTPUT).c_str() << "\"\n"
    << "  \"" 
    << lg->Convert(check.c_str(),
                   cmLocalGenerator::START_OUTPUT).c_str() << "\"\n";
Ken Martin's avatar
Ken Martin committed
341
342
343

  // add in all the directory information files
  std::string tmpStr;
Ken Martin's avatar
Ken Martin committed
344
  for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
345
    {
Ken Martin's avatar
Ken Martin committed
346
347
    lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
Ken Martin's avatar
Ken Martin committed
348
    tmpStr = lg->GetMakefile()->GetStartOutputDirectory();
349
350
    tmpStr += cmake::GetCMakeFilesDirectory();
    tmpStr += "/CMakeDirectoryInformation.cmake";
351
    cmakefileStream << "  \"" << 
Ken Martin's avatar
Ken Martin committed
352
353
354
355
      lg->Convert(tmpStr.c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() 
                    << "\"\n";
    const std::vector<std::string>& outfiles = 
      lg->GetMakefile()->GetOutputFiles();
356
357
358
359
    for(std::vector<std::string>::const_iterator k= outfiles.begin();
        k != outfiles.end(); ++k)
      {
      cmakefileStream << "  \"" << 
Ken Martin's avatar
Ken Martin committed
360
361
        lg->Convert(k->c_str(),cmLocalGenerator::HOME_OUTPUT).c_str() 
                      << "\"\n";
362
      }
Ken Martin's avatar
Ken Martin committed
363
364
    }
  cmakefileStream << "  )\n\n";
Ken Martin's avatar
Ken Martin committed
365

Ken Martin's avatar
Ken Martin committed
366
367
  this->WriteMainCMakefileLanguageRules(cmakefileStream, 
                                        this->LocalGenerators);
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

  if(!this->MultipleOutputPairs.empty())
    {
    cmakefileStream
      << "\n"
      << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
    for(MultipleOutputPairsType::const_iterator pi =
          this->MultipleOutputPairs.begin();
        pi != this->MultipleOutputPairs.end(); ++pi)
      {
      cmakefileStream << "  \"" << pi->first << "\" \""
                      << pi->second << "\"\n";
      }
    cmakefileStream << "  )\n\n";
    }
Ken Martin's avatar
Ken Martin committed
383
}
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3::CheckMultipleOutputs(cmMakefile* mf,
                                                          bool verbose)
{
  // Get the string listing the multiple output pairs.
  const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
  if(!pairs_string)
    {
    return;
    }

  // Convert the string to a list and preserve empty entries.
  std::vector<std::string> pairs;
  cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
  for(std::vector<std::string>::const_iterator i = pairs.begin();
      i != pairs.end(); ++i)
    {
    const std::string& depender = *i;
    if(++i != pairs.end())
      {
      const std::string& dependee = *i;

      // If the depender is missing then delete the dependee to make
      // sure both will be regenerated.
      if(cmSystemTools::FileExists(dependee.c_str()) &&
         !cmSystemTools::FileExists(depender.c_str()))
        {
        if(verbose)
          {
          cmOStringStream msg;
          msg << "Deleting primary custom command output \"" << dependee
              << "\" because another output \""
              << depender << "\" does not exist." << std::endl;
          cmSystemTools::Stdout(msg.str().c_str());
          }
        cmSystemTools::RemoveFile(dependee.c_str());
        }
      }
    }
}

Ken Martin's avatar
Ken Martin committed
426
void cmGlobalUnixMakefileGenerator3
427
::WriteMainCMakefileLanguageRules(cmGeneratedFileStream& cmakefileStream,
Ken Martin's avatar
Ken Martin committed
428
429
                                  std::vector<cmLocalGenerator *> &lGenerators
                                  )
Ken Martin's avatar
Ken Martin committed
430
431
432
{
  cmLocalUnixMakefileGenerator3 *lg;

433
  // now list all the target info files
Ken Martin's avatar
Ken Martin committed
434
435
436
  cmakefileStream
    << "# The set of files whose dependency integrity should be checked:\n";
  cmakefileStream
437
438
    << "SET(CMAKE_DEPEND_INFO_FILES\n";
  for (unsigned int i = 0; i < lGenerators.size(); ++i)
Ken Martin's avatar
Ken Martin committed
439
    {
440
441
442
443
    lg = static_cast<cmLocalUnixMakefileGenerator3 *>(lGenerators[i]);
    // for all of out targets
    for (cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
         l != lg->GetMakefile()->GetTargets().end(); l++)
Ken Martin's avatar
Ken Martin committed
444
      {
445
446
447
448
449
450
451
452
453
454
      if((l->second.GetType() == cmTarget::EXECUTABLE) ||
         (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
         (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
         (l->second.GetType() == cmTarget::MODULE_LIBRARY) )
        {
        std::string tname = lg->GetRelativeTargetDirectory(l->second);
        tname += "/DependInfo.cmake";
        cmSystemTools::ConvertToUnixSlashes(tname);
        cmakefileStream << "  \"" << tname.c_str() << "\"\n";
        }
Ken Martin's avatar
Ken Martin committed
455
456
      }
    }
457
  cmakefileStream << "  )\n";
Ken Martin's avatar
Ken Martin committed
458
459
}

Ken Martin's avatar
Ken Martin committed
460
461
462
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
463
464
465
466
::WriteDirectoryRule2(std::ostream& ruleFileStream,
                      cmLocalUnixMakefileGenerator3* lg,
                      const char* pass, bool check_all,
                      bool check_relink)
Ken Martin's avatar
Ken Martin committed
467
{
468
469
470
471
472
473
474
475
476
477
  // Get the relative path to the subdirectory from the top.
  std::string makeTarget = lg->GetMakefile()->GetStartOutputDirectory();
  makeTarget += "/";
  makeTarget += pass;

  // The directory-level rule should depend on the target-level rules
  // for all targets in the directory.
  std::vector<std::string> depends;
  for(cmTargets::iterator l = lg->GetMakefile()->GetTargets().begin();
      l != lg->GetMakefile()->GetTargets().end(); ++l)
478
    {
479
480
481
482
483
    if((l->second.GetType() == cmTarget::EXECUTABLE) ||
       (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
       (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
       (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
       (l->second.GetType() == cmTarget::UTILITY))
484
      {
485
      // Add this to the list of depends rules in this directory.
Ken Martin's avatar
Ken Martin committed
486
      if((!check_all || !l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
487
         (!check_relink || l->second.NeedRelinkBeforeInstall()))
488
        {
489
490
491
492
        std::string tname = lg->GetRelativeTargetDirectory(l->second);
        tname += "/";
        tname += pass;
        depends.push_back(tname);
493
494
        }
      }
495
496
    }

497
498
  // The directory-level rule should depend on the directory-level
  // rules of the subdirectories.
Ken Martin's avatar
Ken Martin committed
499
500
  for(std::vector<cmLocalGenerator*>::iterator sdi = 
        lg->GetChildren().begin(); sdi != lg->GetChildren().end(); ++sdi)
501
    {
502
503
504
505
506
507
    cmLocalUnixMakefileGenerator3* slg =
      static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
    std::string subdir = slg->GetMakefile()->GetStartOutputDirectory();
    subdir += "/";
    subdir += pass;
    depends.push_back(subdir);
508
    }
509
510
511

  // Work-around for makes that drop rules that have no dependencies
  // or commands.
Ken Martin's avatar
Ken Martin committed
512
  if(depends.empty() && this->EmptyRuleHackDepends != "")
513
    {
Ken Martin's avatar
Ken Martin committed
514
    depends.push_back(this->EmptyRuleHackDepends);
515
516
517
518
519
520
521
522
523
    }

  // Write the rule.
  std::string doc = "Convenience name for \"";
  doc += pass;
  doc += "\" pass in the directory.";
  std::vector<std::string> no_commands;
  lg->WriteMakeRule(ruleFileStream, doc.c_str(),
                    makeTarget.c_str(), depends, no_commands, true);
524
525
526
527
528
}

//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
529
530
::WriteDirectoryRules2(std::ostream& ruleFileStream,
                       cmLocalUnixMakefileGenerator3* lg)
531
{
532
533
  // Only subdirectories need these rules.
  if(!lg->GetParent())
534
    {
535
    return;
536
    }
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  // Begin the directory-level rules section.
  std::string dir = lg->GetMakefile()->GetStartOutputDirectory();
  dir = lg->Convert(dir.c_str(), cmLocalGenerator::HOME_OUTPUT,
                    cmLocalGenerator::MAKEFILE);
  lg->WriteDivider(ruleFileStream);
  ruleFileStream
    << "# Directory level rules for directory "
    << dir << "\n\n";

  // Write directory-level rules for "all".
  this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);

  // Write directory-level rules for "clean".
  this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false);

  // Write directory-level rules for "preinstall".
  this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", false, true);
555
556
}

557

Ken Martin's avatar
Ken Martin committed
558
559
560
std::string cmGlobalUnixMakefileGenerator3
::GenerateBuildCommand(const char* makeProgram, const char *projectName, 
                       const char* additionalOptions, const char *targetName,
561
                       const char* config, bool ignoreErrors, bool fast)
562
563
564
565
566
{
  // Project name and config are not used yet.
  (void)projectName;
  (void)config;

Ken Martin's avatar
Ken Martin committed
567
568
569
  std::string makeCommand = 
    cmSystemTools::ConvertToUnixOutputPath(makeProgram);
  
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  // Since we have full control over the invocation of nmake, let us
  // make it quiet.
  if ( strcmp(this->GetName(), "NMake Makefiles") == 0 )
    {
    makeCommand += " /NOLOGO ";
    }
  if ( ignoreErrors )
    {
    makeCommand += " -i";
    }
  if ( additionalOptions )
    {
    makeCommand += " ";
    makeCommand += additionalOptions;
    }
  if ( targetName && strlen(targetName))
    {
    cmLocalUnixMakefileGenerator3 *lg;
    if (this->LocalGenerators.size())
      {
Ken Martin's avatar
Ken Martin committed
590
591
      lg = static_cast<cmLocalUnixMakefileGenerator3 *>
        (this->LocalGenerators[0]);
592
593
594
      }
    else
      {
Ken Martin's avatar
Ken Martin committed
595
596
      lg = static_cast<cmLocalUnixMakefileGenerator3 *>
        (this->CreateLocalGenerator());
597
598
599
600
601
602
603
604
      // set the Start directories
      lg->GetMakefile()->SetStartDirectory
        (this->CMakeInstance->GetStartDirectory());
      lg->GetMakefile()->SetStartOutputDirectory
        (this->CMakeInstance->GetStartOutputDirectory());
      lg->GetMakefile()->MakeStartDirectoriesCurrent();
      }
    
Ken Martin's avatar
Ken Martin committed
605
    makeCommand += " \"";
606
    std::string tname = targetName;
607
608
609
610
    if(fast)
      {
      tname += "/fast";
      }
611
    tname = lg->Convert(tname.c_str(),cmLocalGenerator::HOME_OUTPUT,
Ken Martin's avatar
Ken Martin committed
612
                        cmLocalGenerator::MAKEFILE);
613
614
615
616
617
618
619
620
621
622
    makeCommand += tname.c_str();
    makeCommand += "\"";
    if (!this->LocalGenerators.size())
      {
      delete lg;
      }
    }
  return makeCommand;
}

623
624
625
626
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::WriteConvenienceRules(std::ostream& ruleFileStream, 
627
                        std::set<cmStdString> &emitted)
628
629
630
631
632
{
  std::vector<std::string> depends;  
  std::vector<std::string> commands;

  depends.push_back("cmake_check_build_system");
633
634
635
636
  
  // write the target convenience rules
  unsigned int i;
  cmLocalUnixMakefileGenerator3 *lg;
Ken Martin's avatar
Ken Martin committed
637
  for (i = 0; i < this->LocalGenerators.size(); ++i)
638
    {
Ken Martin's avatar
Ken Martin committed
639
640
    lg = static_cast<cmLocalUnixMakefileGenerator3 *>
      (this->LocalGenerators[i]);
641
642
643
    // for each target Generate the rule files for each target.
    cmTargets& targets = lg->GetMakefile()->GetTargets();
    for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
644
      {
645
646
647
648
      // Don't emit the same rule twice (e.g. two targets with the same
      // simple name)
      if(t->second.GetName() &&
         strlen(t->second.GetName()) &&
Alexander Neundorf's avatar
   
Alexander Neundorf committed
649
650
651
652
653
654
655
656
         emitted.insert(t->second.GetName()).second &&
         // Handle user targets here.  Global targets are handled in
         // the local generator on a per-directory basis.
         ((t->second.GetType() == cmTarget::EXECUTABLE) ||
          (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
          (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
          (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
          (t->second.GetType() == cmTarget::UTILITY)))
657
        {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
        // Add a rule to build the target by name.
        lg->WriteDivider(ruleFileStream);
        ruleFileStream
          << "# Target rules for targets named "
          << t->second.GetName() << "\n\n";
        
        // Write the rule.
        commands.clear();
        std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
        tmp += "Makefile2";
        commands.push_back(lg->GetRecursiveMakeCall
                            (tmp.c_str(),t->second.GetName()));
        depends.clear();
        depends.push_back("cmake_check_build_system");
        lg->WriteMakeRule(ruleFileStream, 
                          "Build rule for target.",
                          t->second.GetName(), depends, commands,
                          true);
        
        // Add a fast rule to build the target
        std::string localName = lg->GetRelativeTargetDirectory(t->second);
        std::string makefileName;
        makefileName = localName;
        makefileName += "/build.make";          
        depends.clear();
        commands.clear();
        std::string makeTargetName = localName;
        makeTargetName += "/build";
        localName = t->second.GetName();
        localName += "/fast";
        commands.push_back(lg->GetRecursiveMakeCall
                            (makefileName.c_str(), makeTargetName.c_str()));
        lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
                          localName.c_str(), depends, commands, true);
692
        }
693
694
695
696
697
698
699
700
701
702
703
      }
    }
}


//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::WriteConvenienceRules2(std::ostream& ruleFileStream, 
                         cmLocalUnixMakefileGenerator3 *lg,
                         bool exclude)
704
705
706
707
708
709
{
  std::vector<std::string> depends;  
  std::vector<std::string> commands;
  std::string localName;
  std::string makeTargetName;

710

711
  // write the directory level rules for this local gen
712
  this->WriteDirectoryRules2(ruleFileStream,lg);
713
714
  
  depends.push_back("cmake_check_build_system");
715

Ken Martin's avatar
Ken Martin committed
716
  // for each target Generate the rule files for each target.
717
718
  cmTargets& targets = lg->GetMakefile()->GetTargets();
  for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
Ken Martin's avatar
Ken Martin committed
719
    {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
720
721
722
723
724
725
726
    if (t->second.GetName()
     && strlen(t->second.GetName())
     && ((t->second.GetType() == cmTarget::EXECUTABLE)
        || (t->second.GetType() == cmTarget::STATIC_LIBRARY)
        || (t->second.GetType() == cmTarget::SHARED_LIBRARY)
        || (t->second.GetType() == cmTarget::MODULE_LIBRARY)
        || (t->second.GetType() == cmTarget::UTILITY)))
Ken Martin's avatar
Ken Martin committed
727
      {
728
      std::string makefileName;
Ken Martin's avatar
Ken Martin committed
729
730
      // Add a rule to build the target by name.
      localName = lg->GetRelativeTargetDirectory(t->second);
731
      makefileName = localName;
732
      makefileName += "/build.make";
733
      
734
      bool needRequiresStep = this->NeedRequiresStep(t->second);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
735
736
737
738
739
740
741
742
      
      lg->WriteDivider(ruleFileStream);
      ruleFileStream
        << "# Target rules for target "
        << localName << "\n\n";
    
      commands.clear();        
      if (t->second.GetType() != cmTarget::UTILITY)
743
        {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
744
745
746
747
        makeTargetName = localName;
        makeTargetName += "/depend";
        commands.push_back(lg->GetRecursiveMakeCall
                            (makefileName.c_str(),makeTargetName.c_str()));
748
        
Alexander Neundorf's avatar
   
Alexander Neundorf committed
749
750
        // add requires if we need it for this generator
        if (needRequiresStep)
751
752
          {
          makeTargetName = localName;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
753
          makeTargetName += "/requires";
754
          commands.push_back(lg->GetRecursiveMakeCall
Alexander Neundorf's avatar
   
Alexander Neundorf committed
755
                              (makefileName.c_str(),makeTargetName.c_str()));
756
          }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
757
758
759
760
761
762
763
764
765
        }
      makeTargetName = localName;
      makeTargetName += "/build";
      commands.push_back(lg->GetRecursiveMakeCall
                          (makefileName.c_str(),makeTargetName.c_str()));
      
      // Write the rule.
      localName += "/all";
      depends.clear();
766

Alexander Neundorf's avatar
   
Alexander Neundorf committed
767
768
769
      std::string progressDir =
        lg->GetMakefile()->GetHomeOutputDirectory();
      progressDir += cmake::GetCMakeFilesDirectory();
770
771
        {
        cmOStringStream progCmd;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
772
773
        progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report "; 
        // all target counts
774
        progCmd << lg->Convert(progressDir.c_str(),
Alexander Neundorf's avatar
   
Alexander Neundorf committed
775
776
777
778
779
780
781
782
783
                                cmLocalGenerator::FULL,
                                cmLocalGenerator::SHELL);
        progCmd << " ";
        std::vector<int> &progFiles = lg->ProgressFiles[t->first];
        for (std::vector<int>::iterator i = progFiles.begin();
              i != progFiles.end(); ++i)
          {
          progCmd << " " << *i;
          }
784
785
        commands.push_back(progCmd.str());
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
786
787
788
789
790
791
792
793
794
795
      progressDir = "Built target ";
      progressDir += t->first;
      lg->AppendEcho(commands,progressDir.c_str());
      
      this->AppendGlobalTargetDepends(depends,t->second);
      lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
                        localName.c_str(), depends, commands, true);
      
      // add the all/all dependency
      if (!exclude && !t->second.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
796
        {
797
798
        depends.clear();
        depends.push_back(localName);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
799
800
801
802
803
804
805
806
807
808
809
810
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
841
842
843
844
845
846
847
848
849
850
851
852
        commands.clear();
        lg->WriteMakeRule(ruleFileStream, "Include target in all.",
                          "all", depends, commands, true);
        }
      
      // Write the rule.
      commands.clear();
      progressDir = lg->GetMakefile()->GetHomeOutputDirectory();
      progressDir += cmake::GetCMakeFilesDirectory();
      
      {
      // TODO: Convert the total progress count to a make variable.
      cmOStringStream progCmd;
      progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; 
      // # in target
      progCmd << lg->Convert(progressDir.c_str(),
                              cmLocalGenerator::FULL,
                              cmLocalGenerator::SHELL);
      //
      std::set<cmStdString> emitted;
      progCmd << " " 
              << this->GetTargetTotalNumberOfActions(t->second,
                                                      emitted);
      commands.push_back(progCmd.str());
      }
      std::string tmp = cmake::GetCMakeFilesDirectoryPostSlash();
      tmp += "Makefile2";
      commands.push_back(lg->GetRecursiveMakeCall
                          (tmp.c_str(),localName.c_str()));
      {
      cmOStringStream progCmd;
      progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; // # 0
      progCmd << lg->Convert(progressDir.c_str(),
                              cmLocalGenerator::FULL,
                              cmLocalGenerator::SHELL);
      progCmd << " 0";
      commands.push_back(progCmd.str());
      }
      depends.clear();
      depends.push_back("cmake_check_build_system");
      localName = lg->GetRelativeTargetDirectory(t->second);
      localName += "/rule";
      lg->WriteMakeRule(ruleFileStream, 
                        "Build rule for subdir invocation for target.",
                        localName.c_str(), depends, commands, true);
      
      // Add a target with the canonical name (no prefix, suffix or path).
      commands.clear();
      depends.clear();
      depends.push_back(localName);
      lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
                        t->second.GetName(), depends, commands, true);
      
      // Add rules to prepare the target for installation.
853
      if(t->second.NeedRelinkBeforeInstall())
Alexander Neundorf's avatar
   
Alexander Neundorf committed
854
        {
855
        localName = lg->GetRelativeTargetDirectory(t->second);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
856
        localName += "/preinstall";
857
858
859
        depends.clear();
        commands.clear();
        commands.push_back(lg->GetRecursiveMakeCall
Alexander Neundorf's avatar
   
Alexander Neundorf committed
860
861
862
863
                            (makefileName.c_str(), localName.c_str()));
        lg->WriteMakeRule(ruleFileStream, 
                          "Pre-install relink rule for target.",
                          localName.c_str(), depends, commands, true);
Brad King's avatar
Brad King committed
864
865
866
867
868
        depends.clear();
        depends.push_back(localName);
        commands.clear();
        lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
                          "preinstall", depends, commands, true);
869
        }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
      
      // add the clean rule
      localName = lg->GetRelativeTargetDirectory(t->second);
      makeTargetName = localName;
      makeTargetName += "/clean";
      depends.clear();
      commands.clear();
      commands.push_back(lg->GetRecursiveMakeCall
                          (makefileName.c_str(), makeTargetName.c_str()));
      lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
                        makeTargetName.c_str(), depends, commands, true);
      commands.clear();
      depends.push_back(makeTargetName);
      lg->WriteMakeRule(ruleFileStream, "clean rule for target.",
                        "clean", depends, commands, true);
885
886
887
888
      }
    }
}

Ken Martin's avatar
Ken Martin committed
889
890
//----------------------------------------------------------------------------
int cmGlobalUnixMakefileGenerator3
891
892
::GetTargetTotalNumberOfActions(cmTarget& target, 
                                std::set<cmStdString> &emitted)
Ken Martin's avatar
Ken Martin committed
893
{
894
895
  // do not double count
  int result = 0;
Ken Martin's avatar
Ken Martin committed
896

897
  if(emitted.insert(target.GetName()).second)
Ken Martin's avatar
Ken Martin committed
898
    {
899
900
901
902
903
904
905
906
907
908
909
910
    cmLocalUnixMakefileGenerator3 *lg = 
      static_cast<cmLocalUnixMakefileGenerator3 *>
      (target.GetMakefile()->GetLocalGenerator());
    result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
    
    std::vector<cmTarget *>& depends = this->GetTargetDepends(target);
    
    std::vector<cmTarget *>::iterator i;
    for (i = depends.begin(); i != depends.end(); ++i)
      {
      result += this->GetTargetTotalNumberOfActions(**i, emitted);
      }
Ken Martin's avatar
Ken Martin committed
911
912
913
914
915
    }
  
  return result;
}

916
917
unsigned long cmGlobalUnixMakefileGenerator3
::GetNumberOfProgressActionsInAll(cmLocalUnixMakefileGenerator3 *lg)
918
919
920
{
  unsigned long result = 0;

921
922
923
924
  // if this is a project
  if (!lg->GetParent() || 
      strcmp(lg->GetMakefile()->GetProjectName(), 
             lg->GetParent()->GetMakefile()->GetProjectName()))
925
    {
926
927
928
929
930
    // use the new project to target map   
    std::set<cmTarget*> &targets = 
      this->ProjectToTargetMap[lg->GetMakefile()->GetProjectName()];
    std::set<cmTarget*>::iterator t = targets.begin();
    for(; t != targets.end(); ++t)
931
      {
932
933
934
935
936
937
      cmTarget* target = *t;
      cmLocalUnixMakefileGenerator3 *lg3 = 
        static_cast<cmLocalUnixMakefileGenerator3 *>
        (target->GetMakefile()->GetLocalGenerator());
      std::vector<int> &progFiles = lg3->ProgressFiles[target->GetName()];
      result += static_cast<unsigned long>(progFiles.size());
938
939
      }
    }
940
  // for subdirectories
941
942
  else
    {
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
    std::deque<cmLocalUnixMakefileGenerator3 *> lg3Stack;
    lg3Stack.push_back(lg);
    std::vector<cmStdString> targetsInAll;
    std::set<cmTarget *> targets;
    while (lg3Stack.size())
      {
      cmLocalUnixMakefileGenerator3 *lg3 = lg3Stack.front();
      lg3Stack.pop_front();
      for(cmTargets::iterator l = lg3->GetMakefile()->GetTargets().begin();
          l != lg3->GetMakefile()->GetTargets().end(); ++l)
        {
        if((l->second.GetType() == cmTarget::EXECUTABLE) ||
           (l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
           (l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
           (l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
           (l->second.GetType() == cmTarget::UTILITY))
          {
          // Add this to the list of depends rules in this directory.
Ken Martin's avatar
Ken Martin committed
961
          if (!l->second.GetPropertyAsBool("EXCLUDE_FROM_ALL") && 
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
              targets.find(&l->second) == targets.end())
            {
            std::deque<cmTarget *> activeTgts;
            activeTgts.push_back(&(l->second));
            // trace depth of target dependencies
            while (activeTgts.size())
              {
              if (targets.find(activeTgts.front()) == targets.end())
                {
                targets.insert(activeTgts.front());
                cmLocalUnixMakefileGenerator3 *lg4 = 
                  static_cast<cmLocalUnixMakefileGenerator3 *>
                  (activeTgts.front()->GetMakefile()->GetLocalGenerator());
                std::vector<int> &progFiles2 = 
                  lg4->ProgressFiles[activeTgts.front()->GetName()];
Ken Martin's avatar
Ken Martin committed
977
                result += static_cast<unsigned long>(progFiles2.size());
978
979
                std::vector<cmTarget *> deps2 = 
                  this->GetTargetDepends(*activeTgts.front());
Ken Martin's avatar
Ken Martin committed
980
981
982
983
984
                for (std::vector<cmTarget *>::const_iterator di = 
                       deps2.begin(); di != deps2.end(); ++di)
                  {
                  activeTgts.push_back(*di);
                  }
985
986
987
988
989
990
991
992
993
994
                }
              activeTgts.pop_front();
              }
            }
          }
        }
      
      // The directory-level rule depends on the directory-level
      // rules of the subdirectories.
      for(std::vector<cmLocalGenerator*>::iterator sdi = 
Ken Martin's avatar
Ken Martin committed
995
996
            lg3->GetChildren().begin(); 
          sdi != lg3->GetChildren().end(); ++sdi)
997
998
999
1000
1001
1002
        {
        cmLocalUnixMakefileGenerator3* slg =
          static_cast<cmLocalUnixMakefileGenerator3*>(*sdi);
        lg3Stack.push_back(slg);
        }
      }
1003
1004
1005
1006
    }
  return result;
}

Ken Martin's avatar
Ken Martin committed
1007

1008
1009
1010
1011
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
::AppendGlobalTargetDepends(std::vector<std::string>& depends,
1012
                            cmTarget& target)
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
{
  // Keep track of dependencies already listed.
  std::set<cmStdString> emitted;

  // A target should not depend on itself.
  emitted.insert(target.GetName());
  
  // Loop over all library dependencies but not for static libs
  if (target.GetType() != cmTarget::STATIC_LIBRARY)
    {
Ken Martin's avatar
Ken Martin committed
1023
1024
    const cmTarget::LinkLibraryVectorType& tlibs = target.GetLinkLibraries();
    for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
1025
1026
1027
1028
        lib != tlibs.end(); ++lib)
      {
      // Don't emit the same library twice for this target.
      if(emitted.insert(lib->first).second)
Ken Martin's avatar
Ken Martin committed
1029
        {
1030
        // Add this dependency.
1031
1032
        this->AppendAnyGlobalDepend(depends, lib->first.c_str(), 
                                    emitted, target);
Ken Martin's avatar
Ken Martin committed
1033
1034
1035
        }
      }
    }
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  
  // Loop over all utility dependencies.
  const std::set<cmStdString>& tutils = target.GetUtilities();
  for(std::set<cmStdString>::const_iterator util = tutils.begin();
      util != tutils.end(); ++util)
    {
    // Don't emit the same utility twice for this target.
    if(emitted.insert(*util).second)
      {
      // Add this dependency.
1046
      this->AppendAnyGlobalDepend(depends, util->c_str(), emitted, target);
1047
1048
      }
    }
Ken Martin's avatar
Ken Martin committed
1049
1050
1051
}


1052
1053
1054
//----------------------------------------------------------------------------
void
cmGlobalUnixMakefileGenerator3
1055
::AppendAnyGlobalDepend(std::vector<std::string>& depends, const char* name,
1056
                        std::set<cmStdString>& emitted, cmTarget &target)
1057
{
1058
  cmTarget *result;
1059
  cmLocalUnixMakefileGenerator3 *lg3;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1060

1061
1062
1063
  // first check the same dir as the current target
  lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
    (target.GetMakefile()->GetLocalGenerator());
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1064
  result = target.GetMakefile()->FindTarget(name, false);
1065
1066
  
  // search each local generator until a match is found
1067
1068
  if (!result)
    {
Alexander Neundorf's avatar
   
Alexander Neundorf committed
1069
    result = this->FindTarget(0, name, false);
Ken Martin's avatar
Ken Martin committed
1070
    if (result)
1071
      {
Ken Martin's avatar
Ken Martin committed
1072
1073
      lg3 = static_cast<cmLocalUnixMakefileGenerator3 *>
        (result->GetMakefile()->GetLocalGenerator());
1074
1075
1076
1077
1078
      }
    }
  
  // if a match was found then ...
  if (result)
1079
    {
1080
1081
1082
1083
    std::string tgtName = lg3->GetRelativeTargetDirectory(*result);
    tgtName += "/all";
    depends.push_back(tgtName);
    if(result->GetType() == cmTarget::STATIC_LIBRARY)
1084
      {
1085
1086
      // Since the static library itself does not list dependencies we
      // need to chain its dependencies here.
Ken Martin's avatar
Ken Martin committed
1087
1088
1089
      const cmTarget::LinkLibraryVectorType& tlibs 
        = result->GetLinkLibraries();
      for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
1090
          lib != tlibs.end(); ++lib)
1091
        {
1092
1093
        // Don't emit the same library twice for this target.
        if(emitted.insert(lib->first).second)
1094
          {
1095
1096
1097
          // Add this dependency.
          this->AppendAnyGlobalDepend(depends, lib->first.c_str(),
                                      emitted, *result);
1098
1099
          }
        }
1100
      }
1101
    return;
1102
1103
    }
}
1104
1105

//----------------------------------------------------------------------------
1106
1107
void cmGlobalUnixMakefileGenerator3::WriteHelpRule
(std::ostream& ruleFileStream, cmLocalUnixMakefileGenerator3 *lg)
1108
1109
1110
1111
1112
{
  // add the help target
  std::string path;
  std::vector<std::string> no_depends;
  std::vector<std::string> commands;
Ken Martin's avatar
Ken Martin committed
1113
1114
  lg->AppendEcho(commands,"The following are some of the valid targets "
                 "for this Makefile:");
1115
1116
1117
1118
  lg->AppendEcho(commands,"... all (the default if no target is provided)");
  lg->AppendEcho(commands,"... clean");
  lg->AppendEcho(commands,"... depend");
  
1119
1120
1121
  // Keep track of targets already listed.
  std::set<cmStdString> emittedTargets;

1122
1123
  // for each local generator
  unsigned int i;
1124
  cmLocalUnixMakefileGenerator3 *lg2;
Ken Martin's avatar
Ken Martin committed
1125
  for (i = 0; i < this->LocalGenerators.size(); ++i)
1126
    {
Ken Martin's avatar
Ken Martin committed
1127
1128
    lg2 = 
      static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]);
1129
1130
1131
    // for the passed in makefile or if this is the top Makefile wripte out
    // the targets
    if (lg2 == lg || !lg->GetParent())
1132
      {
1133
      // for each target Generate the rule files for each target.
Bill Hoffman's avatar
Bill Hoffman committed
1134
      cmTargets& targets = lg2->GetMakefile()->GetTargets();
1135
      for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
1136
        {
1137
1138
1139
1140
        if((t->second.GetType() == cmTarget::EXECUTABLE) ||
           (t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
           (t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
           (t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
1141
           (t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
1142
           (t->second.GetType() == cmTarget::UTILITY))
1143
          {
1144
1145
1146
1147
1148
1149
          if(emittedTargets.insert(t->second.GetName()).second)
            {
            path = "... ";
            path += t->second.GetName();
            lg->AppendEcho(commands,path.c_str());
            }
1150
          }
1151
        }
1152
1153
1154
      std::vector<cmStdString> const& localHelp = lg->GetLocalHelp();
      for(std::vector<cmStdString>::const_iterator o = localHelp.begin();
          o != localHelp.end(); ++o)
1155
        {
1156
1157
1158
        path = "... ";
        path += *o;
        lg->AppendEcho(commands, path.c_str());
1159
        }
1160
1161
1162
1163
      }
    }
  lg->WriteMakeRule(ruleFileStream, "Help Target",
                    "help:",
1164
                    no_depends, commands, true);
1165
1166
1167
  ruleFileStream << "\n\n";
}

1168
1169

bool cmGlobalUnixMakefileGenerator3
1170
::NeedRequiresStep(cmTarget const& target)
1171
{
1172
1173
1174
1175
  std::set<cmStdString> languages;
  target.GetLanguages(languages);
  for(std::set<cmStdString>::const_iterator l = languages.begin();
      l != languages.end(); ++l)
1176
    {
1177
1178
1179
1180
    std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
    var += *l;
    var += "_FLAG";
    if(target.GetMakefile()->GetDefinition(var.c_str()))
1181
1182
1183
1184
1185
1186
      {
      return true;
      }
    }
  return false;
}