Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmProjectInfoArguments.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 "cmProjectInfoArguments.h"
4
5
#include <utility>
6
7
#include <cm/string_view>
8
9
#include "cmExecutionStatus.h"
10
#include "cmGeneratorExpression.h"
11
#include "cmMakefile.h"
12
#include "cmStateSnapshot.h"
13
#include "cmStringAlgorithms.h"
14
#include "cmValue.h"
15
16
template void cmProjectInfoArguments::Bind<void>(cmArgumentParser<void>&,
17
                                                 cmProjectInfoArguments*);
18
19
#define ENFORCE_REQUIRES(req, value, arg)                                     \
20
  do {                                                                        \
21
    if (ArgWasSpecified(value)) {                                             \
22
      status.SetError(arg " requires " req ".");                              \
23
      return false;                                                           \
24
    }                                                                         \
25
  } while (false)
26
27
#define ENFORCE_EXCLUSIVE(arg1, value, arg2)                                  \
28
0
  do {                                                                        \
29
0
    if (ArgWasSpecified(value)) {                                             \
30
0
      status.SetError(arg1 " and " arg2 " are mutually exclusive.");          \
31
0
      return false;                                                           \
32
0
    }                                                                         \
33
0
  } while (false)
34
35
0
cmProjectInfoArguments::cmProjectInfoArguments() = default;
36
37
bool cmProjectInfoArguments::Check(cmExecutionStatus& status) const
38
0
{
39
  // Check for incompatible options.
40
0
  if (this->NoProjectDefaults) {
41
0
    ENFORCE_EXCLUSIVE("PROJECT", this->ProjectName, "NO_PROJECT_METADATA");
42
0
  }
43
44
  // Validate the package name.
45
0
  if (!this->PackageName.empty()) {
46
0
    if (!cmGeneratorExpression::IsValidTargetName(this->PackageName) ||
47
0
        this->PackageName.find(':') != std::string::npos) {
48
0
      status.SetError(cmStrCat(this->CommandName(),
49
0
                               " given invalid package name \""_s,
50
0
                               this->PackageName, "\"."_s));
51
0
      return false;
52
0
    }
53
0
  }
54
55
0
  return true;
56
0
}
57
58
#undef ENFORCE_REQUIRES
59
#undef ENFORCE_EXCLUSIVE
60
61
bool cmProjectInfoArguments::SetMetadataFromProject(cmExecutionStatus& status)
62
0
{
63
  // Determine what project to use for inherited metadata.
64
0
  if (!this->SetEffectiveProject(status)) {
65
0
    return false;
66
0
  }
67
68
0
  if (this->ProjectName.empty()) {
69
    // We are not inheriting from a project.
70
0
    return true;
71
0
  }
72
73
0
  cmMakefile& mf = status.GetMakefile();
74
0
  auto mapProjectValue = [&](std::string& arg, cm::string_view suffix) {
75
0
    cmValue const& projectValue =
76
0
      mf.GetDefinition(cmStrCat(this->ProjectName, '_', suffix));
77
0
    if (projectValue) {
78
0
      arg = *projectValue;
79
0
      return true;
80
0
    }
81
0
    return false;
82
0
  };
83
84
0
  if (this->Version.empty()) {
85
0
    if (mapProjectValue(this->Version, "VERSION"_s)) {
86
0
      mapProjectValue(this->VersionCompat, "COMPAT_VERSION"_s);
87
0
    }
88
0
  }
89
90
0
  if (this->License.empty()) {
91
0
    mapProjectValue(this->License, "SPDX_LICENSE"_s);
92
0
  }
93
94
0
  if (this->Description.empty()) {
95
0
    mapProjectValue(this->Description, "DESCRIPTION"_s);
96
0
  }
97
98
0
  if (this->Website.empty()) {
99
0
    mapProjectValue(this->Website, "HOMEPAGE_URL"_s);
100
0
  }
101
102
0
  return true;
103
0
}
104
105
bool cmProjectInfoArguments::SetEffectiveProject(cmExecutionStatus& status)
106
0
{
107
0
  if (this->NoProjectDefaults) {
108
    // User requested that metadata not be inherited.
109
0
    return true;
110
0
  }
111
112
0
  cmMakefile& mf = status.GetMakefile();
113
0
  if (!this->ProjectName.empty()) {
114
    // User specified a project; make sure it exists.
115
0
    if (!mf.GetStateSnapshot().CheckProjectName(this->ProjectName)) {
116
0
      status.SetError(cmStrCat(R"(PROJECT given unknown project name ")"_s,
117
0
                               this->ProjectName, R"(".)"_s));
118
0
      return false;
119
0
    }
120
0
  } else {
121
    // No project was specified; check if the package name is also a project.
122
0
    std::string project = mf.GetStateSnapshot().GetProjectName();
123
0
    if (this->PackageName == project) {
124
0
      this->ProjectName = std::move(project);
125
0
    }
126
0
  }
127
128
0
  return true;
129
0
}