cmTarget.cxx 188 KB
Newer Older
1
2
3
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4

5
6
  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.
7

8
9
10
11
  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
12
#include "cmTarget.h"
13
#include "cmake.h"
14
#include "cmMakefile.h"
Ken Martin's avatar
Ken Martin committed
15
#include "cmSourceFile.h"
16
#include "cmLocalGenerator.h"
17
#include "cmGlobalGenerator.h"
18
#include "cmComputeLinkInformation.h"
19
#include "cmListFileCache.h"
20
#include "cmGeneratorExpression.h"
21
#include "cmGeneratorExpressionDAGChecker.h"
22
#include <cmsys/RegularExpression.hxx>
23
24
#include <map>
#include <set>
25
#include <stdlib.h> // required for atof
26
#include <assert.h>
Nicolas Despres's avatar
Nicolas Despres committed
27
28
29
30
31
32
33
34
35
36
37

const char* cmTarget::GetTargetTypeName(TargetType targetType)
{
  switch( targetType )
    {
      case cmTarget::STATIC_LIBRARY:
        return "STATIC_LIBRARY";
      case cmTarget::MODULE_LIBRARY:
        return "MODULE_LIBRARY";
      case cmTarget::SHARED_LIBRARY:
        return "SHARED_LIBRARY";
Brad King's avatar
Brad King committed
38
39
      case cmTarget::OBJECT_LIBRARY:
        return "OBJECT_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
40
41
42
43
44
45
      case cmTarget::EXECUTABLE:
        return "EXECUTABLE";
      case cmTarget::UTILITY:
        return "UTILITY";
      case cmTarget::GLOBAL_TARGET:
        return "GLOBAL_TARGET";
46
47
      case cmTarget::INTERFACE_LIBRARY:
        return "INTERFACE_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
48
49
50
51
52
53
      case cmTarget::UNKNOWN_LIBRARY:
        return "UNKNOWN_LIBRARY";
    }
  assert(0 && "Unexpected target type");
  return 0;
}
54

55
56
57
58
59
//----------------------------------------------------------------------------
struct cmTarget::OutputInfo
{
  std::string OutDir;
  std::string ImpDir;
60
  std::string PdbDir;
61
62
63
64
65
66
67
68
69
70
71
72
};

//----------------------------------------------------------------------------
struct cmTarget::ImportInfo
{
  bool NoSOName;
  std::string Location;
  std::string SOName;
  std::string ImportLibrary;
  cmTarget::LinkInterface LinkInterface;
};

73
74
75
struct TargetConfigPair : public std::pair<cmTarget const* , std::string> {
  TargetConfigPair(cmTarget const* tgt, const std::string &config)
    : std::pair<cmTarget const* , std::string>(tgt, config) {}
76
77
};

78
79
80
81
82
83
//----------------------------------------------------------------------------
class cmTargetInternals
{
public:
  cmTargetInternals()
    {
84
    this->PolicyWarnedCMP0022 = false;
85
86
    this->SourceFileFlagsConstructed = false;
    }
87
  cmTargetInternals(cmTargetInternals const&)
88
    {
89
    this->PolicyWarnedCMP0022 = false;
90
    this->SourceFileFlagsConstructed = false;
91
    }
92
  ~cmTargetInternals();
93
94
95
  typedef cmTarget::SourceFileFlags SourceFileFlags;
  std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
  bool SourceFileFlagsConstructed;
96
97
98

  // The backtrace when the target was created.
  cmListFileBacktrace Backtrace;
99
100
101
102
103
104
105

  // Cache link interface computation from each configuration.
  struct OptionalLinkInterface: public cmTarget::LinkInterface
  {
    OptionalLinkInterface(): Exists(false) {}
    bool Exists;
  };
106
107
  typedef std::map<TargetConfigPair, OptionalLinkInterface>
                                                          LinkInterfaceMapType;
108
  LinkInterfaceMapType LinkInterfaceMap;
109
  bool PolicyWarnedCMP0022;
110
111
112
113

  typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
  OutputInfoMapType OutputInfoMap;

114
115
  typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
                                                            ImportInfoMapType;
116
  ImportInfoMapType ImportInfoMap;
117
118

  // Cache link implementation computation from each configuration.
119
120
  typedef std::map<TargetConfigPair,
                   cmTarget::LinkImplementation> LinkImplMapType;
121
  LinkImplMapType LinkImplMap;
122

123
124
  typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
                                                          LinkClosureMapType;
125
  LinkClosureMapType LinkClosureMap;
126

127
128
  struct TargetPropertyEntry {
    TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
129
130
      const std::string &targetName = std::string())
      : ge(cge), TargetName(targetName)
131
132
    {}
    const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
133
    std::vector<std::string> CachedEntries;
134
    const std::string TargetName;
135
  };
136
  std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
137
  std::vector<TargetPropertyEntry*> CompileOptionsEntries;
138
  std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
139
  std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
140

141
  std::map<std::string, std::vector<TargetPropertyEntry*> >
142
                                CachedLinkInterfaceIncludeDirectoriesEntries;
143
144
  std::map<std::string, std::vector<TargetPropertyEntry*> >
                                CachedLinkInterfaceCompileOptionsEntries;
145
146
  std::map<std::string, std::vector<TargetPropertyEntry*> >
                                CachedLinkInterfaceCompileDefinitionsEntries;
147
148
149

  std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
  std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
150
  std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
151
152
};

