Coverage Report

Created: 2026-10-28 06:38

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
35.5k
  : Makefile(&status.GetMakefile())
14
35.5k
  , Status(status)
15
35.5k
{
16
35.5k
}
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
35.5k
{
27
35.5k
  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
35.5k
  this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]);
34
35.5k
  if (!this->Target) {
35
0
    this->Target = this->Makefile->FindTargetToUse(args[0]);
36
0
  }
37
35.5k
  if (!this->Target) {
38
0
    this->HandleMissingTarget(args[0]);
39
0
    return false;
40
0
  }
41
35.5k
  if (this->Target->IsSymbolic()) {
42
0
    this->SetError("can not be used on a SYMBOLIC target.");
43
0
    return false;
44
0
  }
45
35.5k
  bool const isRegularTarget =
46
35.5k
    (this->Target->GetType() == cm::TargetType::EXECUTABLE) ||
47
35.5k
    (this->Target->GetType() == cm::TargetType::STATIC_LIBRARY) ||
48
35.5k
    (this->Target->GetType() == cm::TargetType::SHARED_LIBRARY) ||
49
35.5k
    (this->Target->GetType() == cm::TargetType::MODULE_LIBRARY) ||
50
35.5k
    (this->Target->GetType() == cm::TargetType::OBJECT_LIBRARY) ||
51
29.6k
    (this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY) ||
52
0
    (this->Target->GetType() == cm::TargetType::UNKNOWN_LIBRARY);
53
35.5k
  bool const isCustomTarget =
54
35.5k
    this->Target->GetType() == cm::TargetType::UTILITY;
55
56
35.5k
  if (prop == "SOURCES") {
57
5.92k
    if (!isRegularTarget && !isCustomTarget) {
58
0
      this->SetError("called with non-compilable target type");
59
0
      return false;
60
0
    }
61
29.6k
  } else {
62
29.6k
    if (!isRegularTarget) {
63
0
      this->SetError("called with non-compilable target type");
64
0
      return false;
65
0
    }
66
29.6k
  }
67
68
35.5k
  bool system = false;
69
35.5k
  unsigned int argIndex = 1;
70
71
35.5k
  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
35.5k
  bool prepend = false;
81
35.5k
  if ((flags & PROCESS_BEFORE) && argIndex < args.size() &&
82
17.7k
      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
35.5k
  } else if ((flags & PROCESS_AFTER) && argIndex < args.size() &&
90
5.92k
             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
35.5k
  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
35.5k
  this->Property = prop;
112
113
71.1k
  while (argIndex < args.size()) {
114
35.5k
    if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
115
0
      return false;
116
0
    }
117
35.5k
  }
118
35.5k
  return true;
119
35.5k
}
120
121
bool cmTargetPropCommandBase::ProcessContentArgs(
122
  std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
123
  bool system)
124
35.5k
{
125
35.5k
  std::string const& scope = args[argIndex];
126
127
35.5k
  if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
128
0
    this->SetError("called with invalid arguments");
129
0
    return false;
130
0
  }
131
132
35.5k
  ++argIndex;
133
134
35.5k
  std::vector<std::string> content;
135
136
118k
  for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
137
82.9k
    if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
138
82.9k
        args[i] == "INTERFACE") {
139
0
      break;
140
0
    }
141
82.9k
    content.push_back(args[i]);
142
82.9k
  }
143
35.5k
  if (!content.empty()) {
144
35.5k
    if (this->Target->GetType() == cm::TargetType::INTERFACE_LIBRARY &&
145
29.6k
        scope != "INTERFACE" && this->Property != "SOURCES") {
146
0
      this->SetError("may only set INTERFACE properties on INTERFACE targets");
147
0
      return false;
148
0
    }
149
35.5k
    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
35.5k
    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
35.5k
  }
159
35.5k
  return this->PopulateTargetProperties(scope, content, prepend, system);
160
35.5k
}
161
162
bool cmTargetPropCommandBase::PopulateTargetProperties(
163
  std::string const& scope, std::vector<std::string> const& content,
164
  bool prepend, bool system)
165
29.6k
{
166
29.6k
  if (content.empty()) {
167
0
    return true;
168
0
  }
169
29.6k
  if (scope == "PRIVATE" || scope == "PUBLIC") {
170
5.92k
    if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
171
0
      return false;
172
0
    }
173
5.92k
  }
174
29.6k
  if (scope == "INTERFACE" || scope == "PUBLIC") {
175
23.7k
    this->HandleInterfaceContent(this->Target, content, prepend, system);
176
23.7k
  }
177
29.6k
  return true;
178
29.6k
}
179
180
void cmTargetPropCommandBase::HandleInterfaceContent(
181
  cmTarget* tgt, std::vector<std::string> const& content, bool prepend, bool)
182
23.7k
{
183
23.7k
  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
23.7k
  } else {
190
23.7k
    tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));
191
23.7k
  }
192
23.7k
}