Coverage Report

Created: 2026-09-14 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmGetPropertyCommand.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
#include "cmGetPropertyCommand.h"
4
5
#include "cmDirectoryPropertyHelper.h"
6
#include "cmExecutionStatus.h"
7
#include "cmFileSet.h"
8
#include "cmInstalledFile.h"
9
#include "cmMakefile.h"
10
#include "cmProperty.h"
11
#include "cmPropertyDefinition.h"
12
#include "cmSetPropertyCommand.h"
13
#include "cmSourceFilePropertyHelper.h"
14
#include "cmState.h"
15
#include "cmStringAlgorithms.h"
16
#include "cmTarget.h"
17
#include "cmTargetPropertyHelper.h"
18
#include "cmTestPropertyHelper.h"
19
#include "cmValue.h"
20
#include "cmake.h"
21
22
namespace {
23
enum OutType
24
{
25
  OutValue,
26
  OutDefined,
27
  OutBriefDoc,
28
  OutFullDoc,
29
  OutSet
30
};
31
32
// Implementation of each property type.
33
bool HandleGlobalMode(cmExecutionStatus& status, std::string const& name,
34
                      OutType infoType, std::string const& variable,
35
                      std::string const& propertyName);
36
bool HandleDirectoryMode(cmExecutionStatus& status, std::string const& name,
37
                         OutType infoType, std::string const& variable,
38
                         std::string const& propertyName);
39
bool HandleTargetMode(cmExecutionStatus& status, std::string const& name,
40
                      OutType infoType, std::string const& variable,
41
                      std::string const& propertyName);
42
bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
43
                       OutType infoType, std::string const& variable,
44
                       std::string const& propertyName, cmTarget* target);
45
bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
46
                      OutType infoType, std::string const& variable,
47
                      std::string const& propertyName,
48
                      bool sourceFileDirectoryOptionEnabled,
49
                      bool sourceFileTargetOptionEnabled,
50
                      std::vector<std::string>& sourceFileDirectories,
51
                      std::vector<std::string>& sourceFileTargetDirectories);
52
bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
53
                    OutType infoType, std::string const& variable,
54
                    std::string const& propertyName,
55
                    bool testDirectoryOptionEnabled,
56
                    std::string& testDirectory);
57
bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
58
                        OutType infoType, std::string const& variable,
59
                        std::string const& propertyName);
60
bool HandleCacheMode(cmExecutionStatus& status, std::string const& name,
61
                     OutType infoType, std::string const& variable,
62
                     std::string const& propertyName);
63
bool HandleInstallMode(cmExecutionStatus& status, std::string const& name,
64
                       OutType infoType, std::string const& variable,
65
                       std::string const& propertyName);
66
}
67
68
bool cmGetPropertyCommand(std::vector<std::string> const& args,
69
                          cmExecutionStatus& status)