153
154
//----------------------------------------------------------------------------
void deleteAndClear(
155
      std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
156
{
157
  for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
158
159
160
161
162
163
164
165
166
      it = entries.begin(),
      end = entries.end();
      it != end; ++it)
    {
      delete *it;
    }
  entries.clear();
}

167
168
169
//----------------------------------------------------------------------------
void deleteAndClear(
  std::map<std::string,
170
          std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
171
172
{
  for (std::map<std::string,
173
          std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
174
175
176
177
178
179
        it = entries.begin(), end = entries.end(); it != end; ++it)
    {
    deleteAndClear(it->second);
    }
}

180
181
182
//----------------------------------------------------------------------------
cmTargetInternals::~cmTargetInternals()
{
Stephen Kelly's avatar
Stephen Kelly committed
183
  deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
184
  deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
185
  deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
186
187
}

188
189
190
//----------------------------------------------------------------------------
cmTarget::cmTarget()
{
191
192
193
194
195
196
197
#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \
  this->PolicyStatus ## POLICY = cmPolicies::WARN;

  CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER)

#undef INITIALIZE_TARGET_POLICY_MEMBER

Ken Martin's avatar
Ken Martin committed
198
199
200
  this->Makefile = 0;
  this->LinkLibrariesAnalyzed = false;
  this->HaveInstallRule = false;
201
  this->DLLPlatform = false;
202
  this->IsApple = false;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
203
  this->IsImportedTarget = false;
204
  this->BuildInterfaceIncludesAppended = false;
205
  this->DebugIncludesDone = false;
206
  this->DebugCompileOptionsDone = false;
207
  this->DebugCompileDefinitionsDone = false;
208
209
}

210
//----------------------------------------------------------------------------
211
212
void cmTarget::DefineProperties(cmake *cm)
{
213
214
  cm->DefineProperty
    ("RULE_LAUNCH_COMPILE", cmProperty::TARGET,
215
     "", "", true);
216
217
  cm->DefineProperty
    ("RULE_LAUNCH_LINK", cmProperty::TARGET,
218
     "", "", true);
219
220
  cm->DefineProperty
    ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET,
221
     "", "", true);
222
}
223

224
void cmTarget::SetType(TargetType type, const char* name)
225
{
Ken Martin's avatar
Ken Martin committed
226
  this->Name = name;
227
  // only add dependency information for library targets
Ken Martin's avatar
Ken Martin committed
228
  this->TargetTypeValue = type;
229
230
  if(this->TargetTypeValue >= STATIC_LIBRARY
     && this->TargetTypeValue <= MODULE_LIBRARY)
Ken Martin's avatar
Ken Martin committed
231
232
    {
    this->RecordDependencies = true;
233
234
    }
  else
Ken Martin's avatar
Ken Martin committed
235
236
237
    {
    this->RecordDependencies = false;
    }
238
239
}

240
241
242
243
//----------------------------------------------------------------------------
void cmTarget::SetMakefile(cmMakefile* mf)
{
  // Set our makefile.
Ken Martin's avatar
Ken Martin committed
244
  this->Makefile = mf;
245

246
247
248
  // set the cmake instance of the properties
  this->Properties.SetCMakeInstance(mf->GetCMakeInstance());

249
250
251
252
253
  // Check whether this is a DLL platform.
  this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
                       this->Makefile->IsOn("CYGWIN") ||
                       this->Makefile->IsOn("MINGW"));

254
255
256
  // Check whether we are targeting an Apple platform.
  this->IsApple = this->Makefile->IsOn("APPLE");

257
  // Setup default property values.
258
  this->SetPropertyDefault("INSTALL_NAME_DIR", 0);
259
  this->SetPropertyDefault("INSTALL_RPATH", "");
260
  this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
261
262
  this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
  this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
263
264
265
  this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
  this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
  this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
266
  this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
267
  this->SetPropertyDefault("Fortran_FORMAT", 0);
268
  this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
269
  this->SetPropertyDefault("GNUtoMS", 0);
270
  this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
271
  this->SetPropertyDefault("AUTOMOC", 0);
272
  this->SetPropertyDefault("AUTOUIC", 0);
273
  this->SetPropertyDefault("AUTORCC", 0);
274
  this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
275
  this->SetPropertyDefault("AUTOUIC_OPTIONS", 0);
276
  this->SetPropertyDefault("AUTORCC_OPTIONS", 0);
277
  this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
278
  this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
279
280
  this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
  this->SetPropertyDefault("MACOSX_BUNDLE", 0);
281
  this->SetPropertyDefault("MACOSX_RPATH", 0);
282
  this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
283

284
285
286

  // Collect the set of configuration types.
  std::vector<std::string> configNames;
287
  mf->GetConfigurations(configNames);
288
289

  // Setup per-configuration property default values.
290
291
292
293
  const char* configProps[] = {
    "ARCHIVE_OUTPUT_DIRECTORY_",
    "LIBRARY_OUTPUT_DIRECTORY_",
    "RUNTIME_OUTPUT_DIRECTORY_",
294
    "PDB_OUTPUT_DIRECTORY_",
295
    "MAP_IMPORTED_CONFIG_",
296
    0};
