cmExportInstallFileGenerator.cxx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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 should wait until the build feature propagation stuff
  154. // is done. Then this can be a propagated include directory.
  155. // this->GenerateImportProperty(config, te->HeaderGenerator,
  156. // properties);
  157. // Generate code in the export file.
  158. this->GenerateImportPropertyCode(os, config, te->Target, properties);
  159. }
  160. }
  161. // Cleanup the import prefix variable.
  162. if(!this->ImportPrefix.empty())
  163. {
  164. os << "# Cleanup temporary variables.\n"
  165. << "SET(_IMPORT_PREFIX)\n"
  166. << "\n";
  167. }
  168. }
  169. //----------------------------------------------------------------------------
  170. void
  171. cmExportInstallFileGenerator
  172. ::SetImportLocationProperty(const char* config, std::string const& suffix,
  173. cmInstallTargetGenerator* itgen,
  174. ImportPropertyMap& properties)
  175. {
  176. // Skip rules that do not match this configuration.
  177. if(!(itgen && itgen->InstallsForConfig(config)))
  178. {
  179. return;
  180. }
  181. {
  182. // Construct the property name.
  183. std::string prop = (itgen->IsImportLibrary()?
  184. "IMPORTED_IMPLIB" : "IMPORTED_LOCATION");
  185. prop += suffix;
  186. // Construct the installed location of the target.
  187. std::string dest = itgen->GetDestination();
  188. std::string value;
  189. if(!cmSystemTools::FileIsFullPath(dest.c_str()))
  190. {
  191. // The target is installed relative to the installation prefix.
  192. if(this->ImportPrefix.empty())
  193. {
  194. this->ComplainAboutImportPrefix(itgen);
  195. }
  196. value = this->ImportPrefix;
  197. }
  198. value += dest;
  199. value += "/";
  200. // Append the installed file name.
  201. std::string fname = itgen->GetInstallFilename(config);
  202. value += fname;
  203. // Fix name for frameworks and bundles.
  204. if(itgen->GetTarget()->IsFrameworkOnApple())
  205. {
  206. value += ".framework/";
  207. value += fname;
  208. }
  209. else if(itgen->GetTarget()->IsAppBundleOnApple())
  210. {
  211. value += ".app/Contents/MacOS/";
  212. value += fname;
  213. }
  214. // Store the property.
  215. properties[prop] = value;
  216. }
  217. }
  218. //----------------------------------------------------------------------------
  219. void
  220. cmExportInstallFileGenerator
  221. ::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
  222. {
  223. const char* installDest = this->InstallExportGenerator->GetDestination();
  224. cmOStringStream e;
  225. e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
  226. << "DESTINATION \"" << installDest << "\" but the export "
  227. << "references an installation of target \""
  228. << itgen->GetTarget()->GetName() << "\" which has relative "
  229. << "DESTINATION \"" << itgen->GetDestination() << "\".";
  230. cmSystemTools::Error(e.str().c_str());
  231. }
  232. //----------------------------------------------------------------------------
  233. void
  234. cmExportInstallFileGenerator
  235. ::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
  236. {
  237. cmOStringStream e;
  238. e << "WARNING: INSTALL(EXPORT \"" << this->Name << "\" ...) "
  239. << "includes target " << target->GetName()
  240. << " which links to target \"" << dep
  241. << "\" that is not in the export set.";
  242. cmSystemTools::Message(e.str().c_str());
  243. }