cmExportInstallFileGenerator.cxx 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmExportInstallFileGenerator.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmInstallExportGenerator.h"
  16. #include "cmInstallTargetGenerator.h"
  17. //----------------------------------------------------------------------------
  18. cmExportInstallFileGenerator
  19. ::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
  20. InstallExportGenerator(iegen)
  21. {
  22. }
  23. //----------------------------------------------------------------------------
  24. std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
  25. {
  26. std::string glob = this->FileBase;
  27. glob += "-*";
  28. glob += this->FileExt;
  29. return glob;
  30. }
  31. //----------------------------------------------------------------------------
  32. bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
  33. {
  34. // Create all the imported targets.
  35. for(std::vector<cmTargetExport*>::const_iterator
  36. tei = this->ExportSet->begin();
  37. tei != this->ExportSet->end(); ++tei)
  38. {
  39. cmTargetExport* te = *tei;
  40. if(this->ExportedTargets.insert(te->Target).second)
  41. {
  42. this->GenerateImportTargetCode(os, te->Target);
  43. }
  44. else
  45. {
  46. cmOStringStream e;
  47. e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
  48. << "includes target \"" << te->Target->GetName()
  49. << "\" more than once in the export set.";
  50. cmSystemTools::Error(e.str().c_str());
  51. return false;
  52. }
  53. }
  54. // Now load per-configuration properties for them.
  55. os << "# Load information for each installed configuration.\n"
  56. << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
  57. << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
  58. << this->GetConfigImportFileGlob() << "\")\n"
  59. << "FOREACH(f ${CONFIG_FILES})\n"
  60. << " INCLUDE(${f})\n"
  61. << "ENDFOREACH(f)\n"
  62. << "\n";
  63. // Generate an import file for each configuration.
  64. bool result = true;
  65. for(std::vector<std::string>::const_iterator
  66. ci = this->Configurations.begin();
  67. ci != this->Configurations.end(); ++ci)
  68. {
  69. if(!this->GenerateImportFileConfig(ci->c_str()))
  70. {
  71. result = false;
  72. }
  73. }
  74. return result;
  75. }
  76. //----------------------------------------------------------------------------
  77. bool
  78. cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
  79. {
  80. // Skip configurations not enabled for this export.
  81. if(!this->InstallExportGenerator->InstallsForConfig(config))
  82. {
  83. return true;
  84. }
  85. // Construct the name of the file to generate.
  86. std::string fileName = this->FileDir;
  87. fileName += "/";
  88. fileName += this->FileBase;
  89. fileName += "-";
  90. if(config && *config)
  91. {
  92. fileName += cmSystemTools::LowerCase(config);
  93. }
  94. else
  95. {
  96. fileName += "noconfig";
  97. }
  98. fileName += this->FileExt;
  99. // Open the output file to generate it.
  100. cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
  101. if(!exportFileStream)
  102. {
  103. std::string se = cmSystemTools::GetLastSystemError();
  104. cmOStringStream e;
  105. e << "cannot write to file \"" << fileName.c_str()
  106. << "\": " << se;
  107. cmSystemTools::Error(e.str().c_str());
  108. return false;
  109. }
  110. std::ostream& os = exportFileStream;
  111. // Start with the import file header.
  112. this->GenerateImportHeaderCode(os, config);
  113. // Generate the per-config target information.
  114. this->GenerateImportConfig(os, config);
  115. // End with the import file footer.
  116. this->GenerateImportFooterCode(os);
  117. // Record this per-config import file.
  118. this->ConfigImportFiles[config] = fileName;
  119. return true;
  120. }
  121. //----------------------------------------------------------------------------
  122. void
  123. cmExportInstallFileGenerator
  124. ::GenerateImportTargetsConfig(std::ostream& os,
  125. const char* config, std::string const& suffix)
  126. {
  127. // Add code to compute the installation prefix relative to the
  128. // import file location.
  129. const char* installDest = this->InstallExportGenerator->GetDestination();
  130. if(!cmSystemTools::FileIsFullPath(installDest))
  131. {
  132. std::string dest = installDest;
  133. os << "# Compute the installation prefix relative to this file.\n"
  134. << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
  135. << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
  136. while(!dest.empty())
  137. {
  138. os <<
  139. "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
  140. dest = cmSystemTools::GetFilenamePath(dest);
  141. }
  142. os << "\n";
  143. // Import location properties may reference this variable.
  144. this->ImportPrefix = "${_IMPORT_PREFIX}/";
  145. }
  146. // Add each target in the set to the export.
  147. for(std::vector<cmTargetExport*>::const_iterator
  148. tei = this->ExportSet->begin();
  149. tei != this->ExportSet->end(); ++tei)
  150. {
  151. // Collect import properties for this target.
  152. cmTargetExport* te = *tei;
  153. ImportPropertyMap properties;
  154. this->SetImportLocationProperty(config, suffix,
  155. te->ArchiveGenerator, properties);
  156. this->SetImportLocationProperty(config, suffix,
  157. te->LibraryGenerator, properties);
  158. this->SetImportLocationProperty(config, suffix,
  159. te->RuntimeGenerator, properties);
  160. this->SetImportLocationProperty(config, suffix,
  161. te->FrameworkGenerator, properties);
  162. this->SetImportLocationProperty(config, suffix,
  163. te->BundleGenerator, properties);
  164. // If any file location was set for the target add it to the
  165. // import file.
  166. if(!properties.empty())
  167. {
  168. // Get the rest of the target details.
  169. this->SetImportDetailProperties(config, suffix,
  170. te->Target, properties);
  171. // TOOD: PUBLIC_HEADER_LOCATION
  172. // This should wait until the build feature propagation stuff
  173. // is done. Then this can be a propagated include directory.
  174. // this->GenerateImportProperty(config, te->HeaderGenerator,
  175. // properties);
  176. // Generate code in the export file.
  177. this->GenerateImportPropertyCode(os, config, te->Target, properties);
  178. }
  179. }
  180. // Cleanup the import prefix variable.
  181. if(!this->ImportPrefix.empty())
  182. {
  183. os << "# Cleanup temporary variables.\n"
  184. << "SET(_IMPORT_PREFIX)\n"
  185. << "\n";
  186. }
  187. }
  188. //----------------------------------------------------------------------------
  189. void
  190. cmExportInstallFileGenerator
  191. ::SetImportLocationProperty(const char* config, std::string const& suffix,
  192. cmInstallTargetGenerator* itgen,
  193. ImportPropertyMap& properties)
  194. {
  195. // Skip rules that do not match this configuration.
  196. if(!(itgen && itgen->InstallsForConfig(config)))
  197. {
  198. return;
  199. }
  200. // Get the target to be installed.
  201. cmTarget* target = itgen->GetTarget();
  202. // Construct the installed location of the target.
  203. std::string dest = itgen->GetDestination();
  204. std::string value;
  205. if(!cmSystemTools::FileIsFullPath(dest.c_str()))
  206. {
  207. // The target is installed relative to the installation prefix.
  208. if(this->ImportPrefix.empty())
  209. {
  210. this->ComplainAboutImportPrefix(itgen);
  211. }
  212. value = this->ImportPrefix;
  213. }
  214. value += dest;
  215. value += "/";
  216. if(itgen->IsImportLibrary())
  217. {
  218. // Construct the property name.
  219. std::string prop = "IMPORTED_IMPLIB";
  220. prop += suffix;
  221. // Append the installed file name.
  222. value += itgen->GetInstallFilename(target, config,
  223. cmInstallTargetGenerator::NameImplib);
  224. // Store the property.
  225. properties[prop] = value;
  226. }
  227. else
  228. {
  229. // Construct the property name.
  230. std::string prop = "IMPORTED_LOCATION";
  231. prop += suffix;
  232. // Append the installed file name.
  233. if(target->IsFrameworkOnApple())
  234. {
  235. value += itgen->GetInstallFilename(target, config);
  236. value += ".framework/";
  237. value += itgen->GetInstallFilename(target, config);
  238. }
  239. else if(target->IsAppBundleOnApple())
  240. {
  241. value += itgen->GetInstallFilename(target, config);
  242. value += ".app/Contents/MacOS/";
  243. value += itgen->GetInstallFilename(target, config);
  244. }
  245. else
  246. {
  247. value += itgen->GetInstallFilename(target, config,
  248. cmInstallTargetGenerator::NameReal);
  249. }
  250. // Store the property.
  251. properties[prop] = value;
  252. }
  253. }
  254. //----------------------------------------------------------------------------
  255. void
  256. cmExportInstallFileGenerator
  257. ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
  258. {
  259. const char* installDest = this->InstallExportGenerator->GetDestination();
  260. cmOStringStream e;
  261. e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
  262. << "DESTINATION \"" << installDest << "\" but the export "
  263. << "references an installation of target \""
  264. << itgen->GetTarget()->GetName() << "\" which has relative "
  265. << "DESTINATION \"" << itgen->GetDestination() << "\".";
  266. cmSystemTools::Error(e.str().c_str());
  267. }
  268. //----------------------------------------------------------------------------
  269. void
  270. cmExportInstallFileGenerator
  271. ::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
  272. {
  273. cmOStringStream e;
  274. e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
  275. << "includes target \"" << depender->GetName()
  276. << "\" which requires target \"" << dependee->GetName()
  277. << "\" that is not in the export set.";
  278. cmSystemTools::Error(e.str().c_str());
  279. }