cmState.cxx 56.1 KB
Newer Older
Stephen Kelly's avatar
Stephen Kelly committed
1
2
3
4
5
6
7
8
9
10
11
12
13
/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2015 Stephen Kelly <steveire@gmail.com>

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

  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.
============================================================================*/
#include "cmState.h"

14
#include "cmAlgorithms.h"
15
#include "cmCacheManager.h"
16
#include "cmCommand.h"
17
#include "cmDefinitions.h"
18
19
#include "cmVersion.h"
#include "cmake.h"
20
21

#include <assert.h>
Stephen Kelly's avatar
Stephen Kelly committed
22

23
24
struct cmState::SnapshotDataType
{
25
  cmState::PositionType ScopeParent;
26
  cmState::PositionType DirectoryParent;
27
28
29
  cmLinkedTree<cmState::PolicyStackEntry>::iterator Policies;
  cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyRoot;
  cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyScope;
30
  cmState::SnapshotType SnapshotType;
31
  bool Keep;
32
  cmLinkedTree<std::string>::iterator ExecutionListFile;
33
  cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator
34
    BuildSystemDirectory;
35
36
37
  cmLinkedTree<cmDefinitions>::iterator Vars;
  cmLinkedTree<cmDefinitions>::iterator Root;
  cmLinkedTree<cmDefinitions>::iterator Parent;
38
39
40
  std::vector<std::string>::size_type IncludeDirectoryPosition;
  std::vector<std::string>::size_type CompileDefinitionsPosition;
  std::vector<std::string>::size_type CompileOptionsPosition;
41
42
};

43
struct cmState::PolicyStackEntry : public cmPolicies::PolicyMap
44
45
{
  typedef cmPolicies::PolicyMap derived;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  PolicyStackEntry(bool w = false)
    : derived()
    , Weak(w)
  {
  }
  PolicyStackEntry(derived const& d, bool w)
    : derived(d)
    , Weak(w)
  {
  }
  PolicyStackEntry(PolicyStackEntry const& r)
    : derived(r)
    , Weak(r.Weak)
  {
  }
61
62
63
  bool Weak;
};

64
65
struct cmState::BuildsystemDirectoryStateType
{
66
67
  cmState::PositionType DirectoryEnd;

68
69
70
71
72
73
74
75
76
77
78
79
  std::string Location;
  std::string OutputLocation;

  std::vector<std::string> CurrentSourceDirectoryComponents;
  std::vector<std::string> CurrentBinaryDirectoryComponents;
  // The top-most directories for relative path conversion.  Both the
  // source and destination location of a relative path conversion
  // must be underneath one of these directories (both under source or
  // both under binary) in order for the relative path to be evaluated
  // safely by the build tools.
  std::string RelativePathTopSource;
  std::string RelativePathTopBinary;
80
81
82
83
84
85
86
87
88

  std::vector<std::string> IncludeDirectories;
  std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces;

  std::vector<std::string> CompileDefinitions;
  std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces;

  std::vector<std::string> CompileOptions;
  std::vector<cmListFileBacktrace> CompileOptionsBacktraces;
89

90
91
  std::string ProjectName;

92
  cmPropertyMap Properties;
93
94

  std::vector<cmState::Snapshot> Children;
95
96
};

97
cmState::cmState()
98
99
100
101
102
103
104
  : IsInTryCompile(false)
  , WindowsShell(false)
  , WindowsVSIDE(false)
  , WatcomWMake(false)
  , MinGWMake(false)
  , NMake(false)
  , MSYSShell(false)
Stephen Kelly's avatar
Stephen Kelly committed
105
{
106
  this->CacheManager = new cmCacheManager;
Stephen Kelly's avatar
Stephen Kelly committed
107
}
108

109
110
cmState::~cmState()
{
111
  delete this->CacheManager;
112
113
114
  cmDeleteAll(this->Commands);
}

