cmTarget.cxx 222 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 "cmAlgorithms.h"
23
#include <cmsys/RegularExpression.hxx>
24
25
#include <map>
#include <set>
26
#include <stdlib.h> // required for atof
27
#include <assert.h>
28
#include <errno.h>
29
30
31
32
33
34
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include <cmsys/hash_set.hxx>
#define UNORDERED_SET cmsys::hash_set
#else
#define UNORDERED_SET std::set
#endif
Nicolas Despres's avatar
Nicolas Despres committed
35
36
37
38
39
40
41
42
43
44
45

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
46
47
      case cmTarget::OBJECT_LIBRARY:
        return "OBJECT_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
48
49
50
51
52
53
      case cmTarget::EXECUTABLE:
        return "EXECUTABLE";
      case cmTarget::UTILITY:
        return "UTILITY";
      case cmTarget::GLOBAL_TARGET:
        return "GLOBAL_TARGET";
54
55
      case cmTarget::INTERFACE_LIBRARY:
        return "INTERFACE_LIBRARY";
Nicolas Despres's avatar
Nicolas Despres committed
56
57
58
59
60
61
      case cmTarget::UNKNOWN_LIBRARY:
        return "UNKNOWN_LIBRARY";
    }
  assert(0 && "Unexpected target type");
  return 0;
}
62

63
64
65
66
67
//----------------------------------------------------------------------------
struct cmTarget::OutputInfo
{
  std::string OutDir;
  std::string ImpDir;
68
  std::string PdbDir;
69
70
71
72
73
};

//----------------------------------------------------------------------------
struct cmTarget::ImportInfo
{
74
  ImportInfo(): NoSOName(false), Multiplicity(0) {}
75
  bool NoSOName;
76
  int Multiplicity;
77
78
79
  std::string Location;
  std::string SOName;
  std::string ImportLibrary;
80
81
82
83
  std::string Languages;
  std::string Libraries;
  std::string LibrariesProp;
  std::string SharedDeps;
84
85
};

86
87
88
//----------------------------------------------------------------------------
struct cmTarget::CompileInfo
{
89
  std::string CompilePdbDir;
90
91
};

92
93
94
95
96
//----------------------------------------------------------------------------
class cmTargetInternals
{
public:
  cmTargetInternals()
97
    : Backtrace(NULL)
98
    {
99
    this->PolicyWarnedCMP0022 = false;
100
    this->UtilityItemsDone = false;
101
    }
102
  cmTargetInternals(cmTargetInternals const&)
103
    : Backtrace(NULL)
104
    {
105
    this->PolicyWarnedCMP0022 = false;
106
    this->UtilityItemsDone = false;
107
    }
108
  ~cmTargetInternals();
109
110
111

  // The backtrace when the target was created.
  cmListFileBacktrace Backtrace;
112
113
114
115