70
0
{
71
0
  OutType infoType = OutValue;
72
0
  if (args.size() < 3) {
73
0
    status.SetError("called with incorrect number of arguments");
74
0
    return false;
75
0
  }
76
77
  // The cmake variable in which to store the result.
78
0
  std::string const& variable = args[0];
79
80
0
  std::string name;
81
0
  std::string propertyName;
82
83
0
  std::string file_set_target_name;
84
0
  bool file_set_target_option_enabled = false;
85
86
0
  std::vector<std::string> source_file_directories;
87
0
  std::vector<std::string> source_file_target_directories;
88
0
  bool source_file_directory_option_enabled = false;
89
0
  bool source_file_target_option_enabled = false;
90
91
0
  std::string test_directory;
92
0
  bool test_directory_option_enabled = false;
93
94
  // Get the scope from which to get the property.
95
0
  cmProperty::ScopeType scope;
96
0
  if (args[1] == "GLOBAL") {
97
0
    scope = cmProperty::GLOBAL;
98
0
  } else if (args[1] == "DIRECTORY") {
99
0
    scope = cmProperty::DIRECTORY;
100
0
  } else if (args[1] == "TARGET") {
101
0
    scope = cmProperty::TARGET;
102
0
  } else if (args[1] == "FILE_SET") {
103
0
    scope = cmProperty::FILE_SET;
104
0
  } else if (args[1] == "SOURCE") {
105
0
    scope = cmProperty::SOURCE_FILE;
106
0
  } else if (args[1] == "TEST") {
107
0
    scope = cmProperty::TEST;
108
0
  } else if (args[1] == "VARIABLE") {
109
0
    scope = cmProperty::VARIABLE;
110
0
  } else if (args[1] == "CACHE") {
111
0
    scope = cmProperty::CACHE;
112
0
  } else if (args[1] == "INSTALL") {
113
0
    scope = cmProperty::INSTALL;
114
0
  } else {
115
0
    status.SetError(cmStrCat("given invalid scope ", args[1],
116
0
                             ".  "
117
0
                             "Valid scopes are "
118
0
                             "GLOBAL, DIRECTORY, TARGET, FILE_SET, SOURCE, "
119
0
                             "TEST, VARIABLE, CACHE, INSTALL."));
120
0
    return false;
121
0
  }
122
123
  // Parse remaining arguments.
124
0
  enum Doing
125
0
  {
126
0
    DoingNone,
127
0
    DoingName,
128
0
    DoingProperty,
129
0
    DoingType,
130
0
    DoingFileSetTarget,
131
0
    DoingSourceDirectory,
132
0
    DoingSourceTargetDirectory,
133
0
    DoingTestDirectory,
134
0
  };
135
0
  Doing doing = DoingName;
136
0
  for (unsigned int i = 2; i < args.size(); ++i) {
137
0
    if (args[i] == "PROPERTY") {
138
0
      doing = DoingProperty;
139
0
    } else if (args[i] == "BRIEF_DOCS") {
140
0
      doing = DoingNone;
141
0
      infoType = OutBriefDoc;
142
0
    } else if (args[i] == "FULL_DOCS") {
143
0
      doing = DoingNone;
144
0
      infoType = OutFullDoc;
145
0
    } else if (args[i] == "SET") {
146
0
      doing = DoingNone;
147
0
      infoType = OutSet;
148
0
    } else if (args[i] == "DEFINED") {
149
0
      doing = DoingNone;
150
0
      infoType = OutDefined;
151
0
    } else if (doing == DoingName) {
152
0
      doing = DoingNone;
153
0
      name = args[i];
154
0
    } else if (doing == DoingNone && scope == cmProperty::FILE_SET &&
155
0
               args[i] == "TARGET") {
156
0
      doing = DoingFileSetTarget;
157
0
      file_set_target_option_enabled = true;
158
0
    } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
159
0
               args[i] == "DIRECTORY") {
160
0
      doing = DoingSourceDirectory;
161
0
      source_file_directory_option_enabled = true;
162
0
    } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
163
0
               args[i] == "TARGET_DIRECTORY") {
164
0
      doing = DoingSourceTargetDirectory;
165
0
      source_file_target_option_enabled = true;
166
0
    } else if (doing == DoingNone && scope == cmProperty::TEST &&
167
0
               args[i] == "DIRECTORY") {
168
0
      doing = DoingTestDirectory;
169
0
      test_directory_option_enabled = true;
170
0
    } else if (doing == DoingFileSetTarget) {
171
0
      file_set_target_name = args[i];
172
0
      doing = DoingNone;
173
0
    } else if (doing == DoingSourceDirectory) {
174
0
      source_file_directories.push_back(args[i]);
175
0
      doing = DoingNone;
176
0
    } else if (doing == DoingSourceTargetDirectory) {
177
0
      source_file_target_directories.push_back(args[i]);
178
0
      doing = DoingNone;
179
0
    } else if (doing == DoingTestDirectory) {
180
0
      test_directory = args[i];
181
0
      doing = DoingNone;
182
0
    } else if (doing == DoingProperty) {
183
0
      doing = DoingNone;
184
0
      propertyName = args[i];
185
0
    } else {
186
0
      status.SetError(cmStrCat("given invalid argument \"", args[i], "\"."));
187
0
      return false;
188
0
    }
