cmTarget.cxx 192 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>
Ken Martin's avatar
Ken Martin committed
25
#include <queue>
26
#include <stdlib.h> // required for atof
27
#include <assert.h>
Nicolas Despres's avatar
Nicolas Despres committed
28
29
30
31
32
33
34
35
36
37
38

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
39
40
      case cmTarget::OBJECT_LIBRARY:
        return "OBJECT_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
41
42
43
44
45
46
      case cmTarget::EXECUTABLE:
        return "EXECUTABLE";
      case cmTarget::UTILITY:
        return "UTILITY";
      case cmTarget::GLOBAL_TARGET:
        return "GLOBAL_TARGET";
47
48
      case cmTarget::INTERFACE_LIBRARY:
        return "INTERFACE_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
49
50
51
52
53
54
      case cmTarget::UNKNOWN_LIBRARY:
        return "UNKNOWN_LIBRARY";
    }
  assert(0 && "Unexpected target type");
  return 0;
}
55

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

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

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

79
80
81
82
83
84
85
86
//----------------------------------------------------------------------------
class cmTargetInternals
{
public:
  cmTargetInternals()
    {
    this->SourceFileFlagsConstructed = false;
    }
87
88
  cmTargetInternals(cmTargetInternals const& r)
    {
89
    this->SourceFileFlagsConstructed = false;
90
91
92
93
    // Only some of these entries are part of the object state.
    // Others not copied here are result caches.
    this->SourceEntries = r.SourceEntries;
    }
94
  ~cmTargetInternals();
95
96
97
  typedef cmTarget::SourceFileFlags SourceFileFlags;
  std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
  bool SourceFileFlagsConstructed;
98
99
100

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

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

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

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

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

124
125
  typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
                                                          LinkClosureMapType;
126
  LinkClosureMapType LinkClosureMap;
127
128
129
130

  struct SourceEntry { std::vector<cmSourceFile*> Depends; };
  typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
  SourceEntriesType SourceEntries;
131

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

146
  std::map<std::string, std::vector<TargetPropertyEntry*> >
147
                                CachedLinkInterfaceIncludeDirectoriesEntries;
148
149
  std::map<std::string, std::vector<TargetPropertyEntry*> >
                                CachedLinkInterfaceCompileOptionsEntries;
150
151
  std::map<std::string, std::vector<TargetPropertyEntry*> >
                                CachedLinkInterfaceCompileDefinitionsEntries;
152
153
154

  std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
  std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
155
  std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
156
157
};

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

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

185
186
187
//----------------------------------------------------------------------------
cmTargetInternals::~cmTargetInternals()
{
Stephen Kelly's avatar
Stephen Kelly committed
188
  deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
189
  deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
190
  deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
191
192
}

193
194
195
//----------------------------------------------------------------------------
cmTarget::cmTarget()
{
196
197
198
199
200
201
202
#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
203
204
205
  this->Makefile = 0;
  this->LinkLibrariesAnalyzed = false;
  this->HaveInstallRule = false;
206
  this->DLLPlatform = false;
207
  this->IsApple = false;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
208
  this->IsImportedTarget = false;
209
  this->BuildInterfaceIncludesAppended = false;
210
  this->DebugIncludesDone = false;
211
  this->DebugCompileOptionsDone = false;
212
  this->DebugCompileDefinitionsDone = false;
213
214
}

215
//----------------------------------------------------------------------------
216
217
void cmTarget::DefineProperties(cmake *cm)
{
218
219
  cm->DefineProperty
    ("RULE_LAUNCH_COMPILE", cmProperty::TARGET,
220
     "", "", true);
221
222
  cm->DefineProperty
    ("RULE_LAUNCH_LINK", cmProperty::TARGET,
223
     "", "", true);
224
225
  cm->DefineProperty
    ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET,
226
     "", "", true);
227
}
228

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

245
246
247
248
//----------------------------------------------------------------------------
void cmTarget::SetMakefile(cmMakefile* mf)
{
  // Set our makefile.
Ken Martin's avatar
Ken Martin committed
249
  this->Makefile = mf;
250

251
252
253
  // set the cmake instance of the properties
  this->Properties.SetCMakeInstance(mf->GetCMakeInstance());

254
255
256
257
258
  // Check whether this is a DLL platform.
  this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
                       this->Makefile->IsOn("CYGWIN") ||
                       this->Makefile->IsOn("MINGW"));