  // Cache link interface computation from each configuration.
  struct OptionalLinkInterface: public cmTarget::LinkInterface
  {
116
    OptionalLinkInterface():
117
      LibrariesDone(false), AllDone(false),
118
119
      Exists(false), HadHeadSensitiveCondition(false),
      ExplicitLibraries(0) {}
120
121
    bool LibrariesDone;
    bool AllDone;
122
    bool Exists;
123
    bool HadHeadSensitiveCondition;
124
    const char* ExplicitLibraries;
125
  };
126
  void ComputeLinkInterface(cmTarget const* thisTarget,
127
128
                            const std::string& config,
                            OptionalLinkInterface& iface,
129
130
131
132
133
134
                            cmTarget const* head) const;
  void ComputeLinkInterfaceLibraries(cmTarget const* thisTarget,
                                     const std::string& config,
                                     OptionalLinkInterface& iface,
                                     cmTarget const* head,
                                     bool usage_requirements_only);
135

136
137
138
  struct HeadToLinkInterfaceMap:
    public std::map<cmTarget const*, OptionalLinkInterface> {};
  typedef std::map<std::string, HeadToLinkInterfaceMap>
139
                                                          LinkInterfaceMapType;
140
  LinkInterfaceMapType LinkInterfaceMap;
141
  LinkInterfaceMapType LinkInterfaceUsageRequirementsOnlyMap;
142
  bool PolicyWarnedCMP0022;
143

144
  typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType;
145
146
  OutputInfoMapType OutputInfoMap;

147
  typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType;
148
  ImportInfoMapType ImportInfoMap;
149

150
151
152
  typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType;
  CompileInfoMapType CompileInfoMap;

153
  // Cache link implementation computation from each configuration.
154
155
156
  struct OptionalLinkImplementation: public cmTarget::LinkImplementation
  {
    OptionalLinkImplementation():
157
158
      LibrariesDone(false), LanguagesDone(false),
      HadHeadSensitiveCondition(false) {}
159
160
    bool LibrariesDone;
    bool LanguagesDone;
161
    bool HadHeadSensitiveCondition;
162
  };
163
164
165
166
167
168
169
170
171
  void ComputeLinkImplementationLibraries(cmTarget const* thisTarget,
                                          const std::string& config,
                                          OptionalLinkImplementation& impl,
                                          cmTarget const* head) const;
  void ComputeLinkImplementationLanguages(cmTarget const* thisTarget,
                                          const std::string& config,
                                          OptionalLinkImplementation& impl
                                          ) const;

172
173
174
175
  struct HeadToLinkImplementationMap:
    public std::map<cmTarget const*, OptionalLinkImplementation> {};
  typedef std::map<std::string,
                   HeadToLinkImplementationMap> LinkImplMapType;
176
  LinkImplMapType LinkImplMap;
177

178
  typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType;
179
  LinkClosureMapType LinkClosureMap;
180

181
182
183
184
185
186
187
  struct LinkImplClosure: public std::vector<cmTarget const*>
  {
    LinkImplClosure(): Done(false) {}
    bool Done;
  };
  std::map<std::string, LinkImplClosure> LinkImplClosureMap;

188
189
190
191
192
193
194
  struct CompatibleInterfaces: public cmTarget::CompatibleInterfaces
  {
    CompatibleInterfaces(): Done(false) {}
    bool Done;
  };
  std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap;

195
196
  typedef std::map<std::string, std::vector<cmSourceFile*> >
                                                       SourceFilesMapType;
197
198
  SourceFilesMapType SourceFilesMap;

199
200
201
  std::set<cmLinkItem> UtilityItems;
  bool UtilityItemsDone;

202
203
204
  class TargetPropertyEntry {
    static cmLinkImplItem NoLinkImplItem;
  public:
205
    TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
206
                        cmLinkImplItem const& item = NoLinkImplItem)
207
      : ge(cge), LinkImplItem(item)
208
209
    {}
    const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
210
    cmLinkImplItem const& LinkImplItem;
211
  };
212
  std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
213
  std::vector<TargetPropertyEntry*> CompileOptionsEntries;
214
  std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
215
  std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
216
  std::vector<TargetPropertyEntry*> SourceEntries;
217
  std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries;
218

219
220
221
  void AddInterfaceEntries(
    cmTarget const* thisTarget, std::string const& config,
    std::string const& prop, std::vector<TargetPropertyEntry*>& entries);
222
223
};

224
225
cmLinkImplItem cmTargetInternals::TargetPropertyEntry::NoLinkImplItem;