189
0
  }
190
191
  // Make sure a property name was found.
192
0
  if (propertyName.empty()) {
193
0
    status.SetError("not given a PROPERTY <name> argument.");
194
0
    return false;
195
0
  }
196
197
  // Compute requested output.
198
0
  if (infoType == OutBriefDoc) {
199
    // Lookup brief documentation.
200
0
    std::string output;
201
0
    if (cmPropertyDefinition const* def =
202
0
          status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
203
0
                                                                 scope)) {
204
0
      output = def->GetShortDescription();
205
0
    }
206
0
    if (output.empty()) {
207
0
      output = "NOTFOUND";
208
0
    }
209
0
    status.GetMakefile().AddDefinition(variable, output);
210
0
  } else if (infoType == OutFullDoc) {
211
    // Lookup full documentation.
212
0
    std::string output;
213
0
    if (cmPropertyDefinition const* def =
214
0
          status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
215
0
                                                                 scope)) {
216
0
      output = def->GetFullDescription();
217
0
    }
218
0
    if (output.empty()) {
219
0
      output = "NOTFOUND";
220
0
    }
221
0
    status.GetMakefile().AddDefinition(variable, output);
222
0
  } else if (infoType == OutDefined) {
223
    // Lookup if the property is defined
224
0
    if (status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
225
0
                                                               scope)) {
226
0
      status.GetMakefile().AddDefinition(variable, "1");
227
0
    } else {
228
0
      status.GetMakefile().AddDefinition(variable, "0");
229
0
    }
230
0
  } else {
231
    // Dispatch property getting.
232
0
    switch (scope) {
233
0
      case cmProperty::GLOBAL:
234
0
        return HandleGlobalMode(status, name, infoType, variable,
235
0
                                propertyName);
236
0
      case cmProperty::DIRECTORY:
237
0
        return HandleDirectoryMode(status, name, infoType, variable,
238
0
                                   propertyName);
239
0
      case cmProperty::TARGET:
240
0
        return HandleTargetMode(status, name, infoType, variable,
241
0
                                propertyName);
242
0
      case cmProperty::FILE_SET: {
243
0
        cmTarget* file_set_target;
244
0
        if (!SetPropertyCommand::HandleAndValidateFileSetTargetScopes(
245
0
              status, file_set_target_option_enabled, file_set_target_name,
246
0
              file_set_target)) {
247
0
          return false;
248
0
        }
249
0
        return HandleFileSetMode(status, name, infoType, variable,
250
0
                                 propertyName, file_set_target);
251
0
      }
252
0
      case cmProperty::SOURCE_FILE:
253
0
        return HandleSourceMode(status, name, infoType, variable, propertyName,
254
0
                                source_file_directory_option_enabled,
255
0
                                source_file_target_option_enabled,
256
0
                                source_file_directories,
257
0
                                source_file_target_directories);
258
0
      case cmProperty::TEST:
259
0
        return HandleTestMode(status, name, infoType, variable, propertyName,
260
0
                              test_directory_option_enabled, test_directory);
261
0
      case cmProperty::VARIABLE:
262
0
        return HandleVariableMode(status, name, infoType, variable,
263
0
                                  propertyName);
264
0
      case cmProperty::CACHE:
265
0
        return HandleCacheMode(status, name, infoType, variable, propertyName);
266
0
      case cmProperty::INSTALL:
267
0
        return HandleInstallMode(status, name, infoType, variable,
268
0
                                 propertyName);
269
270
0
      case cmProperty::CACHED_VARIABLE:
271
0
        break; // should never happen
272
0
    }
273
0
  }
274
275
0
  return true;
