cmGeneratorTarget.cxx 38 KB

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