226
//----------------------------------------------------------------------------
227
static void deleteAndClear(
228
      std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
229
{
230
  cmDeleteAll(entries);
231
232
233
234
235
236
237
238
  entries.clear();
}

//----------------------------------------------------------------------------
cmTargetInternals::~cmTargetInternals()
{
}

239
240
241
//----------------------------------------------------------------------------
cmTarget::cmTarget()
{
242
243
244
245
246
247
248
#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
249
  this->Makefile = 0;
250
#if defined(_WIN32) && !defined(__CYGWIN__)
251
  this->LinkLibrariesForVS6Analyzed = false;
252
#endif
Ken Martin's avatar
Ken Martin committed
253
  this->HaveInstallRule = false;
254
  this->DLLPlatform = false;
255
  this->IsAndroid = false;
256
  this->IsApple = false;
Alexander Neundorf's avatar
   
Alexander Neundorf committed
257
  this->IsImportedTarget = false;
258
  this->BuildInterfaceIncludesAppended = false;
259
  this->DebugIncludesDone = false;
260
  this->DebugCompileOptionsDone = false;
261
  this->DebugCompileFeaturesDone = false;
262
  this->DebugCompileDefinitionsDone = false;
263
  this->DebugSourcesDone = false;
264
  this->LinkImplementationLanguageIsContextDependent = true;
265
266
}

267
void cmTarget::SetType(TargetType type, const std::string& name)
268
{
Ken Martin's avatar
Ken Martin committed
269
  this->Name = name;
270
  // only add dependency information for library targets
Ken Martin's avatar
Ken Martin committed
271
  this->TargetTypeValue = type;
272
273
  if(this->TargetTypeValue >= STATIC_LIBRARY
     && this->TargetTypeValue <= MODULE_LIBRARY)
Ken Martin's avatar
Ken Martin committed
274
275
    {
    this->RecordDependencies = true;
276
277
    }
  else
Ken Martin's avatar
Ken Martin committed
278
279
280
    {
    this->RecordDependencies = false;
    }
281
282
}

283
284
285
286
//----------------------------------------------------------------------------
void cmTarget::SetMakefile(cmMakefile* mf)
{
  // Set our makefile.
Ken Martin's avatar
Ken Martin committed
287
  this->Makefile = mf;
288

289
290
291
  // set the cmake instance of the properties
  this->Properties.SetCMakeInstance(mf->GetCMakeInstance());

292
293
294
295
296
  // Check whether this is a DLL platform.
  this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
                       this->Makefile->IsOn("CYGWIN") ||
                       this->Makefile->IsOn("MINGW"));

297
298
299
300
301
  // Check whether we are targeting an Android platform.
  this->IsAndroid =
    strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"),
           "Android") == 0;

302
303
304
  // Check whether we are targeting an Apple platform.
  this->IsApple = this->Makefile->IsOn("APPLE");

305
  // Setup default property values.
306
  if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
307
    {
308
    this->SetPropertyDefault("ANDROID_API", 0);
309
    this->SetPropertyDefault("ANDROID_API_MIN", 0);
310
311
312
313
314
315
316
317
318
    this->SetPropertyDefault("INSTALL_NAME_DIR", 0);
    this->SetPropertyDefault("INSTALL_RPATH", "");
    this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
    this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
    this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
    this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
    this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
    this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
    this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
319
    this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", 0);
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    this->SetPropertyDefault("Fortran_FORMAT", 0);
    this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
    this->SetPropertyDefault("GNUtoMS", 0);
    this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
    this->SetPropertyDefault("AUTOMOC", 0);
    this->SetPropertyDefault("AUTOUIC", 0);
    this->SetPropertyDefault("AUTORCC", 0);
    this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
    this->SetPropertyDefault("AUTOUIC_OPTIONS", 0);
    this->SetPropertyDefault("AUTORCC_OPTIONS", 0);
    this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
    this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
    this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
    this->SetPropertyDefault("MACOSX_BUNDLE", 0);
    this->SetPropertyDefault("MACOSX_RPATH", 0);
    this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
336
    this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", 0);
337
338
339
    this->SetPropertyDefault("C_STANDARD", 0);
    this->SetPropertyDefault("C_STANDARD_REQUIRED", 0);
    this->SetPropertyDefault("C_EXTENSIONS", 0);
340
    this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", 0);
341
    this->SetPropertyDefault("CXX_STANDARD", 0);
342
    this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0);
343
    this->SetPropertyDefault("CXX_EXTENSIONS", 0);
344
    }
345
346
347

  // Collect the set of configuration types.
  std::vector<std::string> configNames;
348
  mf->GetConfigurations(configNames);
349
350

  // Setup per-configuration property default values.
351
  if (this->GetType() != UTILITY)
