cmState.cxx 55.9 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
20
#include "cmListFileCache.h"
#include "cmSystemTools.h"
#include "cmTypeMacro.h"
21
22
#include "cmVersion.h"
#include "cmake.h"
23

24
#include <algorithm>
25
#include <assert.h>
26
27
28
29
30
#include <cmsys/RegularExpression.hxx>
#include <iterator>
#include <stdio.h>
#include <string.h>
#include <utility>
Stephen Kelly's avatar
Stephen Kelly committed
31

32
33
static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES";

34
35
struct cmState::SnapshotDataType
{
36
  cmState::PositionType ScopeParent;
37
  cmState::PositionType DirectoryParent;
38
39
40
  cmLinkedTree<cmState::PolicyStackEntry>::iterator Policies;
  cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyRoot;
  cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyScope;
41
  cmState::SnapshotType SnapshotType;
42
  bool Keep;
43
  cmLinkedTree<std::string>::iterator ExecutionListFile;
44
  cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator
45
    BuildSystemDirectory;
46
47
48
  cmLinkedTree<cmDefinitions>::iterator Vars;
  cmLinkedTree<cmDefinitions>::iterator Root;
  cmLinkedTree<cmDefinitions>::iterator Parent;
49
50
51
  std::vector<std::string>::size_type IncludeDirectoryPosition;
  std::vector<std::string>::size_type CompileDefinitionsPosition;
  std::vector<std::string>::size_type CompileOptionsPosition;
52
53
};

54
struct cmState::PolicyStackEntry : public cmPolicies::PolicyMap
55
56
{
  typedef cmPolicies::PolicyMap derived;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  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)
  {
  }
72
73
74
  bool Weak;
};

75
76
struct cmState::BuildsystemDirectoryStateType
{
77
78
  cmState::PositionType DirectoryEnd;

79
80
81
82
83
84
85
86
87
88
  std::string Location;
  std::string OutputLocation;

  // 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;
89
90
91
92
93
94
95
96
97

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

99
100
  std::vector<std::string> NormalTargetNames;

101
102
  std::string ProjectName;

103
  cmPropertyMap Properties;
104
105

  std::vector<cmState::Snapshot> Children;
106
107
};

108
cmState::cmState()
109
110
111
112
113
114
115
  : IsInTryCompile(false)
  , WindowsShell(false)
  , WindowsVSIDE(false)
  , WatcomWMake(false)
  , MinGWMake(false)
  , NMake(false)
  , MSYSShell(false)
Stephen Kelly's avatar
Stephen Kelly committed
116
{
117
  this->CacheManager = new cmCacheManager;
Stephen Kelly's avatar
Stephen Kelly committed
118
}
119

120
121
cmState::~cmState()
{
122
  delete this->CacheManager;
123
124
125
  cmDeleteAll(this->Commands);
}

126
127
const char* cmState::GetTargetTypeName(cmState::TargetType targetType)
{
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  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";
  }
148
  assert(0 && "Unexpected target type");
Daniel Pfeifer's avatar
Daniel Pfeifer committed
149
  return CM_NULLPTR;
150
151
}

152
153
const char* cmCacheEntryTypes[] = { "BOOL",          "PATH",     "FILEPATH",
                                    "STRING",        "INTERNAL", "STATIC",
Daniel Pfeifer's avatar
Daniel Pfeifer committed
154
                                    "UNINITIALIZED", CM_NULLPTR };
155

