1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmTargetLinkLibrariesCommand.h"
14 #include "cmGeneratorExpression.h"
16 const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
23 // cmTargetLinkLibrariesCommand
24 bool cmTargetLinkLibrariesCommand
25 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
27 // must have one argument
30 this->SetError("called with incorrect number of arguments");
34 // Lookup the target for which libraries are specified.
36 this->Makefile->GetCMakeInstance()
37 ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
40 cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
42 e << "Cannot specify link libraries for target \"" << args[0] << "\" "
43 << "which is not built by this project.";
44 // The bad target is the only argument. Check how policy CMP0016 is set,
45 // and accept, warn or fail respectively:
48 switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016))
50 case cmPolicies::WARN:
51 t = cmake::AUTHOR_WARNING;
54 << "CMake does not support this but it used to work accidentally "
55 << "and is being allowed for compatibility."
56 << "\n" << this->Makefile->GetPolicies()->
57 GetPolicyWarning(cmPolicies::CMP0016);
59 case cmPolicies::OLD: // OLD behavior does not warn.
62 case cmPolicies::REQUIRED_IF_USED:
63 case cmPolicies::REQUIRED_ALWAYS:
64 e << "\n" << this->Makefile->GetPolicies()->
65 GetRequiredPolicyError(cmPolicies::CMP0016);
67 case cmPolicies::NEW: // NEW behavior prints the error.
73 // now actually print the message
76 case cmake::AUTHOR_WARNING:
77 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
79 case cmake::FATAL_ERROR:
80 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
81 cmSystemTools::SetFatalErrorOccured();
89 if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
92 e << "Object library target \"" << args[0] << "\" "
93 << "may not link to anything.";
94 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
95 cmSystemTools::SetFatalErrorOccured();
99 // but we might not have any libs after variable expansion
105 // Keep track of link configuration specifiers.
106 cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
107 bool haveLLT = false;
109 // Start with primary linking and switch to link interface
110 // specification if the keyword is encountered as the first argument.
111 this->CurrentProcessingState = ProcessingLinkLibraries;
113 // add libraries, note that there is an optional prefix
114 // of debug and optimized that can be used
115 for(unsigned int i=1; i < args.size(); ++i)
117 if(args[i] == "LINK_INTERFACE_LIBRARIES")
119 this->CurrentProcessingState = ProcessingLinkInterface;
122 this->Makefile->IssueMessage(
124 "The LINK_INTERFACE_LIBRARIES option must appear as the second "
125 "argument, just after the target name."
130 else if(args[i] == "LINK_PUBLIC")
132 if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
134 this->Makefile->IssueMessage(
136 "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
137 "argument, just after the target name."
141 this->CurrentProcessingState = ProcessingPublicInterface;
143 else if(args[i] == "LINK_PRIVATE")
145 if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
147 this->Makefile->IssueMessage(
149 "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
150 "argument, just after the target name."
154 this->CurrentProcessingState = ProcessingPrivateInterface;
156 else if(args[i] == "debug")
160 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
162 llt = cmTarget::DEBUG;
165 else if(args[i] == "optimized")
169 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
171 llt = cmTarget::OPTIMIZED;
174 else if(args[i] == "general")
178 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
180 llt = cmTarget::GENERAL;
185 // The link type was specified by the previous argument.
187 this->HandleLibrary(args[i].c_str(), llt);
191 // Lookup old-style cache entry if type is unspecified. So if you
192 // do a target_link_libraries(foo optimized bar) it will stay optimized
193 // and not use the lookup. As there maybe the case where someone has
194 // specifed that a library is both debug and optimized. (this check is
195 // only there for backwards compatibility when mixing projects built
196 // with old versions of CMake and new)
197 llt = cmTarget::GENERAL;
198 std::string linkType = args[0];
199 linkType += "_LINK_TYPE";
200 const char* linkTypeString =
201 this->Makefile->GetDefinition( linkType.c_str() );
204 if(strcmp(linkTypeString, "debug") == 0)
206 llt = cmTarget::DEBUG;
208 if(strcmp(linkTypeString, "optimized") == 0)
210 llt = cmTarget::OPTIMIZED;
213 this->HandleLibrary(args[i].c_str(), llt);
217 // Make sure the last argument was not a library type specifier.
221 e << "The \"" << this->LinkLibraryTypeNames[llt]
222 << "\" argument must be followed by a library.";
223 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
224 cmSystemTools::SetFatalErrorOccured();
227 // If any of the LINK_ options were given, make sure the
228 // LINK_INTERFACE_LIBRARIES target property exists.
229 // Use of any of the new keywords implies awareness of
230 // this property. And if no libraries are named, it should
231 // result in an empty link interface.
232 if(this->CurrentProcessingState != ProcessingLinkLibraries &&
233 !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
235 this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
241 //----------------------------------------------------------------------------
243 cmTargetLinkLibrariesCommand
244 ::LinkLibraryTypeSpecifierWarning(int left, int right)
247 w << "Link library type specifier \""
248 << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \""
249 << this->LinkLibraryTypeNames[right] << "\" instead of a library name. "
250 << "The first specifier will be ignored.";
251 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
254 //----------------------------------------------------------------------------
256 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
257 cmTarget::LinkLibraryType llt)
259 // Handle normal case first.
260 if(this->CurrentProcessingState != ProcessingLinkInterface)
263 ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
264 if (this->CurrentProcessingState != ProcessingPublicInterface)
266 // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
271 // Get the list of configurations considered to be DEBUG.
272 std::vector<std::string> const& debugConfigs =
273 this->Makefile->GetCMakeInstance()->GetDebugConfigs();
276 // Include this library in the link interface for the target.
277 if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
279 // Put in the DEBUG configuration interfaces.
280 for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
281 i != debugConfigs.end(); ++i)
283 prop = "LINK_INTERFACE_LIBRARIES_";
285 this->Target->AppendProperty(prop.c_str(), lib);
288 if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
290 // Put in the non-DEBUG configuration interfaces.
291 this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
293 // Make sure the DEBUG configuration interfaces exist so that the
294 // general one will not be used as a fall-back.
295 for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
296 i != debugConfigs.end(); ++i)
298 prop = "LINK_INTERFACE_LIBRARIES_";
300 if(!this->Target->GetProperty(prop.c_str()))
302 this->Target->SetProperty(prop.c_str(), "");