cmGeneratorTarget.cxx 37 KB

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