156
const char* cmState::CacheEntryTypeToString(cmState::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
157
{
158
  if (type > 6) {
159
    return cmCacheEntryTypes[6];
160
  }
161
  return cmCacheEntryTypes[type];
Stephen Kelly's avatar
Stephen Kelly committed
162
163
}

164
cmState::CacheEntryType cmState::StringToCacheEntryType(const char* s)
Stephen Kelly's avatar
Stephen Kelly committed
165
{
166
  int i = 0;
167
168
  while (cmCacheEntryTypes[i]) {
    if (strcmp(s, cmCacheEntryTypes[i]) == 0) {
169
170
      return static_cast<cmState::CacheEntryType>(i);
    }
171
172
    ++i;
  }
173
  return STRING;
Stephen Kelly's avatar
Stephen Kelly committed
174
175
176
177
}

bool cmState::IsCacheEntryType(std::string const& key)
{
178
179
  for (int i = 0; cmCacheEntryTypes[i]; ++i) {
    if (strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) {
180
181
      return true;
    }
182
  }
183
  return false;
Stephen Kelly's avatar
Stephen Kelly committed
184
185
}

186
187
188
189
bool cmState::LoadCache(const std::string& path, bool internal,
                        std::set<std::string>& excludes,
                        std::set<std::string>& includes)
{
190
  return this->CacheManager->LoadCache(path, internal, excludes, includes);
191
192
193
194
}

bool cmState::SaveCache(const std::string& path)
{
195
  return this->CacheManager->SaveCache(path);
196
197
198
199
}

bool cmState::DeleteCache(const std::string& path)
{
200
  return this->CacheManager->DeleteCache(path);
201
202
}

Stephen Kelly's avatar
Stephen Kelly committed
203
204
205
std::vector<std::string> cmState::GetCacheEntryKeys() const
{
  std::vector<std::string> definitions;
206
  definitions.reserve(this->CacheManager->GetSize());
207
208
  cmCacheManager::CacheIterator cit = this->CacheManager->GetCacheIterator();
  for (cit.Begin(); !cit.IsAtEnd(); cit.Next()) {
Stephen Kelly's avatar
Stephen Kelly committed
209
    definitions.push_back(cit.GetName());
210
  }
Stephen Kelly's avatar
Stephen Kelly committed
211
212
213
214
215
  return definitions;
}

const char* cmState::GetCacheEntryValue(std::string const& key) const
{
216
217
  cmCacheManager::CacheEntry* e = this->CacheManager->GetCacheEntry(key);
  if (!e) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
218
    return CM_NULLPTR;
219
  }
Stephen Kelly's avatar
Stephen Kelly committed
220
221
222
  return e->Value.c_str();
}

223
const char* cmState::GetInitializedCacheValue(std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
224
{
225
  return this->CacheManager->GetInitializedCacheValue(key);
Stephen Kelly's avatar
Stephen Kelly committed
226
227
}

228
229
cmState::CacheEntryType cmState::GetCacheEntryType(
  std::string const& key) const
Stephen Kelly's avatar
Stephen Kelly committed
230
231
{
  cmCacheManager::CacheIterator it =
232
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
233
234
235
236
  return it.GetType();
}

void cmState::SetCacheEntryValue(std::string const& key,
237
                                 std::string const& value)
Stephen Kelly's avatar
Stephen Kelly committed
238
{
239
  this->CacheManager->SetCacheEntryValue(key, value);
Stephen Kelly's avatar
Stephen Kelly committed
240
241
242
}

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

void cmState::SetCacheEntryBoolProperty(std::string const& key,
252
253
                                        std::string const& propertyName,
                                        bool value)
Stephen Kelly's avatar
Stephen Kelly committed
254
255
{
  cmCacheManager::CacheIterator it =
256
    this->CacheManager->GetCacheIterator(key.c_str());
Stephen Kelly's avatar
Stephen Kelly committed
257
258
259
  it.SetProperty(propertyName, value);
}

260
261
262
263
264
265
266
267
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
268
const char* cmState::GetCacheEntryProperty(std::string const& key,
269
                                           std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
270
{
271
272
273
  cmCacheManager::CacheIterator it =
    this->CacheManager->GetCacheIterator(key.c_str());
  if (!it.PropertyExists(propertyName)) {
Daniel Pfeifer's avatar
Daniel Pfeifer committed
274
    return CM_NULLPTR;
275
  }
Stephen Kelly's avatar
Stephen Kelly committed
276
277
278
279
  return it.GetProperty(propertyName);
}

bool cmState::GetCacheEntryPropertyAsBool(std::string const& key,
280
                                          std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
281
{
282
283
  return this->CacheManager->GetCacheIterator(key.c_str())
    .GetPropertyAsBool(propertyName);
Stephen Kelly's avatar
Stephen Kelly committed
284
285
286
}

void cmState::AddCacheEntry(const std::string& key, const char* value,
287
288
                            const char* helpString,
                            cmState::CacheEntryType type)
Stephen Kelly's avatar
Stephen Kelly committed
289
{
290
  this->CacheManager->AddCacheEntry(key, value, helpString, type);
Stephen Kelly's avatar
Stephen Kelly committed
291
292
293
294
}

void cmState::RemoveCacheEntry(std::string const& key)
{
295
  this->CacheManager->RemoveCacheEntry(key);
Stephen Kelly's avatar
Stephen Kelly committed
296
297
298
}

void cmState::AppendCacheEntryProperty(const std::string& key,
299
300
                                       const std::string& property,
                                       const std::string& value, bool asString)
Stephen Kelly's avatar
Stephen Kelly committed
301
{
302
303
  this->CacheManager->GetCacheIterator(key.c_str())
    .AppendProperty(property, value.c_str(), asString);
Stephen Kelly's avatar
Stephen Kelly committed
304
305
306
}

void cmState::RemoveCacheEntryProperty(std::string const& key,
307
                                       std::string const& propertyName)
Stephen Kelly's avatar
Stephen Kelly committed
308
{
309
  this->CacheManager->GetCacheIterator(key.c_str())
Daniel Pfeifer's avatar
Daniel Pfeifer committed
310
    .SetProperty(propertyName, (void*)CM_NULLPTR);
Stephen Kelly's avatar
Stephen Kelly committed
311
}
312

313
cmState::Snapshot cmState::Reset()
314
{
315
  this->GlobalProperties.clear();
316
  this->PropertyDefinitions.clear();
317

318
319
320
  PositionType pos = this->SnapshotData.Truncate();
  this->ExecutionListFiles.Truncate();

321
  {
322
    cmLinkedTree<BuildsystemDirectoryStateType>::iterator it =
323
      this->BuildsystemDirectory.Truncate();
324
325
326
327
328
329
330
    it->IncludeDirectories.clear();
    it->IncludeDirectoryBacktraces.clear();
    it->CompileDefinitions.clear();
    it->CompileDefinitionsBacktraces.clear();
    it->CompileOptions.clear();
    it->CompileOptionsBacktraces.clear();
    it->DirectoryEnd = pos;
331
    it->NormalTargetNames.clear();
332
333
    it->Properties.clear();
    it->Children.clear();
334
  }
335

336
337
338
339
340
341
  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());
342
343

  {
344
    std::string srcDir =
345
      cmDefinitions::Get("CMAKE_SOURCE_DIR", pos->Vars, pos->Root);
346
    std::string binDir =
347
      cmDefinitions::Get("CMAKE_BINARY_DIR", pos->Vars, pos->Root);
348
349
350
351
    this->VarTree.Clear();
    pos->Vars = this->VarTree.Push(this->VarTree.Root());
    pos->Parent = this->VarTree.Root();
    pos->Root = this->VarTree.Root();
352

353
354
    pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str());
    pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str());
355
356
  }

357
358
359
360
361
362
363
364
365
366
367
  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);
