cmGeneratorTarget.cxx 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793
  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. cmGeneratorTarget::~cmGeneratorTarget()
  216. {
  217. cmDeleteAll(this->LinkInformation);
  218. this->LinkInformation.clear();
  219. }
  220. cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
  221. {
  222. return this->LocalGenerator;
  223. }
  224. //----------------------------------------------------------------------------
  225. int cmGeneratorTarget::GetType() const
  226. {
  227. return this->Target->GetType();
  228. }
  229. //----------------------------------------------------------------------------
  230. std::string cmGeneratorTarget::GetName() const
  231. {
  232. return this->Target->GetName();
  233. }
  234. //----------------------------------------------------------------------------
  235. const char *cmGeneratorTarget::GetProperty(const std::string& prop) const
  236. {
  237. return this->Target->GetProperty(prop);
  238. }
  239. //----------------------------------------------------------------------------
  240. std::vector<cmSourceFile*> const*
  241. cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const
  242. {
  243. SourceEntriesType::const_iterator i = this->SourceEntries.find(sf);
  244. if(i != this->SourceEntries.end())
  245. {
  246. return &i->second.Depends;
  247. }
  248. return 0;
  249. }
  250. static void handleSystemIncludesDep(cmMakefile *mf, cmTarget const* depTgt,
  251. const std::string& config,
  252. cmTarget *headTarget,
  253. cmGeneratorExpressionDAGChecker *dagChecker,
  254. std::vector<std::string>& result,
  255. bool excludeImported)
  256. {
  257. if (const char* dirs =
  258. depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"))
  259. {
  260. cmGeneratorExpression ge;
  261. cmSystemTools::ExpandListArgument(ge.Parse(dirs)
  262. ->Evaluate(mf,
  263. config, false, headTarget,
  264. depTgt, dagChecker), result);
  265. }
  266. if (!depTgt->IsImported() || excludeImported)
  267. {
  268. return;
  269. }
  270. if (const char* dirs =
  271. depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES"))
  272. {
  273. cmGeneratorExpression ge;
  274. cmSystemTools::ExpandListArgument(ge.Parse(dirs)
  275. ->Evaluate(mf,
  276. config, false, headTarget,
  277. depTgt, dagChecker), result);
  278. }
  279. }
  280. #define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \
  281. { \
  282. std::vector<cmSourceFile*> sourceFiles; \
  283. this->Target->GetSourceFiles(sourceFiles, config); \
  284. TagVisitor<DATA ## Tag DATATYPE> visitor(this->Target, data); \
  285. for(std::vector<cmSourceFile*>::const_iterator si = sourceFiles.begin(); \
  286. si != sourceFiles.end(); ++si) \
  287. { \
  288. visitor.Accept(*si); \
  289. } \
  290. } \
  291. #define IMPLEMENT_VISIT(DATA) \
  292. IMPLEMENT_VISIT_IMPL(DATA, EMPTY) \
  293. #define EMPTY
  294. #define COMMA ,
  295. //----------------------------------------------------------------------------
  296. void
  297. cmGeneratorTarget
  298. ::GetObjectSources(std::vector<cmSourceFile const*> &data,
  299. const std::string& config) const
  300. {
  301. IMPLEMENT_VISIT(ObjectSources);
  302. if (!this->Objects.empty())
  303. {
  304. return;
  305. }
  306. for(std::vector<cmSourceFile const*>::const_iterator it = data.begin();
  307. it != data.end(); ++it)
  308. {
  309. this->Objects[*it];
  310. }
  311. this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
  312. }
  313. void cmGeneratorTarget::ComputeObjectMapping()
  314. {
  315. if(!this->Objects.empty())
  316. {
  317. return;
  318. }
  319. std::vector<std::string> configs;
  320. this->Makefile->GetConfigurations(configs);
  321. if (configs.empty())
  322. {
  323. configs.push_back("");
  324. }
  325. for(std::vector<std::string>::const_iterator ci = configs.begin();
  326. ci != configs.end(); ++ci)
  327. {
  328. std::vector<cmSourceFile const*> sourceFiles;
  329. this->GetObjectSources(sourceFiles, *ci);
  330. }
  331. }
  332. //----------------------------------------------------------------------------
  333. const char* cmGeneratorTarget::GetFeature(const std::string& feature,
  334. const std::string& config) const
  335. {
  336. if(!config.empty())
  337. {
  338. std::string featureConfig = feature;
  339. featureConfig += "_";
  340. featureConfig += cmSystemTools::UpperCase(config);
  341. if(const char* value = this->Target->GetProperty(featureConfig))
  342. {
  343. return value;
  344. }
  345. }
  346. if(const char* value = this->Target->GetProperty(feature))
  347. {
  348. return value;
  349. }
  350. return this->LocalGenerator->GetFeature(feature, config);
  351. }
  352. //----------------------------------------------------------------------------
  353. bool cmGeneratorTarget::GetFeatureAsBool(const std::string& feature,
  354. const std::string& config) const
  355. {
  356. return cmSystemTools::IsOn(this->GetFeature(feature, config));
  357. }
  358. //----------------------------------------------------------------------------
  359. const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
  360. {
  361. this->ComputeObjectMapping();
  362. return this->Objects[file];
  363. }
  364. //----------------------------------------------------------------------------
  365. void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
  366. {
  367. this->ExplicitObjectName.insert(sf);
  368. }
  369. //----------------------------------------------------------------------------
  370. bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
  371. {
  372. const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
  373. std::set<cmSourceFile const*>::const_iterator it
  374. = this->ExplicitObjectName.find(file);
  375. return it != this->ExplicitObjectName.end();
  376. }
  377. //----------------------------------------------------------------------------
  378. void cmGeneratorTarget
  379. ::GetIDLSources(std::vector<cmSourceFile const*>& data,
  380. const std::string& config) const
  381. {
  382. IMPLEMENT_VISIT(IDLSources);
  383. }
  384. //----------------------------------------------------------------------------
  385. void
  386. cmGeneratorTarget
  387. ::GetHeaderSources(std::vector<cmSourceFile const*>& data,
  388. const std::string& config) const
  389. {
  390. IMPLEMENT_VISIT(HeaderSources);
  391. }
  392. //----------------------------------------------------------------------------
  393. void cmGeneratorTarget
  394. ::GetExtraSources(std::vector<cmSourceFile const*>& data,
  395. const std::string& config) const
  396. {
  397. IMPLEMENT_VISIT(ExtraSources);
  398. }
  399. //----------------------------------------------------------------------------
  400. void
  401. cmGeneratorTarget
  402. ::GetCustomCommands(std::vector<cmSourceFile const*>& data,
  403. const std::string& config) const
  404. {
  405. IMPLEMENT_VISIT(CustomCommands);
  406. }
  407. //----------------------------------------------------------------------------
  408. void
  409. cmGeneratorTarget
  410. ::GetExternalObjects(std::vector<cmSourceFile const*>& data,
  411. const std::string& config) const
  412. {
  413. IMPLEMENT_VISIT(ExternalObjects);
  414. }
  415. //----------------------------------------------------------------------------
  416. void
  417. cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& srcs,
  418. const std::string& config) const
  419. {
  420. ResxData data;
  421. IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  422. srcs = data.ExpectedResxHeaders;
  423. }
  424. //----------------------------------------------------------------------------
  425. void cmGeneratorTarget
  426. ::GetResxSources(std::vector<cmSourceFile const*>& srcs,
  427. const std::string& config) const
  428. {
  429. ResxData data;
  430. IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData)
  431. srcs = data.ResxSources;
  432. }
  433. //----------------------------------------------------------------------------
  434. void
  435. cmGeneratorTarget
  436. ::GetAppManifest(std::vector<cmSourceFile const*>& data,
  437. const std::string& config) const
  438. {
  439. IMPLEMENT_VISIT(AppManifest);
  440. }
  441. //----------------------------------------------------------------------------
  442. void
  443. cmGeneratorTarget
  444. ::GetCertificates(std::vector<cmSourceFile const*>& data,
  445. const std::string& config) const
  446. {
  447. IMPLEMENT_VISIT(Certificates);
  448. }
  449. //----------------------------------------------------------------------------
  450. void
  451. cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers,
  452. const std::string& config) const
  453. {
  454. XamlData data;
  455. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  456. headers = data.ExpectedXamlHeaders;
  457. }
  458. //----------------------------------------------------------------------------
  459. void
  460. cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs,
  461. const std::string& config) const
  462. {
  463. XamlData data;
  464. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  465. srcs = data.ExpectedXamlSources;
  466. }
  467. //----------------------------------------------------------------------------
  468. void cmGeneratorTarget
  469. ::GetXamlSources(std::vector<cmSourceFile const*>& srcs,
  470. const std::string& config) const
  471. {
  472. XamlData data;
  473. IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData)
  474. srcs = data.XamlSources;
  475. }
  476. //----------------------------------------------------------------------------
  477. const char* cmGeneratorTarget::GetLocation(const std::string& config) const
  478. {
  479. static std::string location;
  480. if (this->Target->IsImported())
  481. {
  482. location = this->Target->ImportedGetFullPath(config, false);
  483. }
  484. else
  485. {
  486. location = this->GetFullPath(config, false);
  487. }
  488. return location.c_str();
  489. }
  490. bool cmGeneratorTarget::IsImported() const
  491. {
  492. return this->Target->IsImported();
  493. }
  494. //----------------------------------------------------------------------------
  495. const char* cmGeneratorTarget::GetLocationForBuild() const
  496. {
  497. static std::string location;
  498. if(this->IsImported())
  499. {
  500. location = this->Target->ImportedGetFullPath("", false);
  501. return location.c_str();
  502. }
  503. // Now handle the deprecated build-time configuration location.
  504. location = this->Target->GetDirectory();
  505. const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
  506. if(cfgid && strcmp(cfgid, ".") != 0)
  507. {
  508. location += "/";
  509. location += cfgid;
  510. }
  511. if(this->Target->IsAppBundleOnApple())
  512. {
  513. std::string macdir = this->Target->BuildMacContentDirectory("", "",
  514. false);
  515. if(!macdir.empty())
  516. {
  517. location += "/";
  518. location += macdir;
  519. }
  520. }
  521. location += "/";
  522. location += this->Target->GetFullName("", false);
  523. return location.c_str();
  524. }
  525. //----------------------------------------------------------------------------
  526. bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir,
  527. const std::string& config) const
  528. {
  529. assert(this->GetType() != cmTarget::INTERFACE_LIBRARY);
  530. std::string config_upper;
  531. if(!config.empty())
  532. {
  533. config_upper = cmSystemTools::UpperCase(config);
  534. }
  535. typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
  536. IncludeCacheType::const_iterator iter =
  537. this->SystemIncludesCache.find(config_upper);
  538. if (iter == this->SystemIncludesCache.end())
  539. {
  540. cmGeneratorExpressionDAGChecker dagChecker(
  541. this->GetName(),
  542. "SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
  543. bool excludeImported
  544. = this->Target->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
  545. std::vector<std::string> result;
  546. for (std::set<std::string>::const_iterator
  547. it = this->Target->GetSystemIncludeDirectories().begin();
  548. it != this->Target->GetSystemIncludeDirectories().end(); ++it)
  549. {
  550. cmGeneratorExpression ge;
  551. cmSystemTools::ExpandListArgument(ge.Parse(*it)
  552. ->Evaluate(this->Makefile,
  553. config, false, this->Target,
  554. &dagChecker), result);
  555. }
  556. std::vector<cmTarget const*> const& deps =
  557. this->Target->GetLinkImplementationClosure(config);
  558. for(std::vector<cmTarget const*>::const_iterator
  559. li = deps.begin(), le = deps.end(); li != le; ++li)
  560. {
  561. handleSystemIncludesDep(this->Makefile, *li, config, this->Target,
  562. &dagChecker, result, excludeImported);
  563. }
  564. std::set<std::string> unique;
  565. for(std::vector<std::string>::iterator li = result.begin();
  566. li != result.end(); ++li)
  567. {
  568. cmSystemTools::ConvertToUnixSlashes(*li);
  569. unique.insert(*li);
  570. }
  571. result.clear();
  572. result.insert(result.end(), unique.begin(), unique.end());
  573. IncludeCacheType::value_type entry(config_upper, result);
  574. iter = this->SystemIncludesCache.insert(entry).first;
  575. }
  576. return std::binary_search(iter->second.begin(), iter->second.end(), dir);
  577. }
  578. //----------------------------------------------------------------------------
  579. bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const
  580. {
  581. return this->Target->GetPropertyAsBool(prop);
  582. }
  583. //----------------------------------------------------------------------------
  584. void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
  585. const std::string& config) const
  586. {
  587. this->Target->GetSourceFiles(files, config);
  588. }
  589. //----------------------------------------------------------------------------
  590. std::string cmGeneratorTarget::GetSOName(const std::string& config) const
  591. {
  592. if(this->Target->IsImported())
  593. {
  594. // Lookup the imported soname.
  595. if(cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config))
  596. {
  597. if(info->NoSOName)
  598. {
  599. // The imported library has no builtin soname so the name
  600. // searched at runtime will be just the filename.
  601. return cmSystemTools::GetFilenameName(info->Location);
  602. }
  603. else
  604. {
  605. // Use the soname given if any.
  606. if(info->SOName.find("@rpath/") == 0)
  607. {
  608. return info->SOName.substr(6);
  609. }
  610. return info->SOName;
  611. }
  612. }
  613. else
  614. {
  615. return "";
  616. }
  617. }
  618. else
  619. {
  620. // Compute the soname that will be built.
  621. std::string name;
  622. std::string soName;
  623. std::string realName;
  624. std::string impName;
  625. std::string pdbName;
  626. this->Target->GetLibraryNames(name, soName, realName,
  627. impName, pdbName, config);
  628. return soName;
  629. }
  630. }
  631. //----------------------------------------------------------------------------
  632. std::string
  633. cmGeneratorTarget::GetModuleDefinitionFile(const std::string& config) const
  634. {
  635. std::string data;
  636. IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string)
  637. return data;
  638. }
  639. //----------------------------------------------------------------------------
  640. void
  641. cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs,
  642. const std::string &config) const
  643. {
  644. std::vector<cmSourceFile const*> objectFiles;
  645. this->GetExternalObjects(objectFiles, config);
  646. std::vector<cmTarget*> objectLibraries;
  647. for(std::vector<cmSourceFile const*>::const_iterator
  648. it = objectFiles.begin(); it != objectFiles.end(); ++it)
  649. {
  650. std::string objLib = (*it)->GetObjectLibrary();
  651. if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
  652. {
  653. objectLibraries.push_back(tgt);
  654. }
  655. }
  656. std::vector<cmTarget*>::const_iterator end
  657. = cmRemoveDuplicates(objectLibraries);
  658. for(std::vector<cmTarget*>::const_iterator
  659. ti = objectLibraries.begin();
  660. ti != end; ++ti)
  661. {
  662. cmTarget* objLib = *ti;
  663. cmGeneratorTarget* ogt =
  664. this->GlobalGenerator->GetGeneratorTarget(objLib);
  665. std::vector<cmSourceFile const*> objectSources;
  666. ogt->GetObjectSources(objectSources, config);
  667. for(std::vector<cmSourceFile const*>::const_iterator
  668. si = objectSources.begin();
  669. si != objectSources.end(); ++si)
  670. {
  671. std::string obj = ogt->ObjectDirectory;
  672. obj += ogt->Objects[*si];
  673. objs.push_back(obj);
  674. }
  675. }
  676. }
  677. //----------------------------------------------------------------------------
  678. void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result,
  679. const std::string& config) const
  680. {
  681. const char *prop
  682. = this->Target->
  683. GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS",
  684. config);
  685. if (!prop)
  686. {
  687. return;
  688. }
  689. cmGeneratorExpression ge;
  690. cmGeneratorExpressionDAGChecker dagChecker(
  691. this->GetName(),
  692. "AUTOUIC_OPTIONS", 0, 0);
  693. cmSystemTools::ExpandListArgument(ge.Parse(prop)
  694. ->Evaluate(this->Makefile,
  695. config,
  696. false,
  697. this->Target,
  698. &dagChecker),
  699. result);
  700. }
  701. //----------------------------------------------------------------------------
  702. class cmTargetTraceDependencies
  703. {
  704. public:
  705. cmTargetTraceDependencies(cmGeneratorTarget* target);
  706. void Trace();
  707. private:
  708. cmTarget* Target;
  709. cmGeneratorTarget* GeneratorTarget;
  710. cmMakefile* Makefile;
  711. cmGlobalGenerator const* GlobalGenerator;
  712. typedef cmGeneratorTarget::SourceEntry SourceEntry;
  713. SourceEntry* CurrentEntry;
  714. std::queue<cmSourceFile*> SourceQueue;
  715. std::set<cmSourceFile*> SourcesQueued;
  716. typedef std::map<std::string, cmSourceFile*> NameMapType;
  717. NameMapType NameMap;
  718. std::vector<std::string> NewSources;
  719. void QueueSource(cmSourceFile* sf);
  720. void FollowName(std::string const& name);
  721. void FollowNames(std::vector<std::string> const& names);
  722. bool IsUtility(std::string const& dep);
  723. void CheckCustomCommand(cmCustomCommand const& cc);
  724. void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
  725. void FollowCommandDepends(cmCustomCommand const& cc,
  726. const std::string& config,
  727. std::set<std::string>& emitted);
  728. };
  729. //----------------------------------------------------------------------------
  730. cmTargetTraceDependencies
  731. ::cmTargetTraceDependencies(cmGeneratorTarget* target):
  732. Target(target->Target), GeneratorTarget(target)
  733. {
  734. // Convenience.
  735. this->Makefile = this->Target->GetMakefile();
  736. this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
  737. this->CurrentEntry = 0;
  738. // Queue all the source files already specified for the target.
  739. if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
  740. {
  741. std::vector<std::string> configs;
  742. this->Makefile->GetConfigurations(configs);
  743. if (configs.empty())
  744. {
  745. configs.push_back("");
  746. }
  747. std::set<cmSourceFile*> emitted;
  748. for(std::vector<std::string>::const_iterator ci = configs.begin();
  749. ci != configs.end(); ++ci)
  750. {
  751. std::vector<cmSourceFile*> sources;
  752. this->Target->GetSourceFiles(sources, *ci);
  753. for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
  754. si != sources.end(); ++si)
  755. {
  756. cmSourceFile* sf = *si;
  757. const std::set<cmTarget const*> tgts =
  758. this->GlobalGenerator->GetFilenameTargetDepends(sf);
  759. if (tgts.find(this->Target) != tgts.end())
  760. {
  761. std::ostringstream e;
  762. e << "Evaluation output file\n \"" << sf->GetFullPath()
  763. << "\"\ndepends on the sources of a target it is used in. This "
  764. "is a dependency loop and is not allowed.";
  765. this->GeneratorTarget
  766. ->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
  767. return;
  768. }
  769. if(emitted.insert(sf).second && this->SourcesQueued.insert(sf).second)
  770. {
  771. this->SourceQueue.push(sf);
  772. }
  773. }
  774. }
  775. }
  776. // Queue pre-build, pre-link, and post-build rule dependencies.
  777. this->CheckCustomCommands(this->Target->GetPreBuildCommands());
  778. this->CheckCustomCommands(this->Target->GetPreLinkCommands());
  779. this->CheckCustomCommands(this->Target->GetPostBuildCommands());
  780. }
  781. //----------------------------------------------------------------------------
  782. void cmTargetTraceDependencies::Trace()
  783. {
  784. // Process one dependency at a time until the queue is empty.
  785. while(!this->SourceQueue.empty())
  786. {
  787. // Get the next source from the queue.
  788. cmSourceFile* sf = this->SourceQueue.front();
  789. this->SourceQueue.pop();
  790. this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf];
  791. // Queue dependencies added explicitly by the user.
  792. if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
  793. {
  794. std::vector<std::string> objDeps;
  795. cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
  796. for(std::vector<std::string>::iterator odi = objDeps.begin();
  797. odi != objDeps.end(); ++odi)
  798. {
  799. if (cmSystemTools::FileIsFullPath(*odi))
  800. {
  801. *odi = cmSystemTools::CollapseFullPath(*odi);
  802. }
  803. }
  804. this->FollowNames(objDeps);
  805. }
  806. // Queue the source needed to generate this file, if any.
  807. this->FollowName(sf->GetFullPath());
  808. // Queue dependencies added programatically by commands.
  809. this->FollowNames(sf->GetDepends());
  810. // Queue custom command dependencies.
  811. if(cmCustomCommand const* cc = sf->GetCustomCommand())
  812. {
  813. this->CheckCustomCommand(*cc);
  814. }
  815. }
  816. this->CurrentEntry = 0;
  817. this->Target->AddTracedSources(this->NewSources);
  818. }
  819. //----------------------------------------------------------------------------
  820. void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
  821. {
  822. if(this->SourcesQueued.insert(sf).second)
  823. {
  824. this->SourceQueue.push(sf);
  825. // Make sure this file is in the target at the end.
  826. this->NewSources.push_back(sf->GetFullPath());
  827. }
  828. }
  829. //----------------------------------------------------------------------------
  830. void cmTargetTraceDependencies::FollowName(std::string const& name)
  831. {
  832. NameMapType::iterator i = this->NameMap.find(name);
  833. if(i == this->NameMap.end())
  834. {
  835. // Check if we know how to generate this file.
  836. cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name);
  837. NameMapType::value_type entry(name, sf);
  838. i = this->NameMap.insert(entry).first;
  839. }
  840. if(cmSourceFile* sf = i->second)
  841. {
  842. // Record the dependency we just followed.
  843. if(this->CurrentEntry)
  844. {
  845. this->CurrentEntry->Depends.push_back(sf);
  846. }
  847. this->QueueSource(sf);
  848. }
  849. }
  850. //----------------------------------------------------------------------------
  851. void
  852. cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
  853. {
  854. for(std::vector<std::string>::const_iterator i = names.begin();
  855. i != names.end(); ++i)
  856. {
  857. this->FollowName(*i);
  858. }
  859. }
  860. //----------------------------------------------------------------------------
  861. bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
  862. {
  863. // Dependencies on targets (utilities) are supposed to be named by
  864. // just the target name. However for compatibility we support
  865. // naming the output file generated by the target (assuming there is
  866. // no output-name property which old code would not have set). In
  867. // that case the target name will be the file basename of the
  868. // dependency.
  869. std::string util = cmSystemTools::GetFilenameName(dep);
  870. if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
  871. {
  872. util = cmSystemTools::GetFilenameWithoutLastExtension(util);
  873. }
  874. // Check for a target with this name.
  875. if(cmGeneratorTarget* t
  876. = this->Makefile->FindGeneratorTargetToUse(util))
  877. {
  878. // If we find the target and the dep was given as a full path,
  879. // then make sure it was not a full path to something else, and
  880. // the fact that the name matched a target was just a coincidence.
  881. if(cmSystemTools::FileIsFullPath(dep.c_str()))
  882. {
  883. if(t->GetType() >= cmTarget::EXECUTABLE &&
  884. t->GetType() <= cmTarget::MODULE_LIBRARY)
  885. {
  886. // This is really only for compatibility so we do not need to
  887. // worry about configuration names and output names.
  888. std::string tLocation = t->GetLocationForBuild();
  889. tLocation = cmSystemTools::GetFilenamePath(tLocation);
  890. std::string depLocation = cmSystemTools::GetFilenamePath(dep);
  891. depLocation = cmSystemTools::CollapseFullPath(depLocation);
  892. tLocation = cmSystemTools::CollapseFullPath(tLocation);
  893. if(depLocation == tLocation)
  894. {
  895. this->Target->AddUtility(util);
  896. return true;
  897. }
  898. }
  899. }
  900. else
  901. {
  902. // The original name of the dependency was not a full path. It
  903. // must name a target, so add the target-level dependency.
  904. this->Target->AddUtility(util);
  905. return true;
  906. }
  907. }
  908. // The dependency does not name a target built in this project.
  909. return false;
  910. }
  911. //----------------------------------------------------------------------------
  912. void
  913. cmTargetTraceDependencies
  914. ::CheckCustomCommand(cmCustomCommand const& cc)
  915. {
  916. // Transform command names that reference targets built in this
  917. // project to corresponding target-level dependencies.
  918. cmGeneratorExpression ge(cc.GetBacktrace());
  919. // Add target-level dependencies referenced by generator expressions.
  920. std::set<cmTarget*> targets;
  921. for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
  922. cit != cc.GetCommandLines().end(); ++cit)
  923. {
  924. std::string const& command = *cit->begin();
  925. // Check for a target with this name.
  926. if(cmTarget* t = this->Makefile->FindTargetToUse(command))
  927. {
  928. if(t->GetType() == cmTarget::EXECUTABLE)
  929. {
  930. // The command refers to an executable target built in
  931. // this project. Add the target-level dependency to make
  932. // sure the executable is up to date before this custom
  933. // command possibly runs.
  934. this->Target->AddUtility(command);
  935. }
  936. }
  937. // Check for target references in generator expressions.
  938. for(cmCustomCommandLine::const_iterator cli = cit->begin();
  939. cli != cit->end(); ++cli)
  940. {
  941. const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
  942. = ge.Parse(*cli);
  943. cge->Evaluate(this->Makefile, "", true);
  944. std::set<cmTarget*> geTargets = cge->GetTargets();
  945. targets.insert(geTargets.begin(), geTargets.end());
  946. }
  947. }
  948. for(std::set<cmTarget*>::iterator ti = targets.begin();
  949. ti != targets.end(); ++ti)
  950. {
  951. this->Target->AddUtility((*ti)->GetName());
  952. }
  953. // Queue the custom command dependencies.
  954. std::vector<std::string> configs;
  955. std::set<std::string> emitted;
  956. this->Makefile->GetConfigurations(configs);
  957. if (configs.empty())
  958. {
  959. configs.push_back("");
  960. }
  961. for(std::vector<std::string>::const_iterator ci = configs.begin();
  962. ci != configs.end(); ++ci)
  963. {
  964. this->FollowCommandDepends(cc, *ci, emitted);
  965. }
  966. }
  967. //----------------------------------------------------------------------------
  968. void cmTargetTraceDependencies::FollowCommandDepends(cmCustomCommand const& cc,
  969. const std::string& config,
  970. std::set<std::string>& emitted)
  971. {
  972. cmCustomCommandGenerator ccg(cc, config,
  973. this->GeneratorTarget->LocalGenerator);
  974. const std::vector<std::string>& depends = ccg.GetDepends();
  975. for(std::vector<std::string>::const_iterator di = depends.begin();
  976. di != depends.end(); ++di)
  977. {
  978. std::string const& dep = *di;
  979. if(emitted.insert(dep).second)
  980. {
  981. if(!this->IsUtility(dep))
  982. {
  983. // The dependency does not name a target and may be a file we
  984. // know how to generate. Queue it.
  985. this->FollowName(dep);
  986. }
  987. }
  988. }
  989. }
  990. //----------------------------------------------------------------------------
  991. void
  992. cmTargetTraceDependencies
  993. ::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
  994. {
  995. for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
  996. cli != commands.end(); ++cli)
  997. {
  998. this->CheckCustomCommand(*cli);
  999. }
  1000. }
  1001. //----------------------------------------------------------------------------
  1002. void cmGeneratorTarget::TraceDependencies()
  1003. {
  1004. // CMake-generated targets have no dependencies to trace. Normally tracing
  1005. // would find nothing anyway, but when building CMake itself the "install"
  1006. // target command ends up referencing the "cmake" target but we do not
  1007. // really want the dependency because "install" depend on "all" anyway.
  1008. if(this->GetType() == cmTarget::GLOBAL_TARGET)
  1009. {
  1010. return;
  1011. }
  1012. // Use a helper object to trace the dependencies.
  1013. cmTargetTraceDependencies tracer(this);
  1014. tracer.Trace();
  1015. }
  1016. //----------------------------------------------------------------------------
  1017. void cmGeneratorTarget::GetAppleArchs(const std::string& config,
  1018. std::vector<std::string>& archVec) const
  1019. {
  1020. const char* archs = 0;
  1021. if(!config.empty())
  1022. {
  1023. std::string defVarName = "OSX_ARCHITECTURES_";
  1024. defVarName += cmSystemTools::UpperCase(config);
  1025. archs = this->Target->GetProperty(defVarName);
  1026. }
  1027. if(!archs)
  1028. {
  1029. archs = this->Target->GetProperty("OSX_ARCHITECTURES");
  1030. }
  1031. if(archs)
  1032. {
  1033. cmSystemTools::ExpandListArgument(std::string(archs), archVec);
  1034. }
  1035. }
  1036. //----------------------------------------------------------------------------
  1037. std::string
  1038. cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
  1039. std::string const& config) const
  1040. {
  1041. switch(this->GetType())
  1042. {
  1043. case cmTarget::STATIC_LIBRARY:
  1044. {
  1045. std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
  1046. if(this->GetFeatureAsBool(
  1047. "INTERPROCEDURAL_OPTIMIZATION", config))
  1048. {
  1049. std::string varIPO = var + "_IPO";
  1050. if(this->Makefile->GetDefinition(varIPO))
  1051. {
  1052. return varIPO;
  1053. }
  1054. }
  1055. return var;
  1056. }
  1057. case cmTarget::SHARED_LIBRARY:
  1058. return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
  1059. case cmTarget::MODULE_LIBRARY:
  1060. return "CMAKE_" + lang + "_CREATE_SHARED_MODULE";
  1061. case cmTarget::EXECUTABLE:
  1062. return "CMAKE_" + lang + "_LINK_EXECUTABLE";
  1063. default:
  1064. break;
  1065. }
  1066. return "";
  1067. }
  1068. //----------------------------------------------------------------------------
  1069. std::vector<std::string>
  1070. cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
  1071. const std::string& lang) const
  1072. {
  1073. return this->Target->GetIncludeDirectories(config, lang);
  1074. }
  1075. //----------------------------------------------------------------------------
  1076. void cmGeneratorTarget::GenerateTargetManifest(
  1077. const std::string& config) const
  1078. {
  1079. if (this->Target->IsImported())
  1080. {
  1081. return;
  1082. }
  1083. cmMakefile* mf = this->Target->GetMakefile();
  1084. cmGlobalGenerator* gg = mf->GetGlobalGenerator();
  1085. // Get the names.
  1086. std::string name;
  1087. std::string soName;
  1088. std::string realName;
  1089. std::string impName;
  1090. std::string pdbName;
  1091. if(this->GetType() == cmTarget::EXECUTABLE)
  1092. {
  1093. this->Target->GetExecutableNames(name, realName, impName, pdbName,
  1094. config);
  1095. }
  1096. else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
  1097. this->GetType() == cmTarget::SHARED_LIBRARY ||
  1098. this->GetType() == cmTarget::MODULE_LIBRARY)
  1099. {
  1100. this->Target->GetLibraryNames(name, soName, realName, impName, pdbName,
  1101. config);
  1102. }
  1103. else
  1104. {
  1105. return;
  1106. }
  1107. // Get the directory.
  1108. std::string dir = this->Target->GetDirectory(config, false);
  1109. // Add each name.
  1110. std::string f;
  1111. if(!name.empty())
  1112. {
  1113. f = dir;
  1114. f += "/";
  1115. f += name;
  1116. gg->AddToManifest(f);
  1117. }
  1118. if(!soName.empty())
  1119. {
  1120. f = dir;
  1121. f += "/";
  1122. f += soName;
  1123. gg->AddToManifest(f);
  1124. }
  1125. if(!realName.empty())
  1126. {
  1127. f = dir;
  1128. f += "/";
  1129. f += realName;
  1130. gg->AddToManifest(f);
  1131. }
  1132. if(!pdbName.empty())
  1133. {
  1134. f = dir;
  1135. f += "/";
  1136. f += pdbName;
  1137. gg->AddToManifest(f);
  1138. }
  1139. if(!impName.empty())
  1140. {
  1141. f = this->Target->GetDirectory(config, true);
  1142. f += "/";
  1143. f += impName;
  1144. gg->AddToManifest(f);
  1145. }
  1146. }
  1147. //----------------------------------------------------------------------------
  1148. std::string cmGeneratorTarget::GetFullPath(const std::string& config,
  1149. bool implib, bool realname) const
  1150. {
  1151. if(this->Target->IsImported())
  1152. {
  1153. return this->Target->ImportedGetFullPath(config, implib);
  1154. }
  1155. else
  1156. {
  1157. return this->NormalGetFullPath(config, implib, realname);
  1158. }
  1159. }
  1160. std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config,
  1161. bool implib,
  1162. bool realname) const
  1163. {
  1164. std::string fpath = this->Target->GetDirectory(config, implib);
  1165. fpath += "/";
  1166. if(this->Target->IsAppBundleOnApple())
  1167. {
  1168. fpath = this->Target->BuildMacContentDirectory(fpath, config, false);
  1169. fpath += "/";
  1170. }
  1171. // Add the full name of the target.
  1172. if(implib)
  1173. {
  1174. fpath += this->Target->GetFullName(config, true);
  1175. }
  1176. else if(realname)
  1177. {
  1178. fpath += this->NormalGetRealName(config);
  1179. }
  1180. else
  1181. {
  1182. fpath += this->Target->GetFullName(config, false);
  1183. }
  1184. return fpath;
  1185. }
  1186. //----------------------------------------------------------------------------
  1187. std::string
  1188. cmGeneratorTarget::NormalGetRealName(const std::string& config) const
  1189. {
  1190. // This should not be called for imported targets.
  1191. // TODO: Split cmTarget into a class hierarchy to get compile-time
  1192. // enforcement of the limited imported target API.
  1193. if(this->Target->IsImported())
  1194. {
  1195. std::string msg = "NormalGetRealName called on imported target: ";
  1196. msg += this->GetName();
  1197. this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, msg);
  1198. }
  1199. if(this->GetType() == cmTarget::EXECUTABLE)
  1200. {
  1201. // Compute the real name that will be built.
  1202. std::string name;
  1203. std::string realName;
  1204. std::string impName;
  1205. std::string pdbName;
  1206. this->Target->GetExecutableNames(name, realName, impName, pdbName, config);
  1207. return realName;
  1208. }
  1209. else
  1210. {
  1211. // Compute the real name that will be built.
  1212. std::string name;
  1213. std::string soName;
  1214. std::string realName;
  1215. std::string impName;
  1216. std::string pdbName;
  1217. this->Target->GetLibraryNames(name, soName, realName,
  1218. impName, pdbName, config);
  1219. return realName;
  1220. }
  1221. }
  1222. bool cmStrictTargetComparison::operator()(cmTarget const* t1,
  1223. cmTarget const* t2) const
  1224. {
  1225. int nameResult = strcmp(t1->GetName().c_str(), t2->GetName().c_str());
  1226. if (nameResult == 0)
  1227. {
  1228. return strcmp(t1->GetMakefile()->GetCurrentBinaryDirectory(),
  1229. t2->GetMakefile()->GetCurrentBinaryDirectory()) < 0;
  1230. }
  1231. return nameResult < 0;
  1232. }
  1233. //----------------------------------------------------------------------------
  1234. struct cmGeneratorTarget::SourceFileFlags
  1235. cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const
  1236. {
  1237. struct SourceFileFlags flags;
  1238. this->ConstructSourceFileFlags();
  1239. std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
  1240. this->SourceFlagsMap.find(sf);
  1241. if(si != this->SourceFlagsMap.end())
  1242. {
  1243. flags = si->second;
  1244. }
  1245. else
  1246. {
  1247. // Handle the MACOSX_PACKAGE_LOCATION property on source files that
  1248. // were not listed in one of the other lists.
  1249. if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
  1250. {
  1251. flags.MacFolder = location;
  1252. if(strcmp(location, "Resources") == 0)
  1253. {
  1254. flags.Type = cmGeneratorTarget::SourceFileTypeResource;
  1255. }
  1256. else
  1257. {
  1258. flags.Type = cmGeneratorTarget::SourceFileTypeMacContent;
  1259. }
  1260. }
  1261. }
  1262. return flags;
  1263. }
  1264. //----------------------------------------------------------------------------
  1265. void cmGeneratorTarget::ConstructSourceFileFlags() const
  1266. {
  1267. if(this->SourceFileFlagsConstructed)
  1268. {
  1269. return;
  1270. }
  1271. this->SourceFileFlagsConstructed = true;
  1272. // Process public headers to mark the source files.
  1273. if(const char* files = this->Target->GetProperty("PUBLIC_HEADER"))
  1274. {
  1275. std::vector<std::string> relFiles;
  1276. cmSystemTools::ExpandListArgument(files, relFiles);
  1277. for(std::vector<std::string>::iterator it = relFiles.begin();
  1278. it != relFiles.end(); ++it)
  1279. {
  1280. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1281. {
  1282. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1283. flags.MacFolder = "Headers";
  1284. flags.Type = cmGeneratorTarget::SourceFileTypePublicHeader;
  1285. }
  1286. }
  1287. }
  1288. // Process private headers after public headers so that they take
  1289. // precedence if a file is listed in both.
  1290. if(const char* files = this->Target->GetProperty("PRIVATE_HEADER"))
  1291. {
  1292. std::vector<std::string> relFiles;
  1293. cmSystemTools::ExpandListArgument(files, relFiles);
  1294. for(std::vector<std::string>::iterator it = relFiles.begin();
  1295. it != relFiles.end(); ++it)
  1296. {
  1297. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1298. {
  1299. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1300. flags.MacFolder = "PrivateHeaders";
  1301. flags.Type = cmGeneratorTarget::SourceFileTypePrivateHeader;
  1302. }
  1303. }
  1304. }
  1305. // Mark sources listed as resources.
  1306. if(const char* files = this->Target->GetProperty("RESOURCE"))
  1307. {
  1308. std::vector<std::string> relFiles;
  1309. cmSystemTools::ExpandListArgument(files, relFiles);
  1310. for(std::vector<std::string>::iterator it = relFiles.begin();
  1311. it != relFiles.end(); ++it)
  1312. {
  1313. if(cmSourceFile* sf = this->Makefile->GetSource(*it))
  1314. {
  1315. SourceFileFlags& flags = this->SourceFlagsMap[sf];
  1316. flags.MacFolder = "Resources";
  1317. flags.Type = cmGeneratorTarget::SourceFileTypeResource;
  1318. }
  1319. }
  1320. }
  1321. }
  1322. //----------------------------------------------------------------------------
  1323. const cmGeneratorTarget::CompatibleInterfacesBase&
  1324. cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
  1325. {
  1326. cmGeneratorTarget::CompatibleInterfaces& compat =
  1327. this->CompatibleInterfacesMap[config];
  1328. if(!compat.Done)
  1329. {
  1330. compat.Done = true;
  1331. compat.PropsBool.insert("POSITION_INDEPENDENT_CODE");
  1332. compat.PropsString.insert("AUTOUIC_OPTIONS");
  1333. std::vector<cmTarget const*> const& deps =
  1334. this->Target->GetLinkImplementationClosure(config);
  1335. for(std::vector<cmTarget const*>::const_iterator li = deps.begin();
  1336. li != deps.end(); ++li)
  1337. {
  1338. #define CM_READ_COMPATIBLE_INTERFACE(X, x) \
  1339. if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \
  1340. { \
  1341. std::vector<std::string> props; \
  1342. cmSystemTools::ExpandListArgument(prop, props); \
  1343. compat.Props##x.insert(props.begin(), props.end()); \
  1344. }
  1345. CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool)
  1346. CM_READ_COMPATIBLE_INTERFACE(STRING, String)
  1347. CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin)
  1348. CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax)
  1349. #undef CM_READ_COMPATIBLE_INTERFACE
  1350. }
  1351. }
  1352. return compat;
  1353. }
  1354. //----------------------------------------------------------------------------
  1355. bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty(
  1356. const std::string &p, const std::string& config) const
  1357. {
  1358. if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY
  1359. || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
  1360. {
  1361. return false;
  1362. }
  1363. return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0;
  1364. }
  1365. //----------------------------------------------------------------------------
  1366. bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty(
  1367. const std::string &p, const std::string& config) const
  1368. {
  1369. if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY
  1370. || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
  1371. {
  1372. return false;
  1373. }
  1374. return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0;
  1375. }
  1376. //----------------------------------------------------------------------------
  1377. bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty(
  1378. const std::string &p, const std::string& config) const
  1379. {
  1380. if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY
  1381. || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
  1382. {
  1383. return false;
  1384. }
  1385. return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0;
  1386. }
  1387. //----------------------------------------------------------------------------
  1388. bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty(
  1389. const std::string &p, const std::string& config) const
  1390. {
  1391. if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY
  1392. || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
  1393. {
  1394. return false;
  1395. }
  1396. return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0;
  1397. }
  1398. template<typename PropertyType>
  1399. PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  1400. const std::string& prop,
  1401. const std::string& config,
  1402. cmTarget::CompatibleType,
  1403. PropertyType *);
  1404. template<>
  1405. bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  1406. const std::string& prop,
  1407. const std::string& config,
  1408. cmTarget::CompatibleType, bool *)
  1409. {
  1410. return tgt->Target->GetLinkInterfaceDependentBoolProperty(prop, config);
  1411. }
  1412. template<>
  1413. const char * getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt,
  1414. const std::string& prop,
  1415. const std::string& config,
  1416. cmTarget::CompatibleType t,
  1417. const char **)
  1418. {
  1419. switch(t)
  1420. {
  1421. case cmTarget::BoolType:
  1422. assert(0 && "String compatibility check function called for boolean");
  1423. return 0;
  1424. case cmTarget::StringType:
  1425. return tgt->Target->GetLinkInterfaceDependentStringProperty(prop, config);
  1426. case cmTarget::NumberMinType:
  1427. return tgt->Target
  1428. ->GetLinkInterfaceDependentNumberMinProperty(prop, config);
  1429. case cmTarget::NumberMaxType:
  1430. return tgt->Target
  1431. ->GetLinkInterfaceDependentNumberMaxProperty(prop, config);
  1432. }
  1433. assert(0 && "Unreachable!");
  1434. return 0;
  1435. }
  1436. //----------------------------------------------------------------------------
  1437. template<typename PropertyType>
  1438. void checkPropertyConsistency(cmGeneratorTarget const* depender,
  1439. cmTarget const* dependee,
  1440. const std::string& propName,
  1441. std::set<std::string> &emitted,
  1442. const std::string& config,
  1443. cmTarget::CompatibleType t,
  1444. PropertyType *)
  1445. {
  1446. const char *prop = dependee->GetProperty(propName);
  1447. if (!prop)
  1448. {
  1449. return;
  1450. }
  1451. std::vector<std::string> props;
  1452. cmSystemTools::ExpandListArgument(prop, props);
  1453. std::string pdir =
  1454. dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT");
  1455. pdir += "/Help/prop_tgt/";
  1456. for(std::vector<std::string>::iterator pi = props.begin();
  1457. pi != props.end(); ++pi)
  1458. {
  1459. std::string pname = cmSystemTools::HelpFileName(*pi);
  1460. std::string pfile = pdir + pname + ".rst";
  1461. if(cmSystemTools::FileExists(pfile.c_str(), true))
  1462. {
  1463. std::ostringstream e;
  1464. e << "Target \"" << dependee->GetName() << "\" has property \""
  1465. << *pi << "\" listed in its " << propName << " property. "
  1466. "This is not allowed. Only user-defined properties may appear "
  1467. "listed in the " << propName << " property.";
  1468. depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
  1469. return;
  1470. }
  1471. if(emitted.insert(*pi).second)
  1472. {
  1473. getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
  1474. t, 0);
  1475. if (cmSystemTools::GetErrorOccuredFlag())
  1476. {
  1477. return;
  1478. }
  1479. }
  1480. }
  1481. }
  1482. static std::string intersect(const std::set<std::string> &s1,
  1483. const std::set<std::string> &s2)
  1484. {
  1485. std::set<std::string> intersect;
  1486. std::set_intersection(s1.begin(),s1.end(),
  1487. s2.begin(),s2.end(),
  1488. std::inserter(intersect,intersect.begin()));
  1489. if (!intersect.empty())
  1490. {
  1491. return *intersect.begin();
  1492. }
  1493. return "";
  1494. }
  1495. static std::string intersect(const std::set<std::string> &s1,
  1496. const std::set<std::string> &s2,
  1497. const std::set<std::string> &s3)
  1498. {
  1499. std::string result;
  1500. result = intersect(s1, s2);
  1501. if (!result.empty())
  1502. return result;
  1503. result = intersect(s1, s3);
  1504. if (!result.empty())
  1505. return result;
  1506. return intersect(s2, s3);
  1507. }
  1508. static std::string intersect(const std::set<std::string> &s1,
  1509. const std::set<std::string> &s2,
  1510. const std::set<std::string> &s3,
  1511. const std::set<std::string> &s4)
  1512. {
  1513. std::string result;
  1514. result = intersect(s1, s2);
  1515. if (!result.empty())
  1516. return result;
  1517. result = intersect(s1, s3);
  1518. if (!result.empty())
  1519. return result;
  1520. result = intersect(s1, s4);
  1521. if (!result.empty())
  1522. return result;
  1523. return intersect(s2, s3, s4);
  1524. }
  1525. //----------------------------------------------------------------------------
  1526. void cmGeneratorTarget::CheckPropertyCompatibility(
  1527. cmComputeLinkInformation *info, const std::string& config) const
  1528. {
  1529. const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
  1530. std::set<std::string> emittedBools;
  1531. static std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
  1532. std::set<std::string> emittedStrings;
  1533. static std::string strString = "COMPATIBLE_INTERFACE_STRING";
  1534. std::set<std::string> emittedMinNumbers;
  1535. static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
  1536. std::set<std::string> emittedMaxNumbers;
  1537. static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
  1538. for(cmComputeLinkInformation::ItemVector::const_iterator li =
  1539. deps.begin(); li != deps.end(); ++li)
  1540. {
  1541. if (!li->Target)
  1542. {
  1543. continue;
  1544. }
  1545. checkPropertyConsistency<bool>(this, li->Target,
  1546. strBool,
  1547. emittedBools, config, cmTarget::BoolType, 0);
  1548. if (cmSystemTools::GetErrorOccuredFlag())
  1549. {
  1550. return;
  1551. }
  1552. checkPropertyConsistency<const char *>(this, li->Target,
  1553. strString,
  1554. emittedStrings, config,
  1555. cmTarget::StringType, 0);
  1556. if (cmSystemTools::GetErrorOccuredFlag())
  1557. {
  1558. return;
  1559. }
  1560. checkPropertyConsistency<const char *>(this, li->Target,
  1561. strNumMin,
  1562. emittedMinNumbers, config,
  1563. cmTarget::NumberMinType, 0);
  1564. if (cmSystemTools::GetErrorOccuredFlag())
  1565. {
  1566. return;
  1567. }
  1568. checkPropertyConsistency<const char *>(this, li->Target,
  1569. strNumMax,
  1570. emittedMaxNumbers, config,
  1571. cmTarget::NumberMaxType, 0);
  1572. if (cmSystemTools::GetErrorOccuredFlag())
  1573. {
  1574. return;
  1575. }
  1576. }
  1577. std::string prop = intersect(emittedBools,
  1578. emittedStrings,
  1579. emittedMinNumbers,
  1580. emittedMaxNumbers);
  1581. if (!prop.empty())
  1582. {
  1583. // Use a sorted std::vector to keep the error message sorted.
  1584. std::vector<std::string> props;
  1585. std::set<std::string>::const_iterator i = emittedBools.find(prop);
  1586. if (i != emittedBools.end())
  1587. {
  1588. props.push_back(strBool);
  1589. }
  1590. i = emittedStrings.find(prop);
  1591. if (i != emittedStrings.end())
  1592. {
  1593. props.push_back(strString);
  1594. }
  1595. i = emittedMinNumbers.find(prop);
  1596. if (i != emittedMinNumbers.end())
  1597. {
  1598. props.push_back(strNumMin);
  1599. }
  1600. i = emittedMaxNumbers.find(prop);
  1601. if (i != emittedMaxNumbers.end())
  1602. {
  1603. props.push_back(strNumMax);
  1604. }
  1605. std::sort(props.begin(), props.end());
  1606. std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", ");
  1607. propsString += " and the " + props.back();
  1608. std::ostringstream e;
  1609. e << "Property \"" << prop << "\" appears in both the "
  1610. << propsString <<
  1611. " property in the dependencies of target \"" << this->GetName() <<
  1612. "\". This is not allowed. A property may only require compatibility "
  1613. "in a boolean interpretation, a numeric minimum, a numeric maximum or a "
  1614. "string interpretation, but not a mixture.";
  1615. this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str());
  1616. }
  1617. }
  1618. //----------------------------------------------------------------------------
  1619. cmComputeLinkInformation*
  1620. cmGeneratorTarget::GetLinkInformation(const std::string& config) const
  1621. {
  1622. // Lookup any existing information for this configuration.
  1623. std::string key(cmSystemTools::UpperCase(config));
  1624. cmTargetLinkInformationMap::iterator
  1625. i = this->LinkInformation.find(key);
  1626. if(i == this->LinkInformation.end())
  1627. {
  1628. // Compute information for this configuration.
  1629. cmComputeLinkInformation* info =
  1630. new cmComputeLinkInformation(this->Target, config);
  1631. if(!info || !info->Compute())
  1632. {
  1633. delete info;
  1634. info = 0;
  1635. }
  1636. // Store the information for this configuration.
  1637. cmTargetLinkInformationMap::value_type entry(key, info);
  1638. i = this->LinkInformation.insert(entry).first;
  1639. if (info)
  1640. {
  1641. this->CheckPropertyCompatibility(info, config);
  1642. }
  1643. }
  1644. return i->second;
  1645. }