297
298
299
  for(std::vector<std::string>::iterator ci = configNames.begin();
      ci != configNames.end(); ++ci)
    {
300
301
302
303
304
305
306
307
    std::string configUpper = cmSystemTools::UpperCase(*ci);
    for(const char** p = configProps; *p; ++p)
      {
      std::string property = *p;
      property += configUpper;
      this->SetPropertyDefault(property.c_str(), 0);
      }

308
309
310
311
312
313
    // Initialize per-configuration name postfix property from the
    // variable only for non-executable targets.  This preserves
    // compatibility with previous CMake versions in which executables
    // did not support this variable.  Projects may still specify the
    // property directly.  TODO: Make this depend on backwards
    // compatibility setting.
Ken Martin's avatar
Ken Martin committed
314
    if(this->TargetTypeValue != cmTarget::EXECUTABLE)
315
316
317
318
319
320
      {
      std::string property = cmSystemTools::UpperCase(*ci);
      property += "_POSTFIX";
      this->SetPropertyDefault(property.c_str(), 0);
      }
    }
321
322
323

  // Save the backtrace of target construction.
  this->Makefile->GetBacktrace(this->Internal->Backtrace);
324

325
326
  // Initialize the INCLUDE_DIRECTORIES property based on the current value
  // of the same directory property:
327
  const std::vector<cmValueWithOrigin> parentIncludes =
328
329
                              this->Makefile->GetIncludeDirectoriesEntries();

330
  for (std::vector<cmValueWithOrigin>::const_iterator it
331
332
333
334
              = parentIncludes.begin(); it != parentIncludes.end(); ++it)
    {
    this->InsertInclude(*it);
    }
335
336
337
338
339
340
341
342
343
344
345

  const std::set<cmStdString> parentSystemIncludes =
                              this->Makefile->GetSystemIncludeDirectories();

  for (std::set<cmStdString>::const_iterator it
        = parentSystemIncludes.begin();
        it != parentSystemIncludes.end(); ++it)
    {
    this->SystemIncludeDirectories.insert(*it);
    }

346
347
348
349
350
351
352
353
  const std::vector<cmValueWithOrigin> parentOptions =
                              this->Makefile->GetCompileOptionsEntries();

  for (std::vector<cmValueWithOrigin>::const_iterator it
              = parentOptions.begin(); it != parentOptions.end(); ++it)
    {
    this->InsertCompileOption(*it);
    }
354

355
356
  this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
  this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
357
  this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
358

359
360
361
362
363
364
365
  if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
      || this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
    {
    this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
    }
  this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);

366
  // Record current policies for later use.
367
368
369
370
371
372
373
#define CAPTURE_TARGET_POLICY(POLICY) \
  this->PolicyStatus ## POLICY = \
    this->Makefile->GetPolicyStatus(cmPolicies::POLICY);

  CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY)

#undef CAPTURE_TARGET_POLICY
374
375
376
377
378
379
380
381

  if (this->TargetTypeValue == INTERFACE_LIBRARY)
    {
    // This policy is checked in a few conditions. The properties relevant
    // to the policy are always ignored for INTERFACE_LIBRARY targets,
    // so ensure that the conditions don't lead to nonsense.
    this->PolicyStatusCMP0022 = cmPolicies::NEW;
    }
382
383
}

384
385
386
//----------------------------------------------------------------------------
void cmTarget::FinishConfigure()
{
387
388
389
390
391
392
  // Erase any cached link information that might have been comptued
  // on-demand during the configuration.  This ensures that build
  // system generation uses up-to-date information even if other cache
  // invalidation code in this source file is buggy.
  this->ClearLinkMaps();

393
394
395
396
  // Do old-style link dependency analysis.
  this->AnalyzeLibDependencies(*this->Makefile);
}

397
398
399
400
401
402
//----------------------------------------------------------------------------
void cmTarget::ClearLinkMaps()
{
  this->Internal->LinkImplMap.clear();
  this->Internal->LinkInterfaceMap.clear();
  this->Internal->LinkClosureMap.clear();
403
404
405
406
407
408
409
  for (cmTargetLinkInformationMap::const_iterator it
      = this->LinkInformation.begin();
      it != this->LinkInformation.end(); ++it)
    {
    delete it->second;
    }
  this->LinkInformation.clear();
410
411
}

412
413
414
415
//----------------------------------------------------------------------------
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
  return this->Internal->Backtrace;
416
}
417

418
419
420
421
422
423
424
//----------------------------------------------------------------------------
std::string cmTarget::GetSupportDirectory() const
{
  std::string dir = this->Makefile->GetCurrentOutputDirectory();
  dir += cmake::GetCMakeFilesDirectory();
  dir += "/";
  dir += this->Name;
425
426
427
#if defined(__VMS)
  dir += "_dir";
#else
428
  dir += ".dir";
429
#endif
430
431
432
  return dir;
}

433
//----------------------------------------------------------------------------
434
bool cmTarget::IsExecutableWithExports() const
435
{
436
437
438
439
  return (this->GetType() == cmTarget::EXECUTABLE &&
          this->GetPropertyAsBool("ENABLE_EXPORTS"));
}

440
441
442
443
444
445
446
//----------------------------------------------------------------------------
bool cmTarget::IsLinkable()
{
  return (this->GetType() == cmTarget::STATIC_LIBRARY ||
          this->GetType() == cmTarget::SHARED_LIBRARY ||
          this->GetType() == cmTarget::MODULE_LIBRARY ||
          this->GetType() == cmTarget::UNKNOWN_LIBRARY ||
447
          this->GetType() == cmTarget::INTERFACE_LIBRARY ||
448
449
450
          this->IsExecutableWithExports());
}

