cmExportFileGenerator.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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. #include "cmVersion.h"
  19. #include <cmsys/auto_ptr.hxx>
  20. //----------------------------------------------------------------------------
  21. cmExportFileGenerator::cmExportFileGenerator()
  22. {
  23. this->AppendMode = false;
  24. }
  25. //----------------------------------------------------------------------------
  26. void cmExportFileGenerator::AddConfiguration(const char* config)
  27. {
  28. this->Configurations.push_back(config);
  29. }
  30. //----------------------------------------------------------------------------
  31. void cmExportFileGenerator::SetExportFile(const char* mainFile)
  32. {
  33. this->MainImportFile = mainFile;
  34. this->FileDir =
  35. cmSystemTools::GetFilenamePath(this->MainImportFile);
  36. this->FileBase =
  37. cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
  38. this->FileExt =
  39. cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
  40. }
  41. //----------------------------------------------------------------------------
  42. bool cmExportFileGenerator::GenerateImportFile()
  43. {
  44. // Open the output file to generate it.
  45. cmsys::auto_ptr<std::ofstream> foutPtr;
  46. if(this->AppendMode)
  47. {
  48. // Open for append.
  49. cmsys::auto_ptr<std::ofstream>
  50. ap(new std::ofstream(this->MainImportFile.c_str(), std::ios::app));
  51. foutPtr = ap;
  52. }
  53. else
  54. {
  55. // Generate atomically and with copy-if-different.
  56. cmsys::auto_ptr<cmGeneratedFileStream>
  57. ap(new cmGeneratedFileStream(this->MainImportFile.c_str(), true));
  58. ap->SetCopyIfDifferent(true);
  59. foutPtr = ap;
  60. }
  61. if(!foutPtr.get() || !*foutPtr)
  62. {
  63. std::string se = cmSystemTools::GetLastSystemError();
  64. cmOStringStream e;
  65. e << "cannot write to file \"" << this->MainImportFile
  66. << "\": " << se;
  67. cmSystemTools::Error(e.str().c_str());
  68. return false;
  69. }
  70. std::ostream& os = *foutPtr;
  71. // Protect that file against use with older CMake versions.
  72. os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
  73. os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
  74. << " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
  75. << "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n";
  76. // Isolate the file policy level.
  77. // We use 2.6 here instead of the current version because newer
  78. // versions of CMake should be able to export files imported by 2.6
  79. // until the import format changes.
  80. os << "CMAKE_POLICY(PUSH)\n"
  81. << "CMAKE_POLICY(VERSION 2.6)\n";
  82. // Start with the import file header.
  83. this->GenerateImportHeaderCode(os);
  84. // Create all the imported targets.
  85. bool result = this->GenerateMainFile(os);
  86. // End with the import file footer.
  87. this->GenerateImportFooterCode(os);
  88. os << "CMAKE_POLICY(POP)\n";
  89. return result;
  90. }
  91. //----------------------------------------------------------------------------
  92. void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
  93. const char* config)
  94. {
  95. // Construct the property configuration suffix.
  96. std::string suffix = "_";
  97. if(config && *config)
  98. {
  99. suffix += cmSystemTools::UpperCase(config);
  100. }
  101. else
  102. {
  103. suffix += "NOCONFIG";
  104. }
  105. // Generate the per-config target information.
  106. this->GenerateImportTargetsConfig(os, config, suffix);
  107. }
  108. //----------------------------------------------------------------------------
  109. void
  110. cmExportFileGenerator
  111. ::SetImportDetailProperties(const char* config, std::string const& suffix,
  112. cmTarget* target, ImportPropertyMap& properties)
  113. {
  114. // Get the makefile in which to lookup target information.
  115. cmMakefile* mf = target->GetMakefile();
  116. // Add the soname for unix shared libraries.
  117. if(target->GetType() == cmTarget::SHARED_LIBRARY ||
  118. target->GetType() == cmTarget::MODULE_LIBRARY)
  119. {
  120. // Check whether this is a DLL platform.
  121. bool dll_platform =
  122. (mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
  123. if(!dll_platform)
  124. {
  125. std::string soname = target->GetSOName(config);
  126. std::string prop = "IMPORTED_SONAME";
  127. prop += suffix;
  128. properties[prop] = soname;
  129. }
  130. }
  131. // Add the transitive link dependencies for this configuration.
  132. if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config))
  133. {
  134. this->SetImportLinkProperty(suffix, target,
  135. "IMPORTED_LINK_INTERFACE_LANGUAGES",
  136. iface->Languages, properties);
  137. this->SetImportLinkProperty(suffix, target,
  138. "IMPORTED_LINK_INTERFACE_LIBRARIES",
  139. iface->Libraries, properties);
  140. this->SetImportLinkProperty(suffix, target,
  141. "IMPORTED_LINK_DEPENDENT_LIBRARIES",
  142. iface->SharedDeps, properties);
  143. if(iface->Multiplicity > 0)
  144. {
  145. std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
  146. prop += suffix;
  147. cmOStringStream m;
  148. m << iface->Multiplicity;
  149. properties[prop] = m.str();
  150. }
  151. }
  152. }
  153. //----------------------------------------------------------------------------
  154. void
  155. cmExportFileGenerator
  156. ::SetImportLinkProperty(std::string const& suffix,
  157. cmTarget* target,
  158. const char* propName,
  159. std::vector<std::string> const& libs,
  160. ImportPropertyMap& properties)
  161. {
  162. // Skip the property if there are no libraries.
  163. if(libs.empty())
  164. {
  165. return;
  166. }
  167. // Get the makefile in which to lookup target information.
  168. cmMakefile* mf = target->GetMakefile();
  169. // Construct the property value.
  170. std::string link_libs;
  171. const char* sep = "";
  172. for(std::vector<std::string>::const_iterator li = libs.begin();
  173. li != libs.end(); ++li)
  174. {
  175. // Separate this from the previous entry.
  176. link_libs += sep;
  177. sep = ";";
  178. // Append this entry.
  179. if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
  180. {
  181. // This is a target.
  182. if(tgt->IsImported())
  183. {
  184. // The target is imported (and therefore is not in the
  185. // export). Append the raw name.
  186. link_libs += *li;
  187. }
  188. else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
  189. {
  190. // The target is in the export. Append it with the export
  191. // namespace.
  192. link_libs += this->Namespace;
  193. link_libs += *li;
  194. }
  195. else
  196. {
  197. // The target is not in the export.
  198. if(!this->AppendMode)
  199. {
  200. // We are not appending, so all exported targets should be
  201. // known here. This is probably user-error.
  202. this->ComplainAboutMissingTarget(target, tgt);
  203. }
  204. // Assume the target will be exported by another command.
  205. // Append it with the export namespace.
  206. link_libs += this->Namespace;
  207. link_libs += *li;
  208. }
  209. }
  210. else
  211. {
  212. // Append the raw name.
  213. link_libs += *li;
  214. }
  215. }
  216. // Store the property.
  217. std::string prop = propName;
  218. prop += suffix;
  219. properties[prop] = link_libs;
  220. }
  221. //----------------------------------------------------------------------------
  222. void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
  223. const char* config)
  224. {
  225. os << "#----------------------------------------------------------------\n"
  226. << "# Generated CMake target import file";
  227. if(config)
  228. {
  229. os << " for configuration \"" << config << "\".\n";
  230. }
  231. else
  232. {
  233. os << ".\n";
  234. }
  235. os << "#----------------------------------------------------------------\n"
  236. << "\n";
  237. this->GenerateImportVersionCode(os);
  238. }
  239. //----------------------------------------------------------------------------
  240. void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
  241. {
  242. os << "# Commands beyond this point should not need to know the version.\n"
  243. << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
  244. }
  245. //----------------------------------------------------------------------------
  246. void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
  247. {
  248. // Store an import file format version. This will let us change the
  249. // format later while still allowing old import files to work.
  250. os << "# Commands may need to know the format version.\n"
  251. << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
  252. << "\n";
  253. }
  254. //----------------------------------------------------------------------------
  255. void
  256. cmExportFileGenerator
  257. ::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
  258. {
  259. // Construct the imported target name.
  260. std::string targetName = this->Namespace;
  261. targetName += target->GetName();
  262. // Create the imported target.
  263. os << "# Create imported target " << targetName << "\n";
  264. switch(target->GetType())
  265. {
  266. case cmTarget::EXECUTABLE:
  267. os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
  268. break;
  269. case cmTarget::STATIC_LIBRARY:
  270. os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
  271. break;
  272. case cmTarget::SHARED_LIBRARY:
  273. os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
  274. break;
  275. case cmTarget::MODULE_LIBRARY:
  276. os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
  277. break;
  278. default: // should never happen
  279. break;
  280. }
  281. // Mark the imported executable if it has exports.
  282. if(target->IsExecutableWithExports())
  283. {
  284. os << "SET_PROPERTY(TARGET " << targetName
  285. << " PROPERTY ENABLE_EXPORTS 1)\n";
  286. }
  287. // Mark the imported library if it is a framework.
  288. if(target->IsFrameworkOnApple())
  289. {
  290. os << "SET_PROPERTY(TARGET " << targetName
  291. << " PROPERTY FRAMEWORK 1)\n";
  292. }
  293. // Mark the imported executable if it is an application bundle.
  294. if(target->IsAppBundleOnApple())
  295. {
  296. os << "SET_PROPERTY(TARGET " << targetName
  297. << " PROPERTY MACOSX_BUNDLE 1)\n";
  298. }
  299. os << "\n";
  300. }
  301. //----------------------------------------------------------------------------
  302. void
  303. cmExportFileGenerator
  304. ::GenerateImportPropertyCode(std::ostream& os, const char* config,
  305. cmTarget* target,
  306. ImportPropertyMap const& properties)
  307. {
  308. // Construct the imported target name.
  309. std::string targetName = this->Namespace;
  310. targetName += target->GetName();
  311. // Set the import properties.
  312. os << "# Import target \"" << targetName << "\" for configuration \""
  313. << config << "\"\n";
  314. os << "SET_PROPERTY(TARGET " << targetName
  315. << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
  316. if(config && *config)
  317. {
  318. os << cmSystemTools::UpperCase(config);
  319. }
  320. else
  321. {
  322. os << "NOCONFIG";
  323. }
  324. os << ")\n";
  325. os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
  326. for(ImportPropertyMap::const_iterator pi = properties.begin();
  327. pi != properties.end(); ++pi)
  328. {
  329. os << " " << pi->first << " \"" << pi->second << "\"\n";
  330. }
  331. os << " )\n"
  332. << "\n";
  333. }