259
260
261
  // Check whether we are targeting an Apple platform.
  this->IsApple = this->Makefile->IsOn("APPLE");

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

285
286
287

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

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

309
310
311
312
313
314
    // 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
315
    if(this->TargetTypeValue != cmTarget::EXECUTABLE)
316
317
318
319
320
321
      {
      std::string property = cmSystemTools::UpperCase(*ci);
      property += "_POSTFIX";
      this->SetPropertyDefault(property.c_str(), 0);
      }
    }
322
323
324

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

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

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

  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);
    }

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

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

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

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

367
  // Record current policies for later use.
368
369
370
371
372
373
374
#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
375
376
377
378
379
380
381
382

  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;
    }
383
384
}

385
386
387
//----------------------------------------------------------------------------
void cmTarget::FinishConfigure()
{
388
389
390
391
392
393
  // 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();

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

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

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

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

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

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

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

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

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

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

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

491
492
493
494
//----------------------------------------------------------------------------
class cmTargetTraceDependencies
{
public:
495
  cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal);
496
497
498
  void Trace();
private:
  cmTarget* Target;
499
  cmTargetInternals* Internal;
500
501
  cmMakefile* Makefile;
  cmGlobalGenerator* GlobalGenerator;
502
503
  typedef cmTargetInternals::SourceEntry SourceEntry;
  SourceEntry* CurrentEntry;
504
505
506
507
508
509
510
511
  std::queue<cmSourceFile*> SourceQueue;
  std::set<cmSourceFile*> SourcesQueued;
  typedef std::map<cmStdString, cmSourceFile*> NameMapType;
  NameMapType NameMap;

  void QueueSource(cmSourceFile* sf);
  void FollowName(std::string const& name);
  void FollowNames(std::vector<std::string> const& names);
512
513
514
515
  bool IsUtility(std::string const& dep);
  void CheckCustomCommand(cmCustomCommand const& cc);
  void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
};
Alexander Neundorf's avatar
   
Alexander Neundorf committed
516

517
518
//----------------------------------------------------------------------------
cmTargetTraceDependencies
519
::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal):
520
  Target(target), Internal(internal)
521
{
522
523
524
525
  // Convenience.
  this->Makefile = this->Target->GetMakefile();
  this->GlobalGenerator =
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
526
  this->CurrentEntry = 0;
527
528
529
530
531

  // Queue all the source files already specified for the target.
  std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
  for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
      si != sources.end(); ++si)
532
    {
533
    this->QueueSource(*si);
534
535
536
537
538
539
540
541
542
543
544
545
    }

  // Queue pre-build, pre-link, and post-build rule dependencies.
  this->CheckCustomCommands(this->Target->GetPreBuildCommands());
  this->CheckCustomCommands(this->Target->GetPreLinkCommands());
  this->CheckCustomCommands(this->Target->GetPostBuildCommands());
}

//----------------------------------------------------------------------------
void cmTargetTraceDependencies::Trace()
{
  // Process one dependency at a time until the queue is empty.
546
  while(!this->SourceQueue.empty())
547
    {
548
549
550
    // Get the next source from the queue.
    cmSourceFile* sf = this->SourceQueue.front();
    this->SourceQueue.pop();
551
    this->CurrentEntry = &this->Internal->SourceEntries[sf];
552

553
554
    // Queue dependencies added explicitly by the user.
    if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
555
      {
556
557
558
559
560
561
562
      std::vector<std::string> objDeps;
      cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
      this->FollowNames(objDeps);
      }

    // Queue the source needed to generate this file, if any.
    this->FollowName(sf->GetFullPath());
563

564
565
566
567
568
569
570
    // Queue dependencies added programatically by commands.
    this->FollowNames(sf->GetDepends());

    // Queue custom command dependencies.
    if(cmCustomCommand const* cc = sf->GetCustomCommand())
      {
      this->CheckCustomCommand(*cc);
571
572
      }
    }
573
  this->CurrentEntry = 0;
574
575
}