Brad King's avatar
Brad King committed
451
//----------------------------------------------------------------------------
452
bool cmTarget::HasImportLibrary() const
Brad King's avatar
Brad King committed
453
454
455
456
457
458
{
  return (this->DLLPlatform &&
          (this->GetType() == cmTarget::SHARED_LIBRARY ||
           this->IsExecutableWithExports()));
}

459
//----------------------------------------------------------------------------
460
bool cmTarget::IsFrameworkOnApple() const
461
462
463
464
{
  return (this->GetType() == cmTarget::SHARED_LIBRARY &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("FRAMEWORK"));
465
466
}

467
//----------------------------------------------------------------------------
468
bool cmTarget::IsAppBundleOnApple() const
469
470
471
472
473
474
{
  return (this->GetType() == cmTarget::EXECUTABLE &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("MACOSX_BUNDLE"));
}

475
//----------------------------------------------------------------------------
476
bool cmTarget::IsCFBundleOnApple() const
477
478
479
480
481
482
{
  return (this->GetType() == cmTarget::MODULE_LIBRARY &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("BUNDLE"));
}

483
//----------------------------------------------------------------------------
484
bool cmTarget::IsBundleOnApple() const
485
486
487
488
489
{
  return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
         this->IsCFBundleOnApple();
}

490
491
492
493
494
495
496
//----------------------------------------------------------------------------
bool cmTarget::FindSourceFiles()
{
  for(std::vector<cmSourceFile*>::const_iterator
        si = this->SourceFiles.begin();
      si != this->SourceFiles.end(); ++si)
    {
497
498
    std::string e;
    if((*si)->GetFullPath(&e).empty())
499
      {
500
501
502
503
504
505
      if(!e.empty())
        {
        cmake* cm = this->Makefile->GetCMakeInstance();
        cm->IssueMessage(cmake::FATAL_ERROR, e,
                         this->GetBacktrace());
        }
506
507
508
509
510
511
      return false;
      }
    }
  return true;
}

512
//----------------------------------------------------------------------------
513
std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles() const
514
515
516
517
518
519
520
{
  return this->SourceFiles;
}

//----------------------------------------------------------------------------
void cmTarget::AddSourceFile(cmSourceFile* sf)
{
521
522
  if (std::find(this->SourceFiles.begin(), this->SourceFiles.end(), sf)
                                            == this->SourceFiles.end())
523
524
525
526
527
    {
    this->SourceFiles.push_back(sf);
    }
}

528
529
530
531
532
//----------------------------------------------------------------------------
void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
  for(std::vector<std::string>::const_iterator i = srcs.begin();
      i != srcs.end(); ++i)
533
    {
534
535
536
537
538
539
540
541
542
    const char* src = i->c_str();
    if(src[0] == '$' && src[1] == '<')
      {
      this->ProcessSourceExpression(*i);
      }
    else
      {
      this->AddSource(src);
      }
543
544
    }
}
545

546
//----------------------------------------------------------------------------
547
548
549
550
551
552
553
554
555
556
557
558
559
cmSourceFile* cmTarget::AddSource(const char* s)
{
  std::string src = s;

  // For backwards compatibility replace varibles in source names.
  // This should eventually be removed.
  this->Makefile->ExpandVariablesInString(src);

  cmSourceFile* sf = this->Makefile->GetOrCreateSource(src.c_str());
  this->AddSourceFile(sf);
  return sf;
}

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
//----------------------------------------------------------------------------
void cmTarget::ProcessSourceExpression(std::string const& expr)
{
  if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 &&
     expr[expr.size()-1] == '>')
    {
    std::string objLibName = expr.substr(17, expr.size()-18);
    this->ObjectLibraries.push_back(objLibName);
    }
  else
    {
    cmOStringStream e;
    e << "Unrecognized generator expression:\n"
      << "  " << expr;
    this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
    }
}

578
579
580
581
582
//----------------------------------------------------------------------------
struct cmTarget::SourceFileFlags
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
{
  struct SourceFileFlags flags;
583
584
585
586
587
588
589
590
591
  this->ConstructSourceFileFlags();
  std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
    this->Internal->SourceFlagsMap.find(sf);
  if(si != this->Internal->SourceFlagsMap.end())
    {
    flags = si->second;
    }
  return flags;
}
592

593
594
595
596
597
598
599
600
//----------------------------------------------------------------------------
void cmTarget::ConstructSourceFileFlags()
{
  if(this->Internal->SourceFileFlagsConstructed)
    {
    return;
    }
  this->Internal->SourceFileFlagsConstructed = true;
601

602
603
  // Process public headers to mark the source files.
  if(const char* files = this->GetProperty("PUBLIC_HEADER"))
604
605
606
    {
    std::vector<std::string> relFiles;
    cmSystemTools::ExpandListArgument(files, relFiles);
607
608
    for(std::vector<std::string>::iterator it = relFiles.begin();
        it != relFiles.end(); ++it)
609
      {
610
      if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
611
        {
612
613
614
        SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
        flags.MacFolder = "Headers";
        flags.Type = cmTarget::SourceFileTypePublicHeader;
615
616
617
618
        }
      }
    }

619
620
621
  // Process private headers after public headers so that they take
  // precedence if a file is listed in both.
  if(const char* files = this->GetProperty("PRIVATE_HEADER"))
622
    {
623
624
625
626
    std::vector<std::string> relFiles;
    cmSystemTools::ExpandListArgument(files, relFiles);
    for(std::vector<std::string>::iterator it = relFiles.begin();
        it != relFiles.end(); ++it)
627
      {
628
      if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
629
        {
630
631
632
        SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
        flags.MacFolder = "PrivateHeaders";
        flags.Type = cmTarget::SourceFileTypePrivateHeader;
633
634
635
636
        }
      }
    }

637
638
  // Mark sources listed as resources.
  if(const char* files = this->GetProperty("RESOURCE"))
639
    {
640
641
642
643
644
645
646
647
648
649
650
651
    std::vector<std::string> relFiles;
    cmSystemTools::ExpandListArgument(files, relFiles);
    for(std::vector<std::string>::iterator it = relFiles.begin();
        it != relFiles.end(); ++it)
      {
      if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
        {
        SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
        flags.MacFolder = "Resources";
        flags.Type = cmTarget::SourceFileTypeResource;
        }
      }
652
653
    }

654
655
656
657
658
  // Handle the MACOSX_PACKAGE_LOCATION property on source files that
  // were not listed in one of the other lists.
  std::vector<cmSourceFile*> const& sources = this->GetSourceFiles();
  for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
      si != sources.end(); ++si)
