Coverage Report

Created: 2026-07-14 07:09

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 "cmTarget.h"
9
#include "cmTargetTypes.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
  // Lookup the target for which property-values are specified.
33
0
  this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]);
34
0
  if (!this->Target) {
35
0
    this->Target = this->Makefile->FindTargetToUse(args[0]);
36
0
  }
37
0
  if (!this->Target) {
38
0
    this->HandleMissingTarget(args[0]);
39
0
    return false;
40
0
  }
41
0
  if (this->Target->IsSymbolic()) {
42
0
    this->SetError("can not be used on a SYMBOLIC target.");
43
0
    return false;
44
0
  }
45
0
  bool const isRegularTarget =
46
0
    (this->Target->GetType() == cm::TargetType::EXECUTABLE) ||
47
0
    (this->Target->GetType() == cm::TargetType::STATIC_LIBRARY) ||
48
0
    (this->Target->GetType() == cm::TargetType::SHARED_LIBRARY) ||
49
0
    (this->Target->GetType() == cm::TargetType::MODULE_LIBRARY) ||
50
0
    (this->Target->GetType() == cm::TargetType::OBJECT_LIBRARY) ||
51
0
    (this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY) ||
52
0
    (this->Target->GetType() == cm::TargetType::UNKNOWN_LIBRARY);
53
0
  bool const isCustomTarget =
54
0
    this->Target->GetType() == cm::TargetType::UTILITY;
55
56
0
  if (prop == "SOURCES") {
57
0
    if (!isRegularTarget && !isCustomTarget) {
58
0
      this->SetError("called with non-compilable target type");
59
0
      return false;
60
0
    }
61
0
  } else {
62
0
    if (!isRegularTarget) {
63
0
      this->SetError("called with non-compilable target type");
64
0
      return false;
65
0
    }
66
0
  }
67
68
0
  bool system = false;
69
0
  unsigned int argIndex = 1;
70
71
0
  if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
72
0
    if (args.size() < 3) {
73
0
      this->SetError("called with incorrect number of arguments");
74
0
      return false;
75
0
    }
76
0
    system = true;
77
0
    ++argIndex;
78
0
  }
79
80
0
  bool prepend = false;
81
0
  if ((flags & PROCESS_BEFORE) && argIndex < args.size() &&
82
0
      args[argIndex] == "BEFORE") {
83
0
    if (args.size() < 3) {
84
0
      this->SetError("called with incorrect number of arguments");
85
0
      return false;
86
0
    }
87
0
    prepend = true;
88
0
    ++argIndex;
89
0
  } else if ((flags & PROCESS_AFTER) && argIndex < args.size() &&
90
0
             args[argIndex] == "AFTER") {
91
0
    if (args.size() < 3) {
92
0
      this->SetError("called with incorrect number of arguments");
93
0
      return false;
94
0
    }
95
0
    prepend = false;
96
0
    ++argIndex;
97
0
  }
98
99
0
  if ((flags & PROCESS_REUSE_FROM) && argIndex < args.size() &&
100
0
      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() == cm::TargetType::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() == cm::TargetType::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
}