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