/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 | } |