cmState.cxx 55.8 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
138
139
140
  assert(0 && "Unexpected target type");
  return 0;
}

141
142
143
const char* cmCacheEntryTypes[] = { "BOOL",          "PATH",     "FILEPATH",
                                    "STRING",        "INTERNAL", "STATIC",
                                    "UNINITIALIZED", 0 };
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) {
Stephen Kelly's avatar
Stephen Kelly committed
207
    return 0;
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
249
  it.SetProperty(propertyName, value);
}

const char* cmState::GetCacheEntryProperty(std::string const& key,
250
                                           std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
251
{
252
253
254
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  if (!it.PropertyExists(propertyName)) {
Stephen Kelly's avatar
Stephen Kelly committed
255
    return 0;
256
  }
Stephen Kelly's avatar
Stephen Kelly committed
257
258
259
260
  return it.GetProperty(propertyName);
}

bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
261
                                          std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
262
{
263
264
  return this->CacheManager->GetCacheIterator(key.c_str())
    .GetPropertyAsBool(propertyName);
Stephen Kelly's avatar
Stephen Kelly committed
265
266
267
}

void cmState::AddCacheEntry(const std::string& key, const char* value,
268
269
                            const char* helpString,
                            cmState::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
270
{
271
  this->CacheManager->AddCacheEntry(key, value, helpString, type);
Stephen Kelly's avatar
Stephen Kelly committed
272
273
274
275
}

void cmState::RemoveCacheEntry(std::string const& key)
{
276
  this->CacheManager->RemoveCacheEntry(key);
Stephen Kelly's avatar
Stephen Kelly committed
277
278
279
}

void cmState::AppendCacheEntryProperty(const std::string& key,
280
281
                                       const std::string& property,
                                       const std::string& value, bool asString)
Stephen Kelly's avatar
Stephen Kelly committed
282
{
283
284
  this->CacheManager->GetCacheIterator(key.c_str())
    .AppendProperty(property, value.c_str(), asString);
Stephen Kelly's avatar
Stephen Kelly committed
285
286
287
}

void cmState::RemoveCacheEntryProperty(std::string const& key,
288
                                       std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
289
{
290
291
  this->CacheManager->GetCacheIterator(key.c_str())
    .SetProperty(propertyName, (void*)0);
Stephen Kelly's avatar
Stephen Kelly committed
292
}
293

294
cmState::Snapshot cmState::Reset()
295
{
296
  this->GlobalProperties.clear();
297
  this->PropertyDefinitions.clear();
298

299
300
301
  PositionType pos = this->SnapshotData.Truncate();
  this->ExecutionListFiles.Truncate();

302
  {
303
    cmLinkedTree<BuildsystemDirectoryStateType>::iterator it =
304
      this->BuildsystemDirectory.Truncate();
305
306
307
308
309
310
311
312
313
    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();
314
  }
315

316
317
318
319
320
321
  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());
322
323

  {
324
    std::string srcDir =
325
      cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
326
    std::string binDir =
327
      cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
328
329
330
331
    this->VarTree.Clear();
    pos->Vars = this->VarTree.Push(this->VarTree.Root());
    pos->Parent = this->VarTree.Root();
    pos->Root = this->VarTree.Root();
332

333
334
    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
335
336
  }

337
338
339
340
341
342
343
344
345
346
347
  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);
348
349

  return Snapshot(this, pos);
350
351
352
}

void cmState::DefineProperty(const std::string& name,
353
354
355
                             cmProperty::ScopeType scope,
                             const char* ShortDescription,
                             const char* FullDescription, bool chained)
356
{
357
358
  this->PropertyDefinitions[scope].DefineProperty(
    name, scope, ShortDescription, FullDescription, chained);
359
360
}

361
362
cmPropertyDefinition const* cmState::GetPropertyDefinition(
  const std::string& name, cmProperty::ScopeType scope) const
363
{
364
  if (this->IsPropertyDefined(name, scope)) {
365
    cmPropertyDefinitionMap const& defs =
366
      this->PropertyDefinitions.find(scope)->second;
367
    return &defs.find(name)->second;
368
  }
369
370
371
372
  return 0;
}

bool cmState::IsPropertyDefined(const std::string& name,
373
                                cmProperty::ScopeType scope) const
374
{
375
376
377
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
378
    return false;
379
  }
380
  return it->second.IsPropertyDefined(name);
381
382
383
}

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