368
369

  return Snapshot(this, pos);
370
371
372
}

void cmState::DefineProperty(const std::string& name,
373
374
375
                             cmProperty::ScopeType scope,
                             const char* ShortDescription,
                             const char* FullDescription, bool chained)
376
{
377
378
  this->PropertyDefinitions[scope].DefineProperty(
    name, scope, ShortDescription, FullDescription, chained);
379
380
}

381
382
cmPropertyDefinition const* cmState::GetPropertyDefinition(
  const std::string& name, cmProperty::ScopeType scope) const
383
{
384
  if (this->IsPropertyDefined(name, scope)) {
385
    cmPropertyDefinitionMap const& defs =
386
      this->PropertyDefinitions.find(scope)->second;
387
    return &defs.find(name)->second;
388
  }
Daniel Pfeifer's avatar
Daniel Pfeifer committed
389
  return CM_NULLPTR;
390
391
392
}

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

bool cmState::IsPropertyChained(const std::string& name,
404
                                cmProperty::ScopeType scope) const
405
{
406
407
408
  std::map<cmProperty::ScopeType, cmPropertyDefinitionMap>::const_iterator it =
    this->PropertyDefinitions.find(scope);
  if (it == this->PropertyDefinitions.end()) {
409
    return false;
410
  }
411
  return it->second.IsPropertyChained(name);
412
}
413
414
415

void cmState::SetLanguageEnabled(std::string const& l)
{
416
417
418
  std::vector<std::string>::iterator it = std::lower_bound(
    this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l);
  if (it == this->EnabledLanguages.end() || *it != l) {
419
    this->EnabledLanguages.insert(it, l);
420
  }
421
422
423
424
425
426
427
428
429
430
431
432
433
}

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

434
435
436
437
438
void cmState::SetEnabledLanguages(std::vector<std::string> const& langs)
{
  this->EnabledLanguages = langs;
}

439
440
441
442
void cmState::ClearEnabledLanguages()
{
  this->EnabledLanguages.clear();
}
443
444
445
446
447
448
449
450
451
452

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

void cmState::SetIsInTryCompile(bool b)
{
  this->IsInTryCompile = b;
}
453
454
455
456
457
458
459
460

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 =
461
462
    this->Commands.find(sOldName);
  if (pos == this->Commands.end()) {
463
    return;
464
  }
465
466
467
  cmCommand* cmd = pos->second;

  pos = this->Commands.find(sNewName);
468
  if (pos != this->Commands.end()) {
469
470
    delete pos->second;
    this->Commands.erase(pos);
471
  }
472
473
474
475
476
477
478
479
480
481
  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);
482
  if (pos != this->Commands.end()) {
483
484
    delete pos->second;
    this->Commands.erase(pos);
485
  }
