Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmStateSnapshot.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
4
#include "cmStateSnapshot.h"
5
6
#include <algorithm>
7
#include <cassert>
8
#include <set>
9
#include <string>
10
#include <unordered_map>
11
12
#include <cm/iterator>
13
#include <cmext/algorithm>
14
15
#include "cmDefinitions.h"
16
#include "cmLinkedTree.h"
17
#include "cmListFileCache.h"
18
#include "cmPackageState.h"
19
#include "cmPropertyMap.h"
20
#include "cmState.h"
21
#include "cmStateDirectory.h"
22
#include "cmStatePrivate.h"
23
#include "cmSystemTools.h"
24
#include "cmValue.h"
25
#include "cmVersion.h"
26
27
#if defined(__CYGWIN__)
28
#  include "cmStringAlgorithms.h"
29
#endif
30
31
cmStateSnapshot::cmStateSnapshot(cmState* state)
32
35
  : State(state)
33
35
{
34
35
}
35
36
std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren()
37
0
{
38
0
  return this->Position->BuildSystemDirectory->Children;
39
0
}
40
41
cmStateSnapshot::cmStateSnapshot(cmState* state,
42
                                 cmStateDetail::PositionType position)
43
39
  : State(state)
44
39
  , Position(position)
45
39
{
46
39
}
47
48
cmStateEnums::SnapshotType cmStateSnapshot::GetType() const
49
0
{
50
0
  return this->Position->SnapshotType;
51
0
}
52
53
cmStateEnums::SnapshotUnwindType cmStateSnapshot::GetUnwindType() const
54
0
{
55
0
  return this->Position->UnwindType;
56
0
}
57
58
void cmStateSnapshot::SetUnwindType(cmStateEnums::SnapshotUnwindType type)
59
0
{
60
0
  this->Position->UnwindType = type;
61
0
}
62
63
cmStateEnums::SnapshotUnwindState cmStateSnapshot::GetUnwindState() const
64
0
{
65
0
  return this->Position->UnwindState;
66
0
}
67
68
void cmStateSnapshot::SetUnwindState(cmStateEnums::SnapshotUnwindState state)
69
0
{
70
0
  this->Position->UnwindState = state;
71
0
}
72
73
void cmStateSnapshot::SetListFile(std::string const& listfile)
74
0
{
75
0
  *this->Position->ExecutionListFile = listfile;
76
0
}
77
78
std::string const& cmStateSnapshot::GetExecutionListFile() const
79
0
{
80
0
  return *this->Position->ExecutionListFile;
81
0
}
82
83
bool cmStateSnapshot::IsValid() const
84
72
{
85
72
  return this->State && this->Position.IsValid()
86
72
    ? this->Position != this->State->SnapshotData.Root()
87
72
    : false;
88
72
}
89
90
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
91
0
{
92
0
  return { this->State, this->Position->BuildSystemDirectory->CurrentScope };
93
0
}
94
95
cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
96
0
{
97
0
  cmStateSnapshot snapshot;
98
0
  if (!this->State || this->Position == this->State->SnapshotData.Root()) {
99
0
    return snapshot;
100
0
  }
101
0
  cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
102
0
  if (parentPos != this->State->SnapshotData.Root()) {
103
0
    snapshot = cmStateSnapshot(this->State,
104
0
                               parentPos->BuildSystemDirectory->CurrentScope);
105
0
  }
106
107
0
  return snapshot;
108
0
}
109
110
cmStateSnapshot cmStateSnapshot::GetCallStackParent() const
111
0
{
112
0
  assert(this->State);
113
0
  assert(this->Position != this->State->SnapshotData.Root());
114
115
0
  cmStateSnapshot snapshot;
116
0
  cmStateDetail::PositionType parentPos = this->Position;
117
0
  while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
118
0
         parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
119
0
    ++parentPos;
120
0
  }
121
0
  if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType ||
122
0
      parentPos->SnapshotType == cmStateEnums::BaseType) {
123
0
    return snapshot;
124
0
  }
125
126
0
  ++parentPos;
127
0
  while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
128
0
         parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
129
0
    ++parentPos;
130
0
  }
131
132
0
  if (parentPos == this->State->SnapshotData.Root()) {
133
0
    return snapshot;
134
0
  }
135
136
0
  snapshot = cmStateSnapshot(this->State, parentPos);
137
0
  return snapshot;