659
    {
660
661
    cmSourceFile* sf = *si;
    if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
662
      {
663
664
      SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
      if(flags.Type == cmTarget::SourceFileTypeNormal)
665
        {
666
667
        flags.MacFolder = location;
        if(strcmp(location, "Resources") == 0)
668
          {
669
670
671
672
673
          flags.Type = cmTarget::SourceFileTypeResource;
          }
        else
          {
          flags.Type = cmTarget::SourceFileTypeMacContent;
674
675
676
677
678
679
          }
        }
      }
    }
}

680
//----------------------------------------------------------------------------
681
682
void cmTarget::MergeLinkLibraries( cmMakefile& mf,
                                   const char *selfname,
Ken Martin's avatar
Ken Martin committed
683
                                   const LinkLibraryVectorType& libs )
684
{
685
686
  // Only add on libraries we haven't added on before.
  // Assumption: the global link libraries could only grow, never shrink
Ken Martin's avatar
Ken Martin committed
687
688
  LinkLibraryVectorType::const_iterator i = libs.begin();
  i += this->PrevLinkedLibraries.size();
689
  for( ; i != libs.end(); ++i )
690
    {
691
692
693
694
    // This is equivalent to the target_link_libraries plain signature.
    this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
    this->AppendProperty("INTERFACE_LINK_LIBRARIES",
      this->GetDebugGeneratorExpressions(i->first.c_str(), i->second).c_str());
695
    }
Ken Martin's avatar
Ken Martin committed
696
  this->PrevLinkedLibraries = libs;
697
698
}

699
//----------------------------------------------------------------------------
700
701
702
void cmTarget::AddLinkDirectory(const char* d)
{
  // Make sure we don't add unnecessary search directories.
703
  if(this->LinkDirectoriesEmmitted.insert(d).second)
704
    {
705
    this->LinkDirectories.push_back(d);
706
    }
707
708
}

709
//----------------------------------------------------------------------------
710
const std::vector<std::string>& cmTarget::GetLinkDirectories() const
711
{
Ken Martin's avatar
Ken Martin committed
712
  return this->LinkDirectories;
713
}
714

715
//----------------------------------------------------------------------------
716
cmTarget::LinkLibraryType cmTarget::ComputeLinkType(const char* config) const
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
{
  // No configuration is always optimized.
  if(!(config && *config))
    {
    return cmTarget::OPTIMIZED;
    }

  // Get the list of configurations considered to be DEBUG.
  std::vector<std::string> const& debugConfigs =
    this->Makefile->GetCMakeInstance()->GetDebugConfigs();

  // Check if any entry in the list matches this configuration.
  std::string configUpper = cmSystemTools::UpperCase(config);
  for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
      i != debugConfigs.end(); ++i)
    {
    if(*i == configUpper)
      {
      return cmTarget::DEBUG;
      }
    }

  // The current configuration is not a debug configuration.
  return cmTarget::OPTIMIZED;
}

743
744
//----------------------------------------------------------------------------
void cmTarget::ClearDependencyInformation( cmMakefile& mf,
Ken Martin's avatar
Ken Martin committed
745
                                           const char* target )
746
747
748
749
750
{
  // Clear the dependencies. The cache variable must exist iff we are
  // recording dependency information for this target.
  std::string depname = target;
  depname += "_LIB_DEPENDS";
Ken Martin's avatar
Ken Martin committed
751
  if (this->RecordDependencies)
752
753
754
755
756
757
758
759
760
761
762
763
764
765
    {
    mf.AddCacheDefinition(depname.c_str(), "",
                          "Dependencies for target", cmCacheManager::STATIC);
    }
  else
    {
    if (mf.GetDefinition( depname.c_str() ))
      {
      std::string message = "Target ";
      message += target;
      message += " has dependency information when it shouldn't.\n";
      message += "Your cache is probably stale. Please remove the entry\n  ";
      message += depname;
      message += "\nfrom the cache.";
766
      cmSystemTools::Error( message.c_str() );
767
768
769
770
      }
    }
}

771
772
773
774
775
776
777
//----------------------------------------------------------------------------
bool cmTarget::NameResolvesToFramework(const std::string& libname)
{
  return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
    NameResolvesToFramework(libname);
}

778
779
//----------------------------------------------------------------------------
void cmTarget::GetDirectLinkLibraries(const char *config,
780
781
                            std::vector<std::string> &libs,
                            cmTarget const* head) const