115
116
const char* cmState::GetTargetTypeName(cmState::TargetType targetType)
{
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  switch (targetType) {
    case cmState::STATIC_LIBRARY:
      return "STATIC_LIBRARY";
    case cmState::MODULE_LIBRARY:
      return "MODULE_LIBRARY";
    case cmState::SHARED_LIBRARY:
      return "SHARED_LIBRARY";
    case cmState::OBJECT_LIBRARY:
      return "OBJECT_LIBRARY";
    case cmState::EXECUTABLE:
      return "EXECUTABLE";
    case cmState::UTILITY:
      return "UTILITY";
    case cmState::GLOBAL_TARGET:
      return "GLOBAL_TARGET";
    case cmState::INTERFACE_LIBRARY:
      return "INTERFACE_LIBRARY";
    case cmState::UNKNOWN_LIBRARY:
      return "UNKNOWN_LIBRARY";
  }
137
  assert(0 && "Unexpected target type");
Daniel Pfeifer's avatar
Daniel Pfeifer committed
138
  return CM_NULLPTR;
139
140
}

141
142
const char* cmCacheEntryTypes[] = { "BOOL",          "PATH",     "FILEPATH",
                                    "STRING",        "INTERNAL", "STATIC",
Daniel Pfeifer's avatar
Daniel Pfeifer committed
143
                                    "UNINITIALIZED", CM_NULLPTR };
144

145
const char* cmState::CacheEntryTypeToString(cmState::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
146
{
147
  if (type > 6) {
148
    return cmCacheEntryTypes[6];
149
  }
150
  return cmCacheEntryTypes[type];
Stephen Kelly's avatar
Stephen Kelly committed
151
152
}

153
cmState::CacheEntryType cmState::StringToCacheEntryType(const char* s)
Stephen Kelly's avatar
Stephen Kelly committed
154
{
155
  int i = 0;
156
157
  while (cmCacheEntryTypes[i]) {
    if (strcmp(s, cmCacheEntryTypes[i]) == 0) {
158
159
      return static_cast<cmState::CacheEntryType>(i);
    }
160
161
    ++i;
  }
162
  return STRING;
Stephen Kelly's avatar
Stephen Kelly committed
163
164
165
166
}

bool cmState::IsCacheEntryType(std::string const& key)
{
167
168
  for (int i = 0; cmCacheEntryTypes[i]; ++i) {
    if (strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) {
169
170
      return true;
    }
171
  }
172
  return false;
Stephen Kelly's avatar
Stephen Kelly committed
173
174
}

175
176
177
178
bool cmState::LoadCache(const std::string& path, bool internal,
                        std::set<std::string>& excludes,
                        std::set<std::string>& includes)
{
179
  return this->CacheManager->LoadCache(path, internal, excludes, includes);
180
181
182
183
}

bool cmState::SaveCache(const std::string& path)
{
184
  return this->CacheManager->SaveCache(path);
185
186
187
188
}

bool cmState::DeleteCache(const std::string& path)
{
189
  return this->CacheManager->DeleteCache(path);
190
191
}

Stephen Kelly's avatar
Stephen Kelly committed
192
193
194
std::vector<std::string> cmState::GetCacheEntryKeys() const
{
  std::vector<std::string> definitions;
195
  definitions.reserve(this->CacheManager->GetSize());
196
197
  cmCacheManager::CacheIterator cit = this->CacheManager->GetCacheIterator();
  for (cit.Begin(); !cit.IsAtEnd(); cit.Next()) {
Stephen Kelly's avatar
Stephen Kelly committed
198
    definitions.push_back(cit.GetName());
199
  }
Stephen Kelly's avatar
Stephen Kelly committed
200
201
202
203
204
  return definitions;
}

const char* cmState::GetCacheEntryValue(std::string const& key) const
{
205
206
  cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key);
  if (!e) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
207
    return CM_NULLPTR;
208
  }
Stephen Kelly's avatar
Stephen Kelly committed
209
210
211
  return e->Value.c_str();
}

