cmExportInstallFileGenerator.cxx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
  25. {
  26. // Create all the imported targets.
  27. for(std::vector<cmTargetExport*>::const_iterator
  28. tei = this->ExportSet->begin();
  29. tei != this->ExportSet->end(); ++tei)
  30. {
  31. cmTargetExport* te = *tei;
  32. this->ExportedTargets.insert(te->Target);
  33. this->GenerateImportTargetCode(os, te->Target);
  34. }
  35. // Now load per-configuration properties for them.
  36. os << "# Load information for each installed configuration.\n"
  37. << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
  38. << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
  39. << this->FileBase << "-*" << this->FileExt << "\")\n"
  40. << "FOREACH(f ${CONFIG_FILES})\n"
  41. << " INCLUDE(${f})\n"
  42. << "ENDFOREACH(f)\n"
  43. << "\n";
  44. // Generate an import file for each configuration.
  45. bool result = true;
  46. for(std::vector<std::string>::const_iterator
  47. ci = this->Configurations.begin();
  48. ci != this->Configurations.end(); ++ci)
  49. {
  50. if(!this->GenerateImportFileConfig(ci->c_str()))
  51. {
  52. result = false;
  53. }
  54. }
  55. return result;
  56. }
  57. //----------------------------------------------------------------------------
  58. bool
  59. cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
  60. {
  61. // Skip configurations not enabled for this export.
  62. if(!this->InstallExportGenerator->InstallsForConfig(config))
  63. {
  64. return true;
  65. }
  66. // Construct the name of the file to generate.
  67. std::string fileName = this->FileDir;
  68. fileName += "/";
  69. fileName += this->FileBase;
  70. fileName += "-";
  71. if(config && *config)
  72. {
  73. fileName += cmSystemTools::LowerCase(config);
  74. }
  75. else
  76. {
  77. fileName += "noconfig";
  78. }
  79. fileName += this->FileExt;
  80. // Open the output file to generate it.
  81. cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
  82. if(!exportFileStream)
  83. {
  84. std::string se = cmSystemTools::GetLastSystemError();
  85. cmOStringStream e;
  86. e << "cannot write to file \"" << fileName.c_str()
  87. << "\": " << se;
  88. cmSystemTools::Error(e.str().c_str());
  89. return false;
  90. }
  91. std::ostream& os = exportFileStream;
  92. // Start with the import file header.
  93. this->GenerateImportHeaderCode(os, config);
  94. // Generate the per-config target information.
  95. this->GenerateImportConfig(os, config);
  96. // End with the import file footer.
  97. this->GenerateImportFooterCode(os);
  98. // Record this per-config import file.
  99. this->ConfigImportFiles[config] = fileName;
  100. return true;
  101. }
  102. //----------------------------------------------------------------------------
  103. void
  104. cmExportInstallFileGenerator
  105. ::GenerateImportTargetsConfig(std::ostream& os,
  106. const char* config, std::string const& suffix)
  107. {
  108. // Add code to compute the installation prefix relative to the
  109. // import file location.
  110. const char* installDest = this->InstallExportGenerator->GetDestination();
  111. if(!cmSystemTools::FileIsFullPath(installDest))
  112. {
  113. std::string dest = installDest;
  114. os << "# Compute the installation prefix relative to this file.\n"
  115. << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
  116. << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
  117. while(!dest.empty())
  118. {
  119. os <<
  120. "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
  121. dest = cmSystemTools::GetFilenamePath(dest);
  122. }
  123. os << "\n";
  124. // Import location properties may reference this variable.
  125. this->ImportPrefix = "${_IMPORT_PREFIX}/";
  126. }
  127. // Add each target in the set to the export.
  128. for(std::vector<cmTargetExport*>::const_iterator
  129. tei = this->ExportSet->begin();
  130. tei != this->ExportSet->end(); ++tei)
  131. {
  132. // Collect import properties for this target.
  133. cmTargetExport* te = *tei;
  134. ImportPropertyMap properties;
  135. this->SetImportLocationProperty(config, suffix,
  136. te->ArchiveGenerator, properties);
  137. this->SetImportLocationProperty(config, suffix,
  138. te->LibraryGenerator, properties);
  139. this->SetImportLocationProperty(config, suffix,
  140. te->RuntimeGenerator, properties);
  141. this->SetImportLocationProperty(config, suffix,
  142. te->FrameworkGenerator, properties);
  143. this->SetImportLocationProperty(config, suffix,
  144. te->BundleGenerator, properties);
  145. // If any file location was set for the target add it to the
  146. // import file.
  147. if(!properties.empty())
  148. {
  149. // Get the rest of the target details.
  150. this->SetImportDetailProperties(config, suffix,
  151. te->Target, properties);
  152. // TOOD: PUBLIC_HEADER_LOCATION
  153. // this->GenerateImportProperty(config, te->HeaderGenerator,
  154. // properties);
  155. // Generate code in the export file.
  156. this->GenerateImportPropertyCode(os, config, te->Target, properties);
  157. }
  158. }
  159. // Cleanup the import prefix variable.
  160. if(!this->ImportPrefix.empty())
  161. {
  162. os << "# Cleanup temporary variables.\n"
  163. << "SET(_IMPORT_PREFIX)\n"
  164. << "\n";
  165. }
  166. }
  167. //----------------------------------------------------------------------------
  168. void
  169. cmExportInstallFileGenerator
  170. ::SetImportLocationProperty(const char* config, std::string const& suffix,
  171. cmInstallTargetGenerator* itgen,
  172. ImportPropertyMap& properties)
  173. {
  174. // Skip rules that do not match this configuration.
  175. if(!(itgen && itgen->InstallsForConfig(config)))
  176. {
  177. return;
  178. }
  179. {
  180. // Construct the property name.
  181. std::string prop = (itgen->IsImportLibrary()?
  182. "IMPORTED_IMPLIB" : "IMPORTED_LOCATION");
  183. prop += suffix;
  184. // Construct the installed location of the target.
  185. std::string dest = itgen->GetDestination();
  186. std::string value;
  187. if(!cmSystemTools::FileIsFullPath(dest.c_str()))
  188. {
  189. // The target is installed relative to the installation prefix.
  190. if(this->ImportPrefix.empty())
  191. {
  192. this->ComplainAboutImportPrefix(itgen);
  193. }
  194. value = this->ImportPrefix;
  195. }
  196. value += dest;
  197. value += "/";
  198. // Append the installed file name.
  199. std::string fname = itgen->GetInstallFilename(config);
  200. value += fname;
  201. // Fix name for frameworks and bundles.
  202. if(itgen->GetTarget()->IsFrameworkOnApple())
  203. {
  204. value += ".framework/";
  205. value += fname;
  206. }
  207. else if(itgen->GetTarget()->IsAppBundleOnApple())
  208. {
  209. value += ".app/Contents/MacOS/";
  210. value += fname;
  211. }
  212. // Store the property.
  213. properties[prop] = value;
  214. }
  215. }
  216. //----------------------------------------------------------------------------
  217. void
  218. cmExportInstallFileGenerator
  219. ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
  220. {
  221. const char* installDest = this->InstallExportGenerator->GetDestination();
  222. cmOStringStream e;
  223. e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
  224. << "DESTINATION \"" << installDest << "\" but the export "
  225. << "references an installation of target \""
  226. << itgen->GetTarget()->GetName() << "\" which has relative "
  227. << "DESTINATION \"" << itgen->GetDestination() << "\".";
  228. cmSystemTools::Error(e.str().c_str());
  229. }
  230. //----------------------------------------------------------------------------
  231. void
  232. cmExportInstallFileGenerator
  233. ::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
  234. {
  235. cmOStringStream e;
  236. e << "WARNING: INSTALL(EXPORT \"" << this->Name << "\" ...) "
  237. << "includes target " << target->GetName()
  238. << " which links to target \"" << dep
  239. << "\" that is not in the export set.";
  240. cmSystemTools::Message(e.str().c_str());
  241. }