782
783
784
785
786
787
{
  const char *prop = this->GetProperty("LINK_LIBRARIES");
  if (prop)
    {
    cmListFileBacktrace lfbt;
    cmGeneratorExpression ge(lfbt);
788
    const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
789
790
791
792

    cmGeneratorExpressionDAGChecker dagChecker(lfbt,
                                        this->GetName(),
                                        "LINK_LIBRARIES", 0, 0);
793
    cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
794
795
796
797
798
                                        config,
                                        false,
                                        head,
                                        &dagChecker),
                                      libs);
799

800
801
802
803
804
805
806
807
808
    std::set<cmStdString> seenProps = cge->GetSeenTargetProperties();
    for (std::set<cmStdString>::const_iterator it = seenProps.begin();
        it != seenProps.end(); ++it)
      {
      if (!this->GetProperty(it->c_str()))
        {
        this->LinkImplicitNullProperties.insert(*it);
        }
      }
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
//----------------------------------------------------------------------------
void cmTarget::GetInterfaceLinkLibraries(const char *config,
                            std::vector<std::string> &libs, cmTarget *head)
{
  const char *prop = this->GetProperty("INTERFACE_LINK_LIBRARIES");
  if (prop)
    {
    cmListFileBacktrace lfbt;
    cmGeneratorExpression ge(lfbt);
    const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);

    cmGeneratorExpressionDAGChecker dagChecker(lfbt,
                                        this->GetName(),
                                        "INTERFACE_LINK_LIBRARIES", 0, 0);
    cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
                                        config,
                                        false,
                                        head,
                                        &dagChecker),
                                      libs);
    }
}

835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
//----------------------------------------------------------------------------
std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
                                  cmTarget::LinkLibraryType llt)
{
  if (llt == GENERAL)
    {
    return value;
    }

  // Get the list of configurations considered to be DEBUG.
  std::vector<std::string> const& debugConfigs =
                      this->Makefile->GetCMakeInstance()->GetDebugConfigs();

  std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";

  if (debugConfigs.size() > 1)
    {
    for(std::vector<std::string>::const_iterator
          li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li)
      {
      configString += ",$<CONFIG:" + *li + ">";
      }
    configString = "$<OR:" + configString + ">";
    }

  if (llt == OPTIMIZED)
    {
    configString = "$<NOT:" + configString + ">";
    }
  return "$<" + configString + ":" + value + ">";
}

//----------------------------------------------------------------------------
static std::string targetNameGenex(const char *lib)
{
  return std::string("$<TARGET_NAME:") + lib + ">";
}

873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
//----------------------------------------------------------------------------
bool cmTarget::PushTLLCommandTrace(TLLSignature signature)
{
  bool ret = true;
  if (!this->TLLCommands.empty())
    {
    if (this->TLLCommands.back().first != signature)
      {
      ret = false;
      }
    }
  cmListFileBacktrace lfbt;
  this->Makefile->GetBacktrace(lfbt);
  this->TLLCommands.push_back(std::make_pair(signature, lfbt));
  return ret;
}

//----------------------------------------------------------------------------
void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
                                     TLLSignature sig) const
{
  std::vector<cmListFileBacktrace> sigs;
  typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container;
  for(Container::const_iterator it = this->TLLCommands.begin();
      it != this->TLLCommands.end(); ++it)
    {
    if (it->first == sig)
      {
      sigs.push_back(it->second);
      }
    }
  if (!sigs.empty())
    {
    const char *sigString
                        = (sig == cmTarget::KeywordTLLSignature ? "keyword"
                                                                : "plain");
    s << "The uses of the " << sigString << " signature are here:\n";
910
    std::set<cmStdString> emitted;
911
912
913
914
915
916
917
    for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
        it != sigs.end(); ++it)
      {
      cmListFileBacktrace::const_iterator i = it->begin();
      if(i != it->end())
        {
        cmListFileContext const& lfc = *i;
918
919
920
921
922
923
        cmOStringStream line;
        line << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
        if (emitted.insert(line.str()).second)
          {
          s << line.str();
          }
924
925
926
927
928
929
        ++i;
        }
      }
    }
}