212
const char* cmState::GetInitializedCacheValue(std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
213
{
214
  return this->CacheManager->GetInitializedCacheValue(key);
Stephen Kelly's avatar
Stephen Kelly committed
215
216
}

217
218
cmState::CacheEntryType cmState::GetCacheEntryType(
  std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
219
220
{
  cmCacheManager::CacheIterator it =
221
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
222
223
224
225
  return it.GetType();
}

void cmState::SetCacheEntryValue(std::string const& key,
226
                                 std::string const& value)
Stephen Kelly's avatar
Stephen Kelly committed
227
{
228
  this->CacheManager->SetCacheEntryValue(key, value);
Stephen Kelly's avatar
Stephen Kelly committed
229
230
231
}

void cmState::SetCacheEntryProperty(std::string const& key,
232
233
                                    std::string const& propertyName,
                                    std::string const& value)
Stephen Kelly's avatar
Stephen Kelly committed
234
235
{
  cmCacheManager::CacheIterator it =
236
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
237
238
239
240
  it.SetProperty(propertyName, value.c_str());
}

void cmState::SetCacheEntryBoolProperty(std::string const& key,
241
242
                                        std::string const& propertyName,
                                        bool value)
Stephen Kelly's avatar
Stephen Kelly committed
243
244
{
  cmCacheManager::CacheIterator it =
245
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
246
247
248
  it.SetProperty(propertyName, value);
}

249
250
251
252
253
254
255
256
std::vector<std::string> cmState::GetCacheEntryPropertyList(
  const std::string& key)
{
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  return it.GetPropertyList();
}

Stephen Kelly's avatar
Stephen Kelly committed
257
const char* cmState::GetCacheEntryProperty(std::string const& key,
258
                                           std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
259
{
260
261
262
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  if (!it.PropertyExists(propertyName)) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
263
    return CM_NULLPTR;
264
  }
Stephen Kelly's avatar
Stephen Kelly committed
265
266
267
268
  return it.GetProperty(propertyName);
}

bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
269
                                          std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
270
{
271
272
  return this->CacheManager->GetCacheIterator(key.c_str())
    .GetPropertyAsBool(propertyName);
Stephen Kelly's avatar
Stephen Kelly committed
273
274
275
}

void cmState::AddCacheEntry(const std::string& key, const char* value,
276
277
                            const char* helpString,
                            cmState::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
278
{
279
  this->CacheManager->AddCacheEntry(key, value, helpString, type);
Stephen Kelly's avatar
Stephen Kelly committed
280
281
282
283
}

void cmState::RemoveCacheEntry(std::string const& key)
{
284
  this->CacheManager->RemoveCacheEntry(key);
Stephen Kelly's avatar
Stephen Kelly committed
285
286
287
}

void cmState::AppendCacheEntryProperty(const std::string& key,
288
289
                                       const std::string& property,
                                       const std::string& value, bool asString)
Stephen Kelly's avatar
Stephen Kelly committed
290
{
291
292
  this->CacheManager->GetCacheIterator(key.c_str())
    .AppendProperty(property, value.c_str(), asString);
Stephen Kelly's avatar
Stephen Kelly committed
293
294
295
}

void cmState::RemoveCacheEntryProperty(std::string const& key,
296
                                       std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
297
{
298
  this->CacheManager->GetCacheIterator(key.c_str())
Daniel Pfeifer's avatar
Daniel Pfeifer committed
299
    .SetProperty(propertyName, (void*)CM_NULLPTR);
Stephen Kelly's avatar
Stephen Kelly committed
300
}
301

302
cmState::Snapshot cmState::Reset()
303
{
304
  this->GlobalProperties.clear();
305
  this->PropertyDefinitions.clear();
306

307
308
309
  PositionType pos = this->SnapshotData.Truncate();
  this->ExecutionListFiles.Truncate();

310
  {
311
    cmLinkedTree<BuildsystemDirectoryStateType>::iterator it =
312
      this->BuildsystemDirectory.Truncate();
313
314
315
316
317
318
319
320
321
    it->IncludeDirectories.clear();
    it->IncludeDirectoryBacktraces.clear();
    it->CompileDefinitions.clear();
    it->CompileDefinitionsBacktraces.clear();
    it->CompileOptions.clear();
    it->CompileOptionsBacktraces.clear();
    it->DirectoryEnd = pos;
    it->Properties.clear();
    it->Children.clear();
322
  }
323

324
325
326
327
328
329
  this->PolicyStack.Clear();
  pos->Policies = this->PolicyStack.Root();
  pos->PolicyRoot = this->PolicyStack.Root();
  pos->PolicyScope = this->PolicyStack.Root();
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
330
331

  {
332
    std::string srcDir =
333
      cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
334
    std::string binDir =
335
      cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
336
337
338
339
    this->VarTree.Clear();
    pos->Vars = this->VarTree.Push(this->VarTree.Root());
    pos->Parent = this->VarTree.Root();
    pos->Root = this->VarTree.Root();
340

341
342
    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
343
344
  }

345
346
347
348
349
350
351
352
353
354
355
  this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::DIRECTORY, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY, "", "",
                       true);

  this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::TARGET, "", "",
                       true);
  this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true);
  this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true);
356
357

  return Snapshot(this, pos);
358
359
360
}