352
    {
353
354
355
356
357
358
359
360
361
362
    const char* configProps[] = {
      "ARCHIVE_OUTPUT_DIRECTORY_",
      "LIBRARY_OUTPUT_DIRECTORY_",
      "RUNTIME_OUTPUT_DIRECTORY_",
      "PDB_OUTPUT_DIRECTORY_",
      "COMPILE_PDB_OUTPUT_DIRECTORY_",
      "MAP_IMPORTED_CONFIG_",
      0};
    for(std::vector<std::string>::iterator ci = configNames.begin();
        ci != configNames.end(); ++ci)
363
      {
364
365
      std::string configUpper = cmSystemTools::UpperCase(*ci);
      for(const char** p = configProps; *p; ++p)
366
        {
367
368
369
370
371
372
373
374
        if (this->TargetTypeValue == INTERFACE_LIBRARY
            && strcmp(*p, "MAP_IMPORTED_CONFIG_") != 0)
          {
          continue;
          }
        std::string property = *p;
        property += configUpper;
        this->SetPropertyDefault(property, 0);
375
        }
376

377
378
379
380
381
382
383
384
385
386
387
388
      // 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.
      if(this->TargetTypeValue != cmTarget::EXECUTABLE
          && this->TargetTypeValue != cmTarget::INTERFACE_LIBRARY)
        {
        std::string property = cmSystemTools::UpperCase(*ci);
        property += "_POSTFIX";
        this->SetPropertyDefault(property, 0);
        }
389
390
      }
    }
391
392

  // Save the backtrace of target construction.
Ben Boeckel's avatar
Ben Boeckel committed
393
  this->Internal->Backtrace = this->Makefile->GetBacktrace();
394

395
  if (!this->IsImported())
396
    {
397
398
399
400
    // Initialize the INCLUDE_DIRECTORIES property based on the current value
    // of the same directory property:
    const std::vector<cmValueWithOrigin> parentIncludes =
                                this->Makefile->GetIncludeDirectoriesEntries();
401

402
403
404
405
406
    for (std::vector<cmValueWithOrigin>::const_iterator it
                = parentIncludes.begin(); it != parentIncludes.end(); ++it)
      {
      this->InsertInclude(*it);
      }
407
    const std::set<std::string> parentSystemIncludes =
408
                                this->Makefile->GetSystemIncludeDirectories();
409

410
411
    this->SystemIncludeDirectories.insert(parentSystemIncludes.begin(),
                                          parentSystemIncludes.end());
412

413
414
    const std::vector<cmValueWithOrigin> parentOptions =
                                this->Makefile->GetCompileOptionsEntries();
415

416
417
418
419
420
    for (std::vector<cmValueWithOrigin>::const_iterator it
                = parentOptions.begin(); it != parentOptions.end(); ++it)
      {
      this->InsertCompileOption(*it);
      }
421
    }
422

423
  if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
424
425
426
427
428
    {
    this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
    this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
    this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
    }
429

430
431
432
  if(this->TargetTypeValue == cmTarget::EXECUTABLE)
    {
    this->SetPropertyDefault("ANDROID_GUI", 0);
433
    this->SetPropertyDefault("CROSSCOMPILING_EMULATOR", 0);
434
    }
435
436
437
438
439
  if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
      || this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
    {
    this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
    }
440
  if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
441
442
443
    {
    this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
    }
444

445
  // Record current policies for later use.
446
447
448
449
450
451
452
#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
453
454
455
456
457
458
459
460

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

462
463
464
465
466
  if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
    {
    this->SetPropertyDefault("JOB_POOL_COMPILE", 0);
    this->SetPropertyDefault("JOB_POOL_LINK", 0);
    }
467
468
}

469
//----------------------------------------------------------------------------
470
void cmTarget::AddUtility(const std::string& u, cmMakefile *makefile)
471
{
472
473
  if(this->Utilities.insert(u).second && makefile)
    {
Ben Boeckel's avatar
Ben Boeckel committed
474
    UtilityBacktraces.insert(std::make_pair(u, makefile->GetBacktrace()));
475
    }
476
477
478
}

//----------------------------------------------------------------------------
479
480
cmListFileBacktrace const* cmTarget::GetUtilityBacktrace(
    const std::string& u) const
481
{
482
  std::map<std::string, cmListFileBacktrace>::const_iterator i =
483
484
485
486
487
488
    this->UtilityBacktraces.find(u);
  if(i == this->UtilityBacktraces.end()) return 0;

  return &i->second;
}

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
//----------------------------------------------------------------------------
std::set<cmLinkItem> const& cmTarget::GetUtilityItems() const
{
  if(!this->Internal->UtilityItemsDone)
    {
    this->Internal->UtilityItemsDone = true;
    for(std::set<std::string>::const_iterator i = this->Utilities.begin();
        i != this->Utilities.end(); ++i)
      {
      this->Internal->UtilityItems.insert(
        cmLinkItem(*i, this->Makefile->FindTargetToUse(*i)));
      }
    }
  return this->Internal->UtilityItems;
}