930
//----------------------------------------------------------------------------
931
void cmTarget::AddLinkLibrary(cmMakefile& mf,
932
                              const char *target, const char* lib,
933
934
                              LinkLibraryType llt)
{
935
936
937
938
939
  // Never add a self dependency, even if the user asks for it.
  if(strcmp( target, lib ) == 0)
    {
    return;
    }
940
941

  cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
942
  {
943
944
  const bool isNonImportedTarget = tgt && !tgt->IsImported();

945
946
947
  const std::string libName = (isNonImportedTarget && llt != GENERAL)
                                                        ? targetNameGenex(lib)
                                                        : std::string(lib);
948
949
950
951
952
  this->AppendProperty("LINK_LIBRARIES",
                       this->GetDebugGeneratorExpressions(libName,
                                                          llt).c_str());
  }

953
954
  if (cmGeneratorExpression::Find(lib) != std::string::npos
      || (tgt && tgt->GetType() == INTERFACE_LIBRARY))
955
956
957
958
    {
    return;
    }

959
  cmTarget::LibraryID tmp;
Ken Martin's avatar
Ken Martin committed
960
961
962
  tmp.first = lib;
  tmp.second = llt;
  this->LinkLibraries.push_back( tmp );
963
  this->OriginalLinkLibraries.push_back(tmp);
964
  this->ClearLinkMaps();
965

966
967
968
969
  // Add the explicit dependency information for this target. This is
  // simply a set of libraries separated by ";". There should always
  // be a trailing ";". These library names are not canonical, in that
  // they may be "-framework x", "-ly", "/path/libz.a", etc.
970
971
972
973
  // We shouldn't remove duplicates here because external libraries
  // may be purposefully duplicated to handle recursive dependencies,
  // and we removing one instance will break the link line. Duplicates
  // will be appropriately eliminated at emit time.
Ken Martin's avatar
Ken Martin committed
974
  if(this->RecordDependencies)
975
    {
976
977
978
979
980
981
982
983
    std::string targetEntry = target;
    targetEntry += "_LIB_DEPENDS";
    std::string dependencies;
    const char* old_val = mf.GetDefinition( targetEntry.c_str() );
    if( old_val )
      {
      dependencies += old_val;
      }
984
985
986
987
988
989
990
991
992
993
994
995
996
    switch (llt)
      {
      case cmTarget::GENERAL:
        dependencies += "general";
        break;
      case cmTarget::DEBUG:
        dependencies += "debug";
        break;
      case cmTarget::OPTIMIZED:
        dependencies += "optimized";
        break;
      }
    dependencies += ";";
997
998
    dependencies += lib;
    dependencies += ";";
999
    mf.AddCacheDefinition( targetEntry.c_str(), dependencies.c_str(),
1000
                           "Dependencies for the target",
1001
                           cmCacheManager::STATIC );
1002
    }
1003

1004
1005
}

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
//----------------------------------------------------------------------------
void
cmTarget::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
{
  for(std::set<cmStdString>::const_iterator li = incs.begin();
      li != incs.end(); ++li)
    {
    this->SystemIncludeDirectories.insert(*li);
    }
}

//----------------------------------------------------------------------------
void
cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs)
{
  for(std::vector<std::string>::const_iterator li = incs.begin();
      li != incs.end(); ++li)
    {
    this->SystemIncludeDirectories.insert(*li);
    }
}

