Imported Upstream version 2.8.12.2
[platform/upstream/cmake.git] / Source / cmGeneratorTarget.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2012 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 "cmGeneratorTarget.h"
13
14 #include "cmTarget.h"
15 #include "cmMakefile.h"
16 #include "cmLocalGenerator.h"
17 #include "cmGlobalGenerator.h"
18 #include "cmSourceFile.h"
19 #include "cmGeneratorExpression.h"
20 #include "cmGeneratorExpressionDAGChecker.h"
21
22 //----------------------------------------------------------------------------
23 cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
24 {
25   this->Makefile = this->Target->GetMakefile();
26   this->LocalGenerator = this->Makefile->GetLocalGenerator();
27   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
28   this->ClassifySources();
29   this->LookupObjectLibraries();
30 }
31
32 //----------------------------------------------------------------------------
33 int cmGeneratorTarget::GetType() const
34 {
35   return this->Target->GetType();
36 }
37
38 //----------------------------------------------------------------------------
39 const char *cmGeneratorTarget::GetName() const
40 {
41   return this->Target->GetName();
42 }
43
44 //----------------------------------------------------------------------------
45 const char *cmGeneratorTarget::GetProperty(const char *prop)
46 {
47   return this->Target->GetProperty(prop);
48 }
49
50 //----------------------------------------------------------------------------
51 bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
52                                                  const char *config)
53 {
54   std::string config_upper;
55   if(config && *config)
56     {
57     config_upper = cmSystemTools::UpperCase(config);
58     }
59
60   typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
61   IncludeCacheType::iterator iter =
62       this->SystemIncludesCache.find(config_upper);
63
64   if (iter == this->SystemIncludesCache.end())
65     {
66     std::vector<std::string> result;
67     for (std::set<cmStdString>::const_iterator
68         it = this->Target->GetSystemIncludeDirectories().begin();
69         it != this->Target->GetSystemIncludeDirectories().end(); ++it)
70       {
71       cmListFileBacktrace lfbt;
72       cmGeneratorExpression ge(lfbt);
73
74       cmGeneratorExpressionDAGChecker dagChecker(lfbt,
75                                                 this->GetName(),
76                                 "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
77
78       cmSystemTools::ExpandListArgument(ge.Parse(*it)
79                                         ->Evaluate(this->Makefile,
80                                         config, false, this->Target,
81                                         &dagChecker), result);
82       }
83     for(std::vector<std::string>::iterator li = result.begin();
84         li != result.end(); ++li)
85       {
86       cmSystemTools::ConvertToUnixSlashes(*li);
87       }
88
89     IncludeCacheType::value_type entry(config_upper, result);
90     iter = this->SystemIncludesCache.insert(entry).first;
91     }
92
93   if (std::find(iter->second.begin(),
94                 iter->second.end(), dir) != iter->second.end())
95     {
96     return true;
97     }
98   return false;
99 }
100
101 //----------------------------------------------------------------------------
102 bool cmGeneratorTarget::GetPropertyAsBool(const char *prop)
103 {
104   return this->Target->GetPropertyAsBool(prop);
105 }
106
107 //----------------------------------------------------------------------------
108 std::vector<cmSourceFile*> const& cmGeneratorTarget::GetSourceFiles()
109 {
110   return this->Target->GetSourceFiles();
111 }
112
113 //----------------------------------------------------------------------------
114 void cmGeneratorTarget::ClassifySources()
115 {
116   cmsys::RegularExpression header(CM_HEADER_REGEX);
117   bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY;
118   std::vector<cmSourceFile*> badObjLib;
119   std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
120   for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
121       si != sources.end(); ++si)
122     {
123     cmSourceFile* sf = *si;
124     std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
125     if(sf->GetCustomCommand())
126       {
127       this->CustomCommands.push_back(sf);
128       }
129     else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
130       {
131       this->HeaderSources.push_back(sf);
132       }
133     else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
134       {
135       this->ExternalObjects.push_back(sf);
136       if(isObjLib) { badObjLib.push_back(sf); }
137       }
138     else if(sf->GetLanguage())
139       {
140       this->ObjectSources.push_back(sf);
141       }
142     else if(ext == "def")
143       {
144       this->ModuleDefinitionFile = sf->GetFullPath();
145       if(isObjLib) { badObjLib.push_back(sf); }
146       }
147     else if(ext == "idl")
148       {
149       this->IDLSources.push_back(sf);
150       if(isObjLib) { badObjLib.push_back(sf); }
151       }
152     else if(ext == "resx")
153       {
154       // Build and save the name of the corresponding .h file
155       // This relationship will be used later when building the project files.
156       // Both names would have been auto generated from Visual Studio
157       // where the user supplied the file name and Visual Studio
158       // appended the suffix.
159       std::string resx = sf->GetFullPath();
160       std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h";
161       this->ExpectedResxHeaders.insert(hFileName);
162       this->ResxSources.push_back(sf);
163       }
164     else if(header.find(sf->GetFullPath().c_str()))
165       {
166       this->HeaderSources.push_back(sf);
167       }
168     else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
169       {
170       // We only get here if a source file is not an external object
171       // and has an extension that is listed as an ignored file type.
172       // No message or diagnosis should be given.
173       this->ExtraSources.push_back(sf);
174       }
175     else
176       {
177       this->ExtraSources.push_back(sf);
178       if(isObjLib && ext != "txt")
179         {
180         badObjLib.push_back(sf);
181         }
182       }
183     }
184
185   if(!badObjLib.empty())
186     {
187     cmOStringStream e;
188     e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n";
189     for(std::vector<cmSourceFile*>::iterator i = badObjLib.begin();
190         i != badObjLib.end(); ++i)
191       {
192       e << "  " << (*i)->GetLocation().GetName() << "\n";
193       }
194     e << "but may contain only headers and sources that compile.";
195     this->GlobalGenerator->GetCMakeInstance()
196       ->IssueMessage(cmake::FATAL_ERROR, e.str(),
197                      this->Target->GetBacktrace());
198     }
199 }
200
201 //----------------------------------------------------------------------------
202 void cmGeneratorTarget::LookupObjectLibraries()
203 {
204   std::vector<std::string> const& objLibs =
205     this->Target->GetObjectLibraries();
206   for(std::vector<std::string>::const_iterator oli = objLibs.begin();
207       oli != objLibs.end(); ++oli)
208     {
209     std::string const& objLibName = *oli;
210     if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str()))
211       {
212       if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
213         {
214         if(this->Target->GetType() != cmTarget::EXECUTABLE &&
215            this->Target->GetType() != cmTarget::STATIC_LIBRARY &&
216            this->Target->GetType() != cmTarget::SHARED_LIBRARY &&
217            this->Target->GetType() != cmTarget::MODULE_LIBRARY)
218           {
219           this->GlobalGenerator->GetCMakeInstance()
220             ->IssueMessage(cmake::FATAL_ERROR,
221                            "Only executables and non-OBJECT libraries may "
222                            "reference target objects.",
223                            this->Target->GetBacktrace());
224           return;
225           }
226         this->Target->AddUtility(objLib->GetName());
227         this->ObjectLibraries.push_back(objLib);
228         }
229       else
230         {
231         cmOStringStream e;
232         e << "Objects of target \"" << objLibName
233           << "\" referenced but is not an OBJECT library.";
234         this->GlobalGenerator->GetCMakeInstance()
235           ->IssueMessage(cmake::FATAL_ERROR, e.str(),
236                          this->Target->GetBacktrace());
237         return;
238         }
239       }
240     else
241       {
242       cmOStringStream e;
243       e << "Objects of target \"" << objLibName
244         << "\" referenced but no such target exists.";
245       this->GlobalGenerator->GetCMakeInstance()
246         ->IssueMessage(cmake::FATAL_ERROR, e.str(),
247                        this->Target->GetBacktrace());
248       return;
249       }
250     }
251 }
252
253 //----------------------------------------------------------------------------
254 void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
255 {
256   for(std::vector<cmTarget*>::const_iterator
257         ti = this->ObjectLibraries.begin();
258       ti != this->ObjectLibraries.end(); ++ti)
259     {
260     cmTarget* objLib = *ti;
261     cmGeneratorTarget* ogt =
262       this->GlobalGenerator->GetGeneratorTarget(objLib);
263     for(std::vector<cmSourceFile*>::const_iterator
264           si = ogt->ObjectSources.begin();
265         si != ogt->ObjectSources.end(); ++si)
266       {
267       std::string obj = ogt->ObjectDirectory;
268       obj += ogt->Objects[*si];
269       objs.push_back(obj);
270       }
271     }
272 }
273
274 //----------------------------------------------------------------------------
275 void cmGeneratorTarget::GetAppleArchs(const char* config,
276                              std::vector<std::string>& archVec)
277 {
278   const char* archs = 0;
279   if(config && *config)
280     {
281     std::string defVarName = "OSX_ARCHITECTURES_";
282     defVarName += cmSystemTools::UpperCase(config);
283     archs = this->Target->GetProperty(defVarName.c_str());
284     }
285   if(!archs)
286     {
287     archs = this->Target->GetProperty("OSX_ARCHITECTURES");
288     }
289   if(archs)
290     {
291     cmSystemTools::ExpandListArgument(std::string(archs), archVec);
292     }
293 }
294
295 //----------------------------------------------------------------------------
296 const char* cmGeneratorTarget::GetCreateRuleVariable()
297 {
298   switch(this->GetType())
299     {
300     case cmTarget::STATIC_LIBRARY:
301       return "_CREATE_STATIC_LIBRARY";
302     case cmTarget::SHARED_LIBRARY:
303       return "_CREATE_SHARED_LIBRARY";
304     case cmTarget::MODULE_LIBRARY:
305       return "_CREATE_SHARED_MODULE";
306     case cmTarget::EXECUTABLE:
307       return "_LINK_EXECUTABLE";
308     default:
309       break;
310     }
311   return "";
312 }
313
314 //----------------------------------------------------------------------------
315 std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
316                                                           const char *config)
317 {
318   return this->Target->GetIncludeDirectories(config);
319 }