576
//----------------------------------------------------------------------------
577
578
579
580
581
582
583
584
585
586
587
588
589
void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
{
  if(this->SourcesQueued.insert(sf).second)
    {
    this->SourceQueue.push(sf);

    // Make sure this file is in the target.
    this->Target->AddSourceFile(sf);
    }
}

//----------------------------------------------------------------------------
void cmTargetTraceDependencies::FollowName(std::string const& name)
590
{
591
592
  NameMapType::iterator i = this->NameMap.find(name);
  if(i == this->NameMap.end())
593
    {
594
595
596
597
598
599
600
    // Check if we know how to generate this file.
    cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str());
    NameMapType::value_type entry(name, sf);
    i = this->NameMap.insert(entry).first;
    }
  if(cmSourceFile* sf = i->second)
    {
601
602
603
604
605
606
    // Record the dependency we just followed.
    if(this->CurrentEntry)
      {
      this->CurrentEntry->Depends.push_back(sf);
      }

607
    this->QueueSource(sf);
608
609
610
611
    }
}

//----------------------------------------------------------------------------
612
void
613
cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
614
{
615
616
  for(std::vector<std::string>::const_iterator i = names.begin();
      i != names.end(); ++i)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
617
    {
618
    this->FollowName(*i);
Alexander Neundorf's avatar
   
Alexander Neundorf committed
619
620
621
    }
}

622
623
624
625
626
627
628
629
630
631
632
633
634
635
//----------------------------------------------------------------------------
bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
{
  // Dependencies on targets (utilities) are supposed to be named by
  // just the target name.  However for compatibility we support
  // naming the output file generated by the target (assuming there is
  // no output-name property which old code would not have set).  In
  // that case the target name will be the file basename of the
  // dependency.
  std::string util = cmSystemTools::GetFilenameName(dep);
  if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
    {
    util = cmSystemTools::GetFilenameWithoutLastExtension(util);
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
636

637
638
  // Check for a target with this name.
  if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
Ken Martin's avatar
Ken Martin committed
639
    {
640
641
642
643
    // If we find the target and the dep was given as a full path,
    // then make sure it was not a full path to something else, and
    // the fact that the name matched a target was just a coincidence.
    if(cmSystemTools::FileIsFullPath(dep.c_str()))
644
      {
645
      if(t->GetType() >= cmTarget::EXECUTABLE &&
646
         t->GetType() <= cmTarget::MODULE_LIBRARY)
647
        {
648
649
650
651
652
653
654
655
656
657
658
659
        // This is really only for compatibility so we do not need to
        // worry about configuration names and output names.
        std::string tLocation = t->GetLocation(0);
        tLocation = cmSystemTools::GetFilenamePath(tLocation);
        std::string depLocation = cmSystemTools::GetFilenamePath(dep);
        depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
        tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
        if(depLocation == tLocation)
          {
          this->Target->AddUtility(util.c_str());
          return true;
          }
660
661
        }
      }
662
663
664
665
666
667
668
    else
      {
      // The original name of the dependency was not a full path.  It
      // must name a target, so add the target-level dependency.
      this->Target->AddUtility(util.c_str());
      return true;
      }
669
    }
670
671
672
673
674
675
676
677
678
679
680
681

  // The dependency does not name a target built in this project.
  return false;
}

//----------------------------------------------------------------------------
void
cmTargetTraceDependencies
::CheckCustomCommand(cmCustomCommand const& cc)
{
  // Transform command names that reference targets built in this
  // project to corresponding target-level dependencies.
682
683
684
685
686
  cmGeneratorExpression ge(cc.GetBacktrace());

  // Add target-level dependencies referenced by generator expressions.
  std::set<cmTarget*> targets;

687
688
  for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
      cit != cc.GetCommandLines().end(); ++cit)
Ken Martin's avatar
Ken Martin committed
689
    {
690
    std::string const& command = *cit->begin();
691
692
    // Check for a target with this name.
    if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
Ken Martin's avatar
Ken Martin committed
693
      {
694
      if(t->GetType() == cmTarget::EXECUTABLE)
Ken Martin's avatar
Ken Martin committed
695
        {
696
697
698
699
700
        // The command refers to an executable target built in
        // this project.  Add the target-level dependency to make
        // sure the executable is up to date before this custom
        // command possibly runs.
        this->Target->AddUtility(command.c_str());
Ken Martin's avatar
Ken Martin committed
701
702
        }
      }
703
704
705
706
707

    // Check for target references in generator expressions.
    for(cmCustomCommandLine::const_iterator cli = cit->begin();
        cli != cit->end(); ++cli)
      {
708
709
710
711
      const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
                                                              = ge.Parse(*cli);
      cge->Evaluate(this->Makefile, 0, true);
      std::set<cmTarget*> geTargets = cge->GetTargets();
712
713
714
715
716
      for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
          it != geTargets.end(); ++it)
        {
        targets.insert(*it);
        }
717
718
719
720
721
722
723
      }
    }

  for(std::set<cmTarget*>::iterator ti = targets.begin();
      ti != targets.end(); ++ti)
    {
    this->Target->AddUtility((*ti)->GetName());
Ken Martin's avatar
Ken Martin committed
724
    }