505
506
507
//----------------------------------------------------------------------------
void cmTarget::FinishConfigure()
{
508
509
510
511
512
513
  // 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();

514
#if defined(_WIN32) && !defined(__CYGWIN__)
515
  // Do old-style link dependency analysis only for CM_USE_OLD_VS6.
516
  if(this->Makefile->GetGlobalGenerator()->IsForVS6())
517
518
519
    {
    this->AnalyzeLibDependenciesForVS6(*this->Makefile);
    }
520
#endif
521
522
}

523
524
525
//----------------------------------------------------------------------------
void cmTarget::ClearLinkMaps()
{
526
  this->LinkImplementationLanguageIsContextDependent = true;
527
528
  this->Internal->LinkImplMap.clear();
  this->Internal->LinkInterfaceMap.clear();
529
  this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear();
530
  this->Internal->LinkClosureMap.clear();
531
  this->Internal->SourceFilesMap.clear();
532
  cmDeleteAll(this->LinkInformation);
533
  this->LinkInformation.clear();
534
535
}

536
537
538
539
//----------------------------------------------------------------------------
cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
  return this->Internal->Backtrace;
540
}
541

542
543
544
//----------------------------------------------------------------------------
std::string cmTarget::GetSupportDirectory() const
{
545
  std::string dir = this->Makefile->GetCurrentBinaryDirectory();
546
547
548
  dir += cmake::GetCMakeFilesDirectory();
  dir += "/";
  dir += this->Name;
549
550
551
#if defined(__VMS)
  dir += "_dir";
#else
552
  dir += ".dir";
553
#endif
554
555
556
  return dir;
}

557
//----------------------------------------------------------------------------
558
bool cmTarget::IsExecutableWithExports() const
559
{
560
561
562
563
  return (this->GetType() == cmTarget::EXECUTABLE &&
          this->GetPropertyAsBool("ENABLE_EXPORTS"));
}

564
//----------------------------------------------------------------------------
565
bool cmTarget::IsLinkable() const
566
567
568
569
570
{
  return (this->GetType() == cmTarget::STATIC_LIBRARY ||
          this->GetType() == cmTarget::SHARED_LIBRARY ||
          this->GetType() == cmTarget::MODULE_LIBRARY ||
          this->GetType() == cmTarget::UNKNOWN_LIBRARY ||
571
          this->GetType() == cmTarget::INTERFACE_LIBRARY ||
572
573
574
          this->IsExecutableWithExports());
}

Brad King's avatar
Brad King committed
575
//----------------------------------------------------------------------------
576
bool cmTarget::HasImportLibrary() const
Brad King's avatar
Brad King committed
577
578
579
580
581
582
{
  return (this->DLLPlatform &&
          (this->GetType() == cmTarget::SHARED_LIBRARY ||
           this->IsExecutableWithExports()));
}

583
//----------------------------------------------------------------------------
584
bool cmTarget::IsFrameworkOnApple() const
585
586
587
588
{
  return (this->GetType() == cmTarget::SHARED_LIBRARY &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("FRAMEWORK"));
589
590
}

591
//----------------------------------------------------------------------------
592
bool cmTarget::IsAppBundleOnApple() const
593
594
595
596
597
598
{
  return (this->GetType() == cmTarget::EXECUTABLE &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("MACOSX_BUNDLE"));
}

599
//----------------------------------------------------------------------------
600
bool cmTarget::IsCFBundleOnApple() const
601
602
603
604
605
606
{
  return (this->GetType() == cmTarget::MODULE_LIBRARY &&
          this->Makefile->IsOn("APPLE") &&
          this->GetPropertyAsBool("BUNDLE"));
}

607
608
609
610
611
612
613
//----------------------------------------------------------------------------
bool cmTarget::IsXCTestOnApple() const
{
  return (this->IsCFBundleOnApple() &&
          this->GetPropertyAsBool("XCTEST"));
}