138
0
}
139
140
cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
141
0
{
142
0
  assert(this->State);
143
0
  assert(this->Position != this->State->SnapshotData.Root());
144
145
0
  cmStateDetail::PositionType pos = this->Position;
146
0
  while (pos->SnapshotType != cmStateEnums::BaseType &&
147
0
         pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType &&
148
0
         pos != this->State->SnapshotData.Root()) {
149
0
    ++pos;
150
0
  }
151
0
  return { this->State, pos };
152
0
}
153
154
void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
155
1
{
156
1
  cmStateDetail::PositionType pos = this->Position;
157
1
  pos->Policies = this->State->PolicyStack.Push(
158
1
    pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak));
159
1
}
160
161
bool cmStateSnapshot::PopPolicy()
162
0
{
163
0
  cmStateDetail::PositionType pos = this->Position;
164
0
  if (pos->Policies == pos->PolicyScope) {
165
0
    return false;
166
0
  }
167
0
  pos->Policies = this->State->PolicyStack.Pop(pos->Policies);
168
0
  return true;
169
0
}
170
171
bool cmStateSnapshot::CanPopPolicyScope()
172
1
{
173
1
  return this->Position->Policies != this->Position->PolicyScope;
174
1
}
175
176
void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
177
                                cmPolicies::PolicyStatus status)
178
0
{
179
  // Update the policy stack from the top to the top-most strong entry.
180
0
  bool previous_was_weak = true;
181
0
  for (cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator psi =
182
0
         this->Position->Policies;
183
0
       previous_was_weak && psi != this->Position->PolicyRoot; ++psi) {
184
0
    psi->Set(id, status);
185
0
    previous_was_weak = psi->Weak;
186
0
  }
187
0
}
188
189
cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
190
                                                    bool parent_scope) const
191
0
{
192
0
  if (cmPolicies::IsRemoved(id)) {
193
0
    return cmPolicies::NEW;
194
0
  }
195
196
0
  cmPolicies::PolicyStatus status = cmPolicies::WARN;
197
198
0
  cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir =
199
0
    this->Position->BuildSystemDirectory;
200
201
0
  while (true) {
202
0
    assert(dir.IsValid());
203
0
    cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf =
204
0
      dir->CurrentScope->Policies;
205
0
    cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
206
0
      dir->CurrentScope->PolicyRoot;
207
0
    for (; leaf != root; ++leaf) {
208
0
      if (parent_scope) {
209
0
        parent_scope = false;
210
0
        continue;
211
0
      }
212
0
      if (leaf->IsDefined(id)) {
213
0
        status = leaf->Get(id);
214
0
        return status;
215
0
      }
216
0
    }
217
0
    cmStateDetail::PositionType e = dir->CurrentScope;
218
0
    cmStateDetail::PositionType p = e->DirectoryParent;
219
0
    if (p == this->State->SnapshotData.Root()) {
220
0
      break;
221
0
    }
222
0
    dir = p->BuildSystemDirectory;
223
0
  }
224
0
  return status;
225
0
}
226
227
cmValue cmStateSnapshot::GetDefinition(std::string const& name) const
228
6
{
229
6
  assert(this->Position->Vars.IsValid());
230
6
  return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
231
6
}
232
233
bool cmStateSnapshot::IsInitialized(std::string const& name) const
234
0
{
235
0
  return cmDefinitions::HasKey(name, this->Position->Vars,
236
0
                               this->Position->Root);
237
0
}
238
239
void cmStateSnapshot::SetDefinition(std::string const& name,
240
                                    cm::string_view value)
241
95
{
242
95
  this->Position->Vars->Set(name, value);
243
95
}
244
245
void cmStateSnapshot::RemoveDefinition(std::string const& name)
246
1
{
247
1
  this->Position->Vars->Unset(name);
248
1
}
249
250
std::vector<std::string> cmStateSnapshot::ClosureKeys() const
251
0
{
252
0
  return cmDefinitions::ClosureKeys(this->Position->Vars,
253
0
                                    this->Position->Root);
254
0
}
255
256
bool cmStateSnapshot::RaiseScope(std::string const& var, char const* varDef)
257
0
{
258
0
  if (this->Position->ScopeParent == this->Position->DirectoryParent) {
259
0
    cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent();
260
0
    if (!parentDir.IsValid()) {
261
0
      return false;
262
0
    }
263
    // Update the definition in the parent directory top scope.  This
264
    // directory's scope was initialized by the closure of the parent
265
    // scope, so we do not need to localize the definition first.
266
0
    if (varDef) {
267
0
      parentDir.SetDefinition(var, varDef);
268
0
    } else {
269
0
      parentDir.RemoveDefinition(var);
270
0
    }
271
0
    return true;
272
0
  }
273
  // First localize the definition in the current scope.
274
0
  cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
275
276
  // Now update the definition in the parent scope.
277
0
  if (varDef) {
278
0
    this->Position->Parent->Set(var, varDef);
279
0
  } else {
280
0
    this->Position->Parent->Unset(var);
281
0
  }
282
0
  return true;
283
0
}
284
285
template <typename T, typename U>
286
void InitializeContentFromParent(T& parentContent, T& thisContent,
287
                                 U& contentEndPosition)