Alexander Neundorf's avatar
   
Alexander Neundorf committed
725

726
727
728
729
  // Queue the custom command dependencies.
  std::vector<std::string> const& depends = cc.GetDepends();
  for(std::vector<std::string>::const_iterator di = depends.begin();
      di != depends.end(); ++di)
Ken Martin's avatar
Ken Martin committed
730
    {
731
732
    std::string const& dep = *di;
    if(!this->IsUtility(dep))
Ken Martin's avatar
Ken Martin committed
733
      {
734
735
      // The dependency does not name a target and may be a file we
      // know how to generate.  Queue it.
736
      this->FollowName(dep);
Ken Martin's avatar
Ken Martin committed
737
738
739
740
      }
    }
}

741
742
743
744
//----------------------------------------------------------------------------
void
cmTargetTraceDependencies
::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
745
{
746
747
  for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
      cli != commands.end(); ++cli)
748
    {
749
    this->CheckCustomCommand(*cli);
750
    }
751
752
753
}

//----------------------------------------------------------------------------
754
void cmTarget::TraceDependencies()
755
{
756
757
758
759
760
761
762
763
764
  // CMake-generated targets have no dependencies to trace.  Normally tracing
  // would find nothing anyway, but when building CMake itself the "install"
  // target command ends up referencing the "cmake" target but we do not
  // really want the dependency because "install" depend on "all" anyway.
  if(this->GetType() == cmTarget::GLOBAL_TARGET)
    {
    return;
    }

765
  // Use a helper object to trace the dependencies.
766
  cmTargetTraceDependencies tracer(this, this->Internal.Get());
767
768
769
  tracer.Trace();
}

770
771
772
773
774
775
776
//----------------------------------------------------------------------------
bool cmTarget::FindSourceFiles()
{
  for(std::vector<cmSourceFile*>::const_iterator
        si = this->SourceFiles.begin();
      si != this->SourceFiles.end(); ++si)
    {
777
778
    std::string e;
    if((*si)->GetFullPath(&e).empty())
779
      {
780
781
782
783
784
785
      if(!e.empty())
        {
        cmake* cm = this->Makefile->GetCMakeInstance();
        cm->IssueMessage(cmake::FATAL_ERROR, e,
                         this->GetBacktrace());
        }
786
787
788
789
790
791
      return false;
      }
    }
  return true;
}

792
793
794
795
796
797
798
799
800
//----------------------------------------------------------------------------
std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles()
{
  return this->SourceFiles;
}

//----------------------------------------------------------------------------
void cmTarget::AddSourceFile(cmSourceFile* sf)
{
801
802
803
  typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
  SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
  if(i == this->Internal->SourceEntries.end())
804
    {
805
806
807
    typedef cmTargetInternals::SourceEntry SourceEntry;
    SourceEntriesType::value_type entry(sf, SourceEntry());
    i = this->Internal->SourceEntries.insert(entry).first;
808
809
810
811
    this->SourceFiles.push_back(sf);
    }
}

812
813
814
815
816
817
818
819
820
821
822
823
824
//----------------------------------------------------------------------------
std::vector<cmSourceFile*> const*
cmTarget::GetSourceDepends(cmSourceFile* sf)
{
  typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
  SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
  if(i != this->Internal->SourceEntries.end())
    {
    return &i->second.Depends;
    }
  return 0;
}