void cmState::SetLanguageEnabled(std::string const& l)
{
396
397
398
  std::vector<std::string>::iterator it = std::lower_bound(
    this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
  if (it == this->EnabledLanguages.end() || *it != l) {
399
    this->EnabledLanguages.insert(it, l);
400
  }
401
402
403
404
405
406
407
408
409
410
411
412
413
}

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

414
415
416
417
418
void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
{
  this->EnabledLanguages = langs;
}

419
420
421
422
void cmState::ClearEnabledLanguages()
{
  this->EnabledLanguages.clear();
}
423
424
425
426
427
428
429
430
431
432

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

void cmState::SetIsInTryCompile(bool b)
{
  this->IsInTryCompile = b;
}
433
434
435
436
437
438
439
440

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 =
441
442
    this->Commands.find(sOldName);
  if (pos == this->Commands.end()) {
443
    return;
444
  }
445
446
447
  cmCommand* cmd = pos->second;

  pos = this->Commands.find(sNewName);
448
  if (pos != this->Commands.end()) {
449
450
    delete pos->second;
    this->Commands.erase(pos);
451
  }
452
453
454
455
456
457
458
459
460
461
  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);
462
  if (pos != this->Commands.end()) {
463
464
    delete pos->second;
    this->Commands.erase(pos);
465
  }
466
467
468
469
470
471
  this->Commands.insert(std::make_pair(name, command));
}

void cmState::RemoveUnscriptableCommands()
{
  std::vector<std::string> unscriptableCommands;
472
473
474
475
  for (std::map<std::string, cmCommand*>::iterator pos =
         this->Commands.begin();
       pos != this->Commands.end();) {
    if (!pos->second->IsScriptable()) {
476
477
      delete pos->second;
      this->Commands.erase(pos++);
478
    } else {
479
480
      ++pos;
    }
481
  }
482
483
484
485
486
487
488
}

cmCommand* cmState::GetCommand(std::string const& name) const
{
  cmCommand* command = 0;
  std::string sName = cmSystemTools::LowerCase(name);
  std::map<std::string, cmCommand*>::const_iterator pos =
489
490
    this->Commands.find(sName);
  if (pos != this->Commands.end()) {
491
    command = (*pos).second;
492
  }
493
494
495
496
497
498
499
  return command;
}

std::vector<std::string> cmState::GetCommandNames() const
{
  std::vector<std::string> commandNames;
  commandNames.reserve(this->Commands.size());
500
501
502
  std::map<std::string, cmCommand*>::const_iterator cmds =
    this->Commands.begin();
  for (; cmds != this->Commands.end(); ++cmds) {
503
    commandNames.push_back(cmds->first);
504
  }
505
506
507
508
509
  return commandNames;
}

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

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

535
536
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
537
{
538
  this->GlobalProperties.AppendProperty(prop, value, asString);
539
540
}

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

bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
  return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
}
572
573
574
575
576

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

  cmSystemTools::SplitPath(
579
580
    cmSystemTools::CollapseFullPath(this->SourceDirectory),
    this->SourceDirectoryComponents);
581
582
583
584
585
586
587
}

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

588
589
590
591
592
std::vector<std::string> const& cmState::GetSourceDirectoryComponents() const
{
  return this->SourceDirectoryComponents;
}

593
594
595
596
void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
{
  this->BinaryDirectory = binaryDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
597
598

  cmSystemTools::SplitPath(
599
600
    cmSystemTools::CollapseFullPath(this->BinaryDirectory),
    this->BinaryDirectoryComponents);
601
602
}

603
604
605
606
607
608
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
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;
}

663
664
unsigned int cmState::GetCacheMajorVersion() const
{
665
  return this->CacheManager->GetCacheMajorVersion();
666
667
668
669
}

unsigned int cmState::GetCacheMinorVersion() const
{
670
  return this->CacheManager->GetCacheMinorVersion();
671
672
}

673
674
675
676
const char* cmState::GetBinaryDirectory() const
{
  return this->BinaryDirectory.c_str();
}
Stephen Kelly's avatar
Stephen Kelly committed
677

678
679
680
681
682
std::vector<std::string> const& cmState::GetBinaryDirectoryComponents() const
{
  return this->BinaryDirectoryComponents;
}