614
//----------------------------------------------------------------------------
615
bool cmTarget::IsBundleOnApple() const
616
617
618
619
620
{
  return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
         this->IsCFBundleOnApple();
}

621
//----------------------------------------------------------------------------
622
static bool processSources(cmTarget const* tgt,
623
624
      const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
      std::vector<std::string> &srcs,
625
      UNORDERED_SET<std::string> &uniqueSrcs,
626
      cmGeneratorExpressionDAGChecker *dagChecker,
627
      std::string const& config, bool debugSources)
628
{
629
  cmMakefile *mf = tgt->GetMakefile();
630

631
632
  bool contextDependent = false;

633
634
  for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
      it = entries.begin(), end = entries.end(); it != end; ++it)
635
    {
636
637
    cmLinkImplItem const& item = (*it)->LinkImplItem;
    std::string const& targetName = item;
638
639
640
641
642
643
644
645
646
647
    std::vector<std::string> entrySources;
    cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
                                              config,
                                              false,
                                              tgt,
                                              tgt,
                                              dagChecker),
                                    entrySources);

    if ((*it)->ge->GetHadContextSensitiveCondition())
648
      {
649
650
      contextDependent = true;
      }
651

652
653
654
655
656
657
    for(std::vector<std::string>::iterator i = entrySources.begin();
        i != entrySources.end(); ++i)
      {
      std::string& src = *i;
      cmSourceFile* sf = mf->GetOrCreateSource(src);
      std::string e;
658
659
      std::string fullPath = sf->GetFullPath(&e);
      if(fullPath.empty())
660
661
        {
        if(!e.empty())
662
          {
663
664
665
          cmake* cm = mf->GetCMakeInstance();
          cm->IssueMessage(cmake::FATAL_ERROR, e,
                          tgt->GetBacktrace());
666
          }
667
        return contextDependent;
668
        }
669
670
671

      if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src.c_str()))
        {
672
        std::ostringstream err;
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
        if (!targetName.empty())
          {
          err << "Target \"" << targetName << "\" contains relative "
            "path in its INTERFACE_SOURCES:\n"
            "  \"" << src << "\"";
          }
        else
          {
          err << "Found relative path while evaluating sources of "
          "\"" << tgt->GetName() << "\":\n  \"" << src << "\"\n";
          }
        tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, err.str());
        return contextDependent;
        }
      src = fullPath;
688
      }
689
    std::string usedSources;
690
691
    for(std::vector<std::string>::iterator
          li = entrySources.begin(); li != entrySources.end(); ++li)
692
      {
693
694
695
      std::string src = *li;

      if(uniqueSrcs.insert(src).second)
696
        {
697
        srcs.push_back(src);
698
        if (debugSources)
699
          {
700
          usedSources += " * " + src + "\n";
701
          }
702
        }
703
      }
704
705
706
707
708
709
    if (!usedSources.empty())
      {
      mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
                            std::string("Used sources for target ")
                            + tgt->GetName() + ":\n"
                            + usedSources, (*it)->ge->GetBacktrace());
710
711
      }
    }
712
  return contextDependent;
713
714
715
}

//----------------------------------------------------------------------------
716
void cmTarget::GetSourceFiles(std::vector<std::string> &files,
717
                              const std::string& config) const
718
719
720
{
  assert(this->GetType() != INTERFACE_LIBRARY);

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  if (this->Makefile->GetGeneratorTargets().empty())
    {
    // At configure-time, this method can be called as part of getting the
    // LOCATION property or to export() a file to be include()d.  However
    // there is no cmGeneratorTarget at configure-time, so search the SOURCES
    // for TARGET_OBJECTS instead for backwards compatibility with OLD
    // behavior of CMP0024 and CMP0026 only.

    typedef cmTargetInternals::TargetPropertyEntry
                                TargetPropertyEntry;
    for(std::vector<TargetPropertyEntry*>::const_iterator
          i = this->Internal->SourceEntries.begin();
        i != this->Internal->SourceEntries.end(); ++i)
      {
      std::string entry = (*i)->ge->GetInput();

      std::vector<std::string> items;
      cmSystemTools::ExpandListArgument(entry, items);
      for (std::vector<std::string>::const_iterator
          li = items.begin(); li != items.end(); ++li)
        {
        if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
            (*li)[li->size() - 1] == '>')
          {
          continue;
          }
        files.push_back(*li);
        }
      }
    return;
    }