void cmState::DefineProperty(const std::string& name,
361
362
363
                             cmProperty::ScopeType scope,
                             const char* ShortDescription,
                             const char* FullDescription, bool chained)
364
{
365
366
  this->PropertyDefinitions[scope].DefineProperty(
    name, scope, ShortDescription, FullDescription, chained);
367
368
}

369
370
cmPropertyDefinition const* cmState::GetPropertyDefinition(
  const std::string& name, cmProperty::ScopeType scope) const
371
{
372
  if (this->IsPropertyDefined(name, scope)) {
373
    cmPropertyDefinitionMap const& defs =
374
      this->PropertyDefinitions.find(scope)->second;
375
    return &defs.find(name)->second;
376
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
377
  return CM_NULLPTR;
378
379
380
}

bool cmState::IsPropertyDefined(const std::string& name,
381
                                cmProperty::ScopeType scope) const
382
{
383
384
385
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
386
    return false;
387
  }
388
  return it->second.IsPropertyDefined(name);
389
390
391
}

bool cmState::IsPropertyChained(const std::string& name,
392
                                cmProperty::ScopeType scope) const
393
{
394
395
396
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
397
    return false;
398
  }
399
  return it->second.IsPropertyChained(name);
400
}
401
402
403

void cmState::SetLanguageEnabled(std::string const& l)
{
404
405
406
  std::vector<std::string>::iterator it = std::lower_bound(
    this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
  if (it == this->EnabledLanguages.end() || *it != l) {
407
    this->EnabledLanguages.insert(it, l);
408
  }
409
410
411
412
413
414
415
416
417
418
419
420
421
}

bool cmState::GetLanguageEnabled(std::string const& l) const
{
  return std::binary_search(this->EnabledLanguages.begin(),
                            this->EnabledLanguages.end(), l);
}

std::vector<std::string> cmState::GetEnabledLanguages() const
{
  return this->EnabledLanguages;
}

422
423
424
425
426
void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
{
  this->EnabledLanguages = langs;
}

427
428
429
430
void cmState::ClearEnabledLanguages()
{
  this->EnabledLanguages.clear();
}
431
432
433
434
435
436
437
438
439
440

bool cmState::GetIsInTryCompile() const
{
  return this->IsInTryCompile;
}

void cmState::SetIsInTryCompile(bool b)
{
  this->IsInTryCompile = b;
}
441
442
443
444
445
446
447
448

void cmState::RenameCommand(std::string const& oldName,
                            std::string const& newName)
{
  // if the command already exists, free the old one
  std::string sOldName = cmSystemTools::LowerCase(oldName);
  std::string sNewName = cmSystemTools::LowerCase(newName);
  std::map<std::string, cmCommand*>::iterator pos =
449
450
    this->Commands.find(sOldName);
  if (pos == this->Commands.end()) {
451
    return;
452
  }
453
454
455
  cmCommand* cmd = pos->second;

  pos = this->Commands.find(sNewName);
456
  if (pos != this->Commands.end()) {
457
458
    delete pos->second;
    this->Commands.erase(pos);
459
  }
460
461
462
463
464
465
466
467
468
469
  this->Commands.insert(std::make_pair(sNewName, cmd));
  pos = this->Commands.find(sOldName);
  this->Commands.erase(pos);
}

void cmState::AddCommand(cmCommand* command)
{
  std::string name = cmSystemTools::LowerCase(command->GetName());
  // if the command already exists, free the old one
  std::map<std::string, cmCommand*>::iterator pos = this->Commands.find(name);
470
  if (pos != this->Commands.end()) {
471
472
    delete pos->second;
    this->Commands.erase(pos);
473
  }
474
475
476
477
478
479
  this->Commands.insert(std::make_pair(name, command));
}

void cmState::RemoveUnscriptableCommands()
{
  std::vector<std::string> unscriptableCommands;
480
481
482
483
  for (std::map<std::string, cmCommand*>::iterator pos =
         this->Commands.begin();
       pos != this->Commands.end();) {
    if (!pos->second->IsScriptable()) {
484
485
      delete pos->second;
      this->Commands.erase(pos++);
486
    } else {
487
488
      ++pos;
    }
489
  }
490
491
492
493
}

cmCommand* cmState::GetCommand(std::string const& name) const
{
Daniel Pfeifer's avatar
Daniel Pfeifer committed
494
  cmCommand* command = CM_NULLPTR;
495
496
  std::string sName = cmSystemTools::LowerCase(name);
  std::map<std::string, cmCommand*>::const_iterator pos =
497
498
    this->Commands.find(sName);
  if (pos != this->Commands.end()) {
499
    command = (*pos).second;
500
  }
501
502
503
504
505
506
507
  return command;
}

std::vector<std::string> cmState::GetCommandNames() const
{
  std::vector<std::string> commandNames;
  commandNames.reserve(this->Commands.size());
508
509
510
  std::map<std::string, cmCommand*>::const_iterator cmds =
    this->Commands.begin();
  for (; cmds != this->Commands.end(); ++cmds) {
511
    commandNames.push_back(cmds->first);
512
  }
513
514
515
516
517
  return commandNames;
}

void cmState::RemoveUserDefinedCommands()
{
518
  std::vector<cmCommand*> renamedCommands;
519
520
  for (std::map<std::string, cmCommand*>::iterator j = this->Commands.begin();
       j != this->Commands.end();) {
521
    if (j->second->IsA("cmMacroHelperCommand") ||
522
        j->second->IsA("cmFunctionHelperCommand")) {
523
524
      delete j->second;
      this->Commands.erase(j++);
525
    } else if (j->first != j->second->GetName()) {
526
527
      renamedCommands.push_back(j->second);
      this->Commands.erase(j++);
528
    } else {
529
530
      ++j;
    }
531
  }
532
  for (std::vector<cmCommand*>::const_iterator it = renamedCommands.begin();
533
       it != renamedCommands.end(); ++it) {
534
    this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
535
  }
536
}
537
538
539

void cmState::SetGlobalProperty(const std::string& prop, const char* value)
{
540
  this->GlobalProperties.SetProperty(prop, value);
541
542
}

543
544
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
545
{
546
  this->GlobalProperties.AppendProperty(prop, value, asString);
547
548
}

549
const char* cmState::GetGlobalProperty(const std::string& prop)
550
{
551
  if (prop == "CACHE_VARIABLES") {
552
553
    std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
    this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
554
  } else if (prop == "COMMANDS") {
555
556
    std::vector<std::string> commands = this->GetCommandNames();
    this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
557
  } else if (prop == "IN_TRY_COMPILE") {
558
    this->SetGlobalProperty("IN_TRY_COMPILE",
559
560
                            this->IsInTryCompile ? "1" : "0");
  } else if (prop == "ENABLED_LANGUAGES") {
561
562
563
    std::string langs;
    langs = cmJoin(this->EnabledLanguages, ";");
    this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
564
  }
565
#define STRING_LIST_ELEMENT(F) ";" #F
566
  if (prop == "CMAKE_C_KNOWN_FEATURES") {
567
    return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
568
569
  }
  if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
570
    return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
571
  }
572
#undef STRING_LIST_ELEMENT
573
  return this->GlobalProperties.GetPropertyValue(prop);
574
575
576
577
578
579
}

bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
  return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
}
580
581
582
583
584

void cmState::SetSourceDirectory(std::string const& sourceDirectory)
{
  this->SourceDirectory = sourceDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
585
586

  cmSystemTools::SplitPath(
587
588
    cmSystemTools::CollapseFullPath(this->SourceDirectory),
    this->SourceDirectoryComponents);
589
590
591
592
593
594
595
}

const char* cmState::GetSourceDirectory() const
{
  return this->SourceDirectory.c_str();
}

596
597
598
599
600
std::vector<std::string> const& cmState::GetSourceDirectoryComponents() const
{
  return this->SourceDirectoryComponents;
}

601
602
603
604
void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
{
  this->BinaryDirectory = binaryDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
605
606

  cmSystemTools::SplitPath(
607
608
    cmSystemTools::CollapseFullPath(this->BinaryDirectory),
    this->BinaryDirectoryComponents);
609
610
}

611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
void cmState::SetWindowsShell(bool windowsShell)
{
  this->WindowsShell = windowsShell;
}

bool cmState::UseWindowsShell() const
{
  return this->WindowsShell;
}

void cmState::SetWindowsVSIDE(bool windowsVSIDE)
{
  this->WindowsVSIDE = windowsVSIDE;
}

bool cmState::UseWindowsVSIDE() const
{
  return this->WindowsVSIDE;
}