683
void cmState::Directory::ComputeRelativePathTopSource()
684
685
686
687
688
{
  // 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.

689
  cmState::Snapshot snapshot = this->Snapshot_;
690
691
  std::vector<cmState::Snapshot> snapshots;
  snapshots.push_back(snapshot);
692
  while (true) {
693
    snapshot = snapshot.GetBuildsystemDirectoryParent();
694
    if (snapshot.IsValid()) {
695
      snapshots.push_back(snapshot);
696
    } else {
697
698
      break;
    }
699
  }
700

701
  std::string result = snapshots.front().GetDirectory().GetCurrentSource();
702
703

  for (std::vector<cmState::Snapshot>::const_iterator it =
704
705
         snapshots.begin() + 1;
       it != snapshots.end(); ++it) {
706
    std::string currentSource = it->GetDirectory().GetCurrentSource();
707
    if (cmSystemTools::IsSubDirectory(result, currentSource)) {
708
709
      result = currentSource;
    }
710
  }
711
  this->DirectoryState->RelativePathTopSource = result;
712
713
}

714
void cmState::Directory::ComputeRelativePathTopBinary()
715
{
716
  cmState::Snapshot snapshot = this->Snapshot_;
717
718
  std::vector<cmState::Snapshot> snapshots;
  snapshots.push_back(snapshot);
719
  while (true) {
720
    snapshot = snapshot.GetBuildsystemDirectoryParent();
721
    if (snapshot.IsValid()) {
722
      snapshots.push_back(snapshot);
723
    } else {
724
725
      break;
    }
726
  }
727

728
  std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
729
730

  for (std::vector<cmState::Snapshot>::const_iterator it =
731
732
         snapshots.begin() + 1;
       it != snapshots.end(); ++it) {
733
    std::string currentBinary = it->GetDirectory().GetCurrentBinary();
734
    if (cmSystemTools::IsSubDirectory(result, currentBinary)) {
735
736
      result = currentBinary;
    }
737
  }
738
739
740
741

  // The current working directory on Windows cannot be a network
  // path.  Therefore relative paths cannot work when the binary tree
  // is a network path.
742
  if (result.size() < 2 || result.substr(0, 2) != "//") {
743
    this->DirectoryState->RelativePathTopBinary = result;
744
  } else {
745
    this->DirectoryState->RelativePathTopBinary = "";
746
  }
747
748
}

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

776
777
cmState::Snapshot cmState::CreateBuildsystemDirectorySnapshot(
  Snapshot originSnapshot)
Stephen Kelly's avatar
Stephen Kelly committed
778
{
779
  assert(originSnapshot.IsValid());
780
  PositionType pos = this->SnapshotData.Push(originSnapshot.Position);
781
  pos->DirectoryParent = originSnapshot.Position;
782
  pos->ScopeParent = originSnapshot.Position;
783
  pos->SnapshotType = BuildsystemDirectoryType;
784
  pos->Keep = true;
785
786
  pos->BuildSystemDirectory = this->BuildsystemDirectory.Push(
    originSnapshot.Position->BuildSystemDirectory);
787
  pos->ExecutionListFile =
788
    this->ExecutionListFiles.Push(originSnapshot.Position->ExecutionListFile);
789
  pos->BuildSystemDirectory->DirectoryEnd = pos;
790
791
792
793
794
  pos->Policies = originSnapshot.Position->Policies;
  pos->PolicyRoot = originSnapshot.Position->Policies;
  pos->PolicyScope = originSnapshot.Position->Policies;
  assert(pos->Policies.IsValid());
  assert(pos->PolicyRoot.IsValid());
795

796
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
797
798
  pos->Parent = origin;
  pos->Root = origin;
799
  pos->Vars = this->VarTree.Push(origin);
800

801
802
  cmState::Snapshot snapshot = cmState::Snapshot(this, pos);
  originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot);
803
  snapshot.SetDefaultDefinitions();
804
  snapshot.InitializeFromParent();
805
  snapshot.SetDirectoryDefinitions();
806
  return snapshot;
Stephen Kelly's avatar
Stephen Kelly committed
807
808
}

809
810
cmState::Snapshot cmState::CreateFunctionCallSnapshot(
  cmState::Snapshot originSnapshot, std::string const& fileName)
811
{
812
813
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
814
  pos->ScopeParent = originSnapshot.Position;
815
  pos->SnapshotType = FunctionCallType;
816
  pos->Keep = false;
817
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
818
    originSnapshot.Position->ExecutionListFile, fileName);
