b7b7691c8c23d01f29cb039aaa839d2afd893a95
[platform/upstream/cmake.git] / Source / cmTargetLinkLibrariesCommand.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
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"
13
14 #include "cmGeneratorExpression.h"
15
16 const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
17 {
18   "general",
19   "debug",
20   "optimized"
21 };
22
23 // cmTargetLinkLibrariesCommand
24 bool cmTargetLinkLibrariesCommand
25 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
26 {
27   // must have one argument
28   if(args.size() < 1)
29     {
30     this->SetError("called with incorrect number of arguments");
31     return false;
32     }
33
34   // Lookup the target for which libraries are specified.
35   this->Target =
36     this->Makefile->GetCMakeInstance()
37     ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
38   if(!this->Target)
39     {
40     cmake::MessageType t = cmake::FATAL_ERROR;  // fail by default
41     cmOStringStream e;
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:
46     if (args.size() < 2)
47       {
48       switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016))
49         {
50         case cmPolicies::WARN:
51           t = cmake::AUTHOR_WARNING;
52           // Print the warning.
53           e << "\n"
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);
58            break;
59         case cmPolicies::OLD:          // OLD behavior does not warn.
60           t = cmake::MESSAGE;
61           break;
62         case cmPolicies::REQUIRED_IF_USED:
63         case cmPolicies::REQUIRED_ALWAYS:
64           e << "\n" << this->Makefile->GetPolicies()->
65                                   GetRequiredPolicyError(cmPolicies::CMP0016);
66           break;
67         case cmPolicies::NEW:  // NEW behavior prints the error.
68         default:
69           break;
70         }
71       }
72
73     // now actually print the message
74     switch(t)
75       {
76       case cmake::AUTHOR_WARNING:
77         this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
78         break;
79       case cmake::FATAL_ERROR:
80         this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
81         cmSystemTools::SetFatalErrorOccured();
82         break;
83       default:
84         break;
85       }
86     return true;
87     }
88
89   if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
90     {
91     cmOStringStream e;
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();
96     return true;
97     }
98
99   // but we might not have any libs after variable expansion
100   if(args.size() < 2)
101     {
102     return true;
103     }
104
105   // Keep track of link configuration specifiers.
106   cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
107   bool haveLLT = false;
108
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;
112
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)
116     {
117     if(args[i] == "LINK_INTERFACE_LIBRARIES")
118       {
119       this->CurrentProcessingState = ProcessingLinkInterface;
120       if(i != 1)
121         {
122         this->Makefile->IssueMessage(
123           cmake::FATAL_ERROR,
124           "The LINK_INTERFACE_LIBRARIES option must appear as the second "
125           "argument, just after the target name."
126           );
127         return true;
128         }
129       }
130     else if(args[i] == "LINK_PUBLIC")
131       {
132       if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
133         {
134         this->Makefile->IssueMessage(
135           cmake::FATAL_ERROR,
136           "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
137           "argument, just after the target name."
138           );
139         return true;
140         }
141       this->CurrentProcessingState = ProcessingPublicInterface;
142       }
143     else if(args[i] == "LINK_PRIVATE")
144       {
145       if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
146         {
147         this->Makefile->IssueMessage(
148           cmake::FATAL_ERROR,
149           "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
150           "argument, just after the target name."
151           );
152         return true;
153         }
154       this->CurrentProcessingState = ProcessingPrivateInterface;
155       }
156     else if(args[i] == "debug")
157       {
158       if(haveLLT)
159         {
160         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
161         }
162       llt = cmTarget::DEBUG;
163       haveLLT = true;
164       }
165     else if(args[i] == "optimized")
166       {
167       if(haveLLT)
168         {
169         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
170         }
171       llt = cmTarget::OPTIMIZED;
172       haveLLT = true;
173       }
174     else if(args[i] == "general")
175       {
176       if(haveLLT)
177         {
178         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
179         }
180       llt = cmTarget::GENERAL;
181       haveLLT = true;
182       }
183     else if(haveLLT)
184       {
185       // The link type was specified by the previous argument.
186       haveLLT = false;
187       this->HandleLibrary(args[i].c_str(), llt);
188       }
189     else
190       {
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() );
202       if(linkTypeString)
203         {
204         if(strcmp(linkTypeString, "debug") == 0)
205           {
206           llt = cmTarget::DEBUG;
207           }
208         if(strcmp(linkTypeString, "optimized") == 0)
209           {
210           llt = cmTarget::OPTIMIZED;
211           }
212         }
213       this->HandleLibrary(args[i].c_str(), llt);
214       }
215     }
216
217   // Make sure the last argument was not a library type specifier.
218   if(haveLLT)
219     {
220     cmOStringStream e;
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();
225     }
226
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"))
234     {
235     this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
236     }
237
238   return true;
239 }
240
241 //----------------------------------------------------------------------------
242 void
243 cmTargetLinkLibrariesCommand
244 ::LinkLibraryTypeSpecifierWarning(int left, int right)
245 {
246   cmOStringStream w;
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());
252 }
253
254 //----------------------------------------------------------------------------
255 void
256 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
257                                             cmTarget::LinkLibraryType llt)
258 {
259   // Handle normal case first.
260   if(this->CurrentProcessingState != ProcessingLinkInterface)
261     {
262     this->Makefile
263       ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
264     if (this->CurrentProcessingState != ProcessingPublicInterface)
265       {
266       // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
267       return;
268       }
269     }
270
271   // Get the list of configurations considered to be DEBUG.
272   std::vector<std::string> const& debugConfigs =
273     this->Makefile->GetCMakeInstance()->GetDebugConfigs();
274   std::string prop;
275
276   // Include this library in the link interface for the target.
277   if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
278     {
279     // Put in the DEBUG configuration interfaces.
280     for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
281         i != debugConfigs.end(); ++i)
282       {
283       prop = "LINK_INTERFACE_LIBRARIES_";
284       prop += *i;
285       this->Target->AppendProperty(prop.c_str(), lib);
286       }
287     }
288   if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
289     {
290     // Put in the non-DEBUG configuration interfaces.
291     this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
292
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)
297       {
298       prop = "LINK_INTERFACE_LIBRARIES_";
299       prop += *i;
300       if(!this->Target->GetProperty(prop.c_str()))
301         {
302         this->Target->SetProperty(prop.c_str(), "");
303         }
304       }
305     }
306 }