cmGeneratorTarget.cxx 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  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. #include "cmComputeLinkInformation.h"
  19. #include "cmCustomCommandGenerator.h"
  20. #include "cmAlgorithms.h"
  21. #include <queue>
  22. #include "assert.h"
  23. //----------------------------------------------------------------------------
  24. void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib,
  25. cmTarget *target, cmake *cm)
  26. {
  27. if(!badObjLib.empty())
  28. {
  29. std::ostringstream e;
  30. e << "OBJECT library \"" << target->GetName() << "\" contains:\n";
  31. for(std::vector<cmSourceFile*>::const_iterator i = badObjLib.begin();
  32. i != badObjLib.end(); ++i)
  33. {
  34. e << " " << (*i)->GetLocation().GetName() << "\n";
  35. }
  36. e << "but may contain only sources that compile, header files, and "
  37. "other files that would not affect linking of a normal library.";
  38. cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
  39. target->GetBacktrace());
  40. }
  41. }
  42. struct ObjectSourcesTag {};
  43. struct CustomCommandsTag {};
  44. struct ExtraSourcesTag {};
  45. struct HeaderSourcesTag {};
  46. struct ExternalObjectsTag {};
  47. struct IDLSourcesTag {};
  48. struct ResxTag {};
  49. struct ModuleDefinitionFileTag {};
  50. struct AppManifestTag{};
  51. struct CertificatesTag{};
  52. struct XamlTag{};
  53. template<typename Tag, typename OtherTag>
  54. struct IsSameTag
  55. {
  56. enum {
  57. Result = false
  58. };
  59. };
  60. template<typename Tag>
  61. struct IsSameTag<Tag, Tag>
  62. {
  63. enum {
  64. Result = true
  65. };
  66. };
  67. template<bool>
  68. struct DoAccept
  69. {
  70. template <typename T> static void Do(T&, cmSourceFile*) {}
  71. };
  72. template<>
  73. struct DoAccept<true>
  74. {
  75. static void Do(std::vector<cmSourceFile const*>& files, cmSourceFile* f)
  76. {
  77. files.push_back(f);
  78. }
  79. static void Do(cmGeneratorTarget::ResxData& data, cmSourceFile* f)
  80. {
  81. // Build and save the name of the corresponding .h file
  82. // This relationship will be used later when building the project files.
  83. // Both names would have been auto generated from Visual Studio
  84. // where the user supplied the file name and Visual Studio
  85. // appended the suffix.
  86. std::string resx = f->GetFullPath();
  87. std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h";
  88. data.ExpectedResxHeaders.insert(hFileName);
  89. data.ResxSources.push_back(f);
  90. }
  91. static void Do(cmGeneratorTarget::XamlData& data, cmSourceFile* f)
  92. {
  93. // Build and save the name of the corresponding .h and .cpp file
  94. // This relationship will be used later when building the project files.
  95. // Both names would have been auto generated from Visual Studio
  96. // where the user supplied the file name and Visual Studio
  97. // appended the suffix.
  98. std::string xaml = f->GetFullPath();
  99. std::string hFileName = xaml + ".h";
  100. std::string cppFileName = xaml + ".cpp";
  101. data.ExpectedXamlHeaders.insert(hFileName);
  102. data.ExpectedXamlSources.insert(cppFileName);
  103. data.XamlSources.push_back(f);
  104. }
  105. static void Do(std::string& data, cmSourceFile* f)
  106. {
  107. data = f->GetFullPath();
  108. }
  109. };
  110. //----------------------------------------------------------------------------
  111. template<typename Tag, typename DataType = std::vector<cmSourceFile const*> >
  112. struct TagVisitor
  113. {
  114. DataType& Data;
  115. std::vector<cmSourceFile*> BadObjLibFiles;
  116. cmTarget *Target;
  117. cmGlobalGenerator *GlobalGenerator;
  118. cmsys::RegularExpression Header;
  119. bool IsObjLib;
  120. TagVisitor(cmTarget *target, DataType& data)
  121. : Data(data), Target(target),
  122. GlobalGenerator(target->GetMakefile()->GetGlobalGenerator()),
  123. Header(CM_HEADER_REGEX),
  124. IsObjLib(target->GetType() == cmTarget::OBJECT_LIBRARY)
  125. {
  126. }
  127. ~TagVisitor()
  128. {
  129. reportBadObjLib(this->BadObjLibFiles, this->Target,
  130. this->GlobalGenerator->GetCMakeInstance());
  131. }
  132. void Accept(cmSourceFile *sf)
  133. {
  134. std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
  135. if(sf->GetCustomCommand())
  136. {
  137. DoAccept<IsSameTag<Tag, CustomCommandsTag>::Result>::Do(this->Data, sf);
  138. }
  139. else if(this->Target->GetType() == cmTarget::UTILITY)
  140. {
  141. DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
  142. }
  143. else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
  144. {
  145. DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
  146. }
  147. else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
  148. {
  149. DoAccept<IsSameTag<Tag, ExternalObjectsTag>::Result>::Do(this->Data, sf);
  150. if(this->IsObjLib)
  151. {
  152. this->BadObjLibFiles.push_back(sf);
  153. }
  154. }
  155. else if(!sf->GetLanguage().empty())
  156. {
  157. DoAccept<IsSameTag<Tag, ObjectSourcesTag>::Result>::Do(this->Data, sf);
  158. }
  159. else if(ext == "def")
  160. {
  161. DoAccept<IsSameTag<Tag, ModuleDefinitionFileTag>::Result>::Do(this->Data,
  162. sf);
  163. if(this->IsObjLib)
  164. {
  165. this->BadObjLibFiles.push_back(sf);
  166. }
  167. }
  168. else if(ext == "idl")
  169. {
  170. DoAccept<IsSameTag<Tag, IDLSourcesTag>::Result>::Do(this->Data, sf);
  171. if(this->IsObjLib)
  172. {
  173. this->BadObjLibFiles.push_back(sf);
  174. }
  175. }
  176. else if(ext == "resx")
  177. {
  178. DoAccept<IsSameTag<Tag, ResxTag>::Result>::Do(this->Data, sf);
  179. }
  180. else if (ext == "appxmanifest")
  181. {
  182. DoAccept<IsSameTag<Tag, AppManifestTag>::Result>::Do(this->Data, sf);
  183. }
  184. else if (ext == "pfx")
  185. {
  186. DoAccept<IsSameTag<Tag, CertificatesTag>::Result>::Do(this->Data, sf);
  187. }
  188. else if (ext == "xaml")
  189. {
  190. DoAccept<IsSameTag<Tag, XamlTag>::Result>::Do(this->Data, sf);
  191. }
  192. else if(this->Header.find(sf->GetFullPath().c_str()))
  193. {
  194. DoAccept<IsSameTag<Tag, HeaderSourcesTag>::Result>::Do(this->Data, sf);
  195. }
  196. else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
  197. {
  198. DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
  199. }
  200. else
  201. {
  202. DoAccept<IsSameTag<Tag, ExtraSourcesTag>::Result>::Do(this->Data, sf);
  203. }
  204. }
  205. };
  206. //----------------------------------------------------------------------------
  207. cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
  208. : Target(t),
  209. SourceFileFlagsConstructed(false)
  210. {
  211. this->Makefile = this->Target->GetMakefile();
  212. this->LocalGenerator = lg;
  213. this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
  214. }
  215. cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
  216. {
  217. return this->LocalGenerator;
  218. }
  219. //----------------------------------------------------------------------------
  220. int cmGeneratorTarget::GetType() const
  221. {
  222. return this->Target->GetType();
  223. }
  224. //----------------------------------------------------------------------------
  225. std::string cmGeneratorTarget::GetName() const
  226. {
  227. return this->Target->GetName();
  228. }
  229. //----------------------------------------------------------------------------
  230. const char *cmGeneratorTarget::GetProperty(const std::string& prop) const
  231. {
  232. return this->Target->GetProperty(prop);
  233. }
  234. //----------------------------------------------------------------------------
  235. std::vector<cmSourceFile*> const*
  236. cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const
  237. {
  238. SourceEntriesType::const_iterator i = this->SourceEntries.find(sf);
  239. if(i != this->SourceEntries.end())
  240. {
  241. return &i->second.Depends;
  242. }
  243. return 0;
  244. }
  245. static void handleSystemIncludesDep(cmMakefile *mf, cmTarget const* depTgt,
  246. const std::string& config,
  247. cmTarget *headTarget,
  248. cmGeneratorExpressionDAGChecker *dagChecker,
  249. std::vector<std::string>& result,
  250. bool excludeImported)
  251. {
  252. if (const char* dirs =
  253. depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"))
  254. {
  255. cmGeneratorExpression ge;
  256. cmSystemTools::ExpandListArgument(ge.Parse(dirs)
  257. ->Evaluate(mf,
  258. config, false, headTarget,
  259. depTgt, dagChecker), result);
  260. }
  261. if (!depTgt->IsImported() || excludeImported)
  262. {
  263. return;
  264. }
  265. if (const char* dirs =
  266. depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES"))
  267. {
  268. cmGeneratorExpression ge;
  269. cmSystemTools::ExpandListArgument(ge.Parse(dirs)
  270. ->Evaluate(mf,
  271. config, false, headTarget,
  272. depTgt, dagChecker), result);
  273. }
  274. }
  275. #define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \
  276. { \
  277. std::vector<cmSourceFile*> sourceFiles; \
  278. this->Target->GetSourceFiles(sourceFiles, config); \
  279. TagVisitor<DATA ## Tag DATATYPE> visitor(this->Target, data); \
  280. for(std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \
  281. si != sourceFiles.end(); ++si) \
  282. { \
  283. visitor.Accept(*si); \
  284. } \
  285. } \
  286. #define IMPLEMENT_VISIT(DATA) \
  287. IMPLEMENT_VISIT_IMPL(DATA, EMPTY) \
  288. #define EMPTY
  289. #define COMMA ,
  290. //----------------------------------------------------------------------------
  291. void
  292. cmGeneratorTarget
  293. ::GetObjectSources(std::vector<cmSourceFile const*> &data,
  294. const std::string& config) const
  295. {
  296. IMPLEMENT_VISIT(ObjectSources);
  297. if (!this->Objects.empty())
  298. {
  299. return;
  300. }
  301. for(std::vector<cmSourceFile const*>::const_iterator it = data.begin();
  302. it != data.end(); ++it)
  303. {
  304. this->Objects[*it];
  305. }
  306. this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
  307. }
  308. void cmGeneratorTarget::ComputeObjectMapping()
  309. {
  310. if(!this->Objects.empty())
  311. {
  312. return;
  313. }
  314. std::vector<std::string> configs;
  315. this->Makefile->GetConfigurations(configs);
  316. if (configs.empty())
  317. {
  318. configs.push_back("");
  319. }
  320. for(std::vector<std::string>::const_iterator ci = configs.begin();
  321. ci != configs.end(); ++ci)
  322. {
  323. std::vector<cmSourceFile const*> sourceFiles;
  324. this->GetObjectSources(sourceFiles, *ci);
  325. }
  326. }
  327. //----------------------------------------------------------------------------
  328. const char* cmGeneratorTarget::GetFeature(const std::string& feature,
  329. const std::string& config) const
  330. {
  331. if(!config.empty())
  332. {
  333. std::string featureConfig = feature;
  334. featureConfig += "_";
  335. featureConfig += cmSystemTools::UpperCase(config);
  336. if(const char* value = this->Target->GetProperty(featureConfig))
  337. {
  338. return value;
  339. }
  340. }
  341. if(const char* value = this->Target->GetProperty(feature))
  342. {
  343. return value;
  344. }
  345. return this->LocalGenerator->GetFeature(feature, config);
  346. }
  347. //----------------------------------------------------------------------------
  348. bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature,
  349. const std::string& config) const
  350. {
  351. return cmSystemTools::IsOn(this->GetFeature(feature, config));
  352. }
  353. //----------------------------------------------------------------------------
  354. const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
  355. {
  356. this->ComputeObjectMapping();
  357. return this->Objects[file];
  358. }
  359. //----------------------------------------------------------------------------
  360. void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
  361. {
  362. this->ExplicitObjectName.insert(sf);
  363. }
  364. //----------------------------------------------------------------------------
  365. bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
  366. {
  367. const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
  368. std::set<cmSourceFile const*>::const_iterator it
  369. = this->ExplicitObjectName.find(file);
  370. return it != this->ExplicitObjectName.end();
  371. }
  372. //----------------------------------------------------------------------------
  373. void cmGeneratorTarget
  374. ::GetIDLSources(std::vector<cmSourceFile const*>& data,
  375. const std::string& config) const
  376. {
  377. IMPLEMENT_VISIT(IDLSources);
  378. }
  379. //----------------------------------------------------------------------------
  380. void
  381. cmGeneratorTarget
  382. ::GetHeaderSources(std::vector<cmSourceFile const*>& data,
  383. const std::string& config) const
  384. {
  385. IMPLEMENT_VISIT(HeaderSources);
  386. }
  387. //----------------------------------------------------------------------------
  388. void cmGeneratorTarget
  389. ::GetExtraSources(std::vector<cmSourceFile const*>& data,
  390. const std::string& config) const
  391. {
  392. IMPLEMENT_VISIT(ExtraSources);
  393. }
  394. //----------------------------------------------------------------------------
  395. void
  396. cmGeneratorTarget
  397. ::GetCustomCommands(std::vector<cmSourceFile const*>& data,
  398. const std::string& config) const
  399. {
  400. IMPLEMENT_VISIT(CustomCommands);
  401. }
  402. //----------------------------------------------------------------------------
  403. void
  404. cmGeneratorTarget
  405. ::GetExternalObjects(std::vector<cmSourceFile const*>& data,
  406. const std::string& config) const
  407. {
  408. IMPLEMENT_VISIT(ExternalObjects);
  409. }
  410. //----------------------------------------------------------------------------
  411. void
  412. cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs,
  413. const std::string& config) const
  414. {
  415. ResxData data;
  416. IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  417. srcs = data.ExpectedResxHeaders;
  418. }
  419. //----------------------------------------------------------------------------
  420. void cmGeneratorTarget
  421. ::GetResxSources(std::vector<cmSourceFile const*>& srcs,
  422. const std::string& config) const
  423. {
  424. ResxData data;
  425. IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  426. srcs = data.ResxSources;
  427. }
  428. //----------------------------------------------------------------------------
  429. void
  430. cmGeneratorTarget
  431. ::GetAppManifest(std::vector<cmSourceFile const*>& data,
  432. const std::string& config) const
  433. {
  434. IMPLEMENT_VISIT(AppManifest);
  435. }
  436. //----------------------------------------------------------------------------
  437. void
  438. cmGeneratorTarget
  439. ::GetCertificates(std::vector<cmSourceFile const*>& data,
  440. const std::string& config) const
  441. {
  442. IMPLEMENT_VISIT(Certificates);
  443. }
  444. //----------------------------------------------------------------------------
  445. void
  446. cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
  447. const std::string& config) const
  448. {
  449. XamlData data;
  450. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  451. headers = data.ExpectedXamlHeaders;
  452. }
  453. //----------------------------------------------------------------------------
  454. void
  455. cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
  456. const std::string& config) const
  457. {
  458. XamlData data;
  459. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  460. srcs = data.ExpectedXamlSources;
  461. }
  462. //----------------------------------------------------------------------------
  463. void cmGeneratorTarget
  464. ::GetXamlSources(std::vector<cmSourceFile const*>& srcs,
  465. const std::string& config) const
  466. {
  467. XamlData data;
  468. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  469. srcs = data.XamlSources;
  470. }
  471. //----------------------------------------------------------------------------
  472. bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
  473. const std::string& config) const
  474. {
  475. assert(this->GetType() != cmTarget::INTERFACE_LIBRARY);
  476. std::string config_upper;
  477. if(!config.empty())
  478. {
  479. config_upper = cmSystemTools::UpperCase(config);
  480. }
  481. typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
  482. IncludeCacheType::const_iterator iter =
  483. this->SystemIncludesCache.find(config_upper);
  484. if (iter == this->SystemIncludesCache.end())
  485. {
  486. cmGeneratorExpressionDAGChecker dagChecker(
  487. this->GetName(),
  488. "SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
  489. bool excludeImported
  490. = this->Target->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
  491. std::vector<std::string> result;
  492. for (std::set<std::string>::const_iterator
  493. it = this->Target->GetSystemIncludeDirectories().begin();
  494. it != this->Target->GetSystemIncludeDirectories().end(); ++it)
  495. {
  496. cmGeneratorExpression ge;
  497. cmSystemTools::ExpandListArgument(ge.Parse(*it)
  498. ->Evaluate(this->Makefile,
  499. config, false, this->Target,
  500. &dagChecker), result);
  501. }
  502. std::vector<cmTarget const*> const& deps =
  503. this->Target->GetLinkImplementationClosure(config);
  504. for(std::vector<cmTarget const*>::const_iterator
  505. li = deps.begin(), le = deps.end(); li != le; ++li)
  506. {
  507. handleSystemIncludesDep(this->Makefile, *li, config, this->Target,
  508. &dagChecker, result, excludeImported);
  509. }
  510. std::set<std::string> unique;
  511. for(std::vector<std::string>::iterator li = result.begin();
  512. li != result.end(); ++li)
  513. {
  514. cmSystemTools::ConvertToUnixSlashes(*li);
  515. unique.insert(*li);
  516. }
  517. result.clear();
  518. result.insert(result.end(), unique.begin(), unique.end());
  519. IncludeCacheType::value_type entry(config_upper, result);
  520. iter = this->SystemIncludesCache.insert(entry).first;
  521. }
  522. return std::binary_search(iter->second.begin(), iter->second.end(), dir);
  523. }
  524. //----------------------------------------------------------------------------
  525. bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
  526. {
  527. return this->Target->GetPropertyAsBool(prop);
  528. }
  529. //----------------------------------------------------------------------------
  530. void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
  531. const std::string& config) const
  532. {
  533. this->Target->GetSourceFiles(files, config);
  534. }
  535. //----------------------------------------------------------------------------
  536. std::string
  537. cmGeneratorTarget::GetModuleDefinitionFile(const std::string& config) const
  538. {
  539. std::string data;
  540. IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string)
  541. return data;
  542. }
  543. //----------------------------------------------------------------------------
  544. void
  545. cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs,
  546. const std::string &config) const
  547. {
  548. std::vector<cmSourceFile const*> objectFiles;
  549. this->GetExternalObjects(objectFiles, config);
  550. std::vector<cmTarget*> objectLibraries;
  551. for(std::vector<cmSourceFile const*>::const_iterator
  552. it = objectFiles.begin(); it != objectFiles.end(); ++it)
  553. {
  554. std::string objLib = (*it)->GetObjectLibrary();
  555. if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
  556. {
  557. objectLibraries.push_back(tgt);
  558. }
  559. }
  560. std::vector<cmTarget*>::const_iterator end
  561. = cmRemoveDuplicates(objectLibraries);
  562. for(std::vector<cmTarget*>::const_iterator
  563. ti = objectLibraries.begin();
  564. ti != end; ++ti)
  565. {
  566. cmTarget* objLib = *ti;
  567. cmGeneratorTarget* ogt =
  568. this->GlobalGenerator->GetGeneratorTarget(objLib);
  569. std::vector<cmSourceFile const*> objectSources;
  570. ogt->GetObjectSources(objectSources, config);
  571. for(std::vector<cmSourceFile const*>::const_iterator
  572. si = objectSources.begin();
  573. si != objectSources.end(); ++si)
  574. {
  575. std::string obj = ogt->ObjectDirectory;
  576. obj += ogt->Objects[*si];
  577. objs.push_back(obj);
  578. }
  579. }
  580. }
  581. //----------------------------------------------------------------------------
  582. class cmTargetTraceDependencies
  583. {
  584. public:
  585. cmTargetTraceDependencies(cmGeneratorTarget* target);
  586. void Trace();
  587. private:
  588. cmTarget* Target;
  589. cmGeneratorTarget* GeneratorTarget;
  590. cmMakefile* Makefile;
  591. cmGlobalGenerator const* GlobalGenerator;
  592. typedef cmGeneratorTarget::SourceEntry SourceEntry;
  593. SourceEntry* CurrentEntry;
  594. std::queue<cmSourceFile*> SourceQueue;
  595. std::set<cmSourceFile*> SourcesQueued;
  596. typedef std::map<std::string, cmSourceFile*> NameMapType;
  597. NameMapType NameMap;
  598. std::vector<std::string> NewSources;
  599. void QueueSource(cmSourceFile* sf);
  600. void FollowName(std::string const& name);
  601. void FollowNames(std::vector<std::string> const& names);
  602. bool IsUtility(std::string const& dep);
  603. void CheckCustomCommand(cmCustomCommand const& cc);
  604. void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
  605. void FollowCommandDepends(cmCustomCommand const& cc,
  606. const std::string& config,
  607. std::set<std::string>& emitted);
  608. };
  609. //----------------------------------------------------------------------------
  610. cmTargetTraceDependencies
  611. ::cmTargetTraceDependencies(cmGeneratorTarget* target):
  612. Target(target->Target), GeneratorTarget(target)
  613. {
  614. // Convenience.
  615. this->Makefile = this->Target->GetMakefile();
  616. this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
  617. this->CurrentEntry = 0;
  618. // Queue all the source files already specified for the target.
  619. if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
  620. {
  621. std::vector<std::string> configs;
  622. this->Makefile->GetConfigurations(configs);
  623. if (configs.empty())
  624. {
  625. configs.push_back("");
  626. }
  627. std::set<cmSourceFile*> emitted;
  628. for(std::vector<std::string>::const_iterator ci = configs.begin();
  629. ci != configs.end(); ++ci)
  630. {
  631. std::vector<cmSourceFile*> sources;
  632. this->Target->GetSourceFiles(sources, *ci);
  633. for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
  634. si != sources.end(); ++si)
  635. {
  636. cmSourceFile* sf = *si;
  637. const std::set<cmTarget const*> tgts =
  638. this->GlobalGenerator->GetFilenameTargetDepends(sf);
  639. if (tgts.find(this->Target) != tgts.end())
  640. {
  641. std::ostringstream e;
  642. e << "Evaluation output file\n \"" << sf->GetFullPath()
  643. << "\"\ndepends on the sources of a target it is used in. This "
  644. "is a dependency loop and is not allowed.";
  645. this->GeneratorTarget
  646. ->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
  647. return;
  648. }
  649. if(emitted.insert(sf).second && this->SourcesQueued.insert(sf).second)
  650. {
  651. this->SourceQueue.push(sf);
  652. }
  653. }
  654. }
  655. }
  656. // Queue pre-build, pre-link, and post-build rule dependencies.
  657. this->CheckCustomCommands(this->Target->GetPreBuildCommands());
  658. this->CheckCustomCommands(this->Target->GetPreLinkCommands());
  659. this->CheckCustomCommands(this->Target->GetPostBuildCommands());
  660. }
  661. //----------------------------------------------------------------------------
  662. void cmTargetTraceDependencies::Trace()
  663. {
  664. // Process one dependency at a time until the queue is empty.
  665. while(!this->SourceQueue.empty())
  666. {
  667. // Get the next source from the queue.
  668. cmSourceFile* sf = this->SourceQueue.front();
  669. this->SourceQueue.pop();
  670. this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf];
  671. // Queue dependencies added explicitly by the user.
  672. if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
  673. {
  674. std::vector<std::string> objDeps;
  675. cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
  676. for(std::vector<std::string>::iterator odi = objDeps.begin();
  677. odi != objDeps.end(); ++odi)
  678. {
  679. if (cmSystemTools::FileIsFullPath(*odi))
  680. {
  681. *odi = cmSystemTools::CollapseFullPath(*odi);
  682. }
  683. }
  684. this->FollowNames(objDeps);
  685. }
  686. // Queue the source needed to generate this file, if any.
  687. this->FollowName(sf->GetFullPath());
  688. // Queue dependencies added programatically by commands.
  689. this->FollowNames(sf->GetDepends());
  690. // Queue custom command dependencies.
  691. if(cmCustomCommand const* cc = sf->GetCustomCommand())
  692. {
  693. this->CheckCustomCommand(*cc);
  694. }
  695. }
  696. this->CurrentEntry = 0;
  697. this->Target->AddTracedSources(this->NewSources);
  698. }
  699. //----------------------------------------------------------------------------
  700. void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
  701. {
  702. if(this->SourcesQueued.insert(sf).second)
  703. {
  704. this->SourceQueue.push(sf);
  705. // Make sure this file is in the target at the end.
  706. this->NewSources.push_back(sf->GetFullPath());
  707. }
  708. }
  709. //----------------------------------------------------------------------------
  710. void cmTargetTraceDependencies::FollowName(std::string const& name)
  711. {
  712. NameMapType::iterator i = this->NameMap.find(name);
  713. if(i == this->NameMap.end())
  714. {
  715. // Check if we know how to generate this file.
  716. cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name);
  717. NameMapType::value_type entry(name, sf);
  718. i = this->NameMap.insert(entry).first;
  719. }
  720. if(cmSourceFile* sf = i->second)
  721. {
  722. // Record the dependency we just followed.
  723. if(this->CurrentEntry)
  724. {
  725. this->CurrentEntry->Depends.push_back(sf);
  726. }
  727. this->QueueSource(sf);
  728. }
  729. }
  730. //----------------------------------------------------------------------------
  731. void
  732. cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
  733. {
  734. for(std::vector<std::string>::const_iterator i = names.begin();
  735. i != names.end(); ++i)
  736. {
  737. this->FollowName(*i);
  738. }
  739. }
  740. //----------------------------------------------------------------------------
  741. bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
  742. {
  743. // Dependencies on targets (utilities) are supposed to be named by
  744. // just the target name. However for compatibility we support
  745. // naming the output file generated by the target (assuming there is
  746. // no output-name property which old code would not have set). In
  747. // that case the target name will be the file basename of the
  748. // dependency.
  749. std::string util = cmSystemTools::GetFilenameName(dep);
  750. if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
  751. {
  752. util = cmSystemTools::GetFilenameWithoutLastExtension(util);
  753. }
  754. // Check for a target with this name.
  755. if(cmTarget* t = this->Makefile->FindTargetToUse(util))
  756. {
  757. // If we find the target and the dep was given as a full path,
  758. // then make sure it was not a full path to something else, and
  759. // the fact that the name matched a target was just a coincidence.
  760. if(cmSystemTools::FileIsFullPath(dep.c_str()))
  761. {
  762. if(t->GetType() >= cmTarget::EXECUTABLE &&
  763. t->GetType() <= cmTarget::MODULE_LIBRARY)
  764. {
  765. // This is really only for compatibility so we do not need to
  766. // worry about configuration names and output names.
  767. std::string tLocation = t->GetLocationForBuild();
  768. tLocation = cmSystemTools::GetFilenamePath(tLocation);
  769. std::string depLocation = cmSystemTools::GetFilenamePath(dep);
  770. depLocation = cmSystemTools::CollapseFullPath(depLocation);
  771. tLocation = cmSystemTools::CollapseFullPath(tLocation);
  772. if(depLocation == tLocation)
  773. {
  774. this->Target->AddUtility(util);
  775. return true;
  776. }
  777. }
  778. }
  779. else
  780. {
  781. // The original name of the dependency was not a full path. It
  782. // must name a target, so add the target-level dependency.
  783. this->Target->AddUtility(util);
  784. return true;
  785. }
  786. }
  787. // The dependency does not name a target built in this project.
  788. return false;
  789. }
  790. //----------------------------------------------------------------------------
  791. void
  792. cmTargetTraceDependencies
  793. ::CheckCustomCommand(cmCustomCommand const& cc)
  794. {
  795. // Transform command names that reference targets built in this
  796. // project to corresponding target-level dependencies.
  797. cmGeneratorExpression ge(cc.GetBacktrace());
  798. // Add target-level dependencies referenced by generator expressions.
  799. std::set<cmTarget*> targets;
  800. for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
  801. cit != cc.GetCommandLines().end(); ++cit)
  802. {
  803. std::string const& command = *cit->begin();
  804. // Check for a target with this name.
  805. if(cmTarget* t = this->Makefile->FindTargetToUse(command))
  806. {
  807. if(t->GetType() == cmTarget::EXECUTABLE)
  808. {
  809. // The command refers to an executable target built in
  810. // this project. Add the target-level dependency to make
  811. // sure the executable is up to date before this custom
  812. // command possibly runs.
  813. this->Target->AddUtility(command);
  814. }
  815. }
  816. // Check for target references in generator expressions.
  817. for(cmCustomCommandLine::const_iterator cli = cit->begin();
  818. cli != cit->end(); ++cli)
  819. {
  820. const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
  821. = ge.Parse(*cli);
  822. cge->Evaluate(this->Makefile, "", true);
  823. std::set<cmTarget*> geTargets = cge->GetTargets();
  824. targets.insert(geTargets.begin(), geTargets.end());
  825. }
  826. }
  827. for(std::set<cmTarget*>::iterator ti = targets.begin();
  828. ti != targets.end(); ++ti)
  829. {
  830. this->Target->AddUtility((*ti)->GetName());
  831. }
  832. // Queue the custom command dependencies.
  833. std::vector<std::string> configs;
  834. std::set<std::string> emitted;
  835. this->Makefile->GetConfigurations(configs);
  836. if (configs.empty())
  837. {
  838. configs.push_back("");
  839. }
  840. for(std::vector<std::string>::const_iterator ci = configs.begin();
  841. ci != configs.end(); ++ci)
  842. {
  843. this->FollowCommandDepends(cc, *ci, emitted);
  844. }
  845. }
  846. //----------------------------------------------------------------------------
  847. void cmTargetTraceDependencies::FollowCommandDepends(cmCustomCommand const& cc,
  848. const std::string& config,
  849. std::set<std::string>& emitted)
  850. {
  851. cmCustomCommandGenerator ccg(cc, config, this->Makefile);
  852. const std::vector<std::string>& depends = ccg.GetDepends();
  853. for(std::vector<std::string>::const_iterator di = depends.begin();
  854. di != depends.end(); ++di)
  855. {
  856. std::string const& dep = *di;
  857. if(emitted.insert(dep).second)
  858. {
  859. if(!this->IsUtility(dep))
  860. {
  861. // The dependency does not name a target and may be a file we
  862. // know how to generate. Queue it.
  863. this->FollowName(dep);
  864. }
  865. }
  866. }
  867. }
  868. //----------------------------------------------------------------------------
  869. void
  870. cmTargetTraceDependencies
  871. ::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
  872. {
  873. for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
  874. cli != commands.end(); ++cli)
  875. {
  876. this->CheckCustomCommand(*cli);
  877. }
  878. }
  879. //----------------------------------------------------------------------------
  880. void cmGeneratorTarget::TraceDependencies()
  881. {
  882. // CMake-generated targets have no dependencies to trace. Normally tracing
  883. // would find nothing anyway, but when building CMake itself the "install"
  884. // target command ends up referencing the "cmake" target but we do not
  885. // really want the dependency because "install" depend on "all" anyway.
  886. if(this->GetType() == cmTarget::GLOBAL_TARGET)
  887. {
  888. return;
  889. }
  890. // Use a helper object to trace the dependencies.
  891. cmTargetTraceDependencies tracer(this);
  892. tracer.Trace();
  893. }
  894. //----------------------------------------------------------------------------
  895. void cmGeneratorTarget::GetAppleArchs(const std::string& config,
  896. std::vector<std::string>& archVec) const
  897. {
  898. const char* archs = 0;
  899. if(!config.empty())
  900. {
  901. std::string defVarName = "OSX_ARCHITECTURES_";
  902. defVarName += cmSystemTools::UpperCase(config);
  903. archs = this->Target->GetProperty(defVarName);
  904. }
  905. if(!archs)
  906. {
  907. archs = this->Target->GetProperty("OSX_ARCHITECTURES");
  908. }
  909. if(archs)
  910. {
  911. cmSystemTools::ExpandListArgument(std::string(archs), archVec);
  912. }
  913. }
  914. //----------------------------------------------------------------------------
  915. std::string
  916. cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
  917. std::string const& config) const
  918. {
  919. switch(this->GetType())
  920. {
  921. case cmTarget::STATIC_LIBRARY:
  922. {
  923. std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
  924. if(this->GetFeatureAsBool(
  925. "INTERPROCEDURAL_OPTIMIZATION", config))
  926. {
  927. std::string varIPO = var + "_IPO";
  928. if(this->Makefile->GetDefinition(varIPO))
  929. {
  930. return varIPO;
  931. }
  932. }
  933. return var;
  934. }
  935. case cmTarget::SHARED_LIBRARY:
  936. return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
  937. case cmTarget::MODULE_LIBRARY:
  938. return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
  939. case cmTarget::EXECUTABLE:
  940. return "CMAKE_" + lang + "_LINK_EXECUTABLE";
  941. default:
  942. break;
  943. }
  944. return "";
  945. }
  946. //----------------------------------------------------------------------------
  947. std::vector<std::string>
  948. cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
  949. const std::string& lang) const
  950. {
  951. return this->Target->GetIncludeDirectories(config, lang);
  952. }
  953. //----------------------------------------------------------------------------
  954. void cmGeneratorTarget::GenerateTargetManifest(
  955. const std::string& config) const
  956. {
  957. if (this->Target->IsImported())
  958. {
  959. return;
  960. }
  961. cmMakefile* mf = this->Target->GetMakefile();
  962. cmGlobalGenerator* gg = mf->GetGlobalGenerator();
  963. // Get the names.
  964. std::string name;
  965. std::string soName;
  966. std::string realName;
  967. std::string impName;
  968. std::string pdbName;
  969. if(this->GetType() == cmTarget::EXECUTABLE)
  970. {
  971. this->Target->GetExecutableNames(name, realName, impName, pdbName,
  972. config);
  973. }
  974. else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
  975. this->GetType() == cmTarget::SHARED_LIBRARY ||
  976. this->GetType() == cmTarget::MODULE_LIBRARY)
  977. {
  978. this->Target->GetLibraryNames(name, soName, realName, impName, pdbName,
  979. config);
  980. }
  981. else
  982. {
  983. return;
  984. }
  985. // Get the directory.
  986. std::string dir = this->Target->GetDirectory(config, false);
  987. // Add each name.
  988. std::string f;
  989. if(!name.empty())
  990. {
  991. f = dir;
  992. f += "/";
  993. f += name;
  994. gg->AddToManifest(config, f);
  995. }
  996. if(!soName.empty())
  997. {
  998. f = dir;
  999. f += "/";
  1000. f += soName;
  1001. gg->AddToManifest(config, f);
  1002. }
  1003. if(!realName.empty())
  1004. {
  1005. f = dir;
  1006. f += "/";
  1007. f += realName;
  1008. gg->AddToManifest(config, f);
  1009. }
  1010. if(!pdbName.empty())
  1011. {
  1012. f = dir;
  1013. f += "/";
  1014. f += pdbName;
  1015. gg->AddToManifest(config, f);
  1016. }
  1017. if(!impName.empty())
  1018. {
  1019. f = this->Target->GetDirectory(config, true);
  1020. f += "/";
  1021. f += impName;
  1022. gg->AddToManifest(config, f);
  1023. }
  1024. }
  1025. bool cmStrictTargetComparison::operator()(cmTarget const* t1,
  1026. cmTarget const* t2) const
  1027. {
  1028. int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
  1029. if (nameResult == 0)
  1030. {
  1031. return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(),
  1032. t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0;
  1033. }
  1034. return nameResult < 0;
  1035. }
  1036. //----------------------------------------------------------------------------
  1037. struct cmGeneratorTarget::SourceFileFlags
  1038. cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
  1039. {
  1040. struct SourceFileFlags flags;
  1041. this->ConstructSourceFileFlags();
  1042. std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
  1043. this->SourceFlagsMap.find(sf);
  1044. if(si != this->SourceFlagsMap.end())
  1045. {
  1046. flags = si->second;
  1047. }
  1048. else
  1049. {
  1050. // Handle the MACOSX_PACKAGE_LOCATION property on source files that
  1051. // were not listed in one of the other lists.
  1052. if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
  1053. {
  1054. flags.MacFolder = location;
  1055. if(strcmp(location, "Resources") == 0)
  1056. {
  1057. flags.Type = cmGeneratorTarget::SourceFileTypeResource;
  1058. }
  1059. else
  1060. {
  1061. flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
  1062. }
  1063. }
  1064. }
  1065. return flags;
  1066. }
  1067. //----------------------------------------------------------------------------
  1068. void cmGeneratorTarget::ConstructSourceFileFlags() const
  1069. {
  1070. if(this->SourceFileFlagsConstructed)
  1071. {
  1072. return;
  1073. }
  1074. this->SourceFileFlagsConstructed = true;
  1075. // Process public headers to mark the source files.
  1076. if(const char* files = this->Target->GetProperty("PUBLIC_HEADER"))
  1077. {
  1078. std::vector<std::string> relFiles;
  1079. cmSystemTools::ExpandListArgument(files, relFiles);
  1080. for(std::vector<std::string>::iterator it = relFiles.begin();
  1081. it != relFiles.end(); ++it)
  1082. {
  1083. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1084. {
  1085. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1086. flags.MacFolder = "Headers";
  1087. flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader;
  1088. }
  1089. }
  1090. }
  1091. // Process private headers after public headers so that they take
  1092. // precedence if a file is listed in both.
  1093. if(const char* files = this->Target->GetProperty("PRIVATE_HEADER"))
  1094. {
  1095. std::vector<std::string> relFiles;
  1096. cmSystemTools::ExpandListArgument(files, relFiles);
  1097. for(std::vector<std::string>::iterator it = relFiles.begin();
  1098. it != relFiles.end(); ++it)
  1099. {
  1100. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1101. {
  1102. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1103. flags.MacFolder = "PrivateHeaders";
  1104. flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader;
  1105. }
  1106. }
  1107. }
  1108. // Mark sources listed as resources.
  1109. if(const char* files = this->Target->GetProperty("RESOURCE"))
  1110. {
  1111. std::vector<std::string> relFiles;
  1112. cmSystemTools::ExpandListArgument(files, relFiles);
  1113. for(std::vector<std::string>::iterator it = relFiles.begin();
  1114. it != relFiles.end(); ++it)
  1115. {
  1116. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1117. {
  1118. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1119. flags.MacFolder = "Resources";
  1120. flags.Type = cmGeneratorTarget::SourceFileTypeResource;
  1121. }
  1122. }
  1123. }
  1124. }