819
  pos->BuildSystemDirectory->DirectoryEnd = pos;
820
  pos->PolicyScope = originSnapshot.Position->Policies;
821
  assert(originSnapshot.Position->Vars.IsValid());
822
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
823
  pos->Parent = origin;
824
  pos->Vars = this->VarTree.Push(origin);
825
826
827
  return cmState::Snapshot(this, pos);
}

828
829
cmState::Snapshot cmState::CreateMacroCallSnapshot(
  cmState::Snapshot originSnapshot, std::string const& fileName)
830
{
831
832
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
833
  pos->SnapshotType = MacroCallType;
834
  pos->Keep = false;
835
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
836
    originSnapshot.Position->ExecutionListFile, fileName);
837
  assert(originSnapshot.Position->Vars.IsValid());
838
  pos->BuildSystemDirectory->DirectoryEnd = pos;
839
  pos->PolicyScope = originSnapshot.Position->Policies;
840
841
842
  return cmState::Snapshot(this, pos);
}

843
844
cmState::Snapshot cmState::CreateIncludeFileSnapshot(
  cmState::Snapshot originSnapshot, const std::string& fileName)
845
{
846
847
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
848
  pos->SnapshotType = IncludeFileType;
849
  pos->Keep = true;
850
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
851
    originSnapshot.Position->ExecutionListFile, fileName);
852
  assert(originSnapshot.Position->Vars.IsValid());
853
  pos->BuildSystemDirectory->DirectoryEnd = pos;
854
  pos->PolicyScope = originSnapshot.Position->Policies;
855
856
857
  return cmState::Snapshot(this, pos);
}

858
859
cmState::Snapshot cmState::CreateVariableScopeSnapshot(
  cmState::Snapshot originSnapshot)
860
{
861
862
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
863
864
  pos->ScopeParent = originSnapshot.Position;
  pos->SnapshotType = VariableScopeType;
865
  pos->Keep = false;
866
  pos->PolicyScope = originSnapshot.Position->Policies;
867
  assert(originSnapshot.Position->Vars.IsValid());
868

869
  cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars;
870
  pos->Parent = origin;
871
  pos->Vars = this->VarTree.Push(origin);
872
  assert(pos->Vars.IsValid());
873
874
875
  return cmState::Snapshot(this, pos);
}

876
877
cmState::Snapshot cmState::CreateInlineListFileSnapshot(
  cmState::Snapshot originSnapshot, const std::string& fileName)
878
{
879
880
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
881
  pos->SnapshotType = InlineListFileType;
882
  pos->Keep = true;
883
  pos->ExecutionListFile = this->ExecutionListFiles.Push(
884
    originSnapshot.Position->ExecutionListFile, fileName);
885
  pos->BuildSystemDirectory->DirectoryEnd = pos;
886
  pos->PolicyScope = originSnapshot.Position->Policies;
887
888
889
  return cmState::Snapshot(this, pos);
}

890
891
cmState::Snapshot cmState::CreatePolicyScopeSnapshot(
  cmState::Snapshot originSnapshot)
892
{
893
894
  PositionType pos =
    this->SnapshotData.Push(originSnapshot.Position, *originSnapshot.Position);
895
  pos->SnapshotType = PolicyScopeType;
896
  pos->Keep = false;
897
  pos->BuildSystemDirectory->DirectoryEnd = pos;
898
  pos->PolicyScope = originSnapshot.Position->Policies;
899
900
901
  return cmState::Snapshot(this, pos);
}

902
903
904
905
906
cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot)
{
  PositionType pos = originSnapshot.Position;
  PositionType prevPos = pos;
  ++prevPos;
907
  prevPos->IncludeDirectoryPosition =
908
    prevPos->BuildSystemDirectory->IncludeDirectories.size();
909
  prevPos->CompileDefinitionsPosition =
910
    prevPos->BuildSystemDirectory->CompileDefinitions.size();
911
  prevPos->CompileOptionsPosition =
912
    prevPos->BuildSystemDirectory->CompileOptions.size();
913
  prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
914

915
916
  if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
    if (pos->Vars != prevPos->Vars) {
917
918
      assert(this->VarTree.IsLast(pos->Vars));
      this->VarTree.Pop(pos->Vars);