void cmState::SetWatcomWMake(bool watcomWMake)
{
  this->WatcomWMake = watcomWMake;
}

bool cmState::UseWatcomWMake() const
{
  return this->WatcomWMake;
}

void cmState::SetMinGWMake(bool minGWMake)
{
  this->MinGWMake = minGWMake;
}

bool cmState::UseMinGWMake() const
{
  return this->MinGWMake;
}

void cmState::SetNMake(bool nMake)
{
  this->NMake = nMake;
}

bool cmState::UseNMake() const
{
  return this->NMake;
}

void cmState::SetMSYSShell(bool mSYSShell)
{
  this->MSYSShell = mSYSShell;
}

bool cmState::UseMSYSShell() const
{
  return this->MSYSShell;
}

671
672
unsigned int cmState::GetCacheMajorVersion() const
{
673
  return this->CacheManager->GetCacheMajorVersion();
674
675
676
677
}

unsigned int cmState::GetCacheMinorVersion() const
{
678
  return this->CacheManager->GetCacheMinorVersion();
679
680
}

681
682
683
684
const char* cmState::GetBinaryDirectory() const
{
  return this->BinaryDirectory.c_str();
}
Stephen Kelly's avatar
Stephen Kelly committed
685

686
687
688
689
690
std::vector<std::string> const& cmState::GetBinaryDirectoryComponents() const
{
  return this->BinaryDirectoryComponents;
}

691
void cmState::Directory::ComputeRelativePathTopSource()
692
693
694
695
696
{
  // Relative path conversion inside the source tree is not used to
  // construct relative paths passed to build tools so it is safe to use
  // even when the source is a network path.

697
  cmState::Snapshot snapshot = this->Snapshot_;
698
699
  std::vector<cmState::Snapshot> snapshots;
  snapshots.push_back(snapshot);
700
  while (true) {
701
    snapshot = snapshot.GetBuildsystemDirectoryParent();
702
    if (snapshot.IsValid()) {
703
      snapshots.push_back(snapshot);
704
    } else {
705
706
      break;
    }
707
  }
708

709
  std::string result = snapshots.front().GetDirectory().GetCurrentSource();
710
711

  for (std::vector<cmState::Snapshot>::const_iterator it =
712
713
         snapshots.begin() + 1;
       it != snapshots.end(); ++it) {
714
    std::string currentSource = it->GetDirectory().GetCurrentSource();
715
    if (cmSystemTools::IsSubDirectory(result, currentSource)) {
716
717
      result = currentSource;
    }
718
  }
719
  this->DirectoryState->RelativePathTopSource = result;
720
721
}