753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  std::vector<std::string> debugProperties;
  const char *debugProp =
              this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
  if (debugProp)
    {
    cmSystemTools::ExpandListArgument(debugProp, debugProperties);
    }

  bool debugSources = !this->DebugSourcesDone
                    && std::find(debugProperties.begin(),
                                 debugProperties.end(),
                                 "SOURCES")
                        != debugProperties.end();

  if (this->Makefile->IsGeneratingBuildSystem())
    {
    this->DebugSourcesDone = true;
    }
771

772
773
  cmGeneratorExpressionDAGChecker dagChecker(this->GetName(),
                                             "SOURCES", 0, 0);
774

775
  UNORDERED_SET<std::string> uniqueSrcs;
776
  bool contextDependentDirectSources = processSources(this,
777
778
779
780
                 this->Internal->SourceEntries,
                 files,
                 uniqueSrcs,
                 &dagChecker,
781
782
                 config,
                 debugSources);
783

784
785
  std::vector<cmTargetInternals::TargetPropertyEntry*>
    linkInterfaceSourcesEntries;
786

787
788
789
790
791
792
793
  this->Internal->AddInterfaceEntries(
    this, config, "INTERFACE_SOURCES",
    linkInterfaceSourcesEntries);

  std::vector<std::string>::size_type numFilesBefore = files.size();
  bool contextDependentInterfaceSources = processSources(this,
    linkInterfaceSourcesEntries,
794
795
796
                            files,
                            uniqueSrcs,
                            &dagChecker,
797
798
                            config,
                            debugSources);
799

800
801
802
803
804
805
  if (!contextDependentDirectSources
      && !(contextDependentInterfaceSources && numFilesBefore < files.size()))
    {
    this->LinkImplementationLanguageIsContextDependent = false;
    }

806
  deleteAndClear(linkInterfaceSourcesEntries);
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
bool
cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const
{
  std::vector<std::string> configs;
  this->Makefile->GetConfigurations(configs);
  if (configs.empty())
    {
    configs.push_back("");
    }

  std::vector<std::string>::const_iterator it = configs.begin();
  const std::string& firstConfig = *it;
  this->GetSourceFiles(files, firstConfig);

  for ( ; it != configs.end(); ++it)
    {
    std::vector<cmSourceFile*> configFiles;
    this->GetSourceFiles(configFiles, *it);
    if (configFiles != files)
      {
      std::string firstConfigFiles;
      const char* sep = "";
      for (std::vector<cmSourceFile*>::const_iterator fi = files.begin();
           fi != files.end(); ++fi)
        {
        firstConfigFiles += sep;
        firstConfigFiles += (*fi)->GetFullPath();
        sep = "\n  ";
        }

      std::string thisConfigFiles;
      sep = "";
      for (std::vector<cmSourceFile*>::const_iterator fi = configFiles.begin();
           fi != configFiles.end(); ++fi)
        {
        thisConfigFiles += sep;
        thisConfigFiles += (*fi)->GetFullPath();
        sep = "\n  ";
        }
849
      std::ostringstream e;
850
851
      e << "Target \"" << this->Name << "\" has source files which vary by "
        "configuration. This is not supported by the \""
852
        << this->Makefile->GetGlobalGenerator()->GetName()
853
854
855
856
857
858
859
860
861
862
863
864
865
866
        << "\" generator.\n"
          "Config \"" << firstConfig << "\":\n"
          "  " << firstConfigFiles << "\n"
          "Config \"" << *it << "\":\n"
          "  " << thisConfigFiles << "\n";
      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
      return false;
      }
    }
  return true;
}

//----------------------------------------------------------------------------
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
867
                              const std::string& config) const
