CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmTargetPropCommandBase.cxx
blobde2012f1ccdacc81f56fd7b9e4a673163eeba0c4
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmTargetPropCommandBase.h"
5 #include "cmExecutionStatus.h"
6 #include "cmGlobalGenerator.h"
7 #include "cmMakefile.h"
8 #include "cmStateTypes.h"
9 #include "cmTarget.h"
10 #include "cmValue.h"
12 cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
13 : Makefile(&status.GetMakefile())
14 , Status(status)
18 void cmTargetPropCommandBase::SetError(std::string const& e)
20 this->Status.SetError(e);
23 bool cmTargetPropCommandBase::HandleArguments(
24 std::vector<std::string> const& args, const std::string& prop,
25 unsigned int flags)
27 if (args.size() < 2) {
28 this->SetError("called with incorrect number of arguments");
29 return false;
32 if (this->Makefile->IsAlias(args[0])) {
33 this->SetError("can not be used on an ALIAS target.");
34 return false;
36 // Lookup the target for which property-values are specified.
37 this->Target = this->Makefile->GetGlobalGenerator()->FindTarget(args[0]);
38 if (!this->Target) {
39 this->Target = this->Makefile->FindTargetToUse(args[0]);
41 if (!this->Target) {
42 this->HandleMissingTarget(args[0]);
43 return false;
45 const bool isRegularTarget =
46 (this->Target->GetType() == cmStateEnums::EXECUTABLE) ||
47 (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
48 (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
49 (this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
50 (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
51 (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
52 (this->Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY);
53 const bool isCustomTarget = this->Target->GetType() == cmStateEnums::UTILITY;
55 if (prop == "SOURCES") {
56 if (!isRegularTarget && !isCustomTarget) {
57 this->SetError("called with non-compilable target type");
58 return false;
60 } else {
61 if (!isRegularTarget) {
62 this->SetError("called with non-compilable target type");
63 return false;
67 bool system = false;
68 unsigned int argIndex = 1;
70 if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
71 if (args.size() < 3) {
72 this->SetError("called with incorrect number of arguments");
73 return false;
75 system = true;
76 ++argIndex;
79 bool prepend = false;
80 if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
81 if (args.size() < 3) {
82 this->SetError("called with incorrect number of arguments");
83 return false;
85 prepend = true;
86 ++argIndex;
87 } else if ((flags & PROCESS_AFTER) && args[argIndex] == "AFTER") {
88 if (args.size() < 3) {
89 this->SetError("called with incorrect number of arguments");
90 return false;
92 prepend = false;
93 ++argIndex;
96 if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
97 if (args.size() != 3) {
98 this->SetError("called with incorrect number of arguments");
99 return false;
101 ++argIndex;
103 this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]);
104 ++argIndex;
107 this->Property = prop;
109 while (argIndex < args.size()) {
110 if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
111 return false;
114 return true;
117 bool cmTargetPropCommandBase::ProcessContentArgs(
118 std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
119 bool system)
121 std::string const& scope = args[argIndex];
123 if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
124 this->SetError("called with invalid arguments");
125 return false;
128 ++argIndex;
130 std::vector<std::string> content;
132 for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
133 if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
134 args[i] == "INTERFACE") {
135 break;
137 content.push_back(args[i]);
139 if (!content.empty()) {
140 if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
141 scope != "INTERFACE" && this->Property != "SOURCES") {
142 this->SetError("may only set INTERFACE properties on INTERFACE targets");
143 return false;
145 if (this->Target->IsImported() && scope != "INTERFACE") {
146 this->SetError("may only set INTERFACE properties on IMPORTED targets");
147 return false;
149 if (this->Target->GetType() == cmStateEnums::UTILITY &&
150 scope != "PRIVATE") {
151 this->SetError("may only set PRIVATE properties on custom targets");
152 return false;
155 return this->PopulateTargetProperties(scope, content, prepend, system);
158 bool cmTargetPropCommandBase::PopulateTargetProperties(
159 const std::string& scope, const std::vector<std::string>& content,
160 bool prepend, bool system)
162 if (content.empty()) {
163 return true;
165 if (scope == "PRIVATE" || scope == "PUBLIC") {
166 if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
167 return false;
170 if (scope == "INTERFACE" || scope == "PUBLIC") {
171 this->HandleInterfaceContent(this->Target, content, prepend, system);
173 return true;
176 void cmTargetPropCommandBase::HandleInterfaceContent(
177 cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
179 if (prepend) {
180 const std::string propName = std::string("INTERFACE_") + this->Property;
181 cmValue propValue = tgt->GetProperty(propName);
182 const std::string totalContent =
183 this->Join(content) + (propValue ? (";" + *propValue) : std::string());
184 tgt->SetProperty(propName, totalContent);
185 } else {
186 tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));