cmExportBuildFileGenerator.cxx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 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 "cmExportBuildFileGenerator.h"
  11. #include "cmLocalGenerator.h"
  12. #include "cmGlobalGenerator.h"
  13. //----------------------------------------------------------------------------
  14. cmExportBuildFileGenerator::cmExportBuildFileGenerator()
  15. {
  16. this->Makefile = 0;
  17. }
  18. //----------------------------------------------------------------------------
  19. bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
  20. {
  21. {
  22. std::string expectedTargets;
  23. std::string sep;
  24. for(std::vector<std::string>::const_iterator
  25. tei = this->Targets.begin();
  26. tei != this->Targets.end(); ++tei)
  27. {
  28. cmTarget *te = this->Makefile->FindTargetToUse(tei->c_str());
  29. expectedTargets += sep + this->Namespace + te->GetExportName();
  30. sep = " ";
  31. if(this->ExportedTargets.insert(te).second)
  32. {
  33. this->Exports.push_back(te);
  34. }
  35. else
  36. {
  37. cmOStringStream e;
  38. e << "given target \"" << te->GetName() << "\" more than once.";
  39. this->Makefile->GetCMakeInstance()
  40. ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), this->Backtrace);
  41. return false;
  42. }
  43. if (te->GetType() == cmTarget::INTERFACE_LIBRARY)
  44. {
  45. this->GenerateRequiredCMakeVersion(os, "2.8.12.20131007"); // 2.8.13
  46. }
  47. }
  48. this->GenerateExpectedTargetsCode(os, expectedTargets);
  49. }
  50. std::vector<std::string> missingTargets;
  51. // Create all the imported targets.
  52. for(std::vector<cmTarget*>::const_iterator
  53. tei = this->Exports.begin();
  54. tei != this->Exports.end(); ++tei)
  55. {
  56. cmTarget* te = *tei;
  57. this->GenerateImportTargetCode(os, te);
  58. te->AppendBuildInterfaceIncludes();
  59. ImportPropertyMap properties;
  60. this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
  61. cmGeneratorExpression::BuildInterface,
  62. properties, missingTargets);
  63. this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
  64. cmGeneratorExpression::BuildInterface,
  65. properties, missingTargets);
  66. this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te,
  67. cmGeneratorExpression::BuildInterface,
  68. properties, missingTargets);
  69. this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", te,
  70. cmGeneratorExpression::BuildInterface,
  71. properties, missingTargets);
  72. this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
  73. te, properties);
  74. const bool newCMP0022Behavior =
  75. te->GetPolicyStatusCMP0022() != cmPolicies::WARN
  76. && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
  77. if (newCMP0022Behavior)
  78. {
  79. this->PopulateInterfaceLinkLibrariesProperty(te,
  80. cmGeneratorExpression::BuildInterface,
  81. properties, missingTargets);
  82. }
  83. this->PopulateCompatibleInterfaceProperties(te, properties);
  84. this->GenerateInterfaceProperties(te, os, properties);
  85. }
  86. // Generate import file content for each configuration.
  87. for(std::vector<std::string>::const_iterator
  88. ci = this->Configurations.begin();
  89. ci != this->Configurations.end(); ++ci)
  90. {
  91. this->GenerateImportConfig(os, ci->c_str(), missingTargets);
  92. }
  93. this->GenerateMissingTargetsCheckCode(os, missingTargets);
  94. return true;
  95. }
  96. //----------------------------------------------------------------------------
  97. void
  98. cmExportBuildFileGenerator
  99. ::GenerateImportTargetsConfig(std::ostream& os,
  100. const char* config, std::string const& suffix,
  101. std::vector<std::string> &missingTargets)
  102. {
  103. for(std::vector<cmTarget*>::const_iterator
  104. tei = this->Exports.begin();
  105. tei != this->Exports.end(); ++tei)
  106. {
  107. // Collect import properties for this target.
  108. cmTarget* target = *tei;
  109. ImportPropertyMap properties;
  110. if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
  111. {
  112. this->SetImportLocationProperty(config, suffix, target, properties);
  113. }
  114. if(!properties.empty())
  115. {
  116. // Get the rest of the target details.
  117. if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
  118. {
  119. this->SetImportDetailProperties(config, suffix,
  120. target, properties, missingTargets);
  121. this->SetImportLinkInterface(config, suffix,
  122. cmGeneratorExpression::BuildInterface,
  123. target, properties, missingTargets);
  124. }
  125. // TOOD: PUBLIC_HEADER_LOCATION
  126. // This should wait until the build feature propagation stuff
  127. // is done. Then this can be a propagated include directory.
  128. // this->GenerateImportProperty(config, te->HeaderGenerator,
  129. // properties);
  130. // Generate code in the export file.
  131. this->GenerateImportPropertyCode(os, config, target, properties);
  132. }
  133. }
  134. }
  135. //----------------------------------------------------------------------------
  136. void
  137. cmExportBuildFileGenerator
  138. ::SetImportLocationProperty(const char* config, std::string const& suffix,
  139. cmTarget* target, ImportPropertyMap& properties)
  140. {
  141. // Get the makefile in which to lookup target information.
  142. cmMakefile* mf = target->GetMakefile();
  143. // Add the main target file.
  144. {
  145. std::string prop = "IMPORTED_LOCATION";
  146. prop += suffix;
  147. std::string value;
  148. if(target->IsAppBundleOnApple())
  149. {
  150. value = target->GetFullPath(config, false);
  151. }
  152. else
  153. {
  154. value = target->GetFullPath(config, false, true);
  155. }
  156. properties[prop] = value;
  157. }
  158. // Check whether this is a DLL platform.
  159. bool dll_platform =
  160. (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
  161. // Add the import library for windows DLLs.
  162. if(dll_platform &&
  163. (target->GetType() == cmTarget::SHARED_LIBRARY ||
  164. target->IsExecutableWithExports()) &&
  165. mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
  166. {
  167. std::string prop = "IMPORTED_IMPLIB";
  168. prop += suffix;
  169. std::string value = target->GetFullPath(config, true);
  170. target->GetImplibGNUtoMS(value, value,
  171. "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
  172. properties[prop] = value;
  173. }
  174. }
  175. //----------------------------------------------------------------------------
  176. void
  177. cmExportBuildFileGenerator::HandleMissingTarget(
  178. std::string& link_libs, std::vector<std::string>& missingTargets,
  179. cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
  180. {
  181. // The target is not in the export.
  182. if(!this->AppendMode)
  183. {
  184. const std::string name = dependee->GetName();
  185. std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
  186. int targetOccurrences = (int)namespaces.size();
  187. if (targetOccurrences == 1)
  188. {
  189. std::string missingTarget = namespaces[0];
  190. missingTarget += dependee->GetExportName();
  191. link_libs += missingTarget;
  192. missingTargets.push_back(missingTarget);
  193. return;
  194. }
  195. else
  196. {
  197. // We are not appending, so all exported targets should be
  198. // known here. This is probably user-error.
  199. this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
  200. }
  201. }
  202. // Assume the target will be exported by another command.
  203. // Append it with the export namespace.
  204. link_libs += this->Namespace;
  205. link_libs += dependee->GetExportName();
  206. }
  207. //----------------------------------------------------------------------------
  208. std::vector<std::string>
  209. cmExportBuildFileGenerator
  210. ::FindNamespaces(cmMakefile* mf, const std::string& name)
  211. {
  212. std::vector<std::string> namespaces;
  213. cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
  214. std::map<std::string, cmExportBuildFileGenerator*>& exportSets
  215. = gg->GetBuildExportSets();
  216. for(std::map<std::string, cmExportBuildFileGenerator*>::const_iterator
  217. expIt = exportSets.begin(); expIt != exportSets.end(); ++expIt)
  218. {
  219. const cmExportBuildFileGenerator* exportSet = expIt->second;
  220. std::vector<std::string> const& targets = exportSet->GetTargets();
  221. if (std::find(targets.begin(), targets.end(), name) != targets.end())
  222. {
  223. namespaces.push_back(exportSet->GetNamespace());
  224. }
  225. }
  226. return namespaces;
  227. }
  228. //----------------------------------------------------------------------------
  229. void
  230. cmExportBuildFileGenerator
  231. ::ComplainAboutMissingTarget(cmTarget* depender,
  232. cmTarget* dependee,
  233. int occurrences)
  234. {
  235. if(cmSystemTools::GetErrorOccuredFlag())
  236. {
  237. return;
  238. }
  239. cmOStringStream e;
  240. e << "export called with target \"" << depender->GetName()
  241. << "\" which requires target \"" << dependee->GetName() << "\" ";
  242. if (occurrences == 0)
  243. {
  244. e << "that is not in the export set.\n";
  245. }
  246. else
  247. {
  248. e << "that is not in this export set, but " << occurrences
  249. << " times in others.\n";
  250. }
  251. e << "If the required target is not easy to reference in this call, "
  252. << "consider using the APPEND option with multiple separate calls.";
  253. this->Makefile->GetCMakeInstance()
  254. ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(), this->Backtrace);
  255. }
  256. std::string
  257. cmExportBuildFileGenerator::InstallNameDir(cmTarget* target,
  258. const std::string& config)
  259. {
  260. std::string install_name_dir;
  261. cmMakefile* mf = target->GetMakefile();
  262. if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
  263. {
  264. install_name_dir =
  265. target->GetInstallNameDirForBuildTree(config.c_str());
  266. }
  267. return install_name_dir;
  268. }