825
826
827
828
829
//----------------------------------------------------------------------------
void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
  for(std::vector<std::string>::const_iterator i = srcs.begin();
      i != srcs.end(); ++i)
830
    {
831
832
833
834
835
836
837
838
839
    const char* src = i->c_str();
    if(src[0] == '$' && src[1] == '<')
      {
      this->ProcessSourceExpression(*i);
      }
    else
      {
      this->AddSource(src);
      }
840
841
    }
}
842

843
//----------------------------------------------------------------------------
844
845
846
847
848
849
850
851
852
853
854
855
856
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;
}

857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
//----------------------------------------------------------------------------
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());
    }
}

875
876
877
878
879
//----------------------------------------------------------------------------
struct cmTarget::SourceFileFlags
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
{
  struct SourceFileFlags flags;
880
881
882
883
884
885
886
887
888
  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;
}
889

890
891
892
893
894
895
896
897
//----------------------------------------------------------------------------
void cmTarget::ConstructSourceFileFlags()
{
  if(this->Internal->SourceFileFlagsConstructed)
    {
    return;
    }
  this->Internal->SourceFileFlagsConstructed = true;
898

899
900
  // Process public headers to mark the source files.
  if(const char* files = this->GetProperty("PUBLIC_HEADER"))
901
902
903
    {
    std::vector<std::string> relFiles;
    cmSystemTools::ExpandListArgument(files, relFiles);
904
905
    for(std::vector<std::string>::iterator it = relFiles.begin();
        it != relFiles.end(); ++it)
906
      {
907
      if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
908
        {
909
910
911
        SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
        flags.MacFolder = "Headers";
        flags.Type = cmTarget::SourceFileTypePublicHeader;
912
913
914
915
        }
      }
    }

916
917
918
  // 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"))
919
    {
920
921
922
923
    std::vector<std::string> relFiles;
    cmSystemTools::ExpandListArgument(files, relFiles);
    for(std::vector<std::string>::iterator it = relFiles.begin();
        it != relFiles.end(); ++it)
924
      {
925
      if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
926
        {
927
928
929
        SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
        flags.MacFolder = "PrivateHeaders";
        flags.Type = cmTarget::SourceFileTypePrivateHeader;
930
931
932
933
        }
      }
    }

934
935
  // Mark sources listed as resources.
  if(const char* files = this->GetProperty("RESOURCE"))
936
    {
937
938
939
940
941
942
943
944
945
946
947
948
    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;
        }
      }
949
950
    }

951
952
953
954
955
  // 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)
956
    {
957
958
    cmSourceFile* sf = *si;
    if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
959
      {
960
961
      SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
      if(flags.Type == cmTarget::SourceFileTypeNormal)
962
        {
963
964
        flags.MacFolder = location;
        if(strcmp(location, "Resources") == 0)
965
          {
966
967
968
969
970
          flags.Type = cmTarget::SourceFileTypeResource;
          }
        else
          {
          flags.Type = cmTarget::SourceFileTypeMacContent;
971
972
973
974
975
976
          }
        }
      }
    }
}

977
//----------------------------------------------------------------------------
978
979
void cmTarget::MergeLinkLibraries( cmMakefile& mf,
                                   const char *selfname,
Ken Martin's avatar
Ken Martin committed
980
                                   const LinkLibraryVectorType& libs )
981
{
982
983
  // 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
984
985
  LinkLibraryVectorType::const_iterator i = libs.begin();
  i += this->PrevLinkedLibraries.size();
986
  for( ; i != libs.end(); ++i )
987
    {
988
989
    // We call this so that the dependencies get written to the cache
    this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
990
991
992
993
994
995
996
997

    if (this->GetType() == cmTarget::STATIC_LIBRARY)
      {
      this->AppendProperty("INTERFACE_LINK_LIBRARIES",
            ("$<LINK_ONLY:" +
            this->GetDebugGeneratorExpressions(i->first.c_str(), i->second) +
            ">").c_str());
      }
998
    }
Ken Martin's avatar
Ken Martin committed
999
  this->PrevLinkedLibraries = libs;
1000
}