Coverage Report

Created: 2026-02-09 06:05

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