486
487
488
489
490
491
  this->Commands.insert(std::make_pair(name, command));
}

void cmState::RemoveUnscriptableCommands()
{
  std::vector<std::string> unscriptableCommands;
492
493
494
495
  for (std::map<std::string, cmCommand*>::iterator pos =
         this->Commands.begin();
       pos != this->Commands.end();) {
    if (!pos->second->IsScriptable()) {
496
497
      delete pos->second;
      this->Commands.erase(pos++);
498
    } else {
499
500
      ++pos;
    }
501
  }
502
503
504
505
}

cmCommand* cmState::GetCommand(std::string const& name) const
{
Daniel Pfeifer's avatar
Daniel Pfeifer committed
506
  cmCommand* command = CM_NULLPTR;
507
508
  std::string sName = cmSystemTools::LowerCase(name);
  std::map<std::string, cmCommand*>::const_iterator pos =
509
510
    this->Commands.find(sName);
  if (pos != this->Commands.end()) {
511
    command = (*pos).second;
512
  }
513
514
515
516
517
518
519
  return command;
}

std::vector<std::string> cmState::GetCommandNames() const
{
  std::vector<std::string> commandNames;
  commandNames.reserve(this->Commands.size());
520
521
522
  std::map<std::string, cmCommand*>::const_iterator cmds =
    this->Commands.begin();
  for (; cmds != this->Commands.end(); ++cmds) {
523
    commandNames.push_back(cmds->first);
524
  }
525
526
527
528
529
  return commandNames;
}

void cmState::RemoveUserDefinedCommands()
{
530
  std::vector<cmCommand*> renamedCommands;
531
532
  for (std::map<std::string, cmCommand*>::iterator j = this->Commands.begin();
       j != this->Commands.end();) {
533
    if (j->second->IsA("cmMacroHelperCommand") ||
534
        j->second->IsA("cmFunctionHelperCommand")) {
535
536
      delete j->second;
      this->Commands.erase(j++);
537
    } else if (j->first != j->second->GetName()) {
538
539
      renamedCommands.push_back(j->second);
      this->Commands.erase(j++);
540
    } else {
541
542
      ++j;
    }
543
  }
544
  for (std::vector<cmCommand*>::const_iterator it = renamedCommands.begin();
545
       it != renamedCommands.end(); ++it) {
546
    this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it;
547
  }
548
}
549
550
551

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

555
556
void cmState::AppendGlobalProperty(const std::string& prop, const char* value,
                                   bool asString)
557
{
558
  this->GlobalProperties.AppendProperty(prop, value, asString);
559
560
}

561
const char* cmState::GetGlobalProperty(const std::string& prop)
562
{
563
  if (prop == "CACHE_VARIABLES") {
564
565
    std::vector<std::string> cacheKeys = this->GetCacheEntryKeys();
    this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str());
566
  } else if (prop == "COMMANDS") {
567
568
    std::vector<std::string> commands = this->GetCommandNames();
    this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str());
569
  } else if (prop == "IN_TRY_COMPILE") {
570
    this->SetGlobalProperty("IN_TRY_COMPILE",
571
572
                            this->IsInTryCompile ? "1" : "0");
  } else if (prop == "ENABLED_LANGUAGES") {
573
574
575
    std::string langs;
    langs = cmJoin(this->EnabledLanguages, ";");
    this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str());
576
  }
577
#define STRING_LIST_ELEMENT(F) ";" #F
578
  if (prop == "CMAKE_C_KNOWN_FEATURES") {
579
    return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1;
580
581
  }
  if (prop == "CMAKE_CXX_KNOWN_FEATURES") {
582
    return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
583
  }
584
#undef STRING_LIST_ELEMENT
585
  return this->GlobalProperties.GetPropertyValue(prop);
586
587
588
589
590
591
}

bool cmState::GetGlobalPropertyAsBool(const std::string& prop)
{
  return cmSystemTools::IsOn(this->GetGlobalProperty(prop));
}
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

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

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

void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
{
  this->BinaryDirectory = binaryDirectory;
  cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory);
}

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

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

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

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

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

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

703
  std::string result = snapshots.front().GetDirectory().GetCurrentSource();
704
705

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

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

730
  std::string result = snapshots.front().GetDirectory().GetCurrentBinary();
731
732

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

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

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

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

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

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

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

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

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

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

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

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

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

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

917
918
  if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
    if (pos->Vars != prevPos->Vars) {
919
920
      assert(this->VarTree.IsLast(pos->Vars));
      this->VarTree.Pop(pos->Vars);
921
922
    }
    if (pos->ExecutionListFile != prevPos->ExecutionListFile) {
923
924
925
      assert(this->ExecutionListFiles.IsLast(pos->ExecutionListF