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 const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
21 // cmTargetLinkLibrariesCommand
22 bool cmTargetLinkLibrariesCommand
23 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
25 // must have one argument
28 this->SetError("called with incorrect number of arguments");
32 // Lookup the target for which libraries are specified.
34 this->Makefile->GetCMakeInstance()
35 ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
38 cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
40 e << "Cannot specify link libraries for target \"" << args[0] << "\" "
41 << "which is not built by this project.";
42 // The bad target is the only argument. Check how policy CMP0016 is set,
43 // and accept, warn or fail respectively:
46 switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016))
48 case cmPolicies::WARN:
49 t = cmake::AUTHOR_WARNING;
52 << "CMake does not support this but it used to work accidentally "
53 << "and is being allowed for compatibility."
54 << "\n" << this->Makefile->GetPolicies()->
55 GetPolicyWarning(cmPolicies::CMP0016);
57 case cmPolicies::OLD: // OLD behavior does not warn.
60 case cmPolicies::REQUIRED_IF_USED:
61 case cmPolicies::REQUIRED_ALWAYS:
62 e << "\n" << this->Makefile->GetPolicies()->
63 GetRequiredPolicyError(cmPolicies::CMP0016);
65 case cmPolicies::NEW: // NEW behavior prints the error.
71 // now actually print the message
74 case cmake::AUTHOR_WARNING:
75 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
77 case cmake::FATAL_ERROR:
78 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
79 cmSystemTools::SetFatalErrorOccured();
87 if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
90 e << "Object library target \"" << args[0] << "\" "
91 << "may not link to anything.";
92 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
93 cmSystemTools::SetFatalErrorOccured();
97 // but we might not have any libs after variable expansion
103 // Keep track of link configuration specifiers.
104 cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
105 bool haveLLT = false;
107 // Start with primary linking and switch to link interface
108 // specification if the keyword is encountered as the first argument.
109 this->CurrentProcessingState = ProcessingLinkLibraries;
111 // add libraries, nothe that there is an optional prefix
112 // of debug and optimized than can be used
113 for(unsigned int i=1; i < args.size(); ++i)
115 if(args[i] == "LINK_INTERFACE_LIBRARIES")
117 this->CurrentProcessingState = ProcessingLinkInterface;
120 this->Makefile->IssueMessage(
122 "The LINK_INTERFACE_LIBRARIES option must appear as the second "
123 "argument, just after the target name."
128 else if(args[i] == "LINK_PUBLIC")
130 if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
132 this->Makefile->IssueMessage(
134 "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
135 "argument, just after the target name."
139 this->CurrentProcessingState = ProcessingPublicInterface;
141 else if(args[i] == "LINK_PRIVATE")
143 if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
145 this->Makefile->IssueMessage(
147 "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
148 "argument, just after the target name."
152 this->CurrentProcessingState = ProcessingPrivateInterface;
154 else if(args[i] == "debug")
158 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
160 llt = cmTarget::DEBUG;
163 else if(args[i] == "optimized")
167 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
169 llt = cmTarget::OPTIMIZED;
172 else if(args[i] == "general")
176 this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
178 llt = cmTarget::GENERAL;
183 // The link type was specified by the previous argument.
185 this->HandleLibrary(args[i].c_str(), llt);
189 // Lookup old-style cache entry if type is unspecified. So if you
190 // do a target_link_libraries(foo optimized bar) it will stay optimized
191 // and not use the lookup. As there maybe the case where someone has
192 // specifed that a library is both debug and optimized. (this check is
193 // only there for backwards compatibility when mixing projects built
194 // with old versions of CMake and new)
195 llt = cmTarget::GENERAL;
196 std::string linkType = args[0];
197 linkType += "_LINK_TYPE";
198 const char* linkTypeString =
199 this->Makefile->GetDefinition( linkType.c_str() );
202 if(strcmp(linkTypeString, "debug") == 0)
204 llt = cmTarget::DEBUG;
206 if(strcmp(linkTypeString, "optimized") == 0)
208 llt = cmTarget::OPTIMIZED;
211 this->HandleLibrary(args[i].c_str(), llt);
215 // Make sure the last argument was not a library type specifier.
219 e << "The \"" << this->LinkLibraryTypeNames[llt]
220 << "\" argument must be followed by a library.";
221 this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
222 cmSystemTools::SetFatalErrorOccured();
225 // If any of the LINK_ options were given, make sure the
226 // LINK_INTERFACE_LIBRARIES target property exists.
227 // Use of any of the new keywords implies awareness of
228 // this property. And if no libraries are named, it should
229 // result in an empty link interface.
230 if(this->CurrentProcessingState != ProcessingLinkLibraries &&
231 !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
233 this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
239 //----------------------------------------------------------------------------
241 cmTargetLinkLibrariesCommand
242 ::LinkLibraryTypeSpecifierWarning(int left, int right)
245 w << "Link library type specifier \""
246 << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \""
247 << this->LinkLibraryTypeNames[right] << "\" instead of a library name. "
248 << "The first specifier will be ignored.";
249 this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
252 //----------------------------------------------------------------------------
254 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
255 cmTarget::LinkLibraryType llt)
257 // Handle normal case first.
258 if(this->CurrentProcessingState != ProcessingLinkInterface)
261 ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
262 if (this->CurrentProcessingState != ProcessingPublicInterface)
264 // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
269 // Get the list of configurations considered to be DEBUG.
270 std::vector<std::string> const& debugConfigs =
271 this->Makefile->GetCMakeInstance()->GetDebugConfigs();
274 // Include this library in the link interface for the target.
275 if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
277 // Put in the DEBUG configuration interfaces.
278 for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
279 i != debugConfigs.end(); ++i)
281 prop = "LINK_INTERFACE_LIBRARIES_";
283 this->Target->AppendProperty(prop.c_str(), lib);
286 if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
288 // Put in the non-DEBUG configuration interfaces.
289 this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
291 // Make sure the DEBUG configuration interfaces exist so that the
292 // general one will not be used as a fall-back.
293 for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
294 i != debugConfigs.end(); ++i)
296 prop = "LINK_INTERFACE_LIBRARIES_";
298 if(!this->Target->GetProperty(prop.c_str()))
300 this->Target->SetProperty(prop.c_str(), "");