868
{
869

870
  // Lookup any existing link implementation for this configuration.
871
  std::string key = cmSystemTools::UpperCase(config);
872

873
874
875
876
877
878
  if(!this->LinkImplementationLanguageIsContextDependent)
    {
    files = this->Internal->SourceFilesMap.begin()->second;
    return;
    }

879
880
881
882
883
884
885
  cmTargetInternals::SourceFilesMapType::iterator
    it = this->Internal->SourceFilesMap.find(key);
  if(it != this->Internal->SourceFilesMap.end())
    {
    files = it->second;
    }
  else
886
    {
887
    std::vector<std::string> srcs;
888
    this->GetSourceFiles(srcs, config);
889
890
891
892
893

    std::set<cmSourceFile*> emitted;

    for(std::vector<std::string>::const_iterator i = srcs.begin();
        i != srcs.end(); ++i)
894
      {
895
896
897
898
899
      cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
      if (emitted.insert(sf).second)
        {
        files.push_back(sf);
        }
900
      }
901
    this->Internal->SourceFilesMap[key] = files;
902
903
904
    }
}

905
//----------------------------------------------------------------------------
906
907
void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
908
  std::string srcFiles = cmJoin(srcs, ";");
909
910
911
912
  if (!srcFiles.empty())
    {
    this->Internal->SourceFilesMap.clear();
    this->LinkImplementationLanguageIsContextDependent = true;
Ben Boeckel's avatar
Ben Boeckel committed
913
    cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
914
    cmGeneratorExpression ge(&lfbt);
915
916
917
918
919
920
921
922
    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(srcFiles);
    cge->SetEvaluateForBuildsystem(true);
    this->Internal->SourceEntries.push_back(
                          new cmTargetInternals::TargetPropertyEntry(cge));
    }
}

//----------------------------------------------------------------------------
923
924
void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
925
926
  std::string srcFiles;
  const char* sep = "";
927
928
  for(std::vector<std::string>::const_iterator i = srcs.begin();
      i != srcs.end(); ++i)
929
    {
930
931
932
933
    std::string filename = *i;
    const char* src = filename.c_str();

    if(!(src[0] == '$' && src[1] == '<'))
934
      {
935
      if(!filename.empty())
936
        {
937
938
939
940
941
        filename = this->ProcessSourceItemCMP0049(filename);
        if(filename.empty())
          {
          return;
          }
942
943
        }
      this->Makefile->GetOrCreateSource(filename);
944
      }
945
946
947
948
949
950
    srcFiles += sep;
    srcFiles += filename;
    sep = ";";
    }
  if (!srcFiles.empty())
    {
951
    this->Internal->SourceFilesMap.clear();
952
    this->LinkImplementationLanguageIsContextDependent = true;
Ben Boeckel's avatar
Ben Boeckel committed
953
    cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
954
    cmGeneratorExpression ge(&lfbt);
955
956
957
958
    cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(srcFiles);
    cge->SetEvaluateForBuildsystem(true);
    this->Internal->SourceEntries.push_back(
                          new cmTargetInternals::TargetPropertyEntry(cge));
959
960
    }
}
961

962
//----------------------------------------------------------------------------
963
std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
964
965
966
967
968
969
{
  std::string src = s;

  // For backwards compatibility replace varibles in source names.
  // This should eventually be removed.
  this->Makefile->ExpandVariablesInString(src);
970
971
  if (src != s)
    {
972
    std::ostringstream e;
973
974
975
976
977
    bool noMessage = false;
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0049))
      {
      case cmPolicies::WARN:
Stephen Kelly's avatar
Stephen Kelly committed
978
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n";
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
        break;
      case cmPolicies::OLD:
        noMessage = true;
        break;
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::NEW:
        messageType = cmake::FATAL_ERROR;
      }
    if (!noMessage)
      {
      e << "Legacy variable expansion in source file \""
        << s << "\" expanded to \"" << src << "\" in target \""
        << this->GetName() << "\".  This behavior will be removed in a "
        "future version of CMake.";
Stephen Kelly's avatar
Stephen Kelly committed
994
      this->Makefile->IssueMessage(messageType, e.str());
995
996
      if (messageType == cmake::FATAL_ERROR)
        {
997
        return "";
998
999
1000
        }
      }
    }
1001
1002
1003
1004
1005
1006
1007
  return src;
}

//----------------------------------------------------------------------------
cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{
  std::string src = this->ProcessSourceItemCMP0049(s);
1008
  if(!s.empty() && src.empty())
1009
1010
1011
    {
    return 0;
    }
1012
  return this->AddSource(src);
1013
1014
}