Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmTargetPropCommandBase.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 "cmTargetPropCommandBase.h"
4
5
#include "cmExecutionStatus.h"
6
#include "cmGlobalGenerator.h"
7
#include "cmMakefile.h"
8
#include "cmStateTypes.h"
9
#include "cmTarget.h"
10
#include "cmValue.h"
11
12
cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
13
0
  : Makefile(&status.GetMakefile())
14
0
  , Status(status)
15
0
{
16
0
}
17
18
void cmTargetPropCommandBase::SetError(std::string const& e)
19
0
{
20
0
  this->Status.SetError(e);
21
0
}
22
23
bool cmTargetPropCommandBase::HandleArguments(
24
  std::vector<std::string> const& args, std::string const& prop,
25
  unsigned int flags)
26
0
{
27
0
  if (args.size() < 2) {
28
0
    this->SetError("called with incorrect number of arguments");
29
0
    return false;
30
0
  }
31
32
0
  if (this->Makefile->IsAlias(args[0])) {
33
0
    this->SetError("can not be used on an ALIAS target.");
34
0
    return false;
35
0
  }
36
  // Lookup the target for which property-values are specified.
37
0
  this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]);
38
0
  if (!this->Target) {
39
0
    this->Target = this->Makefile->FindTargetToUse(args[0]);
40
0
  }
41
0
  if (!this->Target) {
42
0
    this->HandleMissingTarget(args[0]);
43
0
    return false;
44
0
  }
45
0
  if (this->Target->IsSymbolic()) {
46
0
    this->SetError("can not be used on a SYMBOLIC target.");
47
0
    return false;
48
0
  }
49
0
  bool const isRegularTarget =
50
0
    (this->Target->GetType() == cmStateEnums::EXECUTABLE) ||
51
0
    (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
52
0
    (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
53
0
    (this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
54
0
    (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
55
0
    (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
56
0
    (this->Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY);
57
0
  bool const isCustomTarget = this->Target->GetType() == cmStateEnums::UTILITY;
58
59
0
  if (prop == "SOURCES") {
60
0
    if (!isRegularTarget && !isCustomTarget) {
61
0
      this->SetError("called with non-compilable target type");
62
0
      return false;
63
0
    }
64
0
  } else {
65
0
    if (!isRegularTarget) {
66
0
      this->SetError("called with non-compilable target type");
67
0
      return false;
68
0
    }
69
0
  }
70
71
0
  bool system = false;
72
0
  unsigned int argIndex = 1;
73
74
0
  if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
75
0
    if (args.size() < 3) {
76
0
      this->SetError("called with incorrect number of arguments");
77
0
      return false;
78
0
    }
79
0
    system = true;
80
0
    ++argIndex;
81
0
  }
82
83
0
  bool prepend = false;
84
0
  if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
85
0
    if (args.size() < 3) {
86
0
      this->SetError("called with incorrect number of arguments");
87
0
      return false;
88
0
    }
89
0
    prepend = true;
90
0
    ++argIndex;
91
0
  } else if ((flags & PROCESS_AFTER) && args[argIndex] == "AFTER") {
92
0
    if (args.size() < 3) {
93
0
      this->SetError("called with incorrect number of arguments");
94
0
      return false;
95
0
    }
96
0
    prepend = false;
97
0
    ++argIndex;
98
0
  }
99
100
0
  if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
101
0
    if (args.size() != 3) {
102
0
      this->SetError("called with incorrect number of arguments");
103
0
      return false;
104
0
    }
105
0
    ++argIndex;
106
107
0
    this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]);
108
0
    ++argIndex;
109
0
  }
110
111
0
  this->Property = prop;
112
113
0
  while (argIndex < args.size()) {
114
0
    if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
115
0
      return false;
116
0
    }
117
0
  }
118
0
  return true;
119
0
}
120
121
bool cmTargetPropCommandBase::ProcessContentArgs(
122
  std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
123
  bool system)
124
0
{
125
0
  std::string const& scope = args[argIndex];
126
127
0
  if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
128
0
    this->SetError("called with invalid arguments");
129
0
    return false;
130
0
  }
131
132
0
  ++argIndex;
133
134
0
  std::vector<std::string> content;
135
136
0
  for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
137
0
    if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
138
0
        args[i] == "INTERFACE") {
139
0
      break;
140
0
    }
141
0
    content.push_back(args[i]);
142
0
  }
143
0
  if (!content.empty()) {
144
0
    if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
145
0
        scope != "INTERFACE" && this->Property != "SOURCES") {
146
0
      this->SetError("may only set INTERFACE properties on INTERFACE targets");
147
0
      return false;
148
0
    }
149
0
    if (this->Target->IsImported() && scope != "INTERFACE") {
150
0
      this->SetError("may only set INTERFACE properties on IMPORTED targets");
151
0
      return false;
152
0
    }
153
0
    if (this->Target->GetType() == cmStateEnums::UTILITY &&
154
0
        scope != "PRIVATE") {
155
0
      this->SetError("may only set PRIVATE properties on custom targets");
156
0
      return false;
157
0
    }
158
0
  }
159
0
  return this->PopulateTargetProperties(scope, content, prepend, system);
160
0
}
161
162
bool cmTargetPropCommandBase::PopulateTargetProperties(
163
  std::string const& scope, std::vector<std::string> const& content,
164
  bool prepend, bool system)
165
0
{
166
0
  if (content.empty()) {
167
0
    return true;
168
0
  }
169
0
  if (scope == "PRIVATE" || scope == "PUBLIC") {
170
0
    if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
171
0
      return false;
172
0
    }
173
0
  }
174
0
  if (scope == "INTERFACE" || scope == "PUBLIC") {
175
0
    this->HandleInterfaceContent(this->Target, content, prepend, system);
176
0
  }
177
0
  return true;
178
0
}
179
180
void cmTargetPropCommandBase::HandleInterfaceContent(
181
  cmTarget* tgt, std::vector<std::string> const& content, bool prepend, bool)
182
0
{
183
0
  if (prepend) {
184
0
    std::string const propName = std::string("INTERFACE_") + this->Property;
185
0
    cmValue propValue = tgt->GetProperty(propName);
186
0
    std::string const totalContent =
187
0
      this->Join(content) + (propValue ? (";" + *propValue) : std::string());
188
0
    tgt->SetProperty(propName, totalContent);
189
0
  } else {
190
0
    tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));
191
0
  }
192
0
}