276
0
}
277
278
namespace {
279
280
// Implementation of result storage.
281
template <typename ValueType>
282
bool StoreResult(OutType infoType, cmMakefile& makefile,
283
                 std::string const& variable, ValueType value)
284
0
{
285
0
  if (infoType == OutSet) {
286
0
    makefile.AddDefinition(variable, value ? "1" : "0");
287
0
  } else // if(infoType == OutValue)
288
0
  {
289
0
    if (value) {
290
0
      makefile.AddDefinition(variable, value);
291
0
    } else {
292
0
      makefile.RemoveDefinition(variable);
293
0
    }
294
0
  }
295
0
  return true;
296
0
}
Unexecuted instantiation: cmGetPropertyCommand.cxx:bool (anonymous namespace)::StoreResult<cmValue>((anonymous namespace)::OutType, cmMakefile&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cmValue)
Unexecuted instantiation: cmGetPropertyCommand.cxx:bool (anonymous namespace)::StoreResult<char const*>((anonymous namespace)::OutType, cmMakefile&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*)
297
298
bool HandleGlobalMode(cmExecutionStatus& status, std::string const& name,
299
                      OutType infoType, std::string const& variable,
300
                      std::string const& propertyName)
301
0
{
302
0
  if (!name.empty()) {
303
0
    status.SetError("given name for GLOBAL scope.");
304
0
    return false;
305
0
  }
306
307
  // Get the property.
308
0
  cmake* cm = status.GetMakefile().GetCMakeInstance();
309
0
  return StoreResult(infoType, status.GetMakefile(), variable,
310
0
                     cm->GetState()->GetGlobalProperty(propertyName));
311
0
}
312
313
bool HandleDirectoryMode(cmExecutionStatus& status, std::string const& name,
314
                         OutType infoType, std::string const& variable,
315
                         std::string const& propertyName)
316
0
{
317
0
  cmValue prop;
318
0
  if (!GetPropertyCommand::LookupDirectoryProperty(status, name, propertyName,
319
0
                                                   prop)) {
320
0
    return false;
321
0
  }
322
0
  return StoreResult(infoType, status.GetMakefile(), variable, prop);
323
0
}
324
325
bool HandleTargetMode(cmExecutionStatus& status, std::string const& name,
326
                      OutType infoType, std::string const& variable,
327
                      std::string const& propertyName)
328
0
{
329
0
  cmValue prop;
330
0
  if (!GetPropertyCommand::LookupTargetProperty(status, name, propertyName,
331
0
                                                prop)) {
332
0
    return false;
333
0
  }
334
0
  return StoreResult(infoType, status.GetMakefile(), variable, prop);
335
0
}
336
337
bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
338
                       OutType infoType, std::string const& variable,
339
                       std::string const& propertyName, cmTarget* target)
340
0
{
341
0
  if (name.empty()) {
342
0
    status.SetError("not given name for FILE_SET scope.");
343
0
    return false;
344
0
  }
345
346
0
  if (cmFileSet* fileSet = target->GetFileSet(name)) {
347
0
    cmValue prop = fileSet->GetProperty(propertyName);
348
0
    return StoreResult(infoType, status.GetMakefile(), variable, prop);
349
0
  }
350
0
  status.SetError(cmStrCat("could not find FILE_SET ", name, " for TARGET ",
351
0
                           target->GetName(),
352
0
                           ".  Perhaps it has not yet been created."));
353
0
  return false;
354
0
}
355
356
bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
357
                      OutType infoType, std::string const& variable,
358
                      std::string const& propertyName,
359
                      bool sourceFileDirectoryOptionEnabled,
360
                      bool sourceFileTargetOptionEnabled,
361
                      std::vector<std::string>& sourceFileDirectories,
362
                      std::vector<std::string>& sourceFileTargetDirectories)
363
0
{
364
0
  cmValue prop;
365
0
  if (!GetPropertyCommand::LookupSourceProperty(
366
0
        status, name, propertyName, sourceFileDirectoryOptionEnabled,
367
0
        sourceFileTargetOptionEnabled, sourceFileDirectories,
368
0
        sourceFileTargetDirectories, prop)) {
369
0
    return false;
370
0
  }
371
0
  return StoreResult(infoType, status.GetMakefile(), variable, prop);
372
0
}
373
374
bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
375
                    OutType infoType, std::string const& variable,
