Imported Upstream version 2.8.12.2
[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   if (this->Makefile->IsAlias(args[0].c_str()))
35     {
36     this->SetError("can not be used on an ALIAS target.");
37     return false;
38     }
39   // Lookup the target for which libraries are specified.
40   this->Target =
41     this->Makefile->GetCMakeInstance()
42     ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
43   if(!this->Target)
44     {
45     cmake::MessageType t = cmake::FATAL_ERROR;  // fail by default
46     cmOStringStream e;
47     e << "Cannot specify link libraries for target \"" << args[0] << "\" "
48       << "which is not built by this project.";
49     // The bad target is the only argument. Check how policy CMP0016 is set,
50     // and accept, warn or fail respectively:
51     if (args.size() < 2)
52       {
53       switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0016))
54         {
55         case cmPolicies::WARN:
56           t = cmake::AUTHOR_WARNING;
57           // Print the warning.
58           e << "\n"
59             << "CMake does not support this but it used to work accidentally "
60             << "and is being allowed for compatibility."
61             << "\n" << this->Makefile->GetPolicies()->
62                                         GetPolicyWarning(cmPolicies::CMP0016);
63            break;
64         case cmPolicies::OLD:          // OLD behavior does not warn.
65           t = cmake::MESSAGE;
66           break;
67         case cmPolicies::REQUIRED_IF_USED:
68         case cmPolicies::REQUIRED_ALWAYS:
69           e << "\n" << this->Makefile->GetPolicies()->
70                                   GetRequiredPolicyError(cmPolicies::CMP0016);
71           break;
72         case cmPolicies::NEW:  // NEW behavior prints the error.
73         default:
74           break;
75         }
76       }
77
78     // now actually print the message
79     switch(t)
80       {
81       case cmake::AUTHOR_WARNING:
82         this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
83         break;
84       case cmake::FATAL_ERROR:
85         this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
86         cmSystemTools::SetFatalErrorOccured();
87         break;
88       default:
89         break;
90       }
91     return true;
92     }
93
94   if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
95     {
96     cmOStringStream e;
97     e << "Object library target \"" << args[0] << "\" "
98       << "may not link to anything.";
99     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
100     cmSystemTools::SetFatalErrorOccured();
101     return true;
102     }
103
104   // but we might not have any libs after variable expansion
105   if(args.size() < 2)
106     {
107     return true;
108     }
109
110   // Keep track of link configuration specifiers.
111   cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
112   bool haveLLT = false;
113
114   // Start with primary linking and switch to link interface
115   // specification if the keyword is encountered as the first argument.
116   this->CurrentProcessingState = ProcessingLinkLibraries;
117
118   // add libraries, note that there is an optional prefix
119   // of debug and optimized that can be used
120   for(unsigned int i=1; i < args.size(); ++i)
121     {
122     if(args[i] == "LINK_INTERFACE_LIBRARIES")
123       {
124       this->CurrentProcessingState = ProcessingPlainLinkInterface;
125       if(i != 1)
126         {
127         this->Makefile->IssueMessage(
128           cmake::FATAL_ERROR,
129           "The LINK_INTERFACE_LIBRARIES option must appear as the second "
130           "argument, just after the target name."
131           );
132         return true;
133         }
134       }
135     else if(args[i] == "INTERFACE")
136       {
137       if(i != 1
138           && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
139           && this->CurrentProcessingState != ProcessingKeywordPublicInterface
140           && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
141         {
142         this->Makefile->IssueMessage(
143           cmake::FATAL_ERROR,
144           "The INTERFACE option must appear as the second "
145           "argument, just after the target name."
146           );
147         return true;
148         }
149       this->CurrentProcessingState = ProcessingKeywordLinkInterface;
150       }
151     else if(args[i] == "LINK_PUBLIC")
152       {
153       if(i != 1
154           && this->CurrentProcessingState != ProcessingPlainPrivateInterface)
155         {
156         this->Makefile->IssueMessage(
157           cmake::FATAL_ERROR,
158           "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
159           "argument, just after the target name."
160           );
161         return true;
162         }
163       this->CurrentProcessingState = ProcessingPlainPublicInterface;
164       }
165     else if(args[i] == "PUBLIC")
166       {
167       if(i != 1
168           && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
169           && this->CurrentProcessingState != ProcessingKeywordPublicInterface
170           && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
171         {
172         this->Makefile->IssueMessage(
173           cmake::FATAL_ERROR,
174           "The PUBLIC or PRIVATE option must appear as the second "
175           "argument, just after the target name."
176           );
177         return true;
178         }
179       this->CurrentProcessingState = ProcessingKeywordPublicInterface;
180       }
181     else if(args[i] == "LINK_PRIVATE")
182       {
183       if(i != 1
184           && this->CurrentProcessingState != ProcessingPlainPublicInterface)
185         {
186         this->Makefile->IssueMessage(
187           cmake::FATAL_ERROR,
188           "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second "
189           "argument, just after the target name."
190           );
191         return true;
192         }
193       this->CurrentProcessingState = ProcessingPlainPrivateInterface;
194       }
195     else if(args[i] == "PRIVATE")
196       {
197       if(i != 1
198           && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
199           && this->CurrentProcessingState != ProcessingKeywordPublicInterface
200           && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
201         {
202         this->Makefile->IssueMessage(
203           cmake::FATAL_ERROR,
204           "The PUBLIC or PRIVATE option must appear as the second "
205           "argument, just after the target name."
206           );
207         return true;
208         }
209       this->CurrentProcessingState = ProcessingKeywordPrivateInterface;
210       }
211     else if(args[i] == "debug")
212       {
213       if(haveLLT)
214         {
215         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::DEBUG);
216         }
217       llt = cmTarget::DEBUG;
218       haveLLT = true;
219       }
220     else if(args[i] == "optimized")
221       {
222       if(haveLLT)
223         {
224         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::OPTIMIZED);
225         }
226       llt = cmTarget::OPTIMIZED;
227       haveLLT = true;
228       }
229     else if(args[i] == "general")
230       {
231       if(haveLLT)
232         {
233         this->LinkLibraryTypeSpecifierWarning(llt, cmTarget::GENERAL);
234         }
235       llt = cmTarget::GENERAL;
236       haveLLT = true;
237       }
238     else if(haveLLT)
239       {
240       // The link type was specified by the previous argument.
241       haveLLT = false;
242       if (!this->HandleLibrary(args[i].c_str(), llt))
243         {
244         return false;
245         }
246       }
247     else
248       {
249       // Lookup old-style cache entry if type is unspecified.  So if you
250       // do a target_link_libraries(foo optimized bar) it will stay optimized
251       // and not use the lookup.  As there maybe the case where someone has
252       // specifed that a library is both debug and optimized.  (this check is
253       // only there for backwards compatibility when mixing projects built
254       // with old versions of CMake and new)
255       llt = cmTarget::GENERAL;
256       std::string linkType = args[0];
257       linkType += "_LINK_TYPE";
258       const char* linkTypeString =
259         this->Makefile->GetDefinition( linkType.c_str() );
260       if(linkTypeString)
261         {
262         if(strcmp(linkTypeString, "debug") == 0)
263           {
264           llt = cmTarget::DEBUG;
265           }
266         if(strcmp(linkTypeString, "optimized") == 0)
267           {
268           llt = cmTarget::OPTIMIZED;
269           }
270         }
271       if (!this->HandleLibrary(args[i].c_str(), llt))
272         {
273         return false;
274         }
275       }
276     }
277
278   // Make sure the last argument was not a library type specifier.
279   if(haveLLT)
280     {
281     cmOStringStream e;
282     e << "The \"" << this->LinkLibraryTypeNames[llt]
283       << "\" argument must be followed by a library.";
284     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
285     cmSystemTools::SetFatalErrorOccured();
286     }
287
288   const cmPolicies::PolicyStatus policy22Status
289                       = this->Target->GetPolicyStatusCMP0022();
290
291   // If any of the LINK_ options were given, make sure the
292   // LINK_INTERFACE_LIBRARIES target property exists.
293   // Use of any of the new keywords implies awareness of
294   // this property. And if no libraries are named, it should
295   // result in an empty link interface.
296   if((policy22Status == cmPolicies::OLD ||
297       policy22Status == cmPolicies::WARN) &&
298       this->CurrentProcessingState != ProcessingLinkLibraries &&
299      !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
300     {
301     this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
302     }
303
304   return true;
305 }
306
307 //----------------------------------------------------------------------------
308 void
309 cmTargetLinkLibrariesCommand
310 ::LinkLibraryTypeSpecifierWarning(int left, int right)
311 {
312   cmOStringStream w;
313   w << "Link library type specifier \""
314     << this->LinkLibraryTypeNames[left] << "\" is followed by specifier \""
315     << this->LinkLibraryTypeNames[right] << "\" instead of a library name.  "
316     << "The first specifier will be ignored.";
317   this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
318 }
319
320 //----------------------------------------------------------------------------
321 bool
322 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
323                                             cmTarget::LinkLibraryType llt)
324 {
325   cmTarget::TLLSignature sig =
326         (this->CurrentProcessingState == ProcessingPlainPrivateInterface
327       || this->CurrentProcessingState == ProcessingPlainPublicInterface
328       || this->CurrentProcessingState == ProcessingKeywordPrivateInterface
329       || this->CurrentProcessingState == ProcessingKeywordPublicInterface
330       || this->CurrentProcessingState == ProcessingKeywordLinkInterface)
331         ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature;
332   if (!this->Target->PushTLLCommandTrace(sig))
333     {
334     const char *modal = 0;
335     cmake::MessageType messageType = cmake::AUTHOR_WARNING;
336     switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023))
337       {
338       case cmPolicies::WARN:
339         modal = "should";
340       case cmPolicies::OLD:
341         break;
342       case cmPolicies::REQUIRED_ALWAYS:
343       case cmPolicies::REQUIRED_IF_USED:
344       case cmPolicies::NEW:
345         modal = "must";
346         messageType = cmake::FATAL_ERROR;
347       }
348
349       if(modal)
350         {
351         cmOStringStream e;
352         // If the sig is a keyword form and there is a conflict, the existing
353         // form must be the plain form.
354         const char *existingSig
355                     = (sig == cmTarget::KeywordTLLSignature ? "plain"
356                                                             : "keyword");
357         e << this->Makefile->GetPolicies()
358                               ->GetPolicyWarning(cmPolicies::CMP0023) << "\n"
359             "The " << existingSig << " signature for target_link_libraries "
360             "has already been used with the target \""
361           << this->Target->GetName() << "\".  All uses of "
362              "target_link_libraries with a target " << modal << " be either "
363              "all-keyword or all-plain.\n";
364         this->Target->GetTllSignatureTraces(e,
365                                           sig == cmTarget::KeywordTLLSignature
366                                             ? cmTarget::PlainTLLSignature
367                                             : cmTarget::KeywordTLLSignature);
368         this->Makefile->IssueMessage(messageType, e.str().c_str());
369         if(messageType == cmake::FATAL_ERROR)
370           {
371           return false;
372           }
373         }
374     }
375
376   // Handle normal case first.
377   if(this->CurrentProcessingState != ProcessingKeywordLinkInterface
378       && this->CurrentProcessingState != ProcessingPlainLinkInterface)
379     {
380     this->Makefile
381       ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
382     if(this->CurrentProcessingState == ProcessingLinkLibraries)
383       {
384       this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
385         this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
386       return true;
387       }
388     else if(this->CurrentProcessingState != ProcessingKeywordPublicInterface
389             && this->CurrentProcessingState != ProcessingPlainPublicInterface)
390       {
391       if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
392         {
393         std::string configLib = this->Target
394                                      ->GetDebugGeneratorExpressions(lib, llt);
395         if (cmGeneratorExpression::IsValidTargetName(lib)
396             || cmGeneratorExpression::Find(lib) != std::string::npos)
397           {
398           configLib = "$<LINK_ONLY:" + configLib + ">";
399           }
400         this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
401                                      configLib.c_str());
402         }
403       // Not a 'public' or 'interface' library. Do not add to interface
404       // property.
405       return true;
406       }
407     }
408
409   this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
410               this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
411
412   const cmPolicies::PolicyStatus policy22Status
413                       = this->Target->GetPolicyStatusCMP0022();
414
415   if (policy22Status != cmPolicies::OLD
416       && policy22Status != cmPolicies::WARN)
417     {
418     return true;
419     }
420
421   // Get the list of configurations considered to be DEBUG.
422   std::vector<std::string> const& debugConfigs =
423     this->Makefile->GetCMakeInstance()->GetDebugConfigs();
424   std::string prop;
425
426   // Include this library in the link interface for the target.
427   if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
428     {
429     // Put in the DEBUG configuration interfaces.
430     for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
431         i != debugConfigs.end(); ++i)
432       {
433       prop = "LINK_INTERFACE_LIBRARIES_";
434       prop += *i;
435       this->Target->AppendProperty(prop.c_str(), lib);
436       }
437     }
438   if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
439     {
440     // Put in the non-DEBUG configuration interfaces.
441     this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
442
443     // Make sure the DEBUG configuration interfaces exist so that the
444     // general one will not be used as a fall-back.
445     for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
446         i != debugConfigs.end(); ++i)
447       {
448       prop = "LINK_INTERFACE_LIBRARIES_";
449       prop += *i;
450       if(!this->Target->GetProperty(prop.c_str()))
451         {
452         this->Target->SetProperty(prop.c_str(), "");
453         }
454       }
455     }
456   return true;
457 }