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 "cmAddLibraryCommand.h"
7 #include "cmGeneratorExpression.h"
8 #include "cmGlobalGenerator.h"
9 #include "cmMakefile.h"
11 #include "cmStateTypes.h"
12 #include "cmSystemTools.h"
16 class cmExecutionStatus;
19 bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
23 this->SetError("called with incorrect number of arguments");
26 // Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
27 // otherwise it defaults to static library.
28 cmStateEnums::TargetType type = cmStateEnums::SHARED_LIBRARY;
29 if (cmSystemTools::IsOff(
30 this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
31 type = cmStateEnums::STATIC_LIBRARY;
33 bool excludeFromAll = false;
34 bool importTarget = false;
35 bool importGlobal = false;
37 std::vector<std::string>::const_iterator s = args.begin();
39 std::string const& libName = *s;
43 // If the second argument is "SHARED" or "STATIC", then it controls
44 // the type of library. Otherwise, it is treated as a source or
45 // source list name. There may be two keyword arguments, check for them
46 bool haveSpecifiedType = false;
48 while (s != args.end()) {
49 std::string libType = *s;
50 if (libType == "STATIC") {
51 if (type == cmStateEnums::INTERFACE_LIBRARY) {
53 e << "INTERFACE library specified with conflicting STATIC type.";
54 this->SetError(e.str());
58 type = cmStateEnums::STATIC_LIBRARY;
59 haveSpecifiedType = true;
60 } else if (libType == "SHARED") {
61 if (type == cmStateEnums::INTERFACE_LIBRARY) {
63 e << "INTERFACE library specified with conflicting SHARED type.";
64 this->SetError(e.str());
68 type = cmStateEnums::SHARED_LIBRARY;
69 haveSpecifiedType = true;
70 } else if (libType == "MODULE") {
71 if (type == cmStateEnums::INTERFACE_LIBRARY) {
73 e << "INTERFACE library specified with conflicting MODULE type.";
74 this->SetError(e.str());
78 type = cmStateEnums::MODULE_LIBRARY;
79 haveSpecifiedType = true;
80 } else if (libType == "OBJECT") {
81 if (type == cmStateEnums::INTERFACE_LIBRARY) {
83 e << "INTERFACE library specified with conflicting OBJECT type.";
84 this->SetError(e.str());
88 type = cmStateEnums::OBJECT_LIBRARY;
89 haveSpecifiedType = true;
90 } else if (libType == "UNKNOWN") {
91 if (type == cmStateEnums::INTERFACE_LIBRARY) {
93 e << "INTERFACE library specified with conflicting UNKNOWN type.";
94 this->SetError(e.str());
98 type = cmStateEnums::UNKNOWN_LIBRARY;
99 haveSpecifiedType = true;
100 } else if (libType == "ALIAS") {
101 if (type == cmStateEnums::INTERFACE_LIBRARY) {
102 std::ostringstream e;
103 e << "INTERFACE library specified with conflicting ALIAS type.";
104 this->SetError(e.str());
109 } else if (libType == "INTERFACE") {
110 if (haveSpecifiedType) {
111 std::ostringstream e;
112 e << "INTERFACE library specified with conflicting/multiple types.";
113 this->SetError(e.str());
117 std::ostringstream e;
118 e << "INTERFACE library specified with conflicting ALIAS type.";
119 this->SetError(e.str());
122 if (excludeFromAll) {
123 std::ostringstream e;
124 e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
125 this->SetError(e.str());
129 type = cmStateEnums::INTERFACE_LIBRARY;
130 haveSpecifiedType = true;
131 } else if (*s == "EXCLUDE_FROM_ALL") {
132 if (type == cmStateEnums::INTERFACE_LIBRARY) {
133 std::ostringstream e;
134 e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL.";
135 this->SetError(e.str());
139 excludeFromAll = true;
140 } else if (*s == "IMPORTED") {
143 } else if (importTarget && *s == "GLOBAL") {
146 } else if (type == cmStateEnums::INTERFACE_LIBRARY && *s == "GLOBAL") {
147 std::ostringstream e;
148 e << "GLOBAL option may only be used with IMPORTED libraries.";
149 this->SetError(e.str());
156 if (type == cmStateEnums::INTERFACE_LIBRARY) {
157 if (s != args.end()) {
158 std::ostringstream e;
159 e << "INTERFACE library requires no source arguments.";
160 this->SetError(e.str());
163 if (importGlobal && !importTarget) {
164 std::ostringstream e;
165 e << "INTERFACE library specified as GLOBAL, but not as IMPORTED.";
166 this->SetError(e.str());
171 bool nameOk = cmGeneratorExpression::IsValidTargetName(libName) &&
172 !cmGlobalGenerator::IsReservedTarget(libName);
174 if (nameOk && !importTarget && !isAlias) {
175 nameOk = libName.find(':') == std::string::npos;
177 if (!nameOk && !this->Makefile->CheckCMP0037(libName, type)) {
182 if (!cmGeneratorExpression::IsValidTargetName(libName)) {
183 this->SetError("Invalid name for ALIAS: " + libName);
186 if (excludeFromAll) {
187 this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
190 if (importTarget || importGlobal) {
191 this->SetError("IMPORTED with ALIAS is not allowed.");
194 if (args.size() != 3) {
195 std::ostringstream e;
196 e << "ALIAS requires exactly one target argument.";
197 this->SetError(e.str());
201 std::string const& aliasedName = *s;
202 if (this->Makefile->IsAlias(aliasedName)) {
203 std::ostringstream e;
204 e << "cannot create ALIAS target \"" << libName << "\" because target \""
205 << aliasedName << "\" is itself an ALIAS.";
206 this->SetError(e.str());
209 cmTarget* aliasedTarget =
210 this->Makefile->FindTargetToUse(aliasedName, true);
211 if (!aliasedTarget) {
212 std::ostringstream e;
213 e << "cannot create ALIAS target \"" << libName << "\" because target \""
214 << aliasedName << "\" does not already "
216 this->SetError(e.str());
219 cmStateEnums::TargetType aliasedType = aliasedTarget->GetType();
220 if (aliasedType != cmStateEnums::SHARED_LIBRARY &&
221 aliasedType != cmStateEnums::STATIC_LIBRARY &&
222 aliasedType != cmStateEnums::MODULE_LIBRARY &&
223 aliasedType != cmStateEnums::OBJECT_LIBRARY &&
224 aliasedType != cmStateEnums::INTERFACE_LIBRARY) {
225 std::ostringstream e;
226 e << "cannot create ALIAS target \"" << libName << "\" because target \""
227 << aliasedName << "\" is not a library.";
228 this->SetError(e.str());
231 this->Makefile->AddAlias(libName, aliasedName);
235 if (importTarget && excludeFromAll) {
236 this->SetError("excludeFromAll with IMPORTED target makes no sense.");
240 /* ideally we should check whether for the linker language of the target
241 CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
242 STATIC. But at this point we know only the name of the target, but not
243 yet its linker language. */
244 if ((type == cmStateEnums::SHARED_LIBRARY ||
245 type == cmStateEnums::MODULE_LIBRARY) &&
246 !this->Makefile->GetState()->GetGlobalPropertyAsBool(
247 "TARGET_SUPPORTS_SHARED_LIBS")) {
248 std::ostringstream w;
249 w << "ADD_LIBRARY called with "
250 << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE")
251 << " option but the target platform does not support dynamic linking. "
252 "Building a STATIC library instead. This may lead to problems.";
253 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
254 type = cmStateEnums::STATIC_LIBRARY;
257 // Handle imported target creation.
259 // The IMPORTED signature requires a type to be specified explicitly.
260 if (!haveSpecifiedType) {
261 this->SetError("called with IMPORTED argument but no library type.");
264 if (type == cmStateEnums::OBJECT_LIBRARY) {
266 if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
268 this->Makefile->IssueMessage(
270 "The OBJECT library type may not be used for IMPORTED libraries" +
275 if (type == cmStateEnums::INTERFACE_LIBRARY) {
276 if (!cmGeneratorExpression::IsValidTargetName(libName)) {
277 std::ostringstream e;
278 e << "Invalid name for IMPORTED INTERFACE library target: " << libName;
279 this->SetError(e.str());
284 // Make sure the target does not already exist.
285 if (this->Makefile->FindTargetToUse(libName)) {
286 std::ostringstream e;
287 e << "cannot create imported target \"" << libName
288 << "\" because another target with the same name already exists.";
289 this->SetError(e.str());
293 // Create the imported target.
294 this->Makefile->AddImportedTarget(libName, type, importGlobal);
298 // A non-imported target may not have UNKNOWN type.
299 if (type == cmStateEnums::UNKNOWN_LIBRARY) {
300 this->Makefile->IssueMessage(
302 "The UNKNOWN library type may be used only for IMPORTED libraries.");
306 // Enforce name uniqueness.
309 if (!this->Makefile->EnforceUniqueName(libName, msg)) {
315 std::vector<std::string> srclists;
317 if (type == cmStateEnums::INTERFACE_LIBRARY) {
318 if (!cmGeneratorExpression::IsValidTargetName(libName) ||
319 libName.find("::") != std::string::npos) {
320 std::ostringstream e;
321 e << "Invalid name for INTERFACE library target: " << libName;
322 this->SetError(e.str());
326 this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
330 srclists.insert(srclists.end(), s, args.end());
332 this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);