376
                    std::string const& propertyName,
377
                    bool testDirectoryOptionEnabled,
378
                    std::string& testDirectory)
379
0
{
380
0
  cmValue prop;
381
0
  if (!GetPropertyCommand::LookupTestProperty(status, name, propertyName,
382
0
                                              testDirectoryOptionEnabled,
383
0
                                              testDirectory, prop)) {
384
0
    return false;
385
0
  }
386
0
  return StoreResult(infoType, status.GetMakefile(), variable, prop);
387
0
}
388
389
bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
390
                        OutType infoType, std::string const& variable,
391
                        std::string const& propertyName)
392
0
{
393
0
  if (!name.empty()) {
394
0
    status.SetError("given name for VARIABLE scope.");
395
0
    return false;
396
0
  }
397
398
0
  return StoreResult(infoType, status.GetMakefile(), variable,
399
0
                     status.GetMakefile().GetDefinition(propertyName));
400
0
}
401
402
bool HandleCacheMode(cmExecutionStatus& status, std::string const& name,
403
                     OutType infoType, std::string const& variable,
404
                     std::string const& propertyName)
405
0
{
406
0
  cmValue value;
407
0
  if (!GetPropertyCommand::LookupCacheProperty(status, name, propertyName,
408
0
                                               value)) {
409
0
    return false;
410
0
  }
411
0
  StoreResult(infoType, status.GetMakefile(), variable, value);
412
0
  return true;
413
0
}
414
415
bool HandleInstallMode(cmExecutionStatus& status, std::string const& name,
416
                       OutType infoType, std::string const& variable,
417
                       std::string const& propertyName)