288
0
{
289
0
  auto parentEnd = parentContent.end();
290
291
0
  auto parentRbegin = cm::make_reverse_iterator(parentEnd);
292
0
  auto parentRend = parentContent.rend();
293
0
  parentRbegin =
294
0
    std::find(parentRbegin, parentRend, cmStateDetail::PropertySentinel);
295
0
  auto parentIt = parentRbegin.base();
296
297
0
  thisContent = std::vector<BT<std::string>>(parentIt, parentEnd);
298
299
0
  contentEndPosition = thisContent.size();
300
0
}
301
302
void cmStateSnapshot::SetDefaultDefinitions()
303
1
{
304
  /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set.
305
    With CMake must separate between target and host platform. In most cases
306
    the tests for WIN32, UNIX and APPLE will be for the target system, so an
307
    additional set of variables for the host system is required ->
308
    CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE.
309
    WIN32, UNIX and APPLE are now set in the platform files in
310
    Modules/Platforms/.
311
    To keep cmake scripts (-P) and custom language and compiler modules
312
    working, these variables are still also set here in this place, but they
313
    will be reset in CMakeSystemSpecificInformation.cmake before the platform
314
    files are executed. */
315
1
  cm::string_view hostSystemName = cmSystemTools::GetSystemName();
316
1
  this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName);
317
1
  if (hostSystemName == "Windows") {
318
0
    this->SetDefinition("WIN32", "1");
319
0
    this->SetDefinition("CMAKE_HOST_WIN32", "1");
320
0
    this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", ".exe");
321
1
  } else {
322
1
    this->SetDefinition("UNIX", "1");
323
1
    this->SetDefinition("CMAKE_HOST_UNIX", "1");
324
1
    this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", "");
325
1
  }
326
#if defined(__APPLE__)
327
  this->SetDefinition("APPLE", "1");
328
  this->SetDefinition("CMAKE_HOST_APPLE", "1");
329
#endif
330
#if defined(__sun__)
331
  this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
332
#endif
333
334
#if defined(__OpenBSD__)
335
  this->SetDefinition("BSD", "OpenBSD");
336
  this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD");
337
#elif defined(__FreeBSD__)
338
  this->SetDefinition("BSD", "FreeBSD");
339
  this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD");
340
#elif defined(__NetBSD__)
341
  this->SetDefinition("BSD", "NetBSD");
342
  this->SetDefinition("CMAKE_HOST_BSD", "NetBSD");
343
#elif defined(__DragonFly__)
344
  this->SetDefinition("BSD", "DragonFlyBSD");
345
  this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD");
346
#endif
347
348
1
#if defined(__linux__)
349
1
  this->SetDefinition("LINUX", "1");
350
1
  this->SetDefinition("CMAKE_HOST_LINUX", "1");
351
1
#endif
352
353
#if defined(_AIX)
354
  this->SetDefinition("AIX", "1");
355
  this->SetDefinition("CMAKE_HOST_AIX", "1");
356
#endif
357
358
1
  this->SetDefinition("CMAKE_MAJOR_VERSION",
359
1
                      std::to_string(cmVersion::GetMajorVersion()));
360
1
  this->SetDefinition("CMAKE_MINOR_VERSION",
361
1
                      std::to_string(cmVersion::GetMinorVersion()));
362
1
  this->SetDefinition("CMAKE_PATCH_VERSION",
363
1
                      std::to_string(cmVersion::GetPatchVersion()));
364
1
  this->SetDefinition("CMAKE_TWEAK_VERSION",
365
1
                      std::to_string(cmVersion::GetTweakVersion()));
366
1
  this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
367
368
1
  this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles");
369
370
  // Setup the default include file regular expression (match everything).