722
void cmState::Directory::ComputeRelativePathTopBinary()
723
{
724
  cmState::Snapshot snapshot = this->Snapshot_;
725
726
  std::vector<cmState::Snapshot> snapshots;
  snapshots.push_back(snapshot);
727
  while (true) {
728
    snapshot = snapshot.GetBuildsystemDirectoryParent();
729
    if (snapshot.IsValid()) {
730
      snapshots.push_back(snapshot);
731
    } else {
732
733
      break;
    }
734
  }
735

736
  std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
737
738

  for (std::vector<cmState::Snapshot>::const_iterator it =
739
740
         snapshots.begin() + 1;
       it != snapshots.end(); ++it) {
741
    std::string currentBinary = it->GetDirectory().GetCurrentBinary();
742
    if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
743
744
      result = currentBinary;
    }
745
  }
746
747
748
749

  // The current working directory on Windows cannot be a network
  // path.  Therefore relative paths cannot work when the binary tree
  // is a network path.
750
  if (result.size() < 2 || result.substr(0, 2) != "//") {
751
    this->DirectoryState->RelativePathTopBinary = result;
752
  } else {
753
    this->DirectoryState->RelativePathTopBinary = "";
754
  }
755
756
}

757
758
cmState::Snapshot cmState::CreateBaseSnapshot()
{
759
  PositionType pos = this->SnapshotData.Push(this->SnapshotData.Root());
760
  pos->DirectoryParent = this->SnapshotData.Root();
761
  pos->ScopeParent = this->SnapshotData.Root();
762
  pos->SnapshotType = BaseType;
763
  pos->Keep = true;
764
  pos->BuildSystemDirectory =
765
    this->BuildsystemDirectory.Push(this->BuildsystemDirectory.Root());
766
  pos->ExecutionListFile =
767
    this->ExecutionListFiles.Push(this->ExecutionListFiles.Root());
768
769
770
  pos->IncludeDirectoryPosition = 0;
  pos->CompileDefinitionsPosition = 0;
  pos->CompileOptionsPosition = 0;
771
  pos->BuildSystemDirectory->DirectoryEnd = pos;
772
773
774
775
776
  pos->Policies = this->PolicyStack.Root();
  pos->PolicyRoot = this->PolicyStack.Root();
  pos->PolicyScope = this->PolicyStack.Root();
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
777
  pos->Vars = this->VarTree.Push(this->VarTree.Root());
778
779
780
  assert(pos->Vars.IsValid());
  pos->Parent = this->VarTree.Root();
  pos->Root = this->VarTree.Root();
781
782
783
  return cmState::Snapshot(this, pos);
}

784
785
cmState::Snapshot cmState::CreateBuildsystemDirectorySnapshot(
  Snapshot originSnapshot)
Stephen Kelly's avatar
Stephen Kelly committed
786
{
787
  assert(originSnapshot.IsValid());
788
  PositionType pos = this->SnapshotData.Push(originSnapshot.Position);
789
  pos->DirectoryParent = originSnapshot.Position;
790
  pos->ScopeParent = originSnapshot.Position;
791
  pos->SnapshotType = BuildsystemDirectoryType;
792
  pos->Keep = true;
793
794
  pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
    originSnapshot.Position->BuildSystemDirectory);
795
  pos->ExecutionListFile =
796
    this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
797
  pos->BuildSystemDirectory->DirectoryEnd = pos;
798
799
800
801
802
  pos->Policies = originSnapshot.Position->Policies;
  pos->PolicyRoot = originSnapshot.Position->Policies;
  pos->PolicyScope = originSnapshot.Position->Policies;
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
803

804
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
805
806
  pos->Parent = origin;
  pos->Root = origin;
807
  pos->Vars = this->VarTree.Push(origin);
808

809
810
  cmState::Snapshot snapshot = cmState::Snapshot(this, pos);
  originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
811
  snapshot.SetDefaultDefinitions();
812
  snapshot.InitializeFromParent();
813
  snapshot.SetDirectoryDefinitions();