418
0
{
419
0
  if (name.empty()) {
420
0
    status.SetError("not given name for INSTALL scope.");
421
0
    return false;
422
0
  }
423
424
  // Get the installed file.
425
0
  cmake* cm = status.GetMakefile().GetCMakeInstance();
426
427
0
  if (cmInstalledFile* file =
428
0
        cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) {
429
0
    std::string value;
430
0
    bool isSet = file->GetProperty(propertyName, value);
431
432
0
    return StoreResult(infoType, status.GetMakefile(), variable,
433
0
                       isSet ? value.c_str() : nullptr);
434
0
  }
435
0
  status.SetError(
436
0
    cmStrCat("given INSTALL name that could not be found or created: ", name));
437
0
  return false;
438
0
}
439
}
440
441
namespace GetPropertyCommand {
442
443
bool LookupTargetProperty(cmExecutionStatus& status, std::string const& name,
444
                          std::string const& propertyName, cmValue& out)
445
0
{
446
0
  if (name.empty()) {
447
0
    status.SetError("not given name for TARGET scope.");
448
0
    return false;
449
0
  }
450
451
0
  auto result =
452
0
    cmGetTargetProperty(name, propertyName, status.GetMakefile(), out);
453
0
  if (result == cmGetTargetPropertyResult::Success) {
454
0
    return true;
455
0
  }
456
0
  if (result == cmGetTargetPropertyResult::TargetNotFound) {
457
0
    status.SetError(cmStrCat("could not find TARGET ", name,
458
0
                             ".  Perhaps it has not yet been created."));
459
0
  }
460
0
  return false;
461
0
}
462
463
bool LookupDirectoryProperty(cmExecutionStatus& status,
464
                             std::string const& name,
465
                             std::string const& propertyName, cmValue& out)
466
0
{
467
0
  auto result =
468
0
    cmGetDirectoryProperty(name, propertyName, status.GetMakefile(), out);
469
0
  if (result == cmGetDirectoryPropertyResult::Success) {
470
0
    return true;
471
0
  }
472
0
  if (result == cmGetDirectoryPropertyResult::DirectoryNotFound) {
473
0
    status.SetError(
474
0
      "DIRECTORY scope provided but requested directory was not found. "
475
0
      "This could be because the directory argument was invalid or, "
476
0
      "it is valid but has not been processed yet.");
477
0
  }
478
0
  return false;
479
0
}
480
481
bool LookupSourceProperty(
482
  cmExecutionStatus& status, std::string const& name,
483
  std::string const& propertyName, bool sourceFileDirectoryOptionEnabled,
484
  bool sourceFileTargetOptionEnabled,
485
  std::vector<std::string>& sourceFileDirectories,
486
  std::vector<std::string>& sourceFileTargetDirectories, cmValue& out)
487
0
{
488
0
  if (name.empty()) {
489
0
    status.SetError("not given name for SOURCE scope.");
490
0
    return false;
491
0
  }
492
493
0
  auto result = cmGetSourceFileProperty(
494
0
    name, propertyName, status, sourceFileDirectoryOptionEnabled,
495
0
    sourceFileTargetOptionEnabled, sourceFileDirectories,
496
0
    sourceFileTargetDirectories, out, /*alwaysCreateSource=*/true);
497
0
  if (result == cmGetSourceFilePropertyResult::Success) {
498
0
    return true;
499
0
  }
500
0
  if (result == cmGetSourceFilePropertyResult::Error ||
501
0
      result == cmGetSourceFilePropertyResult::SourceNotFound) {
502
0
    status.SetError(cmStrCat(
503
0
      "given SOURCE name that could not be found or created: ", name));
504
0
  }
505
0
  return false;
506
0
}
507
508
bool LookupSourceProperty(cmExecutionStatus& status, std::string const& name,
509
                          std::string const& propertyName, cmValue& out)
510
0
{
511
0
  std::vector<std::string> noDirectories;
512
0
  std::vector<std::string> noTargetDirectories;
513
0
  return LookupSourceProperty(status, name, propertyName,
514
0
                              /*sourceFileDirectoryOptionEnabled=*/false,
515
0
                              /*sourceFileTargetOptionEnabled=*/false,
516
0
                              noDirectories, noTargetDirectories, out);
517
0
}
518
519
bool LookupTestProperty(cmExecutionStatus& status, std::string const& name,
520
                        std::string const& propertyName,
521
                        bool testDirectoryOptionEnabled,
522
                        std::string& testDirectory, cmValue& out)
523
0
{
524
0
  if (name.empty()) {
525
0
    status.SetError("not given name for TEST scope.");
526
0
    return false;
527
0
  }
528
529
0
  auto result =
530
0
    cmGetTestProperty(name, propertyName, status, testDirectoryOptionEnabled,
531
0
                      testDirectory, out);
532
0
  if (result == cmGetTestPropertyResult::Success) {
533
0
    return true;
534
0
  }
535
0
  if (result == cmGetTestPropertyResult::TestNotFound) {
536
0
    status.SetError(cmStrCat("given TEST name that does not exist: ", name));
537
0
  }
538
0
  return false;
539
0
}
540
541
bool LookupTestProperty(cmExecutionStatus& status, std::string const& name,
542
                        std::string const& propertyName, cmValue& out)
543
0
{
544
0
  std::string noDirectory;
545
0
  return LookupTestProperty(status, name, propertyName,
546
0
                            /*testDirectoryOptionEnabled=*/false, noDirectory,
547
0
                            out);
548
0
}
549
550
bool LookupCacheProperty(cmExecutionStatus& status, std::string const& name,
551
                         std::string const& propertyName, cmValue& out)
552
0
{
553
0
  if (name.empty()) {
554
0
    status.SetError("not given name for CACHE scope.");
555
0
    return false;
556
0
  }
557
558
0
  out = nullptr;
559
0
  if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
560
0
    out = status.GetMakefile().GetState()->GetCacheEntryProperty(name,
561
0
                                                                 propertyName);
562
0
  }
563
0
  return true;
564
0
}
565
566
}