371
1
  this->Position->BuildSystemDirectory->Properties.SetProperty(
372
1
    "INCLUDE_REGULAR_EXPRESSION", "^.*$");
373
1
}
374
375
void cmStateSnapshot::SetDirectoryDefinitions()
376
0
{
377
0
  this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
378
0
  this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR",
379
0
                      this->State->GetSourceDirectory());
380
0
  this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
381
0
  this->SetDefinition("CMAKE_CURRENT_BINARY_DIR",
382
0
                      this->State->GetBinaryDirectory());
383
0
}
384
385
void cmStateSnapshot::InitializeFromParent()
386
0
{
387
0
  cmStateDetail::PositionType parent = this->Position->DirectoryParent;
388
0
  assert(this->Position->Vars.IsValid());
389
0
  assert(parent->Vars.IsValid());
390
391
0
  *this->Position->Vars =
392
0
    cmDefinitions::MakeClosure(parent->Vars, parent->Root);
393
394
0
  InitializeContentFromParent(
395
0
    parent->BuildSystemDirectory->IncludeDirectories,
396
0
    this->Position->BuildSystemDirectory->IncludeDirectories,
397
0
    this->Position->IncludeDirectoryPosition);
398
399
0
  InitializeContentFromParent(
400
0
    parent->BuildSystemDirectory->CompileDefinitions,
401
0
    this->Position->BuildSystemDirectory->CompileDefinitions,
402
0
    this->Position->CompileDefinitionsPosition);
403
404
0
  InitializeContentFromParent(
405
0
    parent->BuildSystemDirectory->CompileOptions,
406
0
    this->Position->BuildSystemDirectory->CompileOptions,
407
0
    this->Position->CompileOptionsPosition);
408
409
0
  InitializeContentFromParent(
410
0
    parent->BuildSystemDirectory->LinkOptions,
411
0
    this->Position->BuildSystemDirectory->LinkOptions,
412
0
    this->Position->LinkOptionsPosition);
413
414
0
  InitializeContentFromParent(
415
0
    parent->BuildSystemDirectory->LinkDirectories,
416
0
    this->Position->BuildSystemDirectory->LinkDirectories,
417
0
    this->Position->LinkDirectoriesPosition);
418
419
0
  cmValue include_regex =
420
0
    parent->BuildSystemDirectory->Properties.GetPropertyValue(
421
0
      "INCLUDE_REGULAR_EXPRESSION");
422
0
  this->Position->BuildSystemDirectory->Properties.SetProperty(
423
0
    "INCLUDE_REGULAR_EXPRESSION", include_regex);
424
0
}
425
426
cmState* cmStateSnapshot::GetState() const
427
1
{
428
1
  return this->State;
429
1
}
430
431
cmStateDirectory cmStateSnapshot::GetDirectory() const
432
3
{
433
3
  return { this->Position->BuildSystemDirectory, *this };
434
3
}
435
436
void cmStateSnapshot::SetProjectName(std::string const& name)
437
0
{
438
0
  this->Position->BuildSystemDirectory->ProjectName = name;
439
0
  this->Position->BuildSystemDirectory->Projects.insert(name);
440
0
}
441
442
std::string cmStateSnapshot::GetProjectName() const
443
0
{
444
0
  return this->Position->BuildSystemDirectory->ProjectName;
445
0
}
446
447
bool cmStateSnapshot::CheckProjectName(std::string const& name) const
448
0
{
449
0
  return cm::contains(this->Position->BuildSystemDirectory->Projects, name);
450
0
}
451
452
cmPackageState& cmStateSnapshot::GetPackageState(
453
  std::string const& packagePath)
454
0
{
455
0
  return this->Position->BuildSystemDirectory->Packages[packagePath];
456
0
}
457
458
void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
459
0
{
460
0
  std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
461
0
  std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
462
0
  this->InitializeFromParent();
463
0
  this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
464
0
  this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
465
466
0
  this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir);
467
0
  this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir);
468
0
}
469
470
bool cmStateSnapshot::StrictWeakOrder::operator()(
471
  cmStateSnapshot const& lhs, cmStateSnapshot const& rhs) const
472
0
{
473
0
  return lhs.Position.StrictWeakOrdered(rhs.Position);
474
0
}
475
476
bool operator==(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs)
477
0
{
478
0
  return lhs.Position == rhs.Position;
479
0
}
480
481
bool operator!=(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs)
482
0
{
483
0
  return lhs.Position != rhs.Position;
484
0
}