cmExportFileGenerator.cxx 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 "cmExportFileGenerator.h"
  14. #include "cmGeneratedFileStream.h"
  15. #include "cmMakefile.h"
  16. #include "cmSystemTools.h"
  17. #include "cmTarget.h"
  18. //----------------------------------------------------------------------------
  19. void cmExportFileGenerator::AddConfiguration(const char* config)
  20. {
  21. this->Configurations.push_back(config);
  22. }
  23. //----------------------------------------------------------------------------
  24. void cmExportFileGenerator::SetExportFile(const char* mainFile)
  25. {
  26. this->MainImportFile = mainFile;
  27. this->FileDir =
  28. cmSystemTools::GetFilenamePath(this->MainImportFile);
  29. this->FileBase =
  30. cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
  31. this->FileExt =
  32. cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
  33. }
  34. //----------------------------------------------------------------------------
  35. bool cmExportFileGenerator::GenerateImportFile()
  36. {
  37. // Open the output file to generate it.
  38. cmGeneratedFileStream exportFileStream(this->MainImportFile.c_str(), true);
  39. if(!exportFileStream)
  40. {
  41. std::string se = cmSystemTools::GetLastSystemError();
  42. cmOStringStream e;
  43. e << "cannot write to file \"" << this->MainImportFile
  44. << "\": " << se;
  45. cmSystemTools::Error(e.str().c_str());
  46. return false;
  47. }
  48. std::ostream& os = exportFileStream;
  49. // Start with the import file header.
  50. this->GenerateImportHeaderCode(os);
  51. // Create all the imported targets.
  52. bool result = this->GenerateMainFile(os);
  53. // End with the import file footer.
  54. this->GenerateImportFooterCode(os);
  55. return result;
  56. }
  57. //----------------------------------------------------------------------------
  58. void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
  59. const char* config)
  60. {
  61. // Construct the property configuration suffix.
  62. std::string suffix = "_";
  63. if(config && *config)
  64. {
  65. suffix += cmSystemTools::UpperCase(config);
  66. }
  67. else
  68. {
  69. suffix += "NOCONFIG";
  70. }
  71. // Generate the per-config target information.
  72. this->GenerateImportTargetsConfig(os, config, suffix);
  73. }
  74. //----------------------------------------------------------------------------
  75. void
  76. cmExportFileGenerator
  77. ::SetImportDetailProperties(const char* config, std::string const& suffix,
  78. cmTarget* target, ImportPropertyMap& properties)
  79. {
  80. // Get the makefile in which to lookup target information.
  81. cmMakefile* mf = target->GetMakefile();
  82. // Add the soname for unix shared libraries.
  83. if(target->GetType() == cmTarget::SHARED_LIBRARY ||
  84. target->GetType() == cmTarget::MODULE_LIBRARY)
  85. {
  86. // Check whether this is a DLL platform.
  87. bool dll_platform =
  88. (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
  89. if(!dll_platform)
  90. {
  91. std::string soname = target->GetSOName(config);
  92. std::string prop = "IMPORTED_SONAME";
  93. prop += suffix;
  94. properties[prop] = soname;
  95. }
  96. }
  97. // Add the transitive link dependencies for this configuration.
  98. {
  99. // Compute which library configuration to link.
  100. cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
  101. if(config && cmSystemTools::UpperCase(config) == "DEBUG")
  102. {
  103. linkType = cmTarget::DEBUG;
  104. }
  105. // Construct the property value.
  106. cmTarget::LinkLibraryVectorType const& libs =
  107. target->GetOriginalLinkLibraries();
  108. std::string link_libs;
  109. const char* sep = "";
  110. for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
  111. li != libs.end(); ++li)
  112. {
  113. // Skip entries that will resolve to the target itself, are empty,
  114. // or are not meant for this configuration.
  115. if(li->first == target->GetName() || li->first.empty() ||
  116. !(li->second == cmTarget::GENERAL || li->second == linkType))
  117. {
  118. continue;
  119. }
  120. // Separate this from the previous entry.
  121. link_libs += sep;
  122. sep = ";";
  123. // Append this entry.
  124. if(cmTarget* tgt = mf->FindTargetToUse(li->first.c_str()))
  125. {
  126. // This is a target. Make sure it is included in the export.
  127. if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
  128. {
  129. // The target is in the export. Append it with the export
  130. // namespace.
  131. link_libs += this->Namespace;
  132. link_libs += li->first;
  133. }
  134. else
  135. {
  136. // The target is not in the export. This is probably
  137. // user-error. Warn but add it anyway.
  138. this->ComplainAboutMissingTarget(target, li->first.c_str());
  139. link_libs += li->first;
  140. }
  141. }
  142. else
  143. {
  144. // Append the raw name.
  145. link_libs += li->first;
  146. }
  147. }
  148. // Store the property.
  149. std::string prop = "IMPORTED_LINK_LIBRARIES";
  150. prop += suffix;
  151. properties[prop] = link_libs;
  152. }
  153. }
  154. //----------------------------------------------------------------------------
  155. void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
  156. const char* config)
  157. {
  158. os << "#----------------------------------------------------------------\n"
  159. << "# Generated CMake target import file";
  160. if(config)
  161. {
  162. os << " for configuration \"" << config << "\".\n";
  163. }
  164. else
  165. {
  166. os << ".\n";
  167. }
  168. os << "#----------------------------------------------------------------\n"
  169. << "\n";
  170. this->GenerateImportVersionCode(os);
  171. }
  172. //----------------------------------------------------------------------------
  173. void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
  174. {
  175. os << "# Commands beyond this point should not need to know the version.\n"
  176. << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
  177. }
  178. //----------------------------------------------------------------------------
  179. void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
  180. {
  181. // Store an import file format version. This will let us change the
  182. // format later while still allowing old import files to work.
  183. os << "# Commands may need to know the format version.\n"
  184. << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
  185. << "\n";
  186. }
  187. //----------------------------------------------------------------------------
  188. void
  189. cmExportFileGenerator
  190. ::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
  191. {
  192. // Construct the imported target name.
  193. std::string targetName = this->Namespace;
  194. targetName += target->GetName();
  195. // Create the imported target.
  196. os << "# Create imported target " << targetName << "\n";
  197. switch(target->GetType())
  198. {
  199. case cmTarget::EXECUTABLE:
  200. os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
  201. break;
  202. case cmTarget::STATIC_LIBRARY:
  203. os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
  204. break;
  205. case cmTarget::SHARED_LIBRARY:
  206. os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
  207. break;
  208. case cmTarget::MODULE_LIBRARY:
  209. os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
  210. break;
  211. default: // should never happen
  212. break;
  213. }
  214. if(target->IsExecutableWithExports())
  215. {
  216. os << "SET_PROPERTY(TARGET " << targetName
  217. << " PROPERTY IMPORTED_ENABLE_EXPORTS 1)\n";
  218. }
  219. os << "\n";
  220. }
  221. //----------------------------------------------------------------------------
  222. void
  223. cmExportFileGenerator
  224. ::GenerateImportPropertyCode(std::ostream& os, const char* config,
  225. cmTarget* target,
  226. ImportPropertyMap const& properties)
  227. {
  228. // Construct the imported target name.
  229. std::string targetName = this->Namespace;
  230. targetName += target->GetName();
  231. // Set the import properties.
  232. os << "# Import target \"" << targetName << "\" for configuration \""
  233. << config << "\"\n";
  234. os << "SET_PROPERTY(TARGET " << targetName
  235. << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
  236. if(config && *config)
  237. {
  238. os << cmSystemTools::UpperCase(config);
  239. }
  240. else
  241. {
  242. os << "NOCONFIG";
  243. }
  244. os << ")\n";
  245. os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
  246. for(ImportPropertyMap::const_iterator pi = properties.begin();
  247. pi != properties.end(); ++pi)
  248. {
  249. os << " " << pi->first << " \"" << pi->second << "\"\n";
  250. }
  251. os << " )\n"
  252. << "\n";
  253. }