814
  return snapshot;
Stephen Kelly's avatar
Stephen Kelly committed
815
816
}

817
818
cmState::Snapshot cmState::CreateFunctionCallSnapshot(
  cmState::Snapshot originSnapshot, std::string const& fileName)
819
{
820
821
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
822
  pos->ScopeParent = originSnapshot.Position;
823
  pos->SnapshotType = FunctionCallType;
824
  pos->Keep = false;
825
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
826
    originSnapshot.Position->ExecutionListFile, fileName);
827
  pos->BuildSystemDirectory->DirectoryEnd = pos;
828
  pos->PolicyScope = originSnapshot.Position->Policies;
829
  assert(originSnapshot.Position->Vars.IsValid());
830
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
831
  pos->Parent = origin;
832
  pos->Vars = this->VarTree.Push(origin);
833
834
835
  return cmState::Snapshot(this, pos);
}

836
837
cmState::Snapshot cmState::CreateMacroCallSnapshot(
  cmState::Snapshot originSnapshot, std::string const& fileName)
838
{
839
840
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
841
  pos->SnapshotType = MacroCallType;
842
  pos->Keep = false;
843
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
844
    originSnapshot.Position->ExecutionListFile, fileName);
845
  assert(originSnapshot.Position->Vars.IsValid());
846
  pos->BuildSystemDirectory->DirectoryEnd = pos;
847
  pos->PolicyScope = originSnapshot.Position->Policies;
848
849
850
  return cmState::Snapshot(this, pos);
}

851
852
cmState::Snapshot cmState::CreateIncludeFileSnapshot(
  cmState::Snapshot originSnapshot, const std::string& fileName)
853
{
854
855
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
856
  pos->SnapshotType = IncludeFileType;
857
  pos->Keep = true;
858
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
859
    originSnapshot.Position->ExecutionListFile, fileName);
860
  assert(originSnapshot.Position->Vars.IsValid());
861
  pos->BuildSystemDirectory->DirectoryEnd = pos;
862
  pos->PolicyScope = originSnapshot.Position->Policies;
863
864
865
  return cmState::Snapshot(this, pos);
}

866
867
cmState::Snapshot cmState::CreateVariableScopeSnapshot(
  cmState::Snapshot originSnapshot)
868
{
869
870
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
871
872
  pos->ScopeParent = originSnapshot.Position;
  pos->SnapshotType = VariableScopeType;
873
  pos->Keep = false;
874
  pos->PolicyScope = originSnapshot.Position->Policies;
875
  assert(originSnapshot.Position->Vars.IsValid());
876

877
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
878
  pos->Parent = origin;
879
  pos->Vars = this->VarTree.Push(origin);
880
  assert(pos->Vars.IsValid());
881
882
883
  return cmState::Snapshot(this, pos);
}

884
885
cmState::Snapshot cmState::CreateInlineListFileSnapshot(
  cmState::Snapshot originSnapshot, const std::string& fileName)
886
{
887
888
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
889
  pos->SnapshotType = InlineListFileType;
890
  pos->Keep = true;
891
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
892
    originSnapshot.Position->ExecutionListFile, fileName);
893
  pos->BuildSystemDirectory->DirectoryEnd = pos;
894
  pos->PolicyScope = originSnapshot.Position->Policies;
895
896
897
  return cmState::Snapshot(this, pos);
}

898
899
cmState::Snapshot cmState::CreatePolicyScopeSnapshot(
  cmState::Snapshot originSnapshot)
900
{
901
902
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
903
  pos->SnapshotType = PolicyScopeType;
904
  pos->Keep = false;
905
  pos->BuildSystemDirectory->DirectoryEnd = pos;
906
  pos->PolicyScope = originSnapshot.Position->Policies;
907
908
909
  return cmState::Snapshot(this, pos);
}

910
911
912
913
914
cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot)
{
  PositionType pos = originSnapshot.Position;
  PositionType prevPos = pos;
  ++prevPos;
915
  prevPos->IncludeDirectoryPosition =
916
    prevPos->BuildSystemDirectory->IncludeDirectories.size();