cmGeneratorTarget.cxx 12 KB

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