Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmAddLibraryCommand.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 "cmAddLibraryCommand.h"
13
14 #include "cmake.h"
15
16 // cmLibraryCommand
17 bool cmAddLibraryCommand
18 ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
19 {
20   if(args.size() < 1 )
21     {
22     this->SetError("called with incorrect number of arguments");
23     return false;
24     }
25   // Library type defaults to value of BUILD_SHARED_LIBS, if it exists,
26   // otherwise it defaults to static library.
27   cmTarget::TargetType type = cmTarget::SHARED_LIBRARY;
28   if (cmSystemTools::IsOff(this->Makefile->GetDefinition("BUILD_SHARED_LIBS")))
29     {
30     type = cmTarget::STATIC_LIBRARY;
31     }
32   bool excludeFromAll = false;
33   bool importTarget = false;
34   bool importGlobal = false;
35
36   std::vector<std::string>::const_iterator s = args.begin();
37
38   std::string libName = *s;
39
40   ++s;
41
42   // If the second argument is "SHARED" or "STATIC", then it controls
43   // the type of library.  Otherwise, it is treated as a source or
44   // source list name. There may be two keyword arguments, check for them
45   bool haveSpecifiedType = false;
46   bool isAlias = false;
47   while ( s != args.end() )
48     {
49     std::string libType = *s;
50     if(libType == "STATIC")
51       {
52       ++s;
53       type = cmTarget::STATIC_LIBRARY;
54       haveSpecifiedType = true;
55       }
56     else if(libType == "SHARED")
57       {
58       ++s;
59       type = cmTarget::SHARED_LIBRARY;
60       haveSpecifiedType = true;
61       }
62     else if(libType == "MODULE")
63       {
64       ++s;
65       type = cmTarget::MODULE_LIBRARY;
66       haveSpecifiedType = true;
67       }
68     else if(libType == "OBJECT")
69       {
70       ++s;
71       type = cmTarget::OBJECT_LIBRARY;
72       haveSpecifiedType = true;
73       }
74     else if(libType == "UNKNOWN")
75       {
76       ++s;
77       type = cmTarget::UNKNOWN_LIBRARY;
78       haveSpecifiedType = true;
79       }
80     else if(libType == "ALIAS")
81       {
82       ++s;
83       isAlias = true;
84       }
85     else if(*s == "EXCLUDE_FROM_ALL")
86       {
87       ++s;
88       excludeFromAll = true;
89       }
90     else if(*s == "IMPORTED")
91       {
92       ++s;
93       importTarget = true;
94       }
95     else if(importTarget && *s == "GLOBAL")
96       {
97       ++s;
98       importGlobal = true;
99       }
100     else
101       {
102       break;
103       }
104     }
105   if (isAlias)
106     {
107     if(!cmGeneratorExpression::IsValidTargetName(libName.c_str()))
108       {
109       this->SetError(("Invalid name for ALIAS: " + libName).c_str());
110       return false;
111       }
112     if(excludeFromAll)
113       {
114       this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
115       return false;
116       }
117     if(importTarget || importGlobal)
118       {
119       this->SetError("IMPORTED with ALIAS is not allowed.");
120       return false;
121       }
122     if(args.size() != 3)
123       {
124       cmOStringStream e;
125       e << "ALIAS requires exactly one target argument.";
126       this->SetError(e.str().c_str());
127       return false;
128       }
129
130     const char *aliasedName = s->c_str();
131     if(this->Makefile->IsAlias(aliasedName))
132       {
133       cmOStringStream e;
134       e << "cannot create ALIAS target \"" << libName
135         << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
136       this->SetError(e.str().c_str());
137       return false;
138       }
139     cmTarget *aliasedTarget =
140                     this->Makefile->FindTargetToUse(aliasedName, true);
141     if(!aliasedTarget)
142       {
143       cmOStringStream e;
144       e << "cannot create ALIAS target \"" << libName
145         << "\" because target \"" << aliasedName << "\" does not already "
146         "exist.";
147       this->SetError(e.str().c_str());
148       return false;
149       }
150     cmTarget::TargetType aliasedType = aliasedTarget->GetType();
151     if(aliasedType != cmTarget::SHARED_LIBRARY
152         && aliasedType != cmTarget::STATIC_LIBRARY
153         && aliasedType != cmTarget::MODULE_LIBRARY
154         && aliasedType != cmTarget::OBJECT_LIBRARY)
155       {
156       cmOStringStream e;
157       e << "cannot create ALIAS target \"" << libName
158         << "\" because target \"" << aliasedName << "\" is not a library.";
159       this->SetError(e.str().c_str());
160       return false;
161       }
162     if(aliasedTarget->IsImported())
163       {
164       cmOStringStream e;
165       e << "cannot create ALIAS target \"" << libName
166         << "\" because target \"" << aliasedName << "\" is IMPORTED.";
167       this->SetError(e.str().c_str());
168       return false;
169       }
170     this->Makefile->AddAlias(libName.c_str(), aliasedTarget);
171     return true;
172     }
173
174   if(importTarget && excludeFromAll)
175     {
176     this->SetError("excludeFromAll with IMPORTED target makes no sense.");
177     return false;
178     }
179
180   /* ideally we should check whether for the linker language of the target
181     CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
182     STATIC. But at this point we know only the name of the target, but not
183     yet its linker language. */
184   if ((type != cmTarget::STATIC_LIBRARY) &&
185       (type != cmTarget::OBJECT_LIBRARY) &&
186        (this->Makefile->GetCMakeInstance()->GetPropertyAsBool(
187                                       "TARGET_SUPPORTS_SHARED_LIBS") == false))
188     {
189     cmOStringStream w;
190     w <<
191       "ADD_LIBRARY called with " <<
192       (type==cmTarget::SHARED_LIBRARY ? "SHARED" : "MODULE") <<
193       " option but the target platform does not support dynamic linking. "
194       "Building a STATIC library instead. This may lead to problems.";
195     this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
196     type = cmTarget::STATIC_LIBRARY;
197     }
198
199   // Handle imported target creation.
200   if(importTarget)
201     {
202     // The IMPORTED signature requires a type to be specified explicitly.
203     if (!haveSpecifiedType)
204       {
205       this->SetError("called with IMPORTED argument but no library type.");
206       return false;
207       }
208     if(type == cmTarget::OBJECT_LIBRARY)
209       {
210       this->Makefile->IssueMessage(
211         cmake::FATAL_ERROR,
212         "The OBJECT library type may not be used for IMPORTED libraries."
213         );
214       return true;
215       }
216
217     // Make sure the target does not already exist.
218     if(this->Makefile->FindTargetToUse(libName.c_str()))
219       {
220       cmOStringStream e;
221       e << "cannot create imported target \"" << libName
222         << "\" because another target with the same name already exists.";
223       this->SetError(e.str().c_str());
224       return false;
225       }
226
227     // Create the imported target.
228     this->Makefile->AddImportedTarget(libName.c_str(), type, importGlobal);
229     return true;
230     }
231
232   // A non-imported target may not have UNKNOWN type.
233   if(type == cmTarget::UNKNOWN_LIBRARY)
234     {
235     this->Makefile->IssueMessage(
236       cmake::FATAL_ERROR,
237       "The UNKNOWN library type may be used only for IMPORTED libraries."
238       );
239     return true;
240     }
241
242   // Enforce name uniqueness.
243   {
244   std::string msg;
245   if(!this->Makefile->EnforceUniqueName(libName, msg))
246     {
247     this->SetError(msg.c_str());
248     return false;
249     }
250   }
251
252   if (s == args.end())
253     {
254     std::string msg = "You have called ADD_LIBRARY for library ";
255     msg += args[0];
256     msg += " without any source files. This typically indicates a problem ";
257     msg += "with your CMakeLists.txt file";
258     cmSystemTools::Message(msg.c_str() ,"Warning");
259     }
260
261   std::vector<std::string> srclists;
262   while (s != args.end())
263     {
264     srclists.push_back(*s);
265     ++s;
266     }
267
268   this->Makefile->AddLibrary(libName.c_str(), type, srclists, excludeFromAll);
269
270   return true;
271 }
272
273