1028
1029
1030
1031
1032
1033
1034
1035
//----------------------------------------------------------------------------
void cmTarget::FinalizeSystemIncludeDirectories()
{
  for (std::vector<cmValueWithOrigin>::const_iterator
      it = this->Internal->LinkInterfacePropertyEntries.begin(),
      end = this->Internal->LinkInterfacePropertyEntries.end();
      it != end; ++it)
    {
1036
1037
1038
1039
1040
    if (!cmGeneratorExpression::IsValidTargetName(it->Value)
        && cmGeneratorExpression::Find(it->Value) == std::string::npos)
      {
      continue;
      }
1041
1042
1043
1044
1045
1046
1047
    {
    cmListFileBacktrace lfbt;
    cmGeneratorExpression ge(lfbt);
    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
                                                      ge.Parse(it->Value);
    std::string targetName = cge->Evaluate(this->Makefile, 0,
                                      false, this, 0, 0);
1048
1049
    cmTarget *tgt = this->Makefile->FindTargetToUse(targetName.c_str());
    if (!tgt)
1050
1051
1052
      {
      continue;
      }
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
    if (tgt->IsImported()
        && tgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")
        && !this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"))
      {
      std::string includeGenex = "$<TARGET_PROPERTY:" +
                                it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
      if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
        {
        // Because it->Value is a generator expression, ensure that it
        // evaluates to the non-empty string before being used in the
        // TARGET_PROPERTY expression.
        includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
        }
      this->SystemIncludeDirectories.insert(includeGenex);
      return; // The INTERFACE_SYSTEM_INCLUDE_DIRECTORIES are a subset
              // of the INTERFACE_INCLUDE_DIRECTORIES
      }
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
    }
    std::string includeGenex = "$<TARGET_PROPERTY:" +
                        it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>";
    if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
      {
      // Because it->Value is a generator expression, ensure that it
      // evaluates to the non-empty string before being used in the
      // TARGET_PROPERTY expression.
      includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
      }
    this->SystemIncludeDirectories.insert(includeGenex);
    }
}

1084
//----------------------------------------------------------------------------
1085
1086
1087
void
cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
{
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
  // There are two key parts of the dependency analysis: (1)
  // determining the libraries in the link line, and (2) constructing
  // the dependency graph for those libraries.
  //
  // The latter is done using the cache entries that record the
  // dependencies of each library.
  //
  // The former is a more thorny issue, since it is not clear how to
  // determine if two libraries listed on the link line refer to the a
  // single library or not. For example, consider the link "libraries"
1098
  //    /usr/lib/libtiff.so -ltiff
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  // Is this one library or two? The solution implemented here is the
  // simplest (and probably the only practical) one: two libraries are
  // the same if their "link strings" are identical. Thus, the two
  // libraries above are considered distinct. This also means that for
  // dependency analysis to be effective, the CMake user must specify
  // libraries build by his project without using any linker flags or
  // file extensions. That is,
  //    LINK_LIBRARIES( One Two )
  // instead of
  //    LINK_LIBRARIES( -lOne ${binarypath}/libTwo.a )
  // The former is probably what most users would do, but it never
  // hurts to document the assumptions. :-) Therefore, in the analysis
  // code, the "canonical name" of a library is simply its name as
  // given to a LINK_LIBRARIES command.
1113
1114
1115
  //
  // Also, we will leave the original link line intact; we will just add any
  // dependencies that were missing.
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
  //
  // There is a problem with recursive external libraries
  // (i.e. libraries with no dependency information that are
  // recursively dependent). We must make sure that the we emit one of
  // the libraries twice to satisfy the recursion, but we shouldn't
  // emit it more times than necessary. In particular, we must make
  // sure that handling this improbable case doesn't cost us when
  // dealing with the common case of non-recursive libraries. The
  // solution is to assume that the recursion is satisfied at one node
  // of the dependency tree. To illustrate, assume libA and libB are
  // extrenal and mutually dependent. Suppose libX depends on
  // libA, and libY on libA and libX. Then
  //   TARGET_LINK_LIBRARIES( Y X A B A )
  //   TARGET_LINK_LIBRARIES( X A B A )
  //   TARGET_LINK_LIBRARIES( Exec Y )
  // would result in "-lY -lX -lA -lB -lA". This is the correct way to
  // specify the dependencies, since the mutual dependency of A and B
  // is resolved *every time libA is specified*.
  //
  // Something like
  //   TARGET_LINK_LIBRARIES( Y X A B A )
  //   TARGET_LINK_LIBRARIES( X A B )
  //   TARGET_LINK_LIBRARIES( Exec Y )
  // would result in "-lY -lX -lA -lB", and the mutual dependency
  // information is lost. This is because in some case (Y), the mutual
  // dependency of A and B is listed, while in another other case (X),
  // it is not. Depending on which line actually emits A, the mutual
  // dependency may or may not be on the final link line.  We can't
  // handle this pathalogical case cleanly without emitting extra
  // libraries for the normal cases. Besides, the dependency
  // information for X is wrong anyway: if we build an executable
  // depending on X alone, we would not have the mutual dependency on
  // A and B resolved.
  //
  // IMPROVEMENTS:
  // -- The current algorithm will not always pick the "optimal" link line
  //    when recursive dependencies are present. It will instead break the
  //    cycles at an aribtrary point. The majority of projects won't have
  //    cyclic dependencies, so this is probably not a big deal. Note that
  //    the link line is always correct, just not necessary optimal.
1156

1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
 {
 // Expand variables in link library names.  This is for backwards
 // compatibility with very early CMake versions and should
 // eventually be removed.  This code was moved here from the end of
 // old source list processing code which was called just before this
 // method.
 for(LinkLibraryVectorType::iterator p = this->LinkLibraries.begin();
     p != this->LinkLibraries.end(); ++p)
   {
   this->Makefile->ExpandVariablesInString(p->first, true, true);
   }
 }

 // The dependency map.
 DependencyMap dep_map;

 // 1. Build the dependency graph
 //
 for(LinkLibraryVectorType::reverse_iterator lib
       = this->LinkLibraries.rbegin();
     lib != this->LinkLibraries.rend(); ++lib)
   {
   this->GatherDependencies( mf, *lib, dep_map);
   }

 // 2. Remove any dependencies that are already satisfied in the original
 // link line.
 //
 for(LinkLibraryVectorType::iterator lib = this->LinkLibraries.begin();
     lib != this->LinkLibraries.end(); ++lib)
   {
   for( LinkLibraryVectorType::iterator lib2 = lib;
        lib2 != this->LinkLibraries.end(); ++lib2)
     {
     this->DeleteDependency( dep_map, *lib, *lib2);
     }
   }


 // 3. Create the new link line by simply emitting any dependencies that are
 // missing.  Start from the back and keep adding.
 //
 std::set<DependencyMap::key_type> done, visited;
 std::vector<DependencyMap::key_type> newLinkLibraries;
 for(LinkLibraryVectorType::reverse_iterator lib =
       this->LinkLibraries.rbegin();
     lib != this->LinkLibraries.rend(); ++lib)
   {
   // skip zero size library entries, this may happen
   // if a variable expands to nothing.
   if (lib->first.size() != 0)
     {
     this->Emit( *lib, dep_map, done, visited, newLinkLibraries );
     }
   }

 // 4. Add the new libraries to the link line.
 //
 for( std::vector<DependencyMap::key_type>::reverse_iterator k =
        newLinkLibraries.rbegin();
      k != newLinkLibraries.rend(); ++k )
   {
   // get the llt from the dep_map
   this->LinkLibraries.push_back( std::make_pair(k->first,k->second) );
   }
 this->LinkLibrariesAnalyzed = true;
1223
1224
}

1225
//----------------------------------------------------------------------------
1226
void cmTarget::InsertDependency( DependencyMap& depMap,
1227
                                 const LibraryID& lib,
1228
                                 const LibraryID& dep)
1229
1230
1231
{
  depMap[lib].push_back(dep);
}
1232

1233
//----------------------------------------------------------------------------
1234
void cmTarget::DeleteDependency( DependencyMap& depMap,
1235
                                 const LibraryID& lib,
1236
                                 const LibraryID& dep)
1237
1238
1239
1240
1241
1242
1243
1244
1245
{
  // Make sure there is an entry in the map for lib. If so, delete all
  // dependencies to dep. There may be repeated entries because of
  // external libraries that are specified multiple times.
  DependencyMap::iterator map_itr = depMap.find( lib );
  if( map_itr != depMap.end() )
    {
    DependencyList& depList = map_itr->second;
    DependencyList::iterator itr;
1246
    while( (itr = std::find(depList.begin(), depList.end(), dep)) !=
Bill Hoffman's avatar
Bill Hoffman committed
1247
           depList.end() )
1248
1249
1250
1251
1252
      {
      depList