1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
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"
15 #include "cmMakefile.h"
16 #include "cmLocalGenerator.h"
17 #include "cmGlobalGenerator.h"
18 #include "cmSourceFile.h"
19 #include "cmGeneratorExpression.h"
20 #include "cmGeneratorExpressionDAGChecker.h"
22 //----------------------------------------------------------------------------
23 cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
25 this->Makefile = this->Target->GetMakefile();
26 this->LocalGenerator = this->Makefile->GetLocalGenerator();
27 this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
28 this->ClassifySources();
29 this->LookupObjectLibraries();
32 //----------------------------------------------------------------------------
33 int cmGeneratorTarget::GetType() const
35 return this->Target->GetType();
38 //----------------------------------------------------------------------------
39 const char *cmGeneratorTarget::GetName() const
41 return this->Target->GetName();
44 //----------------------------------------------------------------------------
45 const char *cmGeneratorTarget::GetProperty(const char *prop)
47 return this->Target->GetProperty(prop);
50 //----------------------------------------------------------------------------
51 bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
54 std::string config_upper;
57 config_upper = cmSystemTools::UpperCase(config);
60 typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
61 IncludeCacheType::iterator iter =
62 this->SystemIncludesCache.find(config_upper);
64 if (iter == this->SystemIncludesCache.end())
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)
71 cmListFileBacktrace lfbt;
72 cmGeneratorExpression ge(lfbt);
74 cmGeneratorExpressionDAGChecker dagChecker(lfbt,
76 "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
78 cmSystemTools::ExpandListArgument(ge.Parse(*it)
79 ->Evaluate(this->Makefile,
80 config, false, this->Target,
81 &dagChecker), result);
83 for(std::vector<std::string>::iterator li = result.begin();
84 li != result.end(); ++li)
86 cmSystemTools::ConvertToUnixSlashes(*li);
89 IncludeCacheType::value_type entry(config_upper, result);
90 iter = this->SystemIncludesCache.insert(entry).first;
93 if (std::find(iter->second.begin(),
94 iter->second.end(), dir) != iter->second.end())
101 //----------------------------------------------------------------------------
102 bool cmGeneratorTarget::GetPropertyAsBool(const char *prop)
104 return this->Target->GetPropertyAsBool(prop);
107 //----------------------------------------------------------------------------
108 std::vector<cmSourceFile*> const& cmGeneratorTarget::GetSourceFiles()
110 return this->Target->GetSourceFiles();
113 //----------------------------------------------------------------------------
114 void cmGeneratorTarget::ClassifySources()
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)
123 cmSourceFile* sf = *si;
124 std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
125 if(sf->GetCustomCommand())
127 this->CustomCommands.push_back(sf);
129 else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
131 this->HeaderSources.push_back(sf);
133 else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
135 this->ExternalObjects.push_back(sf);
136 if(isObjLib) { badObjLib.push_back(sf); }
138 else if(sf->GetLanguage())
140 this->ObjectSources.push_back(sf);
142 else if(ext == "def")
144 this->ModuleDefinitionFile = sf->GetFullPath();
145 if(isObjLib) { badObjLib.push_back(sf); }
147 else if(ext == "idl")
149 this->IDLSources.push_back(sf);
150 if(isObjLib) { badObjLib.push_back(sf); }
152 else if(ext == "resx")
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);
164 else if(header.find(sf->GetFullPath().c_str()))
166 this->HeaderSources.push_back(sf);
168 else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
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);
177 this->ExtraSources.push_back(sf);
178 if(isObjLib && ext != "txt")
180 badObjLib.push_back(sf);
185 if(!badObjLib.empty())
188 e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n";
189 for(std::vector<cmSourceFile*>::iterator i = badObjLib.begin();
190 i != badObjLib.end(); ++i)
192 e << " " << (*i)->GetLocation().GetName() << "\n";
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());
201 //----------------------------------------------------------------------------
202 void cmGeneratorTarget::LookupObjectLibraries()
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)
209 std::string const& objLibName = *oli;
210 if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str()))
212 if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
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)
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());
226 this->Target->AddUtility(objLib->GetName());
227 this->ObjectLibraries.push_back(objLib);
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());
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());
253 //----------------------------------------------------------------------------
254 void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
256 for(std::vector<cmTarget*>::const_iterator
257 ti = this->ObjectLibraries.begin();
258 ti != this->ObjectLibraries.end(); ++ti)
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)
267 std::string obj = ogt->ObjectDirectory;
268 obj += ogt->Objects[*si];
274 //----------------------------------------------------------------------------
275 void cmGeneratorTarget::GetAppleArchs(const char* config,
276 std::vector<std::string>& archVec)
278 const char* archs = 0;
279 if(config && *config)
281 std::string defVarName = "OSX_ARCHITECTURES_";
282 defVarName += cmSystemTools::UpperCase(config);
283 archs = this->Target->GetProperty(defVarName.c_str());
287 archs = this->Target->GetProperty("OSX_ARCHITECTURES");
291 cmSystemTools::ExpandListArgument(std::string(archs), archVec);
295 //----------------------------------------------------------------------------
296 const char* cmGeneratorTarget::GetCreateRuleVariable()
298 switch(this->GetType())
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";
314 //----------------------------------------------------------------------------
315 std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
318 return this->